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 void ShutDownCLient(AsyncIO *IO)
128 event_del(&IO->send_event);
129 event_del(&IO->recv_event);
130 IO->Terminate(IO->Data);
132 // citthread_mutex_lock(&EventQueueMutex);
134 ///QueueEvents /// todo remove from hash.
136 // citthread_mutex_unlock(&EventQueueMutex);
139 eReadState HandleInbound(AsyncIO *IO)
141 eReadState Finished = eBufferNotEmpty;
143 while ((Finished == eBufferNotEmpty) && (IO->NextState == eReadMessage)){
144 if (IO->RecvBuf.nBlobBytesWanted != 0) {
147 else { /* Reading lines... */
148 //// lex line reply in callback, or do it ourselves. as nnn-blabla means continue reading in SMTP
150 Finished = IO->LineReader(IO);
152 Finished = StrBufChunkSipLine(IO->IOBuf, &IO->RecvBuf);
155 case eMustReadMore: /// read new from socket...
158 case eBufferNotEmpty: /* shouldn't happen... */
159 case eReadSuccess: /// done for now...
161 case eReadFail: /// WHUT?
168 if (Finished != eMustReadMore) {
169 event_del(&IO->recv_event);
170 IO->NextState = IO->ReadDone(IO->Data);
171 Finished = StrBufCheckBuffer(&IO->RecvBuf);
176 if ((IO->NextState == eSendReply) ||
177 (IO->NextState == eSendMore))
179 IO->NextState = IO->SendDone(IO->Data);
180 event_add(&IO->send_event, NULL);
183 else if ((IO->NextState == eTerminateConnection) ||
184 (IO->NextState == eAbort) )
191 IO_send_callback(int fd, short event, void *ctx)
199 /// assert(fd == IO->sock);
201 rc = StrBuf_write_one_chunk_callback(fd, event, &IO->SendBuf);
205 event_del(&IO->send_event);
206 switch (IO->NextState) {
210 IO->NextState = IO->SendDone(IO->Data);
212 if ((IO->NextState == eTerminateConnection) ||
213 (IO->NextState == eAbort) )
216 event_add(&IO->send_event, NULL);
219 if (StrBufCheckBuffer(&IO->RecvBuf) == eBufferNotEmpty) {
223 event_add(&IO->recv_event, NULL);
239 IO_recv_callback(int fd, short event, void *ctx)
244 // assert(fd == IO->sock);
246 // assert(fd == sb->fd);
248 nbytes = StrBuf_read_one_chunk_callback(fd, event, &IO->RecvBuf);
251 } else if (nbytes == 0) {
252 /// TODO: this is a timeout??? sock_buff_invoke_free(sb, 0);
254 } else if (nbytes == -1) {
255 /// TODO: FD is gone. kick it. sock_buff_invoke_free(sb, errno);
260 void IOReadNextLine(AsyncIO *IO, int timeout)
265 void IOReadNextBLOB(AsyncIO *IO, int timeout, long size)
269 void InitEventIO(AsyncIO *IO,
271 IO_CallBack ReadDone,
272 IO_CallBack SendDone,
273 IO_CallBack Terminate,
274 IO_LineReaderCallback LineReader,
278 IO->SendDone = SendDone;
279 IO->ReadDone = ReadDone;
280 IO->Terminate = Terminate;
281 IO->LineReader = LineReader;
283 event_set(&IO->recv_event,
289 event_set(&IO->send_event,
296 IO->NextState = eReadMessage;
297 event_add(&IO->recv_event, NULL);
300 IO->NextState = eSendReply;