From 9beb839d0a92cd479bd2452d4d8dfe87e8000c9c Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Wed, 9 Jun 2004 03:54:08 +0000 Subject: [PATCH] * The scheduler can now "wake up" a session to deliver async messages. * Renumbered the "instant msgs waiting" message and changed its usage --- citadel/ChangeLog | 5 ++++- citadel/citserver.c | 8 ++++++++ citadel/citserver.h | 1 + citadel/ipcdef.h | 2 +- citadel/serv_chat.c | 13 +++++++++++-- citadel/serv_extensions.c | 10 ++++++++-- citadel/serv_extensions.h | 8 ++++++-- citadel/serv_imap.c | 2 +- citadel/serv_pop3.c | 3 ++- citadel/serv_smtp.c | 6 ++++-- citadel/server.h | 5 +++++ citadel/server_main.c | 6 ++++-- citadel/sysdep.c | 21 +++++++++++++++++++-- citadel/techdoc/session.txt | 7 ++----- 14 files changed, 76 insertions(+), 21 deletions(-) diff --git a/citadel/ChangeLog b/citadel/ChangeLog index 77701fa74..018f14d1d 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -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 Fri Jul 10 1998 Art Cancro * Initial CVS import - diff --git a/citadel/citserver.c b/citadel/citserver.c index 8f5fd5722..9ef820853 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -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); +} diff --git a/citadel/citserver.h b/citadel/citserver.h index 9c817087c..2288541be 100644 --- a/citadel/citserver.h +++ b/citadel/citserver.h @@ -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, diff --git a/citadel/ipcdef.h b/citadel/ipcdef.h index 5b566c0a1..998255ca8 100644 --- a/citadel/ipcdef.h +++ b/citadel/ipcdef.h @@ -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 */ diff --git a/citadel/serv_chat.c b/citadel/serv_chat.c index e21da82f8..89d715faa 100644 --- a/citadel/serv_chat.c +++ b/citadel/serv_chat.c @@ -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$"; diff --git a/citadel/serv_extensions.c b/citadel/serv_extensions.c index 8d07fe6a3..b10635097 100644 --- a/citadel/serv_extensions.c +++ b/citadel/serv_extensions.c @@ -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) { diff --git a/citadel/serv_extensions.h b/citadel/serv_extensions.h index 6b645ca5a..bd0904e0d 100644 --- a/citadel/serv_extensions.h +++ b/citadel/serv_extensions.h @@ -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 */ diff --git a/citadel/serv_imap.c b/citadel/serv_imap.c index f448ecf40..426484263 100644 --- a/citadel/serv_imap.c +++ b/citadel/serv_imap.c @@ -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$"; } diff --git a/citadel/serv_pop3.c b/citadel/serv_pop3.c index b1c8d9f34..c5325d921 100644 --- a/citadel/serv_pop3.c +++ b/citadel/serv_pop3.c @@ -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$"; } diff --git a/citadel/serv_smtp.c b/citadel/serv_smtp.c index 7946661c4..840cbf1b2 100644 --- a/citadel/serv_smtp.c +++ b/citadel/serv_smtp.c @@ -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); diff --git a/citadel/server.h b/citadel/server.h index f33db3bc5..06ed9b846 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -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; diff --git a/citadel/server_main.c b/citadel/server_main.c index 0472d49c4..a5199b19f 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -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. diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 3b1c54b89..6da856165 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -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; diff --git a/citadel/techdoc/session.txt b/citadel/techdoc/session.txt index b498c54eb..8877b5162 100644 --- a/citadel/techdoc/session.txt +++ b/citadel/techdoc/session.txt @@ -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. -- 2.30.2