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]);
98 void FreeAsyncIOContents(AsyncIO *IO)
100 FreeStrBuf(&IO->IOBuf);
101 FreeStrBuf(&IO->SendBuf.Buf);
102 FreeStrBuf(&IO->RecvBuf.Buf);
108 setup_signal_handlers(struct instance *instance)
110 signal(SIGPIPE, SIG_IGN);
112 event_set(&instance->sigterm_event, SIGTERM, EV_SIGNAL|EV_PERSIST,
113 exit_event_callback, instance);
114 event_add(&instance->sigterm_event, NULL);
116 event_set(&instance->sigint_event, SIGINT, EV_SIGNAL|EV_PERSIST,
117 exit_event_callback, instance);
118 event_add(&instance->sigint_event, NULL);
120 event_set(&instance->sigquit_event, SIGQUIT, EV_SIGNAL|EV_PERSIST,
121 exit_event_callback, instance);
122 event_add(&instance->sigquit_event, NULL);
126 eReadState HandleInbound(AsyncIO *IO)
128 eReadState Finished = eBufferNotEmpty;
130 while ((Finished == eBufferNotEmpty) && (IO->NextState == eReadMessage)){
131 if (IO->RecvBuf.nBlobBytesWanted != 0) {
134 else { /* Reading lines... */
135 //// lex line reply in callback, or do it ourselves. as nnn-blabla means continue reading in SMTP
137 Finished = IO->LineReader(IO);
139 Finished = StrBufChunkSipLine(IO->IOBuf, &IO->RecvBuf);
142 case eMustReadMore: /// read new from socket...
145 case eBufferNotEmpty: /* shouldn't happen... */
146 case eReadSuccess: /// done for now...
148 case eReadFail: /// WHUT?
155 if (Finished != eMustReadMore) {
156 event_del(&IO->recv_event);
157 IO->NextState = IO->ReadDone(IO->Data);
158 Finished = StrBufCheckBuffer(&IO->RecvBuf);
163 if ((IO->NextState == eSendReply) ||
164 (IO->NextState == eSendMore))
166 IO->NextState = IO->SendDone(IO->Data);
167 event_add(&IO->send_event, NULL);
170 else if ((IO->NextState == eTerminateConnection) ||
171 (IO->NextState == eAbort) )
181 IO_send_callback(int fd, short event, void *ctx)
189 /// assert(fd == IO->sock);
191 rc = StrBuf_write_one_chunk_callback(fd, event, &IO->SendBuf);
195 event_del(&IO->send_event);
196 switch (IO->NextState) {
200 IO->NextState = IO->SendDone(IO->Data);
201 event_add(&IO->send_event, NULL);
204 if (StrBufCheckBuffer(&IO->RecvBuf) == eBufferNotEmpty) {
208 event_add(&IO->recv_event, NULL);
224 IO_recv_callback(int fd, short event, void *ctx)
229 // assert(fd == IO->sock);
231 // assert(fd == sb->fd);
233 nbytes = StrBuf_read_one_chunk_callback(fd, event, &IO->RecvBuf);
236 } else if (nbytes == 0) {
237 /// TODO: this is a timeout??? sock_buff_invoke_free(sb, 0);
239 } else if (nbytes == -1) {
240 /// TODO: FD is gone. kick it. sock_buff_invoke_free(sb, errno);
245 void IOReadNextLine(AsyncIO *IO, int timeout)
250 void IOReadNextBLOB(AsyncIO *IO, int timeout, long size)
254 void InitEventIO(AsyncIO *IO,
256 IO_CallBack ReadDone,
257 IO_CallBack SendDone,
258 IO_LineReaderCallback LineReader,
262 IO->SendDone = SendDone;
263 IO->ReadDone = ReadDone;
264 IO->LineReader = LineReader;
266 event_set(&IO->recv_event,
272 event_set(&IO->send_event,
279 IO->NextState = eReadMessage;
280 event_add(&IO->recv_event, NULL);
283 IO->NextState = eSendReply;