8cb5662d89f846728c2b53140692325e18553b79
[citadel.git] / citadel / modules / xmpp / xmpp_queue.c
1 /*
2  * XMPP event queue
3  *
4  * Copyright (c) 2007-2009 by Art Cancro
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  *  
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  
17  *  
18  *  
19  *
20  */
21
22 #include "sysdep.h"
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <signal.h>
28 #include <pwd.h>
29 #include <errno.h>
30 #include <sys/types.h>
31
32 #if TIME_WITH_SYS_TIME
33 # include <sys/time.h>
34 # include <time.h>
35 #else
36 # if HAVE_SYS_TIME_H
37 #  include <sys/time.h>
38 # else
39 #  include <time.h>
40 # endif
41 #endif
42
43 #include <sys/wait.h>
44 #include <string.h>
45 #include <limits.h>
46 #include <ctype.h>
47 #include <expat.h>
48 #include <libcitadel.h>
49 #include "citadel.h"
50 #include "server.h"
51 #include "citserver.h"
52 #include "support.h"
53 #include "config.h"
54 #include "internet_addressing.h"
55 #include "md5.h"
56 #include "ctdl_module.h"
57 #include "serv_xmpp.h"
58
59 int queue_event_seq = 0;
60
61 void xmpp_queue_event(int event_type, char *email_addr) {
62
63         struct xmpp_event *xptr = NULL;
64         struct xmpp_event *new_event = NULL;
65         struct xmpp_event *last = NULL;
66         int purged_something = 0;
67         struct CitContext *cptr;
68
69         XMPP_syslog(LOG_DEBUG, "xmpp_queue_event(%d, %s)\n", event_type, email_addr);
70
71         /* Purge events more than a minute old */
72         begin_critical_section(S_XMPP_QUEUE);
73         do {
74                 purged_something = 0;
75                 if (xmpp_queue != NULL) {
76                         if ((time(NULL) - xmpp_queue->event_time) > 60) {
77                                 xptr = xmpp_queue->next;
78                                 free(xmpp_queue);
79                                 xmpp_queue = xptr;
80                                 purged_something = 1;
81                         }
82                 }
83         } while(purged_something);
84         end_critical_section(S_XMPP_QUEUE);
85
86         /* Create a new event */
87         new_event = (struct xmpp_event *) malloc(sizeof(struct xmpp_event));
88         new_event->next = NULL;
89         new_event->event_time = time(NULL);
90         new_event->event_seq = ++queue_event_seq;
91         new_event->event_type = event_type;
92         new_event->session_which_generated_this_event = CC->cs_pid;
93         safestrncpy(new_event->event_jid, email_addr, sizeof new_event->event_jid);
94
95         /* Add it to the list */
96         begin_critical_section(S_XMPP_QUEUE);
97         if (xmpp_queue == NULL) {
98                 xmpp_queue = new_event;
99         }
100         else {
101                 for (xptr = xmpp_queue; xptr != NULL; xptr = xptr->next) {
102                         if (xptr->next == NULL) {
103                                 last = xptr;
104                         }
105                 }
106                 last->next = new_event;
107         }
108         end_critical_section(S_XMPP_QUEUE);
109
110         /* Tell the sessions that something is happening */
111         begin_critical_section(S_SESSION_TABLE);
112         for (cptr = ContextList; cptr != NULL; cptr = cptr->next) {
113                 if ((cptr->logged_in) && (cptr->h_async_function == xmpp_async_loop)) {
114                         set_async_waiting(cptr);
115                 }
116         }
117         end_critical_section(S_SESSION_TABLE);
118 }
119
120
121 /* 
122  * Are we interested in anything from the queue?  (Called in async loop)
123  */
124 void xmpp_process_events(void) {
125         struct xmpp_event *xptr = NULL;
126         int highest_event = 0;
127
128         for (xptr=xmpp_queue; xptr!=NULL; xptr=xptr->next) {
129                 if (xptr->event_seq > XMPP->last_event_processed) {
130
131                         switch(xptr->event_type) {
132
133                                 case XMPP_EVT_LOGIN:
134                                 case XMPP_EVT_LOGOUT:
135                                         if (xptr->session_which_generated_this_event != CC->cs_pid) {
136                                                 xmpp_presence_notify(xptr->event_jid, xptr->event_type);
137                                         }
138                                         break;
139                         }
140
141                         if (xptr->event_seq > highest_event) {
142                                 highest_event = xptr->event_seq;
143                         }
144                 }
145         }
146
147         XMPP->last_event_processed = highest_event;
148 }
149
150
151 void xmpp_cleanup_events(void)
152 {
153         struct xmpp_event *ptr, *ptr2;
154         begin_critical_section(S_XMPP_QUEUE);
155         ptr = xmpp_queue;
156         xmpp_queue = NULL;
157         while (ptr != NULL) {
158                 ptr2 = ptr->next;
159                 free(ptr);
160                 ptr = ptr2;
161         }
162         end_critical_section(S_XMPP_QUEUE);
163
164 }