* Added support for protocols over Unix domain sockets.
authorArt Cancro <ajc@citadel.org>
Sun, 5 Mar 2000 07:33:23 +0000 (07:33 +0000)
committerArt Cancro <ajc@citadel.org>
Sun, 5 Mar 2000 07:33:23 +0000 (07:33 +0000)
citadel/ChangeLog
citadel/ipc_c_tcp.c
citadel/sysconfig.h
citadel/sysdep.c

index db126f049ebff48ecf05dc6dcc82a6fddcf03172..fd02984d340d4d769b3c2ffe03c6f95d46d794b0 100644 (file)
@@ -1,4 +1,7 @@
 $Log$
+Revision 1.478  2000/03/05 07:33:23  ajc
+* Added support for protocols over Unix domain sockets.
+
 Revision 1.477  2000/03/04 22:36:23  ajc
 * Remove nulls appended to editor files during replace, edit, and print
   operations.  Truncate temp files during same operations.
@@ -1696,4 +1699,3 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncnsrd.mt-kisco.ny.us>
        * Initial CVS import 
-
index d9545d75c28cfc1d92cafd3a991ed864a9c225a7..4be2202271da441e27ae7c4ab2365a6035cb18d7 100644 (file)
@@ -20,6 +20,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <sys/un.h>
 #include <netdb.h>
 #include <string.h>
 #include <pwd.h>
@@ -72,8 +73,34 @@ int connectsock(char *host, char *service, char *protocol)
        struct servent *pse;
        struct protoent *ppe;
        struct sockaddr_in sin;
+       struct sockaddr_un sun;
        int s, type;
 
+
+       if ( (!strcmp(protocol, "unix")) || (atoi(service)<0) ) {
+               memset(&sun, 0, sizeof(sun));
+               sun.sun_family = AF_UNIX;
+               sprintf(sun.sun_path, USOCKPATH, 0-atoi(service) );
+
+               s = socket(AF_UNIX, SOCK_STREAM, 0);
+               if (s < 0) {
+                       fprintf(stderr, "Can't create socket: %s\n",
+                               strerror(errno));
+                       logoff(3);
+               }
+
+               if (connect(s, (struct sockaddr *) &sun, sizeof(sun)) < 0) {
+                       fprintf(stderr, "can't connect: %s\n",
+                               strerror(errno));
+                       logoff(3);
+               }
+
+               return s;
+       }
+
+
+       /* otherwise it's a network connection */
+
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
 
index 7b749753a1766ce57762eca91ebe12d05b89a647..70e2162d8b3339f4beee2d76e480ac6c694abc45 100644 (file)
 #define SMTP_GIVE_UP           259200  /* give up after 3 days */
 
 
+/* 
+ * Pathname template to use for Unix domain sockets
+ */
+#define USOCKPATH              "/tmp/citadel%04x"
+
+
 /*
  * The names of rooms which are automatically created by the system
  */
index 6bb0720e5995104e70a7550eec9977dcf3d92004..59de2f8b5ab682cd8b091a26539ab1c3dfb76933 100644 (file)
@@ -26,6 +26,7 @@
 #include <limits.h>
 #include <netinet/in.h>
 #include <netdb.h>
+#include <sys/un.h>
 #include <string.h>
 #include <pwd.h>
 #include <errno.h>
@@ -259,24 +260,40 @@ void end_critical_section(int which_one)
 /*
  * This is a generic function to set up a master socket for listening on
  * a TCP port.  The server shuts down if the bind fails.
+ *
+ * If a negative number is specified, a Unix domain socket is created.
  */
 int ig_tcp_server(int port_number, int queue_len)
 {
        struct sockaddr_in sin;
+       struct sockaddr_un addr;
        int s, i;
+       int is_unix = 0;
 
-       memset(&sin, 0, sizeof(sin));
-       sin.sin_family = AF_INET;
-       sin.sin_addr.s_addr = INADDR_ANY;
+       if (port_number < 0) {
+               is_unix = 1;
+       }
 
-       if (port_number == 0) {
-               lprintf(1, "citserver: illegal port number specified\n");
-               return(-1);
+       if (is_unix) {
+               memset(&addr, 0, sizeof(addr));
+               addr.sun_family = AF_UNIX;
+               sprintf(addr.sun_path, USOCKPATH, 0-port_number);
+       }
+       else {
+               memset(&sin, 0, sizeof(sin));
+               sin.sin_family = AF_INET;
+               sin.sin_addr.s_addr = INADDR_ANY;
+               sin.sin_port = htons((u_short)port_number);
+       }
+
+       if (is_unix) {
+               s = socket(AF_UNIX, SOCK_STREAM, 0);
+       }
+       else {
+               s = socket(PF_INET, SOCK_STREAM,
+                       (getprotobyname("tcp")->p_proto));
        }
-       
-       sin.sin_port = htons((u_short)port_number);
 
-       s = socket(PF_INET, SOCK_STREAM, (getprotobyname("tcp")->p_proto));
        if (s < 0) {
                lprintf(1, "citserver: Can't create a socket: %s\n",
                        strerror(errno));
@@ -284,12 +301,24 @@ int ig_tcp_server(int port_number, int queue_len)
        }
 
        /* Set the SO_REUSEADDR socket option, because it makes sense. */
-       i = 1;
-       setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
+       if (!is_unix) {
+               i = 1;
+               setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
+       }
 
-       if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
-               lprintf(1, "citserver: Can't bind: %s\n", strerror(errno));
-               return(-1);
+       if (is_unix) {
+               if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+                       lprintf(1, "citserver: Can't bind: %s\n",
+                               strerror(errno));
+                       return(-1);
+               }
+       }
+       else {
+               if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+                       lprintf(1, "citserver: Can't bind: %s\n",
+                               strerror(errno));
+                       return(-1);
+               }
        }
 
        if (listen(s, queue_len) < 0) {
@@ -502,6 +531,7 @@ int client_gets(char *buf)
  */
 void sysdep_master_cleanup(void) {
        struct ServiceFunctionHook *serviceptr;
+       char sockpath[256];
 
        /*
         * close all protocol master sockets
@@ -511,6 +541,13 @@ void sysdep_master_cleanup(void) {
                lprintf(3, "Closing listener on port %d\n",
                        serviceptr->tcp_port);
                close(serviceptr->msock);
+
+               /* If it's a Unix domain socket, remove the file. */
+               if (serviceptr->tcp_port < 0) {
+                       sprintf(sockpath, USOCKPATH, 0-(serviceptr->tcp_port));
+                       lprintf(9, "Removing <%s>\n", sockpath);
+                       unlink(sockpath);
+               }
        }
 }
 
@@ -829,7 +866,10 @@ int main(int argc, char **argv)
        /*
         * Bind the server to our favorite ports.
         */
-       CtdlRegisterServiceHook(config.c_port_number,
+       CtdlRegisterServiceHook(config.c_port_number,           /* TCP */
+                               citproto_begin_session,
+                               do_command_loop);
+       CtdlRegisterServiceHook(0-config.c_port_number,         /* Unix */
                                citproto_begin_session,
                                do_command_loop);