ldmud-3.2.9/doc/
ldmud-3.2.9/doc/efun/
ldmud-3.2.9/mud/
ldmud-3.2.9/mud/heaven7/
ldmud-3.2.9/mud/heaven7/lib/
ldmud-3.2.9/mud/lp-245/
ldmud-3.2.9/mud/lp-245/banish/
ldmud-3.2.9/mud/lp-245/doc/
ldmud-3.2.9/mud/lp-245/doc/examples/
ldmud-3.2.9/mud/lp-245/doc/sefun/
ldmud-3.2.9/mud/lp-245/log/
ldmud-3.2.9/mud/lp-245/obj/Go/
ldmud-3.2.9/mud/lp-245/players/lars/
ldmud-3.2.9/mud/lp-245/room/death/
ldmud-3.2.9/mud/lp-245/room/maze1/
ldmud-3.2.9/mud/lp-245/room/sub/
ldmud-3.2.9/mud/lp-245/secure/
ldmud-3.2.9/mud/morgengrauen/
ldmud-3.2.9/mud/morgengrauen/lib/
ldmud-3.2.9/mud/sticklib/
ldmud-3.2.9/mud/sticklib/src/
ldmud-3.2.9/mudlib/uni-crasher/
ldmud-3.2.9/pkg/
ldmud-3.2.9/pkg/debugger/
ldmud-3.2.9/pkg/diff/
ldmud-3.2.9/pkg/misc/
ldmud-3.2.9/src/autoconf/
ldmud-3.2.9/src/bugs/
ldmud-3.2.9/src/bugs/MudCompress/
ldmud-3.2.9/src/bugs/b-020916-files/
ldmud-3.2.9/src/bugs/doomdark/
ldmud-3.2.9/src/bugs/ferrycode/ferry/
ldmud-3.2.9/src/bugs/ferrycode/obj/
ldmud-3.2.9/src/bugs/psql/
ldmud-3.2.9/src/done/
ldmud-3.2.9/src/done/order_alist/
ldmud-3.2.9/src/done/order_alist/obj/
ldmud-3.2.9/src/done/order_alist/room/
ldmud-3.2.9/src/gcc/
ldmud-3.2.9/src/gcc/2.7.0/
ldmud-3.2.9/src/gcc/2.7.1/
ldmud-3.2.9/src/hosts/
ldmud-3.2.9/src/hosts/GnuWin32/
ldmud-3.2.9/src/hosts/amiga/NetIncl/
ldmud-3.2.9/src/hosts/amiga/NetIncl/netinet/
ldmud-3.2.9/src/hosts/amiga/NetIncl/sys/
ldmud-3.2.9/src/hosts/i386/
ldmud-3.2.9/src/hosts/msdos/byacc/
ldmud-3.2.9/src/hosts/msdos/doc/
ldmud-3.2.9/src/hosts/os2/
ldmud-3.2.9/src/hosts/win32/
ldmud-3.2.9/src/util/
ldmud-3.2.9/src/util/erq/
ldmud-3.2.9/src/util/indent/hosts/next/
ldmud-3.2.9/src/util/xerq/
ldmud-3.2.9/src/util/xerq/lpc/
ldmud-3.2.9/src/util/xerq/lpc/www/
Short: Socket support
From: Ctx@amail.derefence.de
Date: 2002-10-21
Type: Patch
State: New
See also: f-981226-1, f-991104-0, p-020912

Hi Lars ;)

Ich habe ein bisschen mit deinem MUD-Driver herumgespielt, er ist
wirklich super ;)
Ich wollte ihn auch zu Verbindungen mit externen Services wie SMTP,
IMAP, POP3, NNTP, IRC usw. usf. einsetzen und hab festgestellt, dass das
mit dem ERQ-Daemon eigentlich nur sehr unsauber und hakelig geht. Also
dachte ich mir, waere es doch sinnvoll, wenn man den remote service als
"Player" sieht, der einem interaktiven objekt Kommandos schickt.
Bei einer Verbindung zu einem SMTP-Server z.B. wuerde das Kommando
'220' bedeuten, schick mir jetzt deine Befehle.
Bei einem IRC-Server mit festem Prefix (:irc-server.de 376) koennte man
mit modify_command() die Eingabe in ein entsprechendes Format bringen
(Zahlencode zuerst, dann Sender) und hier auch mit add_action arbeiten.
Gerade bei nicht-binaeren (Plaintext) Protokollen wie die oben genannten
finde ich diese Sichtweise elegant.

Ich habe fuer mich den Driver ein wenig geaendert, um eine efun
"connect_external" erweitert.
connect_external("127.0.0.1", 25, smtp_object); wuerde eine Verbindung
zum lokalen SMTP-server herstellen und die Verbindung an das smtp_object
binden. Nach gelungenem Verbindungsaufbau wird dort, wie bei
player-objekten, logon() aufgerufen. Bei Fehlschlag, bzw.
Verbindungsabbruch, wuerde "connerr" mit der entsprechenden errno als
Argument aufgerufen. Ansonsten verhaelt sich das objekt wie jedes andere
interaktive.

Fuer mich ist das ziemlich nuetzlich, vielleicht ja auch fuer dich oder
andere. Vermutlich sind noch Bugs darin (Eine Stelle, bei der ich mir
ziemlich sicher bin, habe ich mit FIXME markiert), ich hatte leider
nicht die Zeit mich in jedes Detail des Drivers einzuarbeiten.

Falls der Patch sinnlos/schlecht/falsch ist, schmeiss die Mail einfach
weg ;) Ueber kurzes Feedback wuerde ich mich trotzdem freuen.

Gruss

Florian Heinz (AKA Ctx)


diff -ru 3-3/src/comm.c 3-3.ctx/src/comm.c
--- 3-3/src/comm.c	2002-10-21 13:06:37.000000000 +0200
+++ 3-3.ctx/src/comm.c	2002-10-21 13:04:56.000000000 +0200
@@ -318,8 +318,15 @@
 /* --- Communication sockets --- */
 
 static SOCKET_T sos[MAXNUMPORTS];
+
+static SOCKET_T soo[MAXNUMPORTS];
+
   /* The login sockets.
    */
+struct soc_item {
+   int fd;
+   svalue_t *ob;
+} soc[MAXNUMPORTS];
 
 static SOCKET_T udp_s = -1;
   /* The UDP socket */
@@ -444,7 +451,8 @@
 static void send_do(int);
 static void send_dont(int);
 static void remove_flush_entry(interactive_t *ip);
-static void new_player(SOCKET_T new_socket, struct sockaddr_in *addr, size_t len, int login_port);
+static void new_player(SOCKET_T new_socket, struct sockaddr_in *addr,
+		       size_t len, int login_port, svalue_t *n_ob);
 
 #ifdef ERQ_DEMON
 
@@ -1198,6 +1206,11 @@
         if (socket_number(sos[i]) >= min_nfds)
             min_nfds = socket_number(sos[i])+1;
     } /* for(i = 0..numports) */
+   
+    for (i = 0; i < MAXNUMPORTS; i++) {
+       soc[i].fd = -1;
+       soc[i].ob = NULL;
+    }
 
     /* We handle SIGPIPEs ourself */
 #if defined(__linux__)
@@ -1214,6 +1227,46 @@
 #endif
 } /* prepare_ipc() */
 
+int
+connect_ext (char *ip, unsigned short int port, svalue_t *n_ob)
+{
+   struct sockaddr_in addr;
+   int fd, st, i;
+   struct soc_item *sptr = NULL;
+   
+   for (i = 0; i < MAXNUMPORTS; i++) {
+      if (soc[i].fd < 0) {
+	 sptr = &soc[i];
+	 break;
+      }
+   }
+   
+   if (!sptr) {
+      errno = ENOMEM;
+      return -1;
+   }
+      
+   
+   addr.sin_family = AF_INET;
+   addr.sin_port = htons(port);
+   addr.sin_addr.s_addr = inet_addr(ip);
+   
+   fd = socket(AF_INET, SOCK_STREAM, 0);
+   if (fd < 0)
+     return -1;
+   
+   sptr->fd = fd;
+   sptr->ob = n_ob;
+   
+   set_socket_nonblocking(fd);
+   set_close_on_exec(fd);
+   st = connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
+   if (st < 0)
+     return -1;
+   return 0;
+}
+
+
 /*-------------------------------------------------------------------------*/
 void
 ipc_remove (void)
@@ -2168,7 +2221,7 @@
 
 {
     /* State information: */
-    static fd_set readfds;
+    static fd_set readfds, writefds;
       /* List of sockets with pending data.
        * You can ignore a 'could be used uninitialized' warning.
        */
@@ -2212,13 +2265,20 @@
                * of the sockets, but don't wait.
                */
 
-            /* Set up readfds */
+            /* Set up readfds and writefds */
 
             FD_ZERO(&readfds);
+            FD_ZERO(&writefds);
             for (i = 0; i < numports; i++) {
                 FD_SET(sos[i], &readfds);
             } /* for */
             nfds = min_nfds;
+	    for (i = 0; i < MAXNUMPORTS; i++) {
+	        if (soc[i].fd >= 0)
+		   FD_SET(soc[i].fd, &writefds);
+	        if (soc[i].fd >= nfds)
+		   nfds = soc[i].fd + 1;
+	    }
             for (i = max_player + 1; --i >= 0;)
             {
                 ip = all_players[i];
@@ -2262,7 +2322,7 @@
                 check_alarm();
                 timeout.tv_sec = twait;
                 timeout.tv_usec = 0;
-                res = socket_select(nfds, &readfds, 0, 0, &timeout);
+                res = socket_select(nfds, &readfds, &writefds, 0, &timeout);
                 if (res == -1)
                 {
                     /* BeOS <= PR2 returns errno -1 instead of EINTR :-( */
@@ -2287,6 +2347,7 @@
                      * commands.
                      */
                     FD_ZERO(&readfds);
+                    FD_ZERO(&writefds);
                 }
                 break;
             } /* for (retries) */
@@ -2573,7 +2634,7 @@
                                               , &length);
                     if ((int)new_socket != -1)
                         new_player(new_socket, &addr, (size_t)length
-                                  , port_numbers[i]);
+                                  , port_numbers[i], NULL);
                     else if ((int)new_socket == -1
                       && errno != EWOULDBLOCK && errno != EINTR
                       && errno != EAGAIN && errno != EPROTO )
@@ -2600,6 +2661,27 @@
                     }
                 }
             } /* for */
+	    for (i = 0; i < MAXNUMPORTS; i++)
+	    {
+	       if ((soc[i].fd >= 0) && (FD_ISSET(soc[i].fd, &writefds))) {
+		  int err, errlen = sizeof(err);
+		  getsockopt(soc[i].fd, SOL_SOCKET, SO_ERROR, &err, &errlen);
+		  if (err) {
+		     close(soc[i].fd);
+		     soc[i].fd = -1;
+		     push_number(inter_sp, err);
+		     /* Notify object here */
+		     apply(STR_CONNERR, soc[i].ob->u.ob, 1);
+		  } else {
+		     struct sockaddr_in addr;
+		     size_t length = sizeof(addr);
+		     
+		     getpeername(soc[i].fd, (struct sockaddr *) &addr, &length);
+		     new_player(soc[i].fd, &addr, length, 0, soc[i].ob);
+		  }
+	       }
+	    }
+				
             /* check for alarm signal (heart beat) */
             if (comm_time_to_call_heart_beat)
             {
@@ -3227,6 +3309,7 @@
 #else
            , int login_port
 #endif
+	   , svalue_t *n_ob
            )
 
 /* Accept (or reject) a new connection on <new_socket> from <addr> (length
@@ -3419,7 +3502,10 @@
 
     /* Call master->connect() and evaluate the result.
      */
-    ret = callback_master(STR_CONNECT, 0);
+
+    ret = callback_master(STR_CONNECT, 0); /* FIXME (leak?) */
+    if (n_ob)
+        ret = n_ob;
     if (new_interactive != O_GET_INTERACTIVE(master_ob))
         return;
     if (ret == NULL
@@ -3439,7 +3525,6 @@
     O_GET_INTERACTIVE(master_ob) = NULL;
     master_ob->flags &= ~O_ONCE_INTERACTIVE;
     check_shadow_sent(master_ob);
-
     assert_shadow_sent(ob);
     O_GET_INTERACTIVE(ob) = new_interactive;
     new_interactive->ob = ob;
Only in 3-3.ctx/src: comm.c.orig
diff -ru 3-3/src/efuns.c 3-3.ctx/src/efuns.c
--- 3-3/src/efuns.c	2002-10-11 06:09:44.000000000 +0200
+++ 3-3.ctx/src/efuns.c	2002-10-21 13:06:10.000000000 +0200
@@ -7306,5 +7306,31 @@
     return sp;
 } /* f_utime() */
 
+/* EFUN connect_external()
+ *
+ *   void connect_external(string ip, int port, object ob)
+ * 
+ * Establishs a TCP-Connection to a remote service.
+ * If the connection succeeds, ob is set interactive, the remote
+ * service is the commandgiver and logon() is called in the object.
+ * If the connection fails or aborts, connerr(int errno) is called.
+ * 
+ */
+
+svalue_t * f_connect_external (svalue_t *sp)
+{
+   if (O_IS_INTERACTIVE(sp->u.ob))
+     error("Bad arg 3 to connect_external(): Object is already interactive.\n");
+   
+   connect_ext(get_txt(sp[-2].u.str), sp[-1].u.number, sp);
+   
+   free_svalue(sp);
+   free_svalue(sp - 1);
+   free_svalue(sp - 2);
+   return sp - 3;
+}
+
+   
+
 /***************************************************************************/
 
Only in 3-3.ctx/src: efuns.c.orig
diff -ru 3-3/src/func_spec 3-3.ctx/src/func_spec
--- 3-3/src/func_spec	2002-10-05 21:02:39.000000000 +0200
+++ 3-3.ctx/src/func_spec	2002-10-21 12:58:46.000000000 +0200
@@ -672,4 +672,6 @@
 #endif /* USE_DEPRECATED */
 
 
+void connect_external(string, int, object);
+
 /***************************************************************************/
Only in 3-3.ctx/src: func_spec.orig
diff -ru 3-3/src/string_spec 3-3.ctx/src/string_spec
--- 3-3/src/string_spec	2002-10-07 08:04:04.000000000 +0200
+++ 3-3.ctx/src/string_spec	2002-10-21 12:58:46.000000000 +0200
@@ -198,6 +198,8 @@
 PC_CHILDREN     "children"
 PC_SHEEP        "sheep"
 
+CONNERR         "connerr"
+
 #endif /* SUPPLY_PARSE_COMMAND */
 
 /***************************************************************************/
Only in 3-3.ctx/src: string_spec.orig