"Fossies" - the Fresh Open Source Software Archive

Member "citadel/modules/roomchat/serv_roomchat.c" (5 Jun 2021, 5537 Bytes) of package /linux/www/citadel.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "serv_roomchat.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * This module handles instant messaging between users.
    3  * 
    4  * Copyright (c) 2012 by the citadel.org team
    5  *
    6  * This program is open source software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License version 3.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  */
   14 #include "sysdep.h"
   15 #include <stdlib.h>
   16 #include <unistd.h>
   17 #include <stdio.h>
   18 #include <fcntl.h>
   19 #include <signal.h>
   20 #include <pwd.h>
   21 #include <errno.h>
   22 #include <sys/types.h>
   23 #include <assert.h>
   24 #include <time.h>
   25 #include <sys/wait.h>
   26 #include <string.h>
   27 #include <limits.h>
   28 #include <libcitadel.h>
   29 #include "citadel.h"
   30 #include "server.h"
   31 #include "citserver.h"
   32 #include "support.h"
   33 #include "config.h"
   34 #include "msgbase.h"
   35 #include "user_ops.h"
   36 #include "ctdl_module.h"
   37 
   38 struct chatmsg {
   39     struct chatmsg *next;
   40     time_t timestamp;
   41     int seq;
   42     long roomnum;
   43     char *sender;
   44     char *msgtext;
   45 };
   46 
   47 struct chatmsg *first_chat_msg = NULL;
   48 struct chatmsg *last_chat_msg = NULL;
   49 
   50 
   51 /* 
   52  * Periodically called for housekeeping.  Expire old chat messages so they don't take up memory forever.
   53  */
   54 void roomchat_timer(void) {
   55     struct chatmsg *ptr;
   56 
   57     begin_critical_section(S_CHATQUEUE);
   58 
   59     while ((first_chat_msg != NULL) && ((time(NULL) - first_chat_msg->timestamp) > 300)) {
   60         ptr = first_chat_msg->next;
   61         free(first_chat_msg->sender);
   62         free(first_chat_msg->msgtext);
   63         free(first_chat_msg);
   64         first_chat_msg = ptr;
   65         if (first_chat_msg == NULL) {
   66             last_chat_msg = NULL;
   67         }
   68     }
   69 
   70     end_critical_section(S_CHATQUEUE);
   71 }
   72 
   73 
   74 /*
   75  * Perform shutdown-related activities...
   76  */
   77 void roomchat_shutdown(void) {
   78     /* if we ever start logging chats, we have to flush them to disk here .*/
   79 }
   80 
   81 
   82 /*
   83  * Add a message into the chat queue
   84  */
   85 void add_to_chat_queue(char *msg) {
   86     static int seq = 0;
   87 
   88     struct chatmsg *m = malloc(sizeof(struct chatmsg));
   89     if (!m) return;
   90 
   91     m->next = NULL;
   92     m->timestamp = time(NULL);
   93     m->roomnum = CC->room.QRnumber;
   94     m->sender = strdup(CC->user.fullname);
   95     m->msgtext = strdup(msg);
   96 
   97     if ((m->sender == NULL) || (m->msgtext == NULL)) {
   98         free(m->sender);
   99         free(m->msgtext);
  100         free(m);
  101         return;
  102     }
  103 
  104     begin_critical_section(S_CHATQUEUE);
  105     m->seq = ++seq;
  106 
  107     if (first_chat_msg == NULL) {
  108         assert(last_chat_msg == NULL);
  109         first_chat_msg = m;
  110         last_chat_msg = m;
  111     }
  112     else {
  113         assert(last_chat_msg != NULL);
  114         assert(last_chat_msg->next == NULL);
  115         last_chat_msg->next = m;
  116         last_chat_msg = m;
  117     }
  118 
  119     end_critical_section(S_CHATQUEUE);
  120 }
  121 
  122 
  123 /*
  124  * Transmit a message into a room chat
  125  */
  126 void roomchat_send(char *argbuf) {
  127     char buf[1024];
  128 
  129     if ((CC->cs_flags & CS_CHAT) == 0) {
  130         cprintf("%d Session is not in chat mode.\n", ERROR);
  131         return;
  132     }
  133 
  134     cprintf("%d send now\n", SEND_LISTING);
  135     while (client_getln(buf, sizeof buf) >= 0 && strcmp(buf, "000")) {
  136         add_to_chat_queue(buf);
  137     }
  138 }
  139 
  140 
  141 /*
  142  * Poll room for incoming chat messages
  143  */
  144 void roomchat_poll(char *argbuf) {
  145     int newer_than = 0;
  146     struct chatmsg *found = NULL;
  147     struct chatmsg *ptr = NULL;
  148 
  149     newer_than = extract_int(argbuf, 1);
  150 
  151     if ((CC->cs_flags & CS_CHAT) == 0) {
  152         cprintf("%d Session is not in chat mode.\n", ERROR);
  153         return;
  154     }
  155 
  156     begin_critical_section(S_CHATQUEUE);
  157     for (ptr = first_chat_msg; ((ptr != NULL) && (found == NULL)); ptr = ptr->next) {
  158         if ((ptr->seq > newer_than) && (ptr->roomnum == CC->room.QRnumber)) {
  159             found = ptr;
  160         }
  161     }
  162     end_critical_section(S_CHATQUEUE);
  163 
  164     if (found == NULL) {
  165         cprintf("%d no messages\n", ERROR + MESSAGE_NOT_FOUND);
  166         return;
  167     }
  168 
  169     cprintf("%d %d|%ld|%s\n", LISTING_FOLLOWS, found->seq, found->timestamp, found->sender);
  170     cprintf("%s\n", found->msgtext);
  171     cprintf("000\n");
  172 }
  173 
  174 
  175 
  176 /*
  177  * list users in chat in this room
  178  */
  179 void roomchat_rwho(char *argbuf) {
  180     struct CitContext *nptr;
  181     int nContexts, i;
  182 
  183     if ((CC->cs_flags & CS_CHAT) == 0) {
  184         cprintf("%d Session is not in chat mode.\n", ERROR);
  185         return;
  186     }
  187 
  188     cprintf("%d%c \n", LISTING_FOLLOWS, CtdlCheckExpress() );
  189     
  190     nptr = CtdlGetContextArray(&nContexts) ;        // grab a copy of the wholist
  191     if (nptr) {
  192         for (i=0; i<nContexts; i++)  {          // list the users
  193                 if ( (nptr[i].room.QRnumber == CC->room.QRnumber) 
  194                && (nptr[i].cs_flags & CS_CHAT)
  195             ) {
  196                 cprintf("%s\n", nptr[i].user.fullname);
  197             }
  198         }
  199         free(nptr);                 // free our copy
  200     }
  201 
  202     cprintf("000\n");
  203 }
  204 
  205 
  206 
  207 /*
  208  * Participate in real time chat in a room
  209  */
  210 void cmd_rcht(char *argbuf)
  211 {
  212     char subcmd[16];
  213 
  214     if (CtdlAccessCheck(ac_logged_in)) return;
  215 
  216     extract_token(subcmd, argbuf, 0, '|', sizeof subcmd);
  217 
  218     if (!strcasecmp(subcmd, "enter")) {
  219         CC->cs_flags |= CS_CHAT;
  220         cprintf("%d Entering chat mode.\n", CIT_OK);
  221     }
  222     else if (!strcasecmp(subcmd, "exit")) {
  223         CC->cs_flags &= ~CS_CHAT;
  224         cprintf("%d Exiting chat mode.\n", CIT_OK);
  225     }
  226     else if (!strcasecmp(subcmd, "send")) {
  227         roomchat_send(argbuf);
  228     }
  229     else if (!strcasecmp(subcmd, "poll")) {
  230         roomchat_poll(argbuf);
  231     }
  232     else if (!strcasecmp(subcmd, "rwho")) {
  233         roomchat_rwho(argbuf);
  234     }
  235     else {
  236         cprintf("%d Invalid subcommand\n", ERROR + CMD_NOT_SUPPORTED);
  237     }
  238 }
  239 
  240 
  241 CTDL_MODULE_INIT(roomchat)
  242 {
  243     if (!threading)
  244     {
  245         CtdlRegisterProtoHook(cmd_rcht, "RCHT", "Participate in real time chat in a room");
  246         CtdlRegisterSessionHook(roomchat_timer, EVT_TIMER, PRIO_CLEANUP + 400);
  247         CtdlRegisterSessionHook(roomchat_shutdown, EVT_SHUTDOWN, PRIO_SHUTDOWN + 55);
  248     }
  249     
  250     /* return our module name for the log */
  251     return "roomchat";
  252 }