* The scheduler can now "wake up" a session to deliver async messages.
authorArt Cancro <ajc@citadel.org>
Wed, 9 Jun 2004 03:54:08 +0000 (03:54 +0000)
committerArt Cancro <ajc@citadel.org>
Wed, 9 Jun 2004 03:54:08 +0000 (03:54 +0000)
* Renumbered the "instant msgs waiting" message and changed its usage

14 files changed:
citadel/ChangeLog
citadel/citserver.c
citadel/citserver.h
citadel/ipcdef.h
citadel/serv_chat.c
citadel/serv_extensions.c
citadel/serv_extensions.h
citadel/serv_imap.c
citadel/serv_pop3.c
citadel/serv_smtp.c
citadel/server.h
citadel/server_main.c
citadel/sysdep.c
citadel/techdoc/session.txt

index 77701fa74990fba89fa7d9c312b7ef9fa640e960..018f14d1d4bb372d5d4249bf73411bb503da64c8 100644 (file)
@@ -1,4 +1,8 @@
  $Log$
+ Revision 621.10  2004/06/09 03:54:07  ajc
+ * The scheduler can now "wake up" a session to deliver async messages.
+ * Renumbered the "instant msgs waiting" message and changed its usage
+
  Revision 621.9  2004/06/07 22:12:19  ajc
  * Removed network/filterlist network/mailinglists network/rnews.xref
    because none of these are used anymore.
@@ -5826,4 +5830,3 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import
-
index 8f5fd57221a21d00245d5b59571bfe353cf6bdfe..9ef8208538f39b4c283a3ae5ca23de3a2028f154 100644 (file)
@@ -1319,3 +1319,11 @@ void do_command_loop(void) {
        /* Run any after-each-command routines registered by modules */
        PerformSessionHooks(EVT_CMD);
 }
+
+
+/*
+ * This loop performs all asynchronous functions.
+ */
+void do_async_loop(void) {
+       PerformSessionHooks(EVT_ASYNC);
+}
index 9c817087cb010a3969bc74508129a62c809f726a..2288541bea976c1dfbeba57ec4153da259eda266 100644 (file)
@@ -34,6 +34,7 @@ void *CtdlGetUserData(unsigned long requested_sym);
 void CtdlAllocUserData(unsigned long requested_sym, size_t num_bytes);
 void CtdlReallocUserData(unsigned long requested_sym, size_t num_bytes);
 void do_command_loop(void);
+void do_async_loop(void);
 void begin_session(struct CitContext *con);
 void citproto_begin_session(void);
 void GenerateRoomDisplay(char *real_room,
index 5b566c0a10a0edc8dd029b1e6d66fc6bd913a2e7..998255ca85de9ef12f2adabbcc4b0d7c35009f4e 100644 (file)
@@ -35,7 +35,7 @@ extern "C" {
 #define MESSAGE_NOT_FOUND      75
 
 #define ASYNC_MSG              900
-#define ASYNC_GEXP             01
+#define ASYNC_GEXP             02
 
 #define QR_PERMANENT   1               /* Room does not purge              */
 #define QR_INUSE       2               /* Set if in use, clear if avail    */
index e21da82f8cb17317d2f3eb73362fa63014614e70..89d715faa6d50103990329fa564e45e4a788d5eb 100644 (file)
@@ -510,7 +510,6 @@ void cmd_gexp_async(void) {
        if (CC->FirstExpressMessage == NULL) return;
 
        cprintf("%d instant msg\n", ASYNC_MSG + ASYNC_GEXP);
-       cmd_gexp("");
 }
 
 /*
@@ -531,6 +530,16 @@ void add_xmsg_to_context(struct CitContext *ccptr,
                }
                findend->next = newmsg;
        }
+
+       /* If the target context is a session which can handle asynchronous
+        * messages, go ahead and set the flag for that.
+        */
+       if (ccptr->is_async) {
+               ccptr->async_waiting = 1;
+               if (ccptr->state == CON_IDLE) {
+                       ccptr->state = CON_READY;
+               }
+       }
 }
 
 
@@ -803,7 +812,7 @@ char *serv_chat_init(void)
        CtdlRegisterProtoHook(cmd_sexp, "SEXP", "Send an instant message");
        CtdlRegisterProtoHook(cmd_dexp, "DEXP", "Disable instant messages");
        CtdlRegisterProtoHook(cmd_reqt, "REQT", "Request client termination");
-       CtdlRegisterSessionHook(cmd_gexp_async, EVT_CMD);
+       CtdlRegisterSessionHook(cmd_gexp_async, EVT_ASYNC);
        CtdlRegisterSessionHook(delete_instant_messages, EVT_STOP);
        CtdlRegisterXmsgHook(send_instant_message, XMSG_PRI_LOCAL);
        return "$Id$";
index 8d07fe6a3c08e3c3b6470888ee1f4f5014aa79eb..b10635097f042969e3013197aaa87d5b0e7d19f2 100644 (file)
@@ -426,7 +426,9 @@ void CtdlUnregisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
 void CtdlRegisterServiceHook(int tcp_port,
                        char *sockpath,
                        void (*h_greeting_function) (void),
-                       void (*h_command_function) (void) )
+                       void (*h_command_function) (void),
+                       void (*h_async_function) (void)
+                       )
 {
        struct ServiceFunctionHook *newfcn;
        char message[SIZ];
@@ -438,6 +440,7 @@ void CtdlRegisterServiceHook(int tcp_port,
        newfcn->sockpath = sockpath;
        newfcn->h_greeting_function = h_greeting_function;
        newfcn->h_command_function = h_command_function;
+       newfcn->h_async_function = h_async_function;
 
        if (sockpath != NULL) {
                newfcn->msock = ig_uds_server(sockpath, config.c_maxsessions);
@@ -468,7 +471,9 @@ void CtdlRegisterServiceHook(int tcp_port,
 
 void CtdlUnregisterServiceHook(int tcp_port, char *sockpath,
                        void (*h_greeting_function) (void),
-                       void (*h_command_function) (void) )
+                       void (*h_command_function) (void),
+                       void (*h_async_function) (void)
+                       )
 {
        struct ServiceFunctionHook *cur, *p;
 
@@ -479,6 +484,7 @@ void CtdlUnregisterServiceHook(int tcp_port, char *sockpath,
                                        strcmp(sockpath, cur->sockpath)) &&
                                h_greeting_function == cur->h_greeting_function &&
                                h_command_function == cur->h_command_function &&
+                               h_async_function == cur->h_async_function &&
                                tcp_port == cur->tcp_port) {
                        close(cur->msock);
                        if (sockpath) {
index 6b645ca5a816dce3d519aaa45ed5fbe73e39dae2..bd0904e0d39f7b292900d697df119696f973e07c 100644 (file)
@@ -78,10 +78,14 @@ void CtdlUnregisterProtoHook(void (*handler)(char *), char *cmd);
 void CtdlRegisterServiceHook(int tcp_port,
                        char *sockpath,
                         void (*h_greeting_function) (void),
-                        void (*h_command_function) (void) ) ;
+                        void (*h_command_function) (void),
+                        void (*h_async_function) (void)
+       ) ;
 void CtdlUnregisterServiceHook(int tcp_port,
                        char *sockpath,
                         void (*h_greeting_function) (void),
-                        void (*h_command_function) (void) ) ;
+                        void (*h_command_function) (void),
+                        void (*h_async_function) (void)
+       ) ;
 
 #endif /* SERV_EXTENSIONS_H */
index f448ecf404fa564571dafad09bc2fc8154e931e3..426484263e27c46805041a060a81e0975ba0db5c 100644 (file)
@@ -1444,7 +1444,7 @@ void imap_command_loop(void)
 char *serv_imap_init(void)
 {
        CtdlRegisterServiceHook(config.c_imap_port,
-                               NULL, imap_greeting, imap_command_loop);
+                               NULL, imap_greeting, imap_command_loop, NULL);
        CtdlRegisterSessionHook(imap_cleanup_function, EVT_STOP);
        return "$Id$";
 }
index b1c8d9f34410519061032ecd17431adb4777d9db..c5325d92136bc67f56b6c516ee1e37bc9ec8fe5c 100644 (file)
@@ -654,7 +654,8 @@ char *serv_pop3_init(void)
        CtdlRegisterServiceHook(config.c_pop3_port,
                                NULL,
                                pop3_greeting,
-                               pop3_command_loop);
+                               pop3_command_loop,
+                               NULL);
        CtdlRegisterSessionHook(pop3_cleanup_function, EVT_STOP);
        return "$Id$";
 }
index 7946661c4cf4ea22ac579f2d12d186687945955b..840cbf1b2304ce70c713dce0db7b672747c136fe 100644 (file)
@@ -1614,12 +1614,14 @@ char *serv_smtp_init(void)
        CtdlRegisterServiceHook(config.c_smtp_port,     /* On the net... */
                                NULL,
                                smtp_greeting,
-                               smtp_command_loop);
+                               smtp_command_loop,
+                               NULL);
 
        CtdlRegisterServiceHook(0,                      /* ...and locally */
                                "lmtp.socket",
                                lmtp_greeting,
-                               smtp_command_loop);
+                               smtp_command_loop,
+                               NULL);
 
        smtp_init_spoolout();
        CtdlRegisterSessionHook(smtp_do_queue, EVT_TIMER);
index f33db3bc5f216a16e59bd16b6f10e5034ffee253..06ed9b84660d88b76125c087f6555d11ac7a362a 100644 (file)
@@ -92,7 +92,10 @@ struct CitContext {
        char lastcmdname[5];    /* name of last command executed */
        unsigned cs_flags;      /* miscellaneous flags */
        void (*h_command_function) (void) ;     /* service command function */
+       void (*h_async_function) (void) ;       /* do async msgs function */
        int is_async;           /* Nonzero if client accepts async msgs */
+       int async_waiting;      /* Nonzero if there are async msgs waiting */
+       int input_waiting;      /* Nonzero if there is client input waiting */
 
        /* feeping creaturisms... */
        int cs_clientdev;       /* client developer ID */
@@ -317,6 +320,7 @@ extern struct SessionFunctionHook *SessionHookTable;
 #define EVT_SETPASS    5       /* Setting or changing password */
 #define EVT_CMD                6       /* Called after each server command */
 #define EVT_RWHO       7       /* An RWHO command is being executed */
+#define EVT_ASYNC      8       /* Doing asynchronous messages */
 
 #define EVT_TIMER      50      /* Timer events are called once per minute
                                   and are not tied to any session */
@@ -409,6 +413,7 @@ struct ServiceFunctionHook {
        char *sockpath;
        void (*h_greeting_function) (void) ;
        void (*h_command_function) (void) ;
+       void (*h_async_function) (void) ;
        int msock;
 };
 extern struct ServiceFunctionHook *ServiceHookTable;
index 0472d49c48107abc32ef8a01e46ffba07fb27d0a..a5199b19fc840920751a1e0561316c368286150d 100644 (file)
@@ -173,7 +173,8 @@ int main(int argc, char **argv)
        CtdlRegisterServiceHook(0,
                                "citadel.socket",
                                citproto_begin_session,
-                               do_command_loop);
+                               do_command_loop,
+                               do_async_loop);
 
        /*
         * Bind the server to our favorite TCP port (usually 504).
@@ -181,7 +182,8 @@ int main(int argc, char **argv)
        CtdlRegisterServiceHook(config.c_port_number,
                                NULL,
                                citproto_begin_session,
-                               do_command_loop);
+                               do_command_loop,
+                               do_async_loop);
 
        /*
         * Load any server-side extensions available here.
index 3b1c54b89267fbd1f0c4f1e4d8847e8c428d71a8..6da856165e68c7b91c7a6ef9b05135f2df6deba0 100644 (file)
@@ -993,6 +993,8 @@ do_select:  /* Only select() if the server isn't being told to shut down. */
                                        con->client_socket = ssock;
                                        con->h_command_function =
                                                serviceptr->h_command_function;
+                                       con->h_async_function =
+                                               serviceptr->h_async_function;
 
                                        /* Determine whether local socket */
                                        if (serviceptr->sockpath != NULL)
@@ -1029,6 +1031,7 @@ do_select:        /* Only select() if the server isn't being told to shut down. */
                for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
                        if ( (FD_ISSET(ptr->client_socket, &readfds))
                           && (ptr->state != CON_EXECUTING) ) {
+                               ptr->input_waiting = 1;
                                if (!bind_me) {
                                        bind_me = ptr;  /* I choose you! */
                                        bind_me->state = CON_EXECUTING;
@@ -1041,10 +1044,24 @@ do_select:      /* Only select() if the server isn't being told to shut down. */
                end_critical_section(S_SESSION_TABLE);
 SKIP_SELECT:   end_critical_section(S_I_WANNA_SELECT);
 
-               /* We're bound to a session, now do *one* command */
+               /* We're bound to a session */
                if (bind_me != NULL) {
                        become_session(bind_me);
-                       CC->h_command_function();
+
+                       /* If the client has sent a command, execute it. */
+                       if (CC->input_waiting) {
+                               CC->h_command_function();
+                               CC->input_waiting = 0;
+                       }
+
+                       /* If there are asynchronous messages waiting and the
+                        * client supports it, do those now */
+                       if ((CC->is_async) && (CC->async_waiting)
+                          && (CC->h_async_function != NULL)) {
+                               CC->h_async_function();
+                               CC->async_waiting = 0;
+                       }
+                       
                        force_purge = CC->kill_me;
                        become_session(NULL);
                        bind_me->state = CON_IDLE;
index b498c54eb4cec2a143f37a4094729e2bfecb41c4..8877b5162f92144aa2126c50effa731ed89420f9 100644 (file)
@@ -2135,9 +2135,6 @@ the writeup of the ASYN command above), the following messages may arrive at
 any time:
 
 
- 901  (instant message arriving)
+ 902  (instant message arriving)
 
- One or more instant messages have arrived for this client.  When the client
-receives this message, it MUST act as if it just sent a GEXP command (the data
-following the 901 message WILL be a LISTING_FOLLOWS data transfer; in fact,
-the current implementation simply executes a GEXP command internally).
+ One or more instant messages have arrived for this client.