Libevent Migration
[citadel.git] / citadel / modules / eventclient / serv_evventclient.c
1 /*
2  * Copyright (c) 1998-2009 by the citadel.org team
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 3 of the License, or
7  *  (at your option) any later version.
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  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "sysdep.h"
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <termios.h>
24 #include <fcntl.h>
25 #include <signal.h>
26 #include <pwd.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <syslog.h>
30
31 #if TIME_WITH_SYS_TIME
32 # include <sys/time.h>
33 # include <time.h>
34 #else
35 # if HAVE_SYS_TIME_H
36 #  include <sys/time.h>
37 # else
38 #  include <time.h>
39 # endif
40 #endif
41 #include <sys/wait.h>
42 #include <ctype.h>
43 #include <string.h>
44 #include <limits.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #include <libcitadel.h>
49 #include "citadel.h"
50 #include "server.h"
51 #include "citserver.h"
52 #include "support.h"
53
54 #include "ctdl_module.h"
55
56 #ifdef EXPERIMENTAL_SMTP_EVENT_CLIENT
57
58 #include "event_client.h"
59
60 int event_add_pipe[2];
61
62 citthread_mutex_t EventQueueMutex; /* locks the access to the following vars: */
63 void *QueueEventAddPtr = NULL;
64 EventContextAttach EventContextAttachPtr;
65 AsyncIO *QueueThisIO;
66 HashList *QueueEvents = NULL;
67
68 static struct event_base *event_base;
69 struct event queue_add_event;
70
71 static void QueueEventAddCallback(int fd, short event, void *ctx)
72 {
73         char buf[10];
74
75         /* get the control command... */
76         read(fd, buf, 1);
77         switch (buf[0]) {
78         case '+':
79                 EventContextAttachPtr(QueueEventAddPtr);
80 /// TODO: add it to QueueEvents
81                 break;
82         case 'x':
83                 event_del(&queue_add_event);
84                 close(event_add_pipe[0]);
85 /// TODO; flush QueueEvents fd's and delete it.
86                 event_base_loopexit(event_base, NULL);
87         }
88         /* Unblock the other side */
89         read(fd, buf, 1);
90 }
91
92 /*
93  * this thread operates the select() etc. via libevent.
94  * 
95  * 
96  */
97 void *client_event_thread(void *arg) {
98         struct CitContext libevent_client_CC;
99         event_base = event_init();
100 /*
101         base = event_base_new();
102         if (!base)
103                 return NULL; /*XXXerr*/
104
105         citthread_mutex_init(&EventQueueMutex, NULL);
106         CtdlFillSystemContext(&libevent_client_CC, "LibEvent Thread");
107 //      citthread_setspecific(MyConKey, (void *)&smtp_queue_CC);
108         CtdlLogPrintf(CTDL_DEBUG, "client_event_thread() initializing\n");
109         
110         if (pipe(event_add_pipe) != 0) {
111                 CtdlLogPrintf(CTDL_EMERG, "Unable to create pipe for libevent queueing: %s\n", strerror(errno));
112                 abort();
113         }
114
115         event_set(&queue_add_event, 
116                   event_add_pipe[0], 
117                   EV_READ|EV_PERSIST,
118                   QueueEventAddCallback, 
119                   NULL);
120         
121         event_add(&queue_add_event, NULL);
122
123
124         event_dispatch();
125         CtdlClearSystemContext();
126         event_base_free(event_base);
127         citthread_mutex_destroy(&EventQueueMutex);
128         return(NULL);
129 }
130
131 #endif
132
133 CTDL_MODULE_INIT(event_client)
134 {
135 #ifdef EXPERIMENTAL_SMTP_EVENT_CLIENT
136         if (!threading)
137         {
138                 CtdlThreadCreate("Client event", CTDLTHREAD_BIGSTACK, client_event_thread, NULL);
139                 QueueEvents = NewHash(1, Flathash);
140 /// todo register shutdown callback.
141         }
142 #endif
143         return "event";
144 }