4 * This module handles instant messaging between users.
6 * Copyright (c) 2010 by the citadel.org team
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include <sys/types.h>
34 #if TIME_WITH_SYS_TIME
35 # include <sys/time.h>
39 # include <sys/time.h>
48 #include <libcitadel.h>
51 #include "citserver.h"
61 #include "ctdl_module.h"
73 struct chatmsg *first_chat_msg = NULL;
74 struct chatmsg *last_chat_msg = NULL;
78 * Periodically called for housekeeping. Expire old chat messages so they don't take up memory forever.
80 void roomchat_timer(void) {
83 begin_critical_section(S_CHATQUEUE);
85 while ((first_chat_msg != NULL) && ((time(NULL) - first_chat_msg->timestamp) > 300)) {
86 ptr = first_chat_msg->next;
87 free(first_chat_msg->sender);
88 free(first_chat_msg->msgtext);
91 if (first_chat_msg == NULL) {
96 end_critical_section(S_CHATQUEUE);
101 * Perform shutdown-related activities...
103 void roomchat_shutdown(void) {
104 /* if we ever start logging chats, we have to flush them to disk here .*/
109 * Add a message into the chat queue
111 void add_to_chat_queue(char *msg) {
114 struct chatmsg *m = malloc(sizeof(struct chatmsg));
118 m->timestamp = time(NULL);
119 m->roomnum = CC->room.QRnumber;
120 m->sender = strdup(CC->user.fullname);
121 m->msgtext = strdup(msg);
123 if ((m->sender == NULL) || (m->msgtext == NULL)) {
130 begin_critical_section(S_CHATQUEUE);
133 if (first_chat_msg == NULL) {
134 assert(last_chat_msg == NULL);
139 assert(last_chat_msg != NULL);
140 assert(last_chat_msg->next == NULL);
141 last_chat_msg->next = m;
145 end_critical_section(S_CHATQUEUE);
150 * Transmit a message into a room chat
152 void roomchat_send(char *argbuf) {
155 if ((CC->cs_flags & CS_CHAT) == 0) {
156 cprintf("%d Session is not in chat mode.\n", ERROR);
160 cprintf("%d send now\n", SEND_LISTING);
161 while (client_getln(buf, sizeof buf) >= 0 && strcmp(buf, "000")) {
162 add_to_chat_queue(buf);
168 * Poll room for incoming chat messages
170 void roomchat_poll(char *argbuf) {
172 struct chatmsg *found = NULL;
173 struct chatmsg *ptr = NULL;
175 newer_than = extract_int(argbuf, 1);
177 if (!CC->cs_flags & CS_CHAT) {
178 cprintf("%d Session is not in chat mode.\n", ERROR);
182 begin_critical_section(S_CHATQUEUE);
183 for (ptr = first_chat_msg; ((ptr != NULL) && (found == NULL)); ptr = ptr->next) {
184 if ((ptr->seq > newer_than) && (ptr->roomnum == CC->room.QRnumber)) {
188 end_critical_section(S_CHATQUEUE);
191 cprintf("%d no messages\n", ERROR + MESSAGE_NOT_FOUND);
195 cprintf("%d %d|%ld|%s\n", LISTING_FOLLOWS, found->seq, found->timestamp, found->sender);
196 cprintf("%s\n", found->msgtext);
202 * Participate in real time chat in a room
204 void cmd_rcht(char *argbuf)
208 if (CtdlAccessCheck(ac_logged_in)) return;
210 extract_token(subcmd, argbuf, 0, '|', sizeof subcmd);
212 if (!strcasecmp(subcmd, "enter")) {
213 CC->cs_flags |= CS_CHAT;
214 cprintf("%d Entering chat mode.\n", CIT_OK);
216 else if (!strcasecmp(subcmd, "exit")) {
217 CC->cs_flags &= ~CS_CHAT;
218 cprintf("%d Exiting chat mode.\n", CIT_OK);
220 else if (!strcasecmp(subcmd, "send")) {
221 roomchat_send(argbuf);
223 else if (!strcasecmp(subcmd, "poll")) {
224 roomchat_poll(argbuf);
227 cprintf("%d Invalid subcommand\n", ERROR + CMD_NOT_SUPPORTED);
232 CTDL_MODULE_INIT(roomchat)
236 CtdlRegisterProtoHook(cmd_rcht, "RCHT", "Participate in real time chat in a room");
237 CtdlRegisterSessionHook(roomchat_timer, EVT_TIMER);
238 CtdlRegisterSessionHook(roomchat_shutdown, EVT_SHUTDOWN);
241 /* return our Subversion id for the Log */