Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/0387362e92ed285e9431ea7df7a2e99da5676e74
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/0387362e92ed285e9431ea7df7a2e99da5676e74
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/0387362e92ed285e9431ea7df7a2e99da5676e74

The branch, jmb/ievent has been updated
       via  0387362e92ed285e9431ea7df7a2e99da5676e74 (commit)
       via  6a93f3b06d183c2bdb0689ccb5658fad4c83faf8 (commit)
       via  0c9ae30064618d23e65f854e45a7a7b4a20678db (commit)
      from  33eebb9aaf94539557a1d86675d01a7b9d699366 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=0387362e92ed285e9431ea7df7a2e99da5676e74
commit 0387362e92ed285e9431ea7df7a2e99da5676e74
Author: John-Mark Bell <[email protected]>
Commit: John-Mark Bell <[email protected]>

    RISC OS: use SocketWatch for Internet Event handling

diff --git a/frontends/riscos/gui.c b/frontends/riscos/gui.c
index 190aacb..02a3020 100644
--- a/frontends/riscos/gui.c
+++ b/frontends/riscos/gui.c
@@ -26,8 +26,10 @@
 #include <assert.h>
 #include <errno.h>
 #include <signal.h>
+#include <unistd.h>
 #include <unixlib/local.h>
 #include <fpu_control.h>
+#include <swis.h>
 #include <oslib/help.h>
 #include <oslib/uri.h>
 #include <oslib/inetsuite.h>
@@ -120,8 +122,6 @@ osspriteop_area *gui_sprites; /**< Sprite area containing 
pointer and hotlist sp
 #define DIR_SEP ('.')
 
 static void *pollword;
-static bool eventv_claimed;
-static bool internet_event_enabled;
 
 /**
  * Accepted wimp user messages.
@@ -393,14 +393,8 @@ static void ro_gui_cleanup(void)
        xhourglass_off();
        /* Uninstall NetSurf-specific fonts */
        xos_cli("FontRemove NetSurf:Resources.Fonts.");
-       if (internet_event_enabled) {
-               xos_byte(osbyte_DISABLE_EVENT, Event_Internet, 0, NULL, NULL);
-       }
-       if (eventv_claimed) {
-               xos_release(EventV, (asm_routine) (((uintptr_t) pollword) + 4),
-                       pollword);
-       }
        if (pollword != NULL) {
+               //XXX: need to make sure _all_ sockets are closed
                xosmodule_free(pollword);
        }
 }
@@ -1128,41 +1122,55 @@ static bool ro_gui__os_alpha_sprites_supported(void)
        return (var_val == (1 << 15));
 }
 
+static int ro_gui_socket_open(int domain, int type, int protocol)
+{
+       int sock = socket(domain, type, protocol);
+       if (sock != -1) {
+               int rosock;
+               _kernel_oserror *error;
+
+               rosock = __get_ro_socket(sock);
+               if (rosock == -1) {
+                       close(sock);
+                       errno = ENOMEM;
+                       return -1;
+               }
+
+               /* SocketWatch_Register */
+               error = _swix(0x52280, _INR(0,2), pollword, 0x1, rosock);
+               if (error != NULL) {
+                       close(sock);
+                       errno = ENOMEM;
+                       return -1;
+               }
+       }
+       return sock;
+}
+
+static int ro_gui_socket_close(int socket)
+{
+       int rosock;
+
+       rosock = __get_ro_socket(socket);
+       if (rosock != -1) {
+               /* SocketWatch_Deregister */
+               (void) _swix(0x52281, _INR(0,1), rosock, pollword);
+       }
+
+       return close(socket);
+}
+
 /**
  * Set up internet event handling
  */
 static os_error *ro_gui_init_internet_event(void)
 {
-       static const uint32_t event_handler_code[] = {
-               0x00000000, // pollword value
-               0xE3300013, // TEQ r0, #Event_Internet
-               0x11A0F00E, // MOVNE pc, lr
-               0xE59C5000, // LDR r5, [r12]
-               0xE2855001, // ADD r5, r5, #1
-               0xE58C5000, // STR r5, [r12]
-               0xE1A0F00E, // MOV pc, lr
-       };
        os_error *error;
 
-       error = xosmodule_alloc(sizeof(event_handler_code), &pollword);
-       if (error != NULL)
-               return error;
-       memcpy(pollword, event_handler_code, sizeof(event_handler_code));
-       error = xos_synchronise_code_areas(os_GIVEN_CODE_RANGE,
-                       (asm_routine) (((uintptr_t) pollword) + 4),
-                       (asm_routine) (((uintptr_t) pollword) +
-                               sizeof(event_handler_code) - 4));
-       if (error != NULL)
-               return error;
-       error = xos_claim(EventV, (asm_routine) (((uintptr_t) pollword) + 4),
-                       pollword);
-       if (error != NULL)
-               return error;
-       eventv_claimed = true;
-       error = xos_byte(osbyte_ENABLE_EVENT, Event_Internet, 0, NULL, NULL);
+       error = xosmodule_alloc(4, &pollword);
        if (error != NULL)
                return error;
-       internet_event_enabled = true;
+       *((uint32_t*) pollword) = 0;
        return NULL;
 }
 
@@ -1901,7 +1909,8 @@ static void ro_gui_handle_event(wimp_event_no event, 
wimp_block *block)
                case wimp_POLLWORD_NON_ZERO:
                        /* simply reset pollword */
                        if (pollword != NULL) {
-                               *((uint32_t *) pollword) = 0;
+                               /* SocketWatch_AtomicReset */
+                               _swix(0x52282, _INR(0,1), pollword, 0);
                        }
                        break;
 
@@ -2467,6 +2476,8 @@ static struct gui_fetch_table riscos_fetch_table = {
 
        .get_resource_url = gui_get_resource_url,
        .mimetype = fetch_mimetype,
+       .socket_open = ro_gui_socket_open,
+       .socket_close = ro_gui_socket_close,
 };
 
 static struct gui_misc_table riscos_misc_table = {
diff --git a/frontends/riscos/scripts/Run b/frontends/riscos/scripts/Run
index 3368140..233322e 100644
--- a/frontends/riscos/scripts/Run
+++ b/frontends/riscos/scripts/Run
@@ -95,6 +95,10 @@ RMEnsure Iconv 0.12 Error NetSurf requires Iconv 0.12 or 
later. Please use the R
 RMEnsure CryptRandom 0.13 NetSurfRMLoad System:Modules.CryptRand
 RMEnsure CryptRandom 0.13 Error NetSurf requires CryptRandom 0.13 or later.  
Please use the RISC OS Configure app to update the computer's !System directory 
from the NetSurf archive.
 
+| Ensure SocketWatch
+RMEnsure SocketWatch 0.07 NetSurfRMLoad System:Modules.Network.SockWatch
+RMEnsure SocketWatch 0.07 Error NetSurf requires SocketWatch 0.07 or later. 
Please use the RISC OS Configure app to update the computer's !System directory 
from the NetSurf archive.
+
 | Disable SpecialFX, if present
 Set NetSurf$SpecialFX 1
 RMEnsure SpecialFX 1.00 Set NetSurf$SpecialFX 0


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=6a93f3b06d183c2bdb0689ccb5658fad4c83faf8
commit 6a93f3b06d183c2bdb0689ccb5658fad4c83faf8
Author: John-Mark Bell <[email protected]>
Commit: John-Mark Bell <[email protected]>

    Fetch/curl: expose socket open/close via fetch vtable
    
    This allows frontends to customise the behaviour of sockets. The
    default implementation simply maps to socket(2)/close(2).

diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index b8bccf0..7e5435e 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -1798,28 +1798,23 @@ fetch_curl_debug(CURL *handle,
 }
 
 
-/**
- * Callback function to set arbitrary socket options
- */
-static int fetch_curl_sockopt(void *clientp, curl_socket_t curlfd,
-               curlsocktype purpose)
+static curl_socket_t fetch_curl_socket_open(void *clientp,
+               curlsocktype purpose, struct curl_sockaddr *address)
 {
        (void) clientp;
-
-//XXX: indirect through fetch vtable?
-#ifdef riscos
-       if (purpose == CURLSOCKTYPE_IPCXN) {
-               int one = 1;
-               ioctl(curlfd, FIOASYNC, &one);
-       }
-#else
-       (void) curlfd;
        (void) purpose;
-#endif
 
-       return CURL_SOCKOPT_OK;
+       return (curl_socket_t) guit->fetch->socket_open(
+                       address->family, address->socktype,
+                       address->protocol);
 }
 
+static int fetch_curl_socket_close(void *clientp, curl_socket_t item)
+{
+       (void) clientp;
+
+       return guit->fetch->socket_close((int) item);
+}
 
 /**
  * Callback function for cURL.
@@ -2076,7 +2071,8 @@ nserror fetch_curl_register(void)
        SETOPT(CURLOPT_LOW_SPEED_TIME, 180L);
        SETOPT(CURLOPT_NOSIGNAL, 1L);
        SETOPT(CURLOPT_CONNECTTIMEOUT, nsoption_uint(curl_fetch_timeout));
-       SETOPT(CURLOPT_SOCKOPTFUNCTION, fetch_curl_sockopt);
+       SETOPT(CURLOPT_OPENSOCKETFUNCTION, fetch_curl_socket_open);
+       SETOPT(CURLOPT_CLOSESOCKETFUNCTION, fetch_curl_socket_close);
 
        if (nsoption_charp(ca_bundle) &&
            strcmp(nsoption_charp(ca_bundle), "")) {
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index 89f2e37..c9dcd8b 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -20,6 +20,9 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 
 #include "utils/config.h"
 #include "utils/errors.h"
@@ -498,6 +501,12 @@ static nserror verify_fetch_register(struct 
gui_fetch_table *gft)
        if (gft->mimetype == NULL) {
                gft->mimetype = gui_default_mimetype;
        }
+       if (gft->socket_open == NULL) {
+               gft->socket_open = socket;
+       }
+       if (gft->socket_close == NULL) {
+               gft->socket_close = close;
+       }
 
        return NSERROR_OK;
 }
diff --git a/include/netsurf/fetch.h b/include/netsurf/fetch.h
index 30b2048..156f4d1 100644
--- a/include/netsurf/fetch.h
+++ b/include/netsurf/fetch.h
@@ -99,6 +99,23 @@ struct gui_fetch_table {
         */
        char *(*mimetype)(const char *ro_path);
 
+       /**
+        * Open a socket
+        *
+        * \param domain Communication domain
+        * \param type Socket type
+        * \param protocol Protocol
+        * \return Socket descriptor on success, -1 on error and errno set
+        */
+       int (*socket_open)(int domain, int type, int protocol);
+
+       /**
+        * Close a socket
+        *
+        * \param socket Socket descriptor
+        * \return 0 on success, -1 on error and errno set
+        */
+       int (*socket_close)(int socket);
 };
 
 #endif


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=0c9ae30064618d23e65f854e45a7a7b4a20678db
commit 0c9ae30064618d23e65f854e45a7a7b4a20678db
Author: John-Mark Bell <[email protected]>
Commit: John-Mark Bell <[email protected]>

    RISC OS: add SocketWatch module to distribution

diff --git 
a/frontends/riscos/distribution/!System/310/Modules/Network/SockWatch,ffa 
b/frontends/riscos/distribution/!System/310/Modules/Network/SockWatch,ffa
new file mode 100644
index 0000000..e589cfd
Binary files /dev/null and 
b/frontends/riscos/distribution/!System/310/Modules/Network/SockWatch,ffa differ
diff --git a/frontends/riscos/distribution/3rdParty/SocketWatch/!Info 
b/frontends/riscos/distribution/3rdParty/SocketWatch/!Info
new file mode 100644
index 0000000..cda7977
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/!Info
@@ -0,0 +1,137 @@
+Name   : SocketWatch
+Purpose: Asynchronous socket operations without null polls
+Version: 0.07  (11-01-2019)
+Status : GNU GPL
+Authors: Dickon Hood, Frank de Bruijn
+
+This isn't an official release.
+
+In November 2003 I noticed SocketWatch 0.04y had a couple of bugs. After I had
+corrected them and was almost ready to release 0.05, I discovered the
+'official' place for SocketWatch was now on the Nettle site
+(http://nettle.sourceforge.net). So I contacted the Nettle maintainers, told
+them about the bugs and sent them all the work I had done on repairing it,
+more or less expecting to hear something about an official release 0.05 within
+a couple of months...
+
+Still nothing three months later, so I sent one more e-mail (which remained
+unanswered) and put 0.05 on my site.
+
+
+Installing
+==========
+The zip archive contains an application called !ModInst. Run it to install the
+module on your computer. If you want to install the module manually, you can
+find it in !ModInst.Resources.!System.310.Modules.Network.
+
+
+Source
+======
+The source code is provided as an ObjAsm file in the Source directory in the
+archive. If you want to assemble the module again, run the Build file. The
+module will be recreated and moved to the !ModInst application for
+installation.
+
+
+Version history
+===============
+11-01-2019  0.07
+----------------
+Catered for errors in SocketWatch_Register better.
+Added notes about use with AcornSSL.
+
+12-06-2012
+----------
+Removed dependency on private library (providing constants) so the source can
+be used stand alone. Added Build script (previous builds were done from
+StrongED, using a multipurpose ObjAsmRun script). Nothing changed otherwise.
+MD5 checksum still f2bb3f8d911d0b20a43d6ee135c3ae97.
+
+23-06-2006  0.06
+----------------
+Fixed small bug in the AtomicReset SWI (flags not restored in 26 bit mode, so
+IRQ bit not cleared). Not sure if this ever bothered anyone (think not as it
+was already present in 0.04y).
+Removed disabling interrupts in EventHandler as event handlers are entered
+with interrupts disabled.
+Also some more source clean ups and more comments added.
+MD5 checksum: f2bb3f8d911d0b20a43d6ee135c3ae97.
+
+14-08-2005
+----------------
+Moved the source to ObjAsm. No functional changes to the code. MD5 checksum
+still 90f3323981a0e287f488e9a59b2e5373. No new release.
+
+12-12-2003  0.05
+----------------
+First one by me. Came about when I was investigating a memory leak on my RPC.
+MD5 checksum of the module: 90f3323981a0e287f488e9a59b2e5373.
+
+The detailed list of changes below was for the benefit of the Nettle
+maintainers and originally sent to Ian in an e-mail on 11-12-2003.
+Use the single file source of 0.04y as a reference.
+
+- Most of the variable definitions from Flags% to r12End% aren't required. You
+  just need SockList% (with a FNdb(-4) instead of a FNdb(4)) and r12End%. The
+  rest was removed.
+- No flag definitions are needed. Removed.
+- Socket structure definitions and ErrorChunk%: no changes.
+- From the module header to EventHandler_GotOne32%: merely some optimisations.
+- Error texts: were placed near the routines that use them. This was mainly
+  cosmetic, but it had the added advantage of allowing me to replace all the
+  FNADRLs with simple ADRs.
+- GetBlock%: removed.
+- ReleaseBlock%: removed.
+- IsHexNum_lp1%: not required. Removed.
+- moveBytes%: not required. Removed.
+- From title string to SWI-handler: no real changes.
+- From Command% to CommandText%: moved the table and the help and syntax texts
+  for the commands to just before the SWDL_Code% routine and 'cleaned up' the
+  texts a bit, but that qualifies as cosmetic.
+- Syslog_Name%: not required. Removed.
+- Syslog_Version%: not required. Removed.
+- From Init% to FinalCode%: several changes, the most important one being the
+  removal of the claiming of a 16K block of temporary workspace which was
+  neither used nor released.
+  There's also the stacking of r7 to r9/r11. It's true that these registers
+  should be saved (according to the PRM) but only if they're modified. So why
+  bother if they're not? Replacing this with just stacking r14 enabled a
+  'cleaner' jump out of the routines on errors.
+  At the very beginning of Init%, I inserted a check for a value in r12 on
+  entry. This has to do with re-initialisation after a 'Tidy' operation. Not
+  sure if that's still required though (hasn't the 'Tidy' functionality been
+  blocked or removed from RISC OS these days or is that an unfounded rumour?).
+  I removed everything connected with the CRC-check, including the error text.
+  SocketWatch is the only module I've ever come across using something like
+  this and I honestly fail to see what use it is here. But if you do see that,
+  then by all means leave it in.
+  In Final% the (unused) ModuleDying% flag was set, but as that had been
+  removed anyway, so were the three instructions involved in this action.
+  Actually, as the variable Flags% was re-used to point at the module flags
+  word, this flag bit isn't set in the first word of the workspace at all. In
+  fact, on finalisation SocketWatch 0.04y sets bit 1 of the word 592 bytes
+  from the address r12 happens to point at. That *could* be in the unused 16K
+  block that was claimed on initialisation, but there's no guarantee. Nasty
+  (and no, I hadn't realised this yet when I wrote the comment on Flags% in
+  the Source_004y file...).
+  FinalCode% (renamed release%) was more or less integrated with Init% (sort
+  of 'glued to the bottom') but otherwise essentially unchanged, apart from
+  removing the call to ReleaseBlock% (including the stacking/unstacking of
+  r14) in favour of a simple MOV r0,#7 / SWI XOS_Module sequence).
+- SWI_Register% contained some code at the start (up to the Bvs instruction) I
+  couldn't make sense of. If you can, please enlighten me. I asked Dickon
+  about this in my first email to him and he didn't understand it anymore
+  either. So I removed it.
+  The rest is essentially unchanged (cosmetics only), but I did replace the
+  call to GetBlock% and the 'push' and 'pop' instructions around it with the
+  MOV/SWI instructions that were actually required here.
+- SWI_Deregister%: no changes except for replacing the call to ReleaseBlock%
+  and its surrounding 'push'/'pop' with the necessary MOV and SWI.
+- SWI_AtomicReset%: optimisations only.
+- SWI_AllocPW%: no changes.
+- SWI_DeallocPW%: no changes.
+- SWDL_Code%: cosmetic changes only.
+
+02-12-2002  0.04y
+-----------------
+By Dickon Hood. See the !ReadMe file.
diff --git a/frontends/riscos/distribution/3rdParty/SocketWatch/Origin,b28 
b/frontends/riscos/distribution/3rdParty/SocketWatch/Origin,b28
new file mode 100644
index 0000000..34a71d9
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/Origin,b28
@@ -0,0 +1 @@
+https://www.aconet.org/tools/
diff --git a/frontends/riscos/distribution/3rdParty/SocketWatch/Source/!ReadMe 
b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/!ReadMe
new file mode 100644
index 0000000..ea24c78
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/!ReadMe
@@ -0,0 +1,133 @@
+Document v0.07.  (C) Dickon Hood, see licence for details of copying etc.
+
+
+SocketWatch
+===========
+
+SocketWatch is a simple module designed to reduce the requirement of Wimp
+applications using sockets to constantly poll them using Null Wimp polls for
+data.
+
+If you're not a programmer, stop reading now, this will probably make little
+sense to you.  If you are a programmer, but don't write networking
+applications, again, this is unlikely to be of interest.
+
+
+Rationale
+---------
+
+At boot time, my machine loads and runs five seperate applications which
+require open sockets.  As none of these have support modules associated with
+them, I'm assuming that they are constantly polling the sockets they open on
+null polls.  This is inefficient.
+
+Sockets can be marked as asynchronous.  If they are, an Internet event (19)
+is generated whenever something interesting happens to them.  Events are only
+accessable to modules, however, and are useless in a Wimp environment.  The
+answer is to write a module which does that and notifies the parent
+application that something has happened.  If every application did this,
+there'd be another five or six modules running on my machine, all doing much
+the same job, which I don't need.
+
+This attempts to address the issue by implementing a module with an open
+interface, and one which is generic enough to be applicable to almost every
+app. which could want to use it.
+
+
+Usage
+-----
+
+SocketWatch relies upon a feature of Risc OS 3.1 and upwards, so won't work
+on ROS2.  Sorry, but there we go.
+
+Sockets are registered with the module.  At this point, the socket is marked
+as asynchronous (so the parent app. doesn't need to).  A pollword and bit
+number to set are also supplied.
+
+As some internal structure has to be created, a pollword of 0 is acceptable,
+and, if passed, the module will use one of the words in this structure as the
+pollword.  This is returned to the app. in r0.
+
+When an Internet event is triggered, the module scans all registered sockets. 
+If one is matched, the appropriate bit is set in the pollword.  This allows
+other bits to be reserved for other things.  Note, it is not an error for a
+socket to have multiple pollwords associated with it; there is no reason I
+can think of for two apps. to share one socket (*why* is another matter, but
+it shouldn't be an error); these may both register PWs for them.
+
+Usage with AcornSSL
+-------------------
+SocketWatch should only be used with the normal socket numbers, not the ssl 
+socket handles used by AcornSSL.
+However, it can be used for secure sockets with a sequence like:
+   Socket_Create              to get socket normal socket descriptor
+   AcornSSL_CreateSession     to get ssl socket
+   SocketWatch_Register       of normal socket descriptor
+
+SWIs
+----
+
+SWI SocketWatch_Register (0x52280)
+
+On entry: r0 => pollword, 0 for module to allocate one,
+          r1 =  bitmask to set if there's activity
+          r2 =  socket number.
+
+On exit:  r0 => pollword.
+          If an error is raised by Socket_Ioctl, r0 is => error block
+          and the socket is not registered.
+
+If the pollword passed is 0, one allocated from the internal structure will
+be returned.  Note that this is freed when at the time of deregistering and
+may not be used afterwards.
+
+
+
+SWI SocketWatch_Deregister (0x52281)
+
+On entry: r0 =  socket,
+          r1 => pollword.
+
+On exit:  all preserved.
+
+The socket is no longer watched.  If the pollword was allocated by the
+module, it is not valid once this call is called.
+
+
+
+SWI SocketWatch_AtomicReset (0x52282)
+
+On entry: r0 => pollword
+          r1 =  new value
+
+On exit:  r0 =  old value
+          r1 preserved.
+
+This SWI reads from r0, writes r1 to r0, then exits, all with IRQs off,
+making it an atomic operation (ie., one which may not be interrupted).  It is
+a problem with Pollwords in that they're used by IRQ or Callback code, yet
+read and reset by usermode code which can't disable IRQs easily.  This
+removes the problem where the app. reads the PW, IRQ routine sets a couple of
+bits, then the forground resets it.
+
+
+
+SWI SocketWatch_AllocPW (0x52283)
+
+On entry: -
+
+On exit:  r0 => 4 bytes of RAM which may be released by SWI
+SocketWatch_DeallocPW.
+
+ATM, this SWI claims four bytes of RMA; this isn't efficient, and may be
+changed in later releases.  The SWI is provided for convenience's sake.
+
+
+
+SWI SocketWatch_DeallocPW (0x52284)
+
+On entry: r0 => pollword, as allocated by SWI SocketWatch_AllocPW.
+
+On exit:  all preserved.
+
+ATM this calls OS_Module 7 to free the word.
diff --git 
a/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Build,fd7 
b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Build,fd7
new file mode 100644
index 0000000..e741870
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Build,fd7
@@ -0,0 +1,16 @@
+| SocketWatchBuild  1.00  12-06-2012
+
+Set SocketWatchSource$Dir <Obey$Dir>
+Set SocketWatchTarget$Dir 
<SocketWatchSource$Dir>.^.!ModInst.Resources.!System.310.Modules.Network
+
+RMEnsure DDEUtils 0.00 IfThere System:Modules.DDEUtils Then RMLoad 
System:Modules.DDEUtils
+RMEnsure DDEUtils 0.00 Error DDEUtils module not found
+
+ObjAsm -throwback <SocketWatchSource$Dir>.Source 
<SocketWatchSource$Dir>.[Object]
+Link -verbose -rmf -output <SocketWatchSource$Dir>.SockWatch 
<SocketWatchSource$Dir>.[Object]
+Remove <SocketWatchSource$Dir>.[Object]
+
+IfThere <SocketWatchTarget$Dir> Then Copy <SocketWatchSource$Dir>.SockWatch 
<SocketWatchTarget$Dir>.* A~CDF~L~N~P~Q~R~S~T~V
+
+Unset SocketWatchTarget$Dir
+Unset SocketWatchSource$Dir
\ No newline at end of file
diff --git a/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Licence 
b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Licence
new file mode 100644
index 0000000..dc63aac
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Licence
@@ -0,0 +1,340 @@
+
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Source 
b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Source
new file mode 100644
index 0000000..03b48b0
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Source
@@ -0,0 +1,461 @@
+; SocketWatch.Source  0.07  11-01-2019
+
+; This is the source code for version 0.07 of the SocketWatch module, 
originally by Dickon Hood.
+; It's GNU GPL (see the file 'Licence').
+; See the !Info file for more information.
+;
+; Frank de Bruijn, June 2006.
+; v0.07 (11/01/2019) Martin Avison catered for errors using AcornSSL, and any 
other Ioctl errors:
+;       AcornSSL_Ioctl will set FIOASYNC for SSL sockets ... but Internet 
event gives
+;       base integer socket, so SocketWatch cannot match it on socket & 
pollword.
+;       Socketwatch must therefore only be used with base integer socket 
descriptors,
+;       (although they may be secured using AcornSSL_CreateSession).
+;       If Socket_Ioctl is called with SSL socket, it gives error 'Bad file 
descriptor' but registers it.
+;       This change removes any registration after any Ioctl error, and 
returns the error.
+;
+
+        GBLS    NAME
+        GBLS    VERSION
+        GBLS    DATE
+NAME    SETS    "SocketWatch"
+VERSION SETS    "0.07"
+DATE    SETS    "11 Jan 2019"
+
+wp              RN r12                           ; workspace pointer
+
+X               * &20000                         ; bit 17
+
+OS_Write0       * &02                            ; some SWIs
+OS_NewLine      * &03
+OS_Byte         * &06
+OS_Module       * &1E
+OS_Claim        * &1F
+OS_Release      * &20
+OS_ConvertHex8  * &D4
+Socket_Ioctl    * &41212
+
+iFlag26         * 1<<27                          ; IRQ flags
+iFlag32         * 1<<7
+
+                ^ 0
+SockList        # 4                              ; workspace block : entry to 
linked list, defined below
+WorkspaceSize   * @                              ;                   size of 
block
+
+                ^ 0
+SockNext        # 4                              ; socket structure: next in 
list
+SockDescriptor  # 4                              ;                   the 
socket this describes
+SockPollword    # 4                              ;                   pollword 
for this socket
+SockBits        # 4                              ;                   bit to 
set (0..31) in the pollword if there's activity
+SockSize        # 4                              ;                   size of 
an entry
+
+SWIChunk        * &52280
+ErrorChunk      * &815B00
+
+
+        AREA    codeblock,CODE,READONLY
+
+
+        ENTRY
+
+
+ModuleHeader
+        DCD     0                                ; no start code
+        DCD     Initialise - ModuleHeader
+        DCD     Finalise   - ModuleHeader
+        DCD     0                                ; no service call handler
+        DCD     Title      - ModuleHeader
+        DCD     Help       - ModuleHeader
+        DCD     Commands   - ModuleHeader
+        DCD     SWIChunk
+        DCD     SWIHandler - ModuleHeader
+        DCD     SWITable   - ModuleHeader
+        DCD     0                                ; no SWI decoding code
+        DCD     0                                ; no Messages filename offset
+        DCD     Flags      - ModuleHeader
+
+
+Flags   DCD     1
+
+
+Title   DCB     NAME,0
+
+
+Help    DCB     NAME,9,VERSION," (",DATE,") ? 2002 Dickon Hood",0
+        ALIGN
+
+
+; 
------------------------------------------------------------------------------------------------------------------------------------
+; Initialisation, finalisation - SVC mode
+; 
------------------------------------------------------------------------------------------------------------------------------------
+
+Initialise                   ROUT
+; Entry   :     r10 = pointer to environment string
+;               r11 = I/O base of instantiation number (PRM 1-208)
+;               r12 = pointer to private word (non zero? then after OS_Module 
8)
+;               r13 = pointer to supervisor stack
+        STR     lr, [sp, #-4]!
+        LDR     r2, [wp]
+        TEQ     r2, #0                           ; don't (re)initialise if 
there's a value (pointer) in wp
+        LDRNE   pc, [sp], #4
+        MOV     r0, #6
+        MOV     r3, #WorkspaceSize
+        SWI     X+OS_Module
+        LDRVS   pc, [sp], #4                     ; exit if no room in RMA
+        STR     r2, [wp]
+        MOV     wp, r2
+        MOV     r0, #0
+0000    STR     r0, [r2], #4                     ; clear workspace
+        SUBS    r3, r3, #4
+        BGT     %b0000
+        MOV     r0, #16                          ; EventV
+        ADR     r1, EventHandler
+        MOV     r2, wp                           ; workspace pointer
+        SWI     X+OS_Claim
+        MOVVS   r3, r0
+        BVS     %f0020
+        MOV     r0, #14                          ; enable
+        MOV     r1, #19                          ; Internet event
+        SWI     X+OS_Byte
+        LDRVC   pc, [sp], #4
+        B       %f0010
+Finalise                                         ; (PRM 1-209, 3-73)
+; Entry   :     r10 = fatality indicator: 0=non fatal, 1=fatal
+;               r11 = instantiation number
+;               r12 = pointer to private word
+;               r13 = pointer to supervisor stack
+        STR     lr, [sp, #-4]!
+        LDR     wp, [wp]
+        LDR     r0, [wp, #SockList]
+        TEQ     r0, #0
+        ADRNE   r0, Finalise_Error
+        BNE     %f0030
+0010    MOV     r3, r0
+        MOV     r0, #13                          ; disable
+        MOV     r1, #19                          ; Internet event
+        SWI     X+OS_Byte
+0020    MOV     r0, #16                          ; EventV
+        ADR     r1, EventHandler
+        MOV     r2, wp                           ; workspace pointer
+        SWI     X+OS_Release
+        MOV     r0, #7
+        MOV     r2, wp
+        SWI     X+OS_Module                      ; free workspace
+        SUBS    r0, r3, #0
+        LDREQ   pc, [sp], #4                     ; V will be clear if Z is set
+0030    CMPVC   r0, #1<<31
+        CMNVC   r0, #1<<31                       ; set V
+        LDR     pc, [sp], #4
+Finalise_Error
+        DCD     ErrorChunk+5
+        DCB     "Still watching sockets - can't be killed yet",0
+        ALIGN
+
+
+; 
------------------------------------------------------------------------------------------------------------------------------------
+; Event handling - SVC or IRQ mode
+; 
------------------------------------------------------------------------------------------------------------------------------------
+
+EventHandler                 ROUT
+; Function:     Handle an event by checking the thread flag and then setting 
up a callback flag (pollword) to process it.
+; Entry   :     r0 = event number
+;               r1 = event reason
+;               r2 = socket descriptor
+;               interrupts disabled (PRM 1-146)
+        TEQ     r0, #19
+        MOVNE   pc, lr                           ; exit if not Internet event
+        TEQ     r1, #1                           ; or not 'data waiting'
+        TEQNE   r1, #2                           ; or not 'urgent data'
+        TEQNE   r1, #3                           ; or not 'connection broken'
+        MOVNE   pc, lr
+        LDR     r0, [wp, #SockList]
+        TEQ     r0, #0                           ; or not watching anything
+        MOVEQ   r0, #19
+        MOVEQ   pc, lr
+        STMFD   sp!, {r1-r3, lr}
+0000    LDR     lr, [r0, #SockDescriptor]
+        TEQ     lr, r2                           ; else find the right 
descriptor(s)
+        BNE     %f0010
+        LDR     r2, [r0, #SockBits]
+        LDR     lr, [r0, #SockPollword]
+        LDR     r1, [lr]
+        ORR     r1, r1, r2
+        STR     r1, [lr]
+0010    LDR     r0, [r0, #SockNext]
+        TEQ     r0, #0
+        BNE     %b0000
+        MOV     r0, #19                          ; Internet event
+        LDMFD   sp!, {r1-r3, pc}
+
+
+; 
------------------------------------------------------------------------------------------------------------------------------------
+; SWI's - SVC mode
+; ----------------
+; Entry   :     r0-r9 = caller's values
+;               r11   = five bottom bits of SWI number
+;               r12   = pointer to private word
+;               r13   = pointer to supervisor stack
+;               r14   = return address as usual
+; 
------------------------------------------------------------------------------------------------------------------------------------
+
+SWITable
+        DCB     NAME,0
+        DCB     "Register",0
+        DCB     "Deregister",0
+        DCB     "AtomicReset",0
+        DCB     "AllocPW",0
+        DCB     "DeallocPW",0
+        DCB     0                                ; end of table
+        ALIGN
+
+
+SWIHandler                   ROUT
+        LDR     wp, [wp]
+        CMP     r11, #(%f0010-%f0000)/4
+        ADDLE   pc, pc, r11, lsl #2
+        B       %f0010
+0000    B       SWI_Register
+        B       SWI_Deregister
+        B       SWI_AtomicReset
+        B       SWI_AllocPW
+        B       SWI_DeallocPW
+0010    CMPVC   r0, #1<<31
+        CMNVC   r0, #1<<31                       ; set V
+        ADD     r0, pc, #0
+        MOV     pc, lr
+        DCD     &1E6
+        DCB     "No such SWI",0
+        ALIGN
+
+
+SWI_Register                 ROUT
+; Function:     Returns the pollword in r0; if this is zero on entry, it 
assigns one itself.
+; Entry   :     r0 = pointer to pollword or zero
+;               r1 = flag bits
+;               r2 = socket descriptor (not a AcornSSL socket)
+        STMFD   sp!, {r0-r4, lr}
+        MOV     r4, r2                           ; socket descriptor
+        TEQ     r0, #0
+        MOVEQ   r3, #SockSize+4                  ; claim one word extra if the 
pollword is zero on entry
+        MOVNE   r3, #SockSize
+        MOV     r0, #6
+        SWI     X+OS_Module
+        BVS     %f0000
+        LDR     r3, [wp, #SockList]              ; previous start entry or zero
+        STR     r2, [wp, #SockList]              ; pointer to new block
+        STR     r3, [r2, #SockNext]
+        LDR     r0, [sp]
+        TEQ     r0, #0
+        ADDEQ   r0, r2, #SockSize                ; use word in structure if 
pollword was zero on entry
+        STR     r0, [r2, #SockPollword]
+        STR     r0, [sp]                         ; store pointer to pollword 
in r0 on stack
+        STR     r1, [r2, #SockBits]
+        STR     r4, [r2, #SockDescriptor]
+        MOV     r0, r4
+        LDR     r1, Ioctl_FIOASYNC
+        ADR     r2, Ioctl_Arg                    ; 'On'
+        SWI     X+Socket_Ioctl                   ; set FIOASYNC
+        LDMVCFD sp!, {r0-r4, pc}
+; An error leaves the socket still 'registered' with some RMA workspace        
+v0.07
+; and returned r0 => error not pollword, so cannot be deregistered!            
+v0.07
+; Fixed to free the block again (and adjust chain) & then return error.        
+v0.07
+        STR     r0, [sp]                         ; save error ptr for return   
+v0.07
+        LDR     r2, [wp, #SockList]              ; pointer to new block        
+v0.07
+        LDR     r3, [r2, #SockNext]              ; => next block               
+v0.07
+        STR     r3, [wp, #SockList]              ; and re-link                 
+v0.07
+        MOV     r0, #7                           ; free the new block          
+v0.07
+        SWI     X+OS_Module                      ;                             
+v0.07
+        CMPVC   r0, #1<<31                       ; clear V                     
+v0.07
+        CMNVC   r0, #1<<31                       ; set V                       
+v0.07
+        LDMFD   sp!, {r0-r4, pc}                 ;                             
+v0.07
+
+0000    ADD     sp, sp, #4                       ; discard stacked r0
+        LDMFD   sp!, {r1-r4, pc}
+Ioctl_FIOASYNC  DCD &8004667D
+Ioctl_Arg       DCD 1
+
+
+SWI_Deregister               ROUT
+        STMFD   sp!, {r0-r4, lr}
+        LDR     r4, [wp, #SockList]              ; get pointer to list
+        MOV     r2, #0                           ; set 'last' to zero
+0000    TEQ     r4, #0
+        BEQ     %f0010
+        LDR     r3, [r4, #SockDescriptor]
+        TEQ     r0, r3                           ; sockets the same?
+        LDREQ   r3, [r4, #SockPollword]
+        TEQEQ   r1, r3                           ; same pollword?
+        MOVNE   r2, r4
+        LDRNE   r4, [r4, #SockNext]
+        BNE     %b0000
+        LDR     r3, [r4, #SockNext]
+        TEQ     r2, #0                           ; was there a last one?
+        STRNE   r3, [r2, #SockNext]
+        STREQ   r3, [wp, #SockList]
+        MOV     r2, r4
+        MOV     r0, #7                           ; free the block
+        SWI     X+OS_Module
+        LDMFD   sp!, {r0-r4, pc}
+0010    CMPVC   r0, #1<<31
+        CMNVC   r0, #1<<31                       ; set V
+        ADD     sp, sp, #4                       ; discard stacked r0
+        ADD     r0, pc, #0
+        LDMFD   sp!, {r1-r4, pc}
+        DCD     ErrorChunk+4
+        DCB     "Attempt to free an unregistered socket/pollword pair",0
+        ALIGN
+
+
+SWI_AtomicReset              ROUT
+        TEQ     pc, pc
+        BEQ     %f0000                           ; in 32 bit mode
+        STMFD   sp!, {lr}
+        TST     lr, #iFlag26
+        TEQEQP  lr, #iFlag26                     ; IRQ off (no mode change, so 
no NOP required)
+        LDR     lr, [r0]
+        STR     r1, [r0]
+        MOV     r0, lr
+        LDMFD   sp!, {pc}^                       ; IRQ restored (also clears V 
as this was clear on entry)
+0000    STMFD   sp!, {r2, lr}
+        MRS     r2, cpsr
+        ORR     lr, r2, #iFlag32
+        MSR     cpsr_c, lr                       ; IRQ off
+        LDR     lr, [r0]
+        STR     r1, [r0]
+        MOV     r0, lr
+        MSR     cpsr_c, r2                       ; IRQ restored (also clears V 
as this was clear on entry)
+        LDMFD   sp!, {r2, pc}
+
+
+SWI_AllocPW
+        STMFD   sp!, {r2-r3, lr}
+        MOV     r0, #6
+        MOV     r3, #4
+        SWI     X+OS_Module
+        MOVVC   r0, r2
+        LDMFD   sp!, {r2-r3, pc}
+
+
+SWI_DeallocPW                ROUT
+        STMFD   sp!, {r0-r3, lr}
+        MOV     r3, r0
+        MOV     r1, r0
+        LDR     r2, [wp, #SockList]
+        TEQ     r2, #0
+        BEQ     %f0010
+0000    LDR     r0, [r2, #SockPollword]
+        TEQ     r0, r1
+        LDREQ   r0, [r2, #SockDescriptor]
+        LDR     r2, [r2, #SockNext]
+        BLEQ    SWI_Deregister
+        TEQ     r2, #0
+        BNE     %b0000
+0010    MOV     r2, r3
+        MOV     r0, #7
+        SWI     X+OS_Module
+        LDMVCFD sp!, {r0-r3, pc}
+        ADD     sp, sp, #4
+        LDMFD   sp!, {r1-r3, pc}
+
+
+; 
------------------------------------------------------------------------------------------------------------------------------------
+; Commands - SVC mode
+; -------------------
+; Entry   :     r0 = pointer to command tail
+;               r1 = number of parameters
+;              r12 = pointer to private word
+;              r13 = stack pointer
+;              r14 = return address
+; Exit    :     r0 = pointer to error block if V=1
+;           r7-r11 = must be unaltered
+; 
------------------------------------------------------------------------------------------------------------------------------------
+
+Commands
+        DCB     NAME,0                           ; command name
+        ALIGN
+        DCD     0                                ; no command code
+        DCD     0                                ; no information
+        DCD     0                                ; no invalid syntax - use 
default
+        DCD     Help_Name        - ModuleHeader
+
+        DCB     NAME,"_DumpList",0               ; command name
+        ALIGN
+        DCD     Command_DumpList - ModuleHeader
+        DCD     0                                ; no information
+        DCD     Syntax_DumpList  - ModuleHeader
+        DCD     Help_DumpList    - ModuleHeader
+
+        DCD     0                                ; end of table
+
+Help_Name
+        DCB     "The ",NAME," module enables applications to do asynchronous 
socket",13,10
+        DCB     "operations without null polls. See the !ReadMe file for more 
information.",13,10
+        DCB     "This module is released under the terms of the GNU General 
Public License.",0
+
+Help_DumpList
+        DCB     "*",NAME,"_DumpList dumps the current list of watched 
sockets.",13,10
+        DCB     "Useful for debugging purposes.",13,10
+        DCB     "Syntax: "
+Syntax_DumpList
+        DCB     "*",NAME,"_DumpList",0
+
+        ALIGN
+
+
+Command_DumpList             ROUT
+        LDR     wp, [wp]
+        STR     lr, [sp, #-4]!
+        LDR     r6, [wp, #SockList]
+        TEQ     r6, #0
+        BEQ     %f0010
+        SUB     sp, sp, #12                      ; get some scratch space...
+0000    ADR     r0, SWDL_x
+        SWI     X+OS_Write0
+        LDR     r0, [r6, #SockDescriptor]
+        MOV     r1, sp
+        MOV     r2, #9
+        SWI     X+OS_ConvertHex8
+        ADDVS   r0, r0, #4
+        SWI     X+OS_Write0
+        ADR     r0, SWDL_y
+        SWI     X+OS_Write0
+        LDR     r0, [r6, #SockPollword]
+        MOV     r1, sp
+        MOV     r2, #9
+        SWI     X+OS_ConvertHex8
+        ADDVS   r0, r0, #4
+        SWI     X+OS_Write0
+        ADR     r0, SWDL_z
+        SWI     X+OS_Write0
+        LDR     r0, [r6, #SockBits]
+        MOV     r1, sp
+        MOV     r2, #9
+        SWI     X+OS_ConvertHex8
+        ADDVS   r0, r0, #4
+        SWI     X+OS_Write0
+        SWI     X+OS_NewLine
+        LDR     r6, [r6, #SockNext]
+        TEQ     r6, #0
+        BNE     %b0000
+        ADD     sp, sp, #12
+        LDR     pc, [sp], #4
+0010    ADR     r0, SWDL_NowtString
+        SWI     OS_Write0
+        SWI     OS_NewLine
+        LDR     pc, [sp], #4
+SWDL_x  DCB     "Socket 0x",0
+SWDL_y  DCB     ", pollword 0x",0
+SWDL_z  DCB     ", bitmask 0x",0
+        ALIGN
+SWDL_NowtString
+        DCB     "Nothing registered - nothing to do",0
+        ALIGN
+
+
+        DCB     10,10
+        DCB     "Dickon Hood: [email protected], [email protected], in order 
of preference.",10
+        DCB     "Frank de Bruijn: [email protected]",10
+        DCB     10
+        ALIGN
+
+
+        END


-----------------------------------------------------------------------

Summary of changes:
 content/fetchers/curl.c                            |   30 +-
 desktop/gui_factory.c                              |    9 +
 .../!System/310/Modules/Network/SockWatch,ffa      |  Bin 0 -> 1840 bytes
 .../riscos/distribution/3rdParty/SocketWatch/!Info |  137 ++++++
 .../distribution/3rdParty/SocketWatch/Origin,b28   |    1 +
 .../3rdParty/SocketWatch/Source/!ReadMe            |  133 ++++++
 .../3rdParty/SocketWatch/Source/Build,fd7          |   16 +
 .../3rdParty/SocketWatch/Source/Licence            |   59 +--
 .../3rdParty/SocketWatch/Source/Source             |  461 ++++++++++++++++++++
 frontends/riscos/gui.c                             |   83 ++--
 frontends/riscos/scripts/Run                       |    4 +
 include/netsurf/fetch.h                            |   17 +
 12 files changed, 843 insertions(+), 107 deletions(-)
 create mode 100644 
frontends/riscos/distribution/!System/310/Modules/Network/SockWatch,ffa
 create mode 100644 frontends/riscos/distribution/3rdParty/SocketWatch/!Info
 create mode 100644 
frontends/riscos/distribution/3rdParty/SocketWatch/Origin,b28
 create mode 100644 
frontends/riscos/distribution/3rdParty/SocketWatch/Source/!ReadMe
 create mode 100644 
frontends/riscos/distribution/3rdParty/SocketWatch/Source/Build,fd7
 copy COPYING => 
frontends/riscos/distribution/3rdParty/SocketWatch/Source/Licence (87%)
 create mode 100644 
frontends/riscos/distribution/3rdParty/SocketWatch/Source/Source

diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index b8bccf0..7e5435e 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -1798,28 +1798,23 @@ fetch_curl_debug(CURL *handle,
 }
 
 
-/**
- * Callback function to set arbitrary socket options
- */
-static int fetch_curl_sockopt(void *clientp, curl_socket_t curlfd,
-               curlsocktype purpose)
+static curl_socket_t fetch_curl_socket_open(void *clientp,
+               curlsocktype purpose, struct curl_sockaddr *address)
 {
        (void) clientp;
-
-//XXX: indirect through fetch vtable?
-#ifdef riscos
-       if (purpose == CURLSOCKTYPE_IPCXN) {
-               int one = 1;
-               ioctl(curlfd, FIOASYNC, &one);
-       }
-#else
-       (void) curlfd;
        (void) purpose;
-#endif
 
-       return CURL_SOCKOPT_OK;
+       return (curl_socket_t) guit->fetch->socket_open(
+                       address->family, address->socktype,
+                       address->protocol);
 }
 
+static int fetch_curl_socket_close(void *clientp, curl_socket_t item)
+{
+       (void) clientp;
+
+       return guit->fetch->socket_close((int) item);
+}
 
 /**
  * Callback function for cURL.
@@ -2076,7 +2071,8 @@ nserror fetch_curl_register(void)
        SETOPT(CURLOPT_LOW_SPEED_TIME, 180L);
        SETOPT(CURLOPT_NOSIGNAL, 1L);
        SETOPT(CURLOPT_CONNECTTIMEOUT, nsoption_uint(curl_fetch_timeout));
-       SETOPT(CURLOPT_SOCKOPTFUNCTION, fetch_curl_sockopt);
+       SETOPT(CURLOPT_OPENSOCKETFUNCTION, fetch_curl_socket_open);
+       SETOPT(CURLOPT_CLOSESOCKETFUNCTION, fetch_curl_socket_close);
 
        if (nsoption_charp(ca_bundle) &&
            strcmp(nsoption_charp(ca_bundle), "")) {
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index 89f2e37..c9dcd8b 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -20,6 +20,9 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 
 #include "utils/config.h"
 #include "utils/errors.h"
@@ -498,6 +501,12 @@ static nserror verify_fetch_register(struct 
gui_fetch_table *gft)
        if (gft->mimetype == NULL) {
                gft->mimetype = gui_default_mimetype;
        }
+       if (gft->socket_open == NULL) {
+               gft->socket_open = socket;
+       }
+       if (gft->socket_close == NULL) {
+               gft->socket_close = close;
+       }
 
        return NSERROR_OK;
 }
diff --git 
a/frontends/riscos/distribution/!System/310/Modules/Network/SockWatch,ffa 
b/frontends/riscos/distribution/!System/310/Modules/Network/SockWatch,ffa
new file mode 100644
index 0000000..e589cfd
Binary files /dev/null and 
b/frontends/riscos/distribution/!System/310/Modules/Network/SockWatch,ffa differ
diff --git a/frontends/riscos/distribution/3rdParty/SocketWatch/!Info 
b/frontends/riscos/distribution/3rdParty/SocketWatch/!Info
new file mode 100644
index 0000000..cda7977
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/!Info
@@ -0,0 +1,137 @@
+Name   : SocketWatch
+Purpose: Asynchronous socket operations without null polls
+Version: 0.07  (11-01-2019)
+Status : GNU GPL
+Authors: Dickon Hood, Frank de Bruijn
+
+This isn't an official release.
+
+In November 2003 I noticed SocketWatch 0.04y had a couple of bugs. After I had
+corrected them and was almost ready to release 0.05, I discovered the
+'official' place for SocketWatch was now on the Nettle site
+(http://nettle.sourceforge.net). So I contacted the Nettle maintainers, told
+them about the bugs and sent them all the work I had done on repairing it,
+more or less expecting to hear something about an official release 0.05 within
+a couple of months...
+
+Still nothing three months later, so I sent one more e-mail (which remained
+unanswered) and put 0.05 on my site.
+
+
+Installing
+==========
+The zip archive contains an application called !ModInst. Run it to install the
+module on your computer. If you want to install the module manually, you can
+find it in !ModInst.Resources.!System.310.Modules.Network.
+
+
+Source
+======
+The source code is provided as an ObjAsm file in the Source directory in the
+archive. If you want to assemble the module again, run the Build file. The
+module will be recreated and moved to the !ModInst application for
+installation.
+
+
+Version history
+===============
+11-01-2019  0.07
+----------------
+Catered for errors in SocketWatch_Register better.
+Added notes about use with AcornSSL.
+
+12-06-2012
+----------
+Removed dependency on private library (providing constants) so the source can
+be used stand alone. Added Build script (previous builds were done from
+StrongED, using a multipurpose ObjAsmRun script). Nothing changed otherwise.
+MD5 checksum still f2bb3f8d911d0b20a43d6ee135c3ae97.
+
+23-06-2006  0.06
+----------------
+Fixed small bug in the AtomicReset SWI (flags not restored in 26 bit mode, so
+IRQ bit not cleared). Not sure if this ever bothered anyone (think not as it
+was already present in 0.04y).
+Removed disabling interrupts in EventHandler as event handlers are entered
+with interrupts disabled.
+Also some more source clean ups and more comments added.
+MD5 checksum: f2bb3f8d911d0b20a43d6ee135c3ae97.
+
+14-08-2005
+----------------
+Moved the source to ObjAsm. No functional changes to the code. MD5 checksum
+still 90f3323981a0e287f488e9a59b2e5373. No new release.
+
+12-12-2003  0.05
+----------------
+First one by me. Came about when I was investigating a memory leak on my RPC.
+MD5 checksum of the module: 90f3323981a0e287f488e9a59b2e5373.
+
+The detailed list of changes below was for the benefit of the Nettle
+maintainers and originally sent to Ian in an e-mail on 11-12-2003.
+Use the single file source of 0.04y as a reference.
+
+- Most of the variable definitions from Flags% to r12End% aren't required. You
+  just need SockList% (with a FNdb(-4) instead of a FNdb(4)) and r12End%. The
+  rest was removed.
+- No flag definitions are needed. Removed.
+- Socket structure definitions and ErrorChunk%: no changes.
+- From the module header to EventHandler_GotOne32%: merely some optimisations.
+- Error texts: were placed near the routines that use them. This was mainly
+  cosmetic, but it had the added advantage of allowing me to replace all the
+  FNADRLs with simple ADRs.
+- GetBlock%: removed.
+- ReleaseBlock%: removed.
+- IsHexNum_lp1%: not required. Removed.
+- moveBytes%: not required. Removed.
+- From title string to SWI-handler: no real changes.
+- From Command% to CommandText%: moved the table and the help and syntax texts
+  for the commands to just before the SWDL_Code% routine and 'cleaned up' the
+  texts a bit, but that qualifies as cosmetic.
+- Syslog_Name%: not required. Removed.
+- Syslog_Version%: not required. Removed.
+- From Init% to FinalCode%: several changes, the most important one being the
+  removal of the claiming of a 16K block of temporary workspace which was
+  neither used nor released.
+  There's also the stacking of r7 to r9/r11. It's true that these registers
+  should be saved (according to the PRM) but only if they're modified. So why
+  bother if they're not? Replacing this with just stacking r14 enabled a
+  'cleaner' jump out of the routines on errors.
+  At the very beginning of Init%, I inserted a check for a value in r12 on
+  entry. This has to do with re-initialisation after a 'Tidy' operation. Not
+  sure if that's still required though (hasn't the 'Tidy' functionality been
+  blocked or removed from RISC OS these days or is that an unfounded rumour?).
+  I removed everything connected with the CRC-check, including the error text.
+  SocketWatch is the only module I've ever come across using something like
+  this and I honestly fail to see what use it is here. But if you do see that,
+  then by all means leave it in.
+  In Final% the (unused) ModuleDying% flag was set, but as that had been
+  removed anyway, so were the three instructions involved in this action.
+  Actually, as the variable Flags% was re-used to point at the module flags
+  word, this flag bit isn't set in the first word of the workspace at all. In
+  fact, on finalisation SocketWatch 0.04y sets bit 1 of the word 592 bytes
+  from the address r12 happens to point at. That *could* be in the unused 16K
+  block that was claimed on initialisation, but there's no guarantee. Nasty
+  (and no, I hadn't realised this yet when I wrote the comment on Flags% in
+  the Source_004y file...).
+  FinalCode% (renamed release%) was more or less integrated with Init% (sort
+  of 'glued to the bottom') but otherwise essentially unchanged, apart from
+  removing the call to ReleaseBlock% (including the stacking/unstacking of
+  r14) in favour of a simple MOV r0,#7 / SWI XOS_Module sequence).
+- SWI_Register% contained some code at the start (up to the Bvs instruction) I
+  couldn't make sense of. If you can, please enlighten me. I asked Dickon
+  about this in my first email to him and he didn't understand it anymore
+  either. So I removed it.
+  The rest is essentially unchanged (cosmetics only), but I did replace the
+  call to GetBlock% and the 'push' and 'pop' instructions around it with the
+  MOV/SWI instructions that were actually required here.
+- SWI_Deregister%: no changes except for replacing the call to ReleaseBlock%
+  and its surrounding 'push'/'pop' with the necessary MOV and SWI.
+- SWI_AtomicReset%: optimisations only.
+- SWI_AllocPW%: no changes.
+- SWI_DeallocPW%: no changes.
+- SWDL_Code%: cosmetic changes only.
+
+02-12-2002  0.04y
+-----------------
+By Dickon Hood. See the !ReadMe file.
diff --git a/frontends/riscos/distribution/3rdParty/SocketWatch/Origin,b28 
b/frontends/riscos/distribution/3rdParty/SocketWatch/Origin,b28
new file mode 100644
index 0000000..34a71d9
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/Origin,b28
@@ -0,0 +1 @@
+https://www.aconet.org/tools/
diff --git a/frontends/riscos/distribution/3rdParty/SocketWatch/Source/!ReadMe 
b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/!ReadMe
new file mode 100644
index 0000000..ea24c78
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/!ReadMe
@@ -0,0 +1,133 @@
+Document v0.07.  (C) Dickon Hood, see licence for details of copying etc.
+
+
+SocketWatch
+===========
+
+SocketWatch is a simple module designed to reduce the requirement of Wimp
+applications using sockets to constantly poll them using Null Wimp polls for
+data.
+
+If you're not a programmer, stop reading now, this will probably make little
+sense to you.  If you are a programmer, but don't write networking
+applications, again, this is unlikely to be of interest.
+
+
+Rationale
+---------
+
+At boot time, my machine loads and runs five seperate applications which
+require open sockets.  As none of these have support modules associated with
+them, I'm assuming that they are constantly polling the sockets they open on
+null polls.  This is inefficient.
+
+Sockets can be marked as asynchronous.  If they are, an Internet event (19)
+is generated whenever something interesting happens to them.  Events are only
+accessable to modules, however, and are useless in a Wimp environment.  The
+answer is to write a module which does that and notifies the parent
+application that something has happened.  If every application did this,
+there'd be another five or six modules running on my machine, all doing much
+the same job, which I don't need.
+
+This attempts to address the issue by implementing a module with an open
+interface, and one which is generic enough to be applicable to almost every
+app. which could want to use it.
+
+
+Usage
+-----
+
+SocketWatch relies upon a feature of Risc OS 3.1 and upwards, so won't work
+on ROS2.  Sorry, but there we go.
+
+Sockets are registered with the module.  At this point, the socket is marked
+as asynchronous (so the parent app. doesn't need to).  A pollword and bit
+number to set are also supplied.
+
+As some internal structure has to be created, a pollword of 0 is acceptable,
+and, if passed, the module will use one of the words in this structure as the
+pollword.  This is returned to the app. in r0.
+
+When an Internet event is triggered, the module scans all registered sockets. 
+If one is matched, the appropriate bit is set in the pollword.  This allows
+other bits to be reserved for other things.  Note, it is not an error for a
+socket to have multiple pollwords associated with it; there is no reason I
+can think of for two apps. to share one socket (*why* is another matter, but
+it shouldn't be an error); these may both register PWs for them.
+
+Usage with AcornSSL
+-------------------
+SocketWatch should only be used with the normal socket numbers, not the ssl 
+socket handles used by AcornSSL.
+However, it can be used for secure sockets with a sequence like:
+   Socket_Create              to get socket normal socket descriptor
+   AcornSSL_CreateSession     to get ssl socket
+   SocketWatch_Register       of normal socket descriptor
+
+SWIs
+----
+
+SWI SocketWatch_Register (0x52280)
+
+On entry: r0 => pollword, 0 for module to allocate one,
+          r1 =  bitmask to set if there's activity
+          r2 =  socket number.
+
+On exit:  r0 => pollword.
+          If an error is raised by Socket_Ioctl, r0 is => error block
+          and the socket is not registered.
+
+If the pollword passed is 0, one allocated from the internal structure will
+be returned.  Note that this is freed when at the time of deregistering and
+may not be used afterwards.
+
+
+
+SWI SocketWatch_Deregister (0x52281)
+
+On entry: r0 =  socket,
+          r1 => pollword.
+
+On exit:  all preserved.
+
+The socket is no longer watched.  If the pollword was allocated by the
+module, it is not valid once this call is called.
+
+
+
+SWI SocketWatch_AtomicReset (0x52282)
+
+On entry: r0 => pollword
+          r1 =  new value
+
+On exit:  r0 =  old value
+          r1 preserved.
+
+This SWI reads from r0, writes r1 to r0, then exits, all with IRQs off,
+making it an atomic operation (ie., one which may not be interrupted).  It is
+a problem with Pollwords in that they're used by IRQ or Callback code, yet
+read and reset by usermode code which can't disable IRQs easily.  This
+removes the problem where the app. reads the PW, IRQ routine sets a couple of
+bits, then the forground resets it.
+
+
+
+SWI SocketWatch_AllocPW (0x52283)
+
+On entry: -
+
+On exit:  r0 => 4 bytes of RAM which may be released by SWI
+SocketWatch_DeallocPW.
+
+ATM, this SWI claims four bytes of RMA; this isn't efficient, and may be
+changed in later releases.  The SWI is provided for convenience's sake.
+
+
+
+SWI SocketWatch_DeallocPW (0x52284)
+
+On entry: r0 => pollword, as allocated by SWI SocketWatch_AllocPW.
+
+On exit:  all preserved.
+
+ATM this calls OS_Module 7 to free the word.
diff --git 
a/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Build,fd7 
b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Build,fd7
new file mode 100644
index 0000000..e741870
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Build,fd7
@@ -0,0 +1,16 @@
+| SocketWatchBuild  1.00  12-06-2012
+
+Set SocketWatchSource$Dir <Obey$Dir>
+Set SocketWatchTarget$Dir 
<SocketWatchSource$Dir>.^.!ModInst.Resources.!System.310.Modules.Network
+
+RMEnsure DDEUtils 0.00 IfThere System:Modules.DDEUtils Then RMLoad 
System:Modules.DDEUtils
+RMEnsure DDEUtils 0.00 Error DDEUtils module not found
+
+ObjAsm -throwback <SocketWatchSource$Dir>.Source 
<SocketWatchSource$Dir>.[Object]
+Link -verbose -rmf -output <SocketWatchSource$Dir>.SockWatch 
<SocketWatchSource$Dir>.[Object]
+Remove <SocketWatchSource$Dir>.[Object]
+
+IfThere <SocketWatchTarget$Dir> Then Copy <SocketWatchSource$Dir>.SockWatch 
<SocketWatchTarget$Dir>.* A~CDF~L~N~P~Q~R~S~T~V
+
+Unset SocketWatchTarget$Dir
+Unset SocketWatchSource$Dir
\ No newline at end of file
diff --git a/COPYING 
b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Licence
similarity index 87%
copy from COPYING
copy to frontends/riscos/distribution/3rdParty/SocketWatch/Source/Licence
index 2b22bcd..dc63aac 100644
--- a/COPYING
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Licence
@@ -1,57 +1,9 @@
-The source code, documentation, translatable messages files and UI 
-definitions contained within NetSurf are licensed under the following terms:
-
-  NetSurf is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; version 2 of the License.
-  
-  In addition, as a special exception, permission is granted to link the
-  code of this release of NetSurf with the OpenSSL project's "OpenSSL"
-  library (or with modified versions of it that use the same licence as 
-  the "OpenSSL" library), and distribute the linked executables. You must
-  obey the GNU General Public License version 2 in all respects for all of 
-  the code used other than "OpenSSL". If you modify the code, you may 
-  extend this exception to your version of the code, but you are not
-  obligated to do so. If you do not wish to do so, delete this exception
-  statement from your version.
-
-All visual artwork contained within NetSurf is licensed under the terms of 
-the MIT License.
-
-The full text of the MIT and GPL licenses are provided in Annex A and 
-Annex B of this document.
-
-
-Annex A: The MIT License
-------------------------
-
-Permission is hereby granted, free of charge, to any person obtaining a copy 
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights 
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
-copies of the Software, and to permit persons to whom the Software is 
-furnished to do so, subject to the following conditions: 
-
-The above copyright notice and this permission notice shall be included in 
-all copies or substantial portions of the Software. 
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
-THE SOFTWARE. 
-
-
-Annex B: The GNU General Public License
----------------------------------------
 
                    GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+                          675 Mass Ave, Cambridge, MA 02139, USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
@@ -328,7 +280,7 @@ POSSIBILITY OF SUCH DAMAGES.
 
                     END OF TERMS AND CONDITIONS
 
-           How to Apply These Terms to Your New Programs
+       Appendix: How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
 possible use to the public, the best way to achieve this is to make it
@@ -340,7 +292,7 @@ convey the exclusion of warranty; and each file should have 
at least
 the "copyright" line and a pointer to where the full notice is found.
 
     <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
+    Copyright (C) 19yy  <name of author>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -354,15 +306,14 @@ the "copyright" line and a pointer to where the full 
notice is found.
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
-
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 Also add information on how to contact you by electronic and paper mail.
 
 If the program is interactive, make it output a short notice like this
 when it starts in an interactive mode:
 
-    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision version 69, Copyright (C) 19yy name of author
     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     This is free software, and you are welcome to redistribute it
     under certain conditions; type `show c' for details.
diff --git a/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Source 
b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Source
new file mode 100644
index 0000000..03b48b0
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SocketWatch/Source/Source
@@ -0,0 +1,461 @@
+; SocketWatch.Source  0.07  11-01-2019
+
+; This is the source code for version 0.07 of the SocketWatch module, 
originally by Dickon Hood.
+; It's GNU GPL (see the file 'Licence').
+; See the !Info file for more information.
+;
+; Frank de Bruijn, June 2006.
+; v0.07 (11/01/2019) Martin Avison catered for errors using AcornSSL, and any 
other Ioctl errors:
+;       AcornSSL_Ioctl will set FIOASYNC for SSL sockets ... but Internet 
event gives
+;       base integer socket, so SocketWatch cannot match it on socket & 
pollword.
+;       Socketwatch must therefore only be used with base integer socket 
descriptors,
+;       (although they may be secured using AcornSSL_CreateSession).
+;       If Socket_Ioctl is called with SSL socket, it gives error 'Bad file 
descriptor' but registers it.
+;       This change removes any registration after any Ioctl error, and 
returns the error.
+;
+
+        GBLS    NAME
+        GBLS    VERSION
+        GBLS    DATE
+NAME    SETS    "SocketWatch"
+VERSION SETS    "0.07"
+DATE    SETS    "11 Jan 2019"
+
+wp              RN r12                           ; workspace pointer
+
+X               * &20000                         ; bit 17
+
+OS_Write0       * &02                            ; some SWIs
+OS_NewLine      * &03
+OS_Byte         * &06
+OS_Module       * &1E
+OS_Claim        * &1F
+OS_Release      * &20
+OS_ConvertHex8  * &D4
+Socket_Ioctl    * &41212
+
+iFlag26         * 1<<27                          ; IRQ flags
+iFlag32         * 1<<7
+
+                ^ 0
+SockList        # 4                              ; workspace block : entry to 
linked list, defined below
+WorkspaceSize   * @                              ;                   size of 
block
+
+                ^ 0
+SockNext        # 4                              ; socket structure: next in 
list
+SockDescriptor  # 4                              ;                   the 
socket this describes
+SockPollword    # 4                              ;                   pollword 
for this socket
+SockBits        # 4                              ;                   bit to 
set (0..31) in the pollword if there's activity
+SockSize        # 4                              ;                   size of 
an entry
+
+SWIChunk        * &52280
+ErrorChunk      * &815B00
+
+
+        AREA    codeblock,CODE,READONLY
+
+
+        ENTRY
+
+
+ModuleHeader
+        DCD     0                                ; no start code
+        DCD     Initialise - ModuleHeader
+        DCD     Finalise   - ModuleHeader
+        DCD     0                                ; no service call handler
+        DCD     Title      - ModuleHeader
+        DCD     Help       - ModuleHeader
+        DCD     Commands   - ModuleHeader
+        DCD     SWIChunk
+        DCD     SWIHandler - ModuleHeader
+        DCD     SWITable   - ModuleHeader
+        DCD     0                                ; no SWI decoding code
+        DCD     0                                ; no Messages filename offset
+        DCD     Flags      - ModuleHeader
+
+
+Flags   DCD     1
+
+
+Title   DCB     NAME,0
+
+
+Help    DCB     NAME,9,VERSION," (",DATE,") ? 2002 Dickon Hood",0
+        ALIGN
+
+
+; 
------------------------------------------------------------------------------------------------------------------------------------
+; Initialisation, finalisation - SVC mode
+; 
------------------------------------------------------------------------------------------------------------------------------------
+
+Initialise                   ROUT
+; Entry   :     r10 = pointer to environment string
+;               r11 = I/O base of instantiation number (PRM 1-208)
+;               r12 = pointer to private word (non zero? then after OS_Module 
8)
+;               r13 = pointer to supervisor stack
+        STR     lr, [sp, #-4]!
+        LDR     r2, [wp]
+        TEQ     r2, #0                           ; don't (re)initialise if 
there's a value (pointer) in wp
+        LDRNE   pc, [sp], #4
+        MOV     r0, #6
+        MOV     r3, #WorkspaceSize
+        SWI     X+OS_Module
+        LDRVS   pc, [sp], #4                     ; exit if no room in RMA
+        STR     r2, [wp]
+        MOV     wp, r2
+        MOV     r0, #0
+0000    STR     r0, [r2], #4                     ; clear workspace
+        SUBS    r3, r3, #4
+        BGT     %b0000
+        MOV     r0, #16                          ; EventV
+        ADR     r1, EventHandler
+        MOV     r2, wp                           ; workspace pointer
+        SWI     X+OS_Claim
+        MOVVS   r3, r0
+        BVS     %f0020
+        MOV     r0, #14                          ; enable
+        MOV     r1, #19                          ; Internet event
+        SWI     X+OS_Byte
+        LDRVC   pc, [sp], #4
+        B       %f0010
+Finalise                                         ; (PRM 1-209, 3-73)
+; Entry   :     r10 = fatality indicator: 0=non fatal, 1=fatal
+;               r11 = instantiation number
+;               r12 = pointer to private word
+;               r13 = pointer to supervisor stack
+        STR     lr, [sp, #-4]!
+        LDR     wp, [wp]
+        LDR     r0, [wp, #SockList]
+        TEQ     r0, #0
+        ADRNE   r0, Finalise_Error
+        BNE     %f0030
+0010    MOV     r3, r0
+        MOV     r0, #13                          ; disable
+        MOV     r1, #19                          ; Internet event
+        SWI     X+OS_Byte
+0020    MOV     r0, #16                          ; EventV
+        ADR     r1, EventHandler
+        MOV     r2, wp                           ; workspace pointer
+        SWI     X+OS_Release
+        MOV     r0, #7
+        MOV     r2, wp
+        SWI     X+OS_Module                      ; free workspace
+        SUBS    r0, r3, #0
+        LDREQ   pc, [sp], #4                     ; V will be clear if Z is set
+0030    CMPVC   r0, #1<<31
+        CMNVC   r0, #1<<31                       ; set V
+        LDR     pc, [sp], #4
+Finalise_Error
+        DCD     ErrorChunk+5
+        DCB     "Still watching sockets - can't be killed yet",0
+        ALIGN
+
+
+; 
------------------------------------------------------------------------------------------------------------------------------------
+; Event handling - SVC or IRQ mode
+; 
------------------------------------------------------------------------------------------------------------------------------------
+
+EventHandler                 ROUT
+; Function:     Handle an event by checking the thread flag and then setting 
up a callback flag (pollword) to process it.
+; Entry   :     r0 = event number
+;               r1 = event reason
+;               r2 = socket descriptor
+;               interrupts disabled (PRM 1-146)
+        TEQ     r0, #19
+        MOVNE   pc, lr                           ; exit if not Internet event
+        TEQ     r1, #1                           ; or not 'data waiting'
+        TEQNE   r1, #2                           ; or not 'urgent data'
+        TEQNE   r1, #3                           ; or not 'connection broken'
+        MOVNE   pc, lr
+        LDR     r0, [wp, #SockList]
+        TEQ     r0, #0                           ; or not watching anything
+        MOVEQ   r0, #19
+        MOVEQ   pc, lr
+        STMFD   sp!, {r1-r3, lr}
+0000    LDR     lr, [r0, #SockDescriptor]
+        TEQ     lr, r2                           ; else find the right 
descriptor(s)
+        BNE     %f0010
+        LDR     r2, [r0, #SockBits]
+        LDR     lr, [r0, #SockPollword]
+        LDR     r1, [lr]
+        ORR     r1, r1, r2
+        STR     r1, [lr]
+0010    LDR     r0, [r0, #SockNext]
+        TEQ     r0, #0
+        BNE     %b0000
+        MOV     r0, #19                          ; Internet event
+        LDMFD   sp!, {r1-r3, pc}
+
+
+; 
------------------------------------------------------------------------------------------------------------------------------------
+; SWI's - SVC mode
+; ----------------
+; Entry   :     r0-r9 = caller's values
+;               r11   = five bottom bits of SWI number
+;               r12   = pointer to private word
+;               r13   = pointer to supervisor stack
+;               r14   = return address as usual
+; 
------------------------------------------------------------------------------------------------------------------------------------
+
+SWITable
+        DCB     NAME,0
+        DCB     "Register",0
+        DCB     "Deregister",0
+        DCB     "AtomicReset",0
+        DCB     "AllocPW",0
+        DCB     "DeallocPW",0
+        DCB     0                                ; end of table
+        ALIGN
+
+
+SWIHandler                   ROUT
+        LDR     wp, [wp]
+        CMP     r11, #(%f0010-%f0000)/4
+        ADDLE   pc, pc, r11, lsl #2
+        B       %f0010
+0000    B       SWI_Register
+        B       SWI_Deregister
+        B       SWI_AtomicReset
+        B       SWI_AllocPW
+        B       SWI_DeallocPW
+0010    CMPVC   r0, #1<<31
+        CMNVC   r0, #1<<31                       ; set V
+        ADD     r0, pc, #0
+        MOV     pc, lr
+        DCD     &1E6
+        DCB     "No such SWI",0
+        ALIGN
+
+
+SWI_Register                 ROUT
+; Function:     Returns the pollword in r0; if this is zero on entry, it 
assigns one itself.
+; Entry   :     r0 = pointer to pollword or zero
+;               r1 = flag bits
+;               r2 = socket descriptor (not a AcornSSL socket)
+        STMFD   sp!, {r0-r4, lr}
+        MOV     r4, r2                           ; socket descriptor
+        TEQ     r0, #0
+        MOVEQ   r3, #SockSize+4                  ; claim one word extra if the 
pollword is zero on entry
+        MOVNE   r3, #SockSize
+        MOV     r0, #6
+        SWI     X+OS_Module
+        BVS     %f0000
+        LDR     r3, [wp, #SockList]              ; previous start entry or zero
+        STR     r2, [wp, #SockList]              ; pointer to new block
+        STR     r3, [r2, #SockNext]
+        LDR     r0, [sp]
+        TEQ     r0, #0
+        ADDEQ   r0, r2, #SockSize                ; use word in structure if 
pollword was zero on entry
+        STR     r0, [r2, #SockPollword]
+        STR     r0, [sp]                         ; store pointer to pollword 
in r0 on stack
+        STR     r1, [r2, #SockBits]
+        STR     r4, [r2, #SockDescriptor]
+        MOV     r0, r4
+        LDR     r1, Ioctl_FIOASYNC
+        ADR     r2, Ioctl_Arg                    ; 'On'
+        SWI     X+Socket_Ioctl                   ; set FIOASYNC
+        LDMVCFD sp!, {r0-r4, pc}
+; An error leaves the socket still 'registered' with some RMA workspace        
+v0.07
+; and returned r0 => error not pollword, so cannot be deregistered!            
+v0.07
+; Fixed to free the block again (and adjust chain) & then return error.        
+v0.07
+        STR     r0, [sp]                         ; save error ptr for return   
+v0.07
+        LDR     r2, [wp, #SockList]              ; pointer to new block        
+v0.07
+        LDR     r3, [r2, #SockNext]              ; => next block               
+v0.07
+        STR     r3, [wp, #SockList]              ; and re-link                 
+v0.07
+        MOV     r0, #7                           ; free the new block          
+v0.07
+        SWI     X+OS_Module                      ;                             
+v0.07
+        CMPVC   r0, #1<<31                       ; clear V                     
+v0.07
+        CMNVC   r0, #1<<31                       ; set V                       
+v0.07
+        LDMFD   sp!, {r0-r4, pc}                 ;                             
+v0.07
+
+0000    ADD     sp, sp, #4                       ; discard stacked r0
+        LDMFD   sp!, {r1-r4, pc}
+Ioctl_FIOASYNC  DCD &8004667D
+Ioctl_Arg       DCD 1
+
+
+SWI_Deregister               ROUT
+        STMFD   sp!, {r0-r4, lr}
+        LDR     r4, [wp, #SockList]              ; get pointer to list
+        MOV     r2, #0                           ; set 'last' to zero
+0000    TEQ     r4, #0
+        BEQ     %f0010
+        LDR     r3, [r4, #SockDescriptor]
+        TEQ     r0, r3                           ; sockets the same?
+        LDREQ   r3, [r4, #SockPollword]
+        TEQEQ   r1, r3                           ; same pollword?
+        MOVNE   r2, r4
+        LDRNE   r4, [r4, #SockNext]
+        BNE     %b0000
+        LDR     r3, [r4, #SockNext]
+        TEQ     r2, #0                           ; was there a last one?
+        STRNE   r3, [r2, #SockNext]
+        STREQ   r3, [wp, #SockList]
+        MOV     r2, r4
+        MOV     r0, #7                           ; free the block
+        SWI     X+OS_Module
+        LDMFD   sp!, {r0-r4, pc}
+0010    CMPVC   r0, #1<<31
+        CMNVC   r0, #1<<31                       ; set V
+        ADD     sp, sp, #4                       ; discard stacked r0
+        ADD     r0, pc, #0
+        LDMFD   sp!, {r1-r4, pc}
+        DCD     ErrorChunk+4
+        DCB     "Attempt to free an unregistered socket/pollword pair",0
+        ALIGN
+
+
+SWI_AtomicReset              ROUT
+        TEQ     pc, pc
+        BEQ     %f0000                           ; in 32 bit mode
+        STMFD   sp!, {lr}
+        TST     lr, #iFlag26
+        TEQEQP  lr, #iFlag26                     ; IRQ off (no mode change, so 
no NOP required)
+        LDR     lr, [r0]
+        STR     r1, [r0]
+        MOV     r0, lr
+        LDMFD   sp!, {pc}^                       ; IRQ restored (also clears V 
as this was clear on entry)
+0000    STMFD   sp!, {r2, lr}
+        MRS     r2, cpsr
+        ORR     lr, r2, #iFlag32
+        MSR     cpsr_c, lr                       ; IRQ off
+        LDR     lr, [r0]
+        STR     r1, [r0]
+        MOV     r0, lr
+        MSR     cpsr_c, r2                       ; IRQ restored (also clears V 
as this was clear on entry)
+        LDMFD   sp!, {r2, pc}
+
+
+SWI_AllocPW
+        STMFD   sp!, {r2-r3, lr}
+        MOV     r0, #6
+        MOV     r3, #4
+        SWI     X+OS_Module
+        MOVVC   r0, r2
+        LDMFD   sp!, {r2-r3, pc}
+
+
+SWI_DeallocPW                ROUT
+        STMFD   sp!, {r0-r3, lr}
+        MOV     r3, r0
+        MOV     r1, r0
+        LDR     r2, [wp, #SockList]
+        TEQ     r2, #0
+        BEQ     %f0010
+0000    LDR     r0, [r2, #SockPollword]
+        TEQ     r0, r1
+        LDREQ   r0, [r2, #SockDescriptor]
+        LDR     r2, [r2, #SockNext]
+        BLEQ    SWI_Deregister
+        TEQ     r2, #0
+        BNE     %b0000
+0010    MOV     r2, r3
+        MOV     r0, #7
+        SWI     X+OS_Module
+        LDMVCFD sp!, {r0-r3, pc}
+        ADD     sp, sp, #4
+        LDMFD   sp!, {r1-r3, pc}
+
+
+; 
------------------------------------------------------------------------------------------------------------------------------------
+; Commands - SVC mode
+; -------------------
+; Entry   :     r0 = pointer to command tail
+;               r1 = number of parameters
+;              r12 = pointer to private word
+;              r13 = stack pointer
+;              r14 = return address
+; Exit    :     r0 = pointer to error block if V=1
+;           r7-r11 = must be unaltered
+; 
------------------------------------------------------------------------------------------------------------------------------------
+
+Commands
+        DCB     NAME,0                           ; command name
+        ALIGN
+        DCD     0                                ; no command code
+        DCD     0                                ; no information
+        DCD     0                                ; no invalid syntax - use 
default
+        DCD     Help_Name        - ModuleHeader
+
+        DCB     NAME,"_DumpList",0               ; command name
+        ALIGN
+        DCD     Command_DumpList - ModuleHeader
+        DCD     0                                ; no information
+        DCD     Syntax_DumpList  - ModuleHeader
+        DCD     Help_DumpList    - ModuleHeader
+
+        DCD     0                                ; end of table
+
+Help_Name
+        DCB     "The ",NAME," module enables applications to do asynchronous 
socket",13,10
+        DCB     "operations without null polls. See the !ReadMe file for more 
information.",13,10
+        DCB     "This module is released under the terms of the GNU General 
Public License.",0
+
+Help_DumpList
+        DCB     "*",NAME,"_DumpList dumps the current list of watched 
sockets.",13,10
+        DCB     "Useful for debugging purposes.",13,10
+        DCB     "Syntax: "
+Syntax_DumpList
+        DCB     "*",NAME,"_DumpList",0
+
+        ALIGN
+
+
+Command_DumpList             ROUT
+        LDR     wp, [wp]
+        STR     lr, [sp, #-4]!
+        LDR     r6, [wp, #SockList]
+        TEQ     r6, #0
+        BEQ     %f0010
+        SUB     sp, sp, #12                      ; get some scratch space...
+0000    ADR     r0, SWDL_x
+        SWI     X+OS_Write0
+        LDR     r0, [r6, #SockDescriptor]
+        MOV     r1, sp
+        MOV     r2, #9
+        SWI     X+OS_ConvertHex8
+        ADDVS   r0, r0, #4
+        SWI     X+OS_Write0
+        ADR     r0, SWDL_y
+        SWI     X+OS_Write0
+        LDR     r0, [r6, #SockPollword]
+        MOV     r1, sp
+        MOV     r2, #9
+        SWI     X+OS_ConvertHex8
+        ADDVS   r0, r0, #4
+        SWI     X+OS_Write0
+        ADR     r0, SWDL_z
+        SWI     X+OS_Write0
+        LDR     r0, [r6, #SockBits]
+        MOV     r1, sp
+        MOV     r2, #9
+        SWI     X+OS_ConvertHex8
+        ADDVS   r0, r0, #4
+        SWI     X+OS_Write0
+        SWI     X+OS_NewLine
+        LDR     r6, [r6, #SockNext]
+        TEQ     r6, #0
+        BNE     %b0000
+        ADD     sp, sp, #12
+        LDR     pc, [sp], #4
+0010    ADR     r0, SWDL_NowtString
+        SWI     OS_Write0
+        SWI     OS_NewLine
+        LDR     pc, [sp], #4
+SWDL_x  DCB     "Socket 0x",0
+SWDL_y  DCB     ", pollword 0x",0
+SWDL_z  DCB     ", bitmask 0x",0
+        ALIGN
+SWDL_NowtString
+        DCB     "Nothing registered - nothing to do",0
+        ALIGN
+
+
+        DCB     10,10
+        DCB     "Dickon Hood: [email protected], [email protected], in order 
of preference.",10
+        DCB     "Frank de Bruijn: [email protected]",10
+        DCB     10
+        ALIGN
+
+
+        END
diff --git a/frontends/riscos/gui.c b/frontends/riscos/gui.c
index 190aacb..02a3020 100644
--- a/frontends/riscos/gui.c
+++ b/frontends/riscos/gui.c
@@ -26,8 +26,10 @@
 #include <assert.h>
 #include <errno.h>
 #include <signal.h>
+#include <unistd.h>
 #include <unixlib/local.h>
 #include <fpu_control.h>
+#include <swis.h>
 #include <oslib/help.h>
 #include <oslib/uri.h>
 #include <oslib/inetsuite.h>
@@ -120,8 +122,6 @@ osspriteop_area *gui_sprites; /**< Sprite area containing 
pointer and hotlist sp
 #define DIR_SEP ('.')
 
 static void *pollword;
-static bool eventv_claimed;
-static bool internet_event_enabled;
 
 /**
  * Accepted wimp user messages.
@@ -393,14 +393,8 @@ static void ro_gui_cleanup(void)
        xhourglass_off();
        /* Uninstall NetSurf-specific fonts */
        xos_cli("FontRemove NetSurf:Resources.Fonts.");
-       if (internet_event_enabled) {
-               xos_byte(osbyte_DISABLE_EVENT, Event_Internet, 0, NULL, NULL);
-       }
-       if (eventv_claimed) {
-               xos_release(EventV, (asm_routine) (((uintptr_t) pollword) + 4),
-                       pollword);
-       }
        if (pollword != NULL) {
+               //XXX: need to make sure _all_ sockets are closed
                xosmodule_free(pollword);
        }
 }
@@ -1128,41 +1122,55 @@ static bool ro_gui__os_alpha_sprites_supported(void)
        return (var_val == (1 << 15));
 }
 
+static int ro_gui_socket_open(int domain, int type, int protocol)
+{
+       int sock = socket(domain, type, protocol);
+       if (sock != -1) {
+               int rosock;
+               _kernel_oserror *error;
+
+               rosock = __get_ro_socket(sock);
+               if (rosock == -1) {
+                       close(sock);
+                       errno = ENOMEM;
+                       return -1;
+               }
+
+               /* SocketWatch_Register */
+               error = _swix(0x52280, _INR(0,2), pollword, 0x1, rosock);
+               if (error != NULL) {
+                       close(sock);
+                       errno = ENOMEM;
+                       return -1;
+               }
+       }
+       return sock;
+}
+
+static int ro_gui_socket_close(int socket)
+{
+       int rosock;
+
+       rosock = __get_ro_socket(socket);
+       if (rosock != -1) {
+               /* SocketWatch_Deregister */
+               (void) _swix(0x52281, _INR(0,1), rosock, pollword);
+       }
+
+       return close(socket);
+}
+
 /**
  * Set up internet event handling
  */
 static os_error *ro_gui_init_internet_event(void)
 {
-       static const uint32_t event_handler_code[] = {
-               0x00000000, // pollword value
-               0xE3300013, // TEQ r0, #Event_Internet
-               0x11A0F00E, // MOVNE pc, lr
-               0xE59C5000, // LDR r5, [r12]
-               0xE2855001, // ADD r5, r5, #1
-               0xE58C5000, // STR r5, [r12]
-               0xE1A0F00E, // MOV pc, lr
-       };
        os_error *error;
 
-       error = xosmodule_alloc(sizeof(event_handler_code), &pollword);
-       if (error != NULL)
-               return error;
-       memcpy(pollword, event_handler_code, sizeof(event_handler_code));
-       error = xos_synchronise_code_areas(os_GIVEN_CODE_RANGE,
-                       (asm_routine) (((uintptr_t) pollword) + 4),
-                       (asm_routine) (((uintptr_t) pollword) +
-                               sizeof(event_handler_code) - 4));
-       if (error != NULL)
-               return error;
-       error = xos_claim(EventV, (asm_routine) (((uintptr_t) pollword) + 4),
-                       pollword);
-       if (error != NULL)
-               return error;
-       eventv_claimed = true;
-       error = xos_byte(osbyte_ENABLE_EVENT, Event_Internet, 0, NULL, NULL);
+       error = xosmodule_alloc(4, &pollword);
        if (error != NULL)
                return error;
-       internet_event_enabled = true;
+       *((uint32_t*) pollword) = 0;
        return NULL;
 }
 
@@ -1901,7 +1909,8 @@ static void ro_gui_handle_event(wimp_event_no event, 
wimp_block *block)
                case wimp_POLLWORD_NON_ZERO:
                        /* simply reset pollword */
                        if (pollword != NULL) {
-                               *((uint32_t *) pollword) = 0;
+                               /* SocketWatch_AtomicReset */
+                               _swix(0x52282, _INR(0,1), pollword, 0);
                        }
                        break;
 
@@ -2467,6 +2476,8 @@ static struct gui_fetch_table riscos_fetch_table = {
 
        .get_resource_url = gui_get_resource_url,
        .mimetype = fetch_mimetype,
+       .socket_open = ro_gui_socket_open,
+       .socket_close = ro_gui_socket_close,
 };
 
 static struct gui_misc_table riscos_misc_table = {
diff --git a/frontends/riscos/scripts/Run b/frontends/riscos/scripts/Run
index 3368140..233322e 100644
--- a/frontends/riscos/scripts/Run
+++ b/frontends/riscos/scripts/Run
@@ -95,6 +95,10 @@ RMEnsure Iconv 0.12 Error NetSurf requires Iconv 0.12 or 
later. Please use the R
 RMEnsure CryptRandom 0.13 NetSurfRMLoad System:Modules.CryptRand
 RMEnsure CryptRandom 0.13 Error NetSurf requires CryptRandom 0.13 or later.  
Please use the RISC OS Configure app to update the computer's !System directory 
from the NetSurf archive.
 
+| Ensure SocketWatch
+RMEnsure SocketWatch 0.07 NetSurfRMLoad System:Modules.Network.SockWatch
+RMEnsure SocketWatch 0.07 Error NetSurf requires SocketWatch 0.07 or later. 
Please use the RISC OS Configure app to update the computer's !System directory 
from the NetSurf archive.
+
 | Disable SpecialFX, if present
 Set NetSurf$SpecialFX 1
 RMEnsure SpecialFX 1.00 Set NetSurf$SpecialFX 0
diff --git a/include/netsurf/fetch.h b/include/netsurf/fetch.h
index 30b2048..156f4d1 100644
--- a/include/netsurf/fetch.h
+++ b/include/netsurf/fetch.h
@@ -99,6 +99,23 @@ struct gui_fetch_table {
         */
        char *(*mimetype)(const char *ro_path);
 
+       /**
+        * Open a socket
+        *
+        * \param domain Communication domain
+        * \param type Socket type
+        * \param protocol Protocol
+        * \return Socket descriptor on success, -1 on error and errno set
+        */
+       int (*socket_open)(int domain, int type, int protocol);
+
+       /**
+        * Close a socket
+        *
+        * \param socket Socket descriptor
+        * \return 0 on success, -1 on error and errno set
+        */
+       int (*socket_close)(int socket);
 };
 
 #endif


-- 
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to