3 * Copyright (c) 1998-2009 by the citadel.org team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <sys/types.h>
32 #if TIME_WITH_SYS_TIME
33 # include <sys/time.h>
37 # include <sys/time.h>
46 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
49 #include <libcitadel.h>
52 #include "citserver.h"
59 #include "internet_addressing.h"
62 #include "clientsocket.h"
63 #include "locate_host.h"
64 #include "citadel_dirs.h"
66 #ifdef EXPERIMENTAL_SMTP_EVENT_CLIENT
69 #include "event_client.h"
71 extern int event_add_pipe[2];
72 extern citthread_mutex_t EventQueueMutex;
73 extern void *QueueEventAddPtr;
74 extern AsyncIO *QueueThisIO;
75 extern EventContextAttach EventContextAttachPtr;
77 int QueueEventContext(void *Ctx, AsyncIO *IO, EventContextAttach CB)
79 citthread_mutex_lock(&EventQueueMutex);
81 QueueEventAddPtr = Ctx;
82 EventContextAttachPtr = CB;
85 write(event_add_pipe[1], "+_", 1);
86 citthread_mutex_unlock(&EventQueueMutex);
91 int ShutDownEventQueue(void)
93 write(event_add_pipe[1], "x_", 1);
94 close(event_add_pipe[1]);
102 setup_signal_handlers(struct instance *instance)
104 signal(SIGPIPE, SIG_IGN);
106 event_set(&instance->sigterm_event, SIGTERM, EV_SIGNAL|EV_PERSIST,
107 exit_event_callback, instance);
108 event_add(&instance->sigterm_event, NULL);
110 event_set(&instance->sigint_event, SIGINT, EV_SIGNAL|EV_PERSIST,
111 exit_event_callback, instance);
112 event_add(&instance->sigint_event, NULL);
114 event_set(&instance->sigquit_event, SIGQUIT, EV_SIGNAL|EV_PERSIST,
115 exit_event_callback, instance);
116 event_add(&instance->sigquit_event, NULL);
120 eReadState HandleInbound(AsyncIO *IO)
122 eReadState Finished = eBufferNotEmpty;
124 while ((Finished == eBufferNotEmpty) && (IO->NextState == eReadMessage)){
125 if (IO->RecvBuf.nBlobBytesWanted != 0) {
128 else { /* Reading lines... */
129 //// lex line reply in callback, or do it ourselves. as nnn-blabla means continue reading in SMTP
131 Finished = IO->LineReader(IO);
133 Finished = StrBufChunkSipLine(IO->IOBuf, &IO->RecvBuf);
136 case eMustReadMore: /// read new from socket...
139 case eBufferNotEmpty: /* shouldn't happen... */
140 case eReadSuccess: /// done for now...
142 case eReadFail: /// WHUT?
149 if (Finished != eMustReadMore) {
150 event_del(&IO->recv_event);
151 IO->NextState = IO->ReadDone(IO->Data);
152 Finished = StrBufCheckBuffer(&IO->RecvBuf);
157 if ((IO->NextState == eSendReply) ||
158 (IO->NextState == eSendMore))
160 IO->NextState = IO->SendDone(IO->Data);
161 event_add(&IO->send_event, NULL);
169 IO_send_callback(int fd, short event, void *ctx)
177 /// assert(fd == IO->sock);
179 rc = StrBuf_write_one_chunk_callback(fd, event, &IO->SendBuf);
183 event_del(&IO->send_event);
184 switch (IO->NextState) {
188 IO->NextState = IO->SendDone(IO->Data);
189 event_add(&IO->send_event, NULL);
192 if (StrBufCheckBuffer(&IO->RecvBuf) == eBufferNotEmpty) {
196 event_add(&IO->recv_event, NULL);
212 IO_recv_callback(int fd, short event, void *ctx)
217 // assert(fd == IO->sock);
219 // assert(fd == sb->fd);
221 nbytes = StrBuf_read_one_chunk_callback(fd, event, &IO->RecvBuf);
224 } else if (nbytes == 0) {
225 /// TODO: this is a timeout??? sock_buff_invoke_free(sb, 0);
227 } else if (nbytes == -1) {
228 /// TODO: FD is gone. kick it. sock_buff_invoke_free(sb, errno);
233 void IOReadNextLine(AsyncIO *IO, int timeout)
238 void IOReadNextBLOB(AsyncIO *IO, int timeout, long size)
242 void InitEventIO(AsyncIO *IO,
244 IO_CallBack ReadDone,
245 IO_CallBack SendDone,
246 IO_LineReaderCallback LineReader,
250 IO->SendDone = SendDone;
251 IO->ReadDone = ReadDone;
252 IO->LineReader = LineReader;
254 event_set(&IO->recv_event,
260 event_set(&IO->send_event,
267 IO->NextState = eReadMessage;
268 event_add(&IO->recv_event, NULL);
271 IO->NextState = eSendReply;