[IOMultiplexerV2] coding style fixes
[NextIRCd.git] / src / IOHandler / IOSockets.c
1 /* IOSockets.c - IOMultiplexer v2
2  * Copyright (C) 2014  Philipp Kreil (pk910)
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, see <http://www.gnu.org/licenses/>. 
16  */
17 #define _IOHandler_internals
18 #include "IOInternal.h"
19 #include "IOHandler.h"
20 #include "IOSockets.h"
21 #include "IOLog.h"
22 #include "IODNSLookup.h"
23 #include "IOSSLBackend.h"
24
25 #ifdef WIN32
26 #define _WIN32_WINNT 0x501
27 #include <windows.h>
28 #include <winsock2.h>
29 #include <ws2tcpip.h>
30 #else
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <netinet/ip.h> 
34 #include <arpa/inet.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #endif
38 #include "compat/inet.h"
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <signal.h>
43 #include <errno.h>
44 #include <stdarg.h>
45
46 #ifndef EWOULDBLOCK
47 #define EWOULDBLOCK EAGAIN
48 #endif
49
50 struct _IOSocket *iosocket_first = NULL;
51 struct _IOSocket *iosocket_last = NULL;
52
53 struct IOEngine *engine = NULL;
54
55 static void iosocket_increase_buffer(struct IOSocketBuffer *iobuf, size_t required);
56 static int iosocket_parse_address(const char *hostname, struct IODNSAddress *addr, int records);
57 static int iosocket_lookup_hostname(struct _IOSocket *iosock, const char *hostname, int records, int bindaddr);
58 static int iosocket_lookup_apply(struct _IOSocket *iosock, int noip6);
59 static void socket_lookup_clear(struct _IOSocket *iosock);
60 static void iosocket_connect_finish(struct _IOSocket *iosock);
61 static void iosocket_listen_finish(struct _IOSocket *iosock);
62 static int iosocket_try_write(struct _IOSocket *iosock);
63 static void iosocket_trigger_event(struct IOSocketEvent *event);
64
65 #ifdef WIN32
66 static int close(int fd) {
67         return closesocket(fd);
68 }
69 #endif
70
71 static void iosockets_init_engine() {
72         //try other engines
73         if(!engine && engine_kevent.init && engine_kevent.init())
74                 engine = &engine_kevent;
75         if(!engine && engine_epoll.init && engine_epoll.init())
76                 engine = &engine_epoll;
77         if(!engine && engine_win32.init && engine_win32.init())
78                 engine = &engine_win32;
79         
80         if (!engine) {
81                 if(engine_select.init())
82                         engine = &engine_select;
83                 else {
84                         iolog_trigger(IOLOG_FATAL, "found no useable IO engine");
85                         return;
86                 }
87         }
88         iolog_trigger(IOLOG_DEBUG, "using %s IOSockets engine", engine->name);
89 }
90
91 void _init_sockets() {
92         #ifdef WIN32
93         WSADATA wsaData;
94         int iResult;
95         //Initialize Winsock
96         iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
97         if(iResult != 0){
98                 iolog_trigger(IOLOG_ERROR, "WSAStartup returned error code: %d", iResult);
99         }
100         #endif
101         
102         iosockets_init_engine();\r
103         iossl_init();
104 }
105
106
107 struct _IOSocket *_create_socket() {
108         struct _IOSocket *iosock = calloc(1, sizeof(*iosock));
109         if(!iosock) {
110                 iolog_trigger(IOLOG_ERROR, "could not allocate memory for _IOSocket in %s:%d", __FILE__, __LINE__);
111                 return NULL;
112         }
113         if(iosocket_last)
114                 iosocket_last->next = iosock;
115         else
116                 iosocket_first = iosock;
117         iosock->prev = iosocket_last;
118         iosocket_last = iosock;
119         return iosock;
120 }
121
122 void _free_socket(struct _IOSocket *iosock) {
123         iosocket_deactivate(iosock);
124         if(iosock->prev)
125                 iosock->prev->next = iosock->next;
126         else
127                 iosocket_first = iosock->next;
128         if(iosock->next)
129                 iosock->next->prev = iosock->prev;
130         else
131                 iosocket_last = iosock->prev;
132         
133         if(iosock->bind.addr.addresslen)
134                 free(iosock->bind.addr.address);
135         if(iosock->dest.addr.addresslen)
136                 free(iosock->dest.addr.address);
137         if(iosock->bind.addrlookup || iosock->dest.addrlookup)
138                 socket_lookup_clear(iosock);
139         if(iosock->readbuf.buffer)
140                 free(iosock->readbuf.buffer);
141         if(iosock->writebuf.buffer)
142                 free(iosock->writebuf.buffer);
143         if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))\r
144                 iossl_disconnect(iosock);\r
145         
146         free(iosock);
147 }
148
149 void iosocket_activate(struct _IOSocket *iosock) {
150         if((iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
151                 return;
152         iosock->socket_flags |= IOSOCKETFLAG_ACTIVE;
153         engine->add(iosock);
154 }
155
156 void iosocket_deactivate(struct _IOSocket *iosock) {
157         if(!(iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
158                 return;
159         iosock->socket_flags &= ~IOSOCKETFLAG_ACTIVE;
160         engine->remove(iosock);
161 }
162
163 void iosocket_update(struct _IOSocket *iosock) {
164         if(!(iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
165                 return;
166         engine->update(iosock);
167 }
168
169 static void iosocket_increase_buffer(struct IOSocketBuffer *iobuf, size_t required) {
170         if(iobuf->buflen >= required) return;
171         char *new_buf;
172         if(iobuf->buffer)
173                 new_buf = realloc(iobuf->buffer, required + 2);
174         else
175                 new_buf = malloc(required + 2);
176         if(new_buf) {
177                 iobuf->buffer = new_buf;
178                 iobuf->buflen = required;
179         }
180 }
181
182 static int iosocket_parse_address(const char *hostname, struct IODNSAddress *addr, int records) {
183         int ret;
184         if((records & IOSOCKET_ADDR_IPV4)) {
185                 struct sockaddr_in ip4addr;
186                 ret = inet_pton(AF_INET, hostname, &(ip4addr.sin_addr));
187                 if(ret == 1) {
188                         addr->addresslen = sizeof(ip4addr);
189                         addr->address = malloc(addr->addresslen);
190                         if(!addr->address) {
191                                 iolog_trigger(IOLOG_ERROR, "could not allocate memory for sockaddr in %s:%d", __FILE__, __LINE__);
192                                 return -1;
193                         }
194                         memcpy(addr->address, &ip4addr, sizeof(ip4addr));
195                         return 1;
196                 }
197         }
198         if((records & IOSOCKET_ADDR_IPV6)) {
199                 struct sockaddr_in6 ip6addr;
200                 ret = inet_pton(AF_INET6, hostname, &(ip6addr.sin6_addr));
201                 if(ret == 1) {
202                         addr->addresslen = sizeof(ip6addr);
203                         addr->address = malloc(addr->addresslen);
204                         if(!addr->address) {
205                                 iolog_trigger(IOLOG_ERROR, "could not allocate memory for sockaddr in %s:%d", __FILE__, __LINE__);
206                                 return -1;
207                         }
208                         memcpy(addr->address, &ip6addr, sizeof(ip6addr));
209                         return 1;
210                 }
211         }
212         return 0;
213 }
214
215 static int iosocket_lookup_hostname(struct _IOSocket *iosock, const char *hostname, int records, int bindaddr) {
216         struct IOSocketDNSLookup *lookup = calloc(1, sizeof(*lookup));
217         if(!lookup) {
218                 iolog_trigger(IOLOG_ERROR, "could not allocate memory for IOSocketDNSLookup in %s:%d", __FILE__, __LINE__);
219                 return 0;
220         }
221         
222         struct _IODNSQuery *query = _create_dnsquery();
223         if(!query) {
224                 free(lookup);
225                 return 0;
226         }
227         
228         query->parent = lookup;
229         query->flags |= IODNSFLAG_PARENT_SOCKET;
230         lookup->iosocket = iosock;
231         lookup->query = query;
232         strncpy(lookup->hostname, hostname, sizeof(lookup->hostname));
233         lookup->hostname[sizeof(lookup->hostname)-1] = 0;
234         if(bindaddr) {
235                 lookup->bindlookup = 1;
236                 iosock->bind.addrlookup = lookup;
237         } else {
238                 lookup->bindlookup = 0;
239                 iosock->dest.addrlookup = lookup;
240         }
241         
242         int dnsrecords = 0;
243         if((records & IOSOCKET_ADDR_IPV4))
244                 dnsrecords |= IODNS_RECORD_A;
245         if((records & IOSOCKET_ADDR_IPV6))
246                 dnsrecords |= IODNS_RECORD_AAAA;
247         
248         query->request.host = strdup(hostname);
249         query->type = (dnsrecords & IODNS_FORWARD);
250         
251         _start_dnsquery(query);
252         return 1;
253 }
254
255 void iosocket_lookup_callback(struct IOSocketDNSLookup *lookup, struct IODNSEvent *event) {
256         lookup->query = NULL;
257         struct _IOSocket *iosock = lookup->iosocket;
258         if(iosock == NULL)
259                 return;
260         
261         if(event->type == IODNSEVENT_SUCCESS)
262                 lookup->result = event->result;
263         else
264                 lookup->result = NULL;
265         
266         if(lookup->bindlookup) {
267                 iosock->socket_flags &= ~IOSOCKETFLAG_PENDING_BINDDNS;
268                 iosock->socket_flags |= IOSOCKETFLAG_DNSDONE_BINDDNS;
269         } else {
270                 iosock->socket_flags &= ~IOSOCKETFLAG_PENDING_DESTDNS;
271                 iosock->socket_flags |= IOSOCKETFLAG_DNSDONE_DESTDNS;
272         }
273         
274         int dns_finished = 0;
275         if((iosock->socket_flags & (IOSOCKETFLAG_PENDING_BINDDNS | IOSOCKETFLAG_PENDING_DESTDNS)) == 0)
276                 dns_finished = 1;
277         
278         if(dns_finished) {
279                 int ret;
280                 ret = iosocket_lookup_apply(iosock, 0);
281                 if(ret) { //if ret=0 an error occured in iosocket_lookup_apply and we should stop here.
282                         if((iosock->socket_flags & IOSOCKETFLAG_LISTENING)) {
283                                 socket_lookup_clear(iosock);
284                                 iosocket_listen_finish(iosock);
285                         } else
286                                 iosocket_connect_finish(iosock);
287                 }
288         }
289 }
290
291 static int iosocket_lookup_apply(struct _IOSocket *iosock, int noip6) {
292         char errbuf[512];
293         struct IOSocketDNSLookup *bind_lookup = ((iosock->socket_flags & IOSOCKETFLAG_DNSDONE_BINDDNS) ? iosock->bind.addrlookup : NULL);
294         struct IOSocketDNSLookup *dest_lookup = ((iosock->socket_flags & IOSOCKETFLAG_DNSDONE_DESTDNS) ? iosock->dest.addrlookup : NULL);
295         
296         iolog_trigger(IOLOG_DEBUG, "all pending lookups finished. trying to apply lookup results...");
297         
298         if(!bind_lookup && !dest_lookup) {
299                 iosock->socket_flags |= IOSOCKETFLAG_DNSERROR;
300                 sprintf(errbuf, "Internal Error");
301                 iolog_trigger(IOLOG_ERROR, "trying to apply lookup results without any lookups processed in %s:%d", __FILE__, __LINE__);
302                 goto iosocket_lookup_apply_end;
303         }
304         
305         struct IODNSResult *result;
306         int bind_numip4 = 0, bind_numip6 = 0;
307         int dest_numip4 = 0, dest_numip6 = 0;
308         
309         if(bind_lookup) {
310                 for(result = bind_lookup->result; result; result = result->next) {
311                         if((result->type & IODNS_RECORD_A))
312                                 bind_numip4++;
313                         if((result->type & IODNS_RECORD_AAAA))
314                                 bind_numip6++;
315                 }
316         }
317         if(dest_lookup) {
318                 for(result = dest_lookup->result; result; result = result->next) {
319                         if((result->type & IODNS_RECORD_A))
320                                 dest_numip4++;
321                         if((result->type & IODNS_RECORD_AAAA))
322                                 dest_numip6++;
323                 }
324         }
325         int useip6 = 0;
326         int useip4 = 0;
327         if(bind_lookup && (bind_numip6 == 0 && bind_numip4 == 0)) {
328                 iosock->socket_flags |= IOSOCKETFLAG_DNSERROR;
329                 sprintf(errbuf, "could not lookup bind address (%s)", bind_lookup->hostname);
330                 goto iosocket_lookup_apply_end;
331         } else if(dest_lookup && (dest_numip6 == 0 && dest_numip4 == 0)) {
332                 iosock->socket_flags |= IOSOCKETFLAG_DNSERROR;
333                 sprintf(errbuf, "could not lookup destination address (%s)", dest_lookup->hostname);
334                 goto iosocket_lookup_apply_end;
335         } else if(bind_lookup && dest_lookup) {
336                 if(bind_numip6 > 0 && dest_numip6 > 0)
337                         useip6 = 1;
338                 if(bind_numip4 > 0 && dest_numip4 > 0)
339                         useip4 = 1;
340         } else if(bind_lookup) {
341                 if(bind_numip6)
342                         useip6 = 1;
343                 if(bind_numip4)
344                         useip4 = 1;
345         } else if(dest_lookup) {
346                 if(dest_numip6)
347                         useip6 = 1;
348                 if(dest_numip4)
349                         useip4 = 1;
350         }
351         
352         int usetype = 0;
353         if(useip6 && !noip6) {
354                 usetype = IODNS_RECORD_AAAA;
355                 iosock->socket_flags |= IOSOCKETFLAG_IPV6SOCKET;
356                 if(useip4)
357                         iosock->socket_flags |= IOSOCKETFLAG_RECONNECT_IPV4;
358         } else if(useip4) {
359                 usetype = IODNS_RECORD_A;
360                 iosock->socket_flags &= ~(IOSOCKETFLAG_IPV6SOCKET | IOSOCKETFLAG_RECONNECT_IPV4);
361         } else {
362                 iosock->socket_flags |= IOSOCKETFLAG_DNSERROR;
363                 sprintf(errbuf, "could not lookup adresses of the same IP family for bind and destination host. (bind: %d ip4, %d ip6 | dest: %d ip4, %d ip6)", bind_numip4, bind_numip6, dest_numip4, dest_numip6);
364                 goto iosocket_lookup_apply_end;
365         }
366         
367         #define IOSOCKET_APPLY_COPYADDR(type) \
368         iosock->type.addr.addresslen = result->result.addr.addresslen; \
369         iosock->type.addr.address = malloc(result->result.addr.addresslen); \
370         if(!iosock->type.addr.address) { \
371                 iolog_trigger(IOLOG_ERROR, "could not allocate memory for sockaddr in %s:%d", __FILE__, __LINE__); \
372                 iosock->type.addr.addresslen = 0; \
373                 iosock->socket_flags |= IOSOCKETFLAG_DNSERROR; \
374                 sprintf(errbuf, "could not allocate memory for dns information"); \
375                 goto iosocket_lookup_apply_end; \
376         } \
377         memcpy(iosock->type.addr.address, result->result.addr.address, result->result.addr.addresslen);
378         
379         
380         if(bind_lookup) {
381                 int usenum = ((usetype == IODNS_RECORD_AAAA) ? bind_numip6 : bind_numip4);
382                 usenum = rand() % usenum;
383                 for(result = bind_lookup->result; result; result = result->next) {
384                         if((result->type & usetype)) {
385                                 if(usenum == 0) {
386                                         inet_ntop(((usetype == IODNS_RECORD_AAAA) ? AF_INET6 : AF_INET), ((usetype == IODNS_RECORD_AAAA) ? (void *)(&((struct sockaddr_in6 *)result->result.addr.address)->sin6_addr) : (void *)(&((struct sockaddr_in *)result->result.addr.address)->sin_addr)), errbuf, sizeof(errbuf));
387                                         iolog_trigger(IOLOG_DEBUG, "using IPv%s Address (%s) as bind address", ((usetype == IODNS_RECORD_AAAA) ? "6" : "4"), errbuf);
388                                         IOSOCKET_APPLY_COPYADDR(bind)
389                                         break;
390                                 }
391                                 usenum--;
392                         }
393                 }
394         } else
395                 iosock->bind.addr.addresslen = 0;
396         
397         if(dest_lookup) {
398                 int usenum = ((usetype == IODNS_RECORD_AAAA) ? dest_numip6 : dest_numip4);
399                 usenum = rand() % usenum;
400                 for(result = dest_lookup->result; result; result = result->next) {
401                         if((result->type & usetype)) {
402                                 if(usenum == 0) {
403                                         inet_ntop(((usetype == IODNS_RECORD_AAAA) ? AF_INET6 : AF_INET), ((usetype == IODNS_RECORD_AAAA) ? (void *)(&((struct sockaddr_in6 *)result->result.addr.address)->sin6_addr) : (void *)(&((struct sockaddr_in *)result->result.addr.address)->sin_addr)), errbuf, sizeof(errbuf));
404                                         iolog_trigger(IOLOG_DEBUG, "using IPv%s Address (%s) as dest address", ((usetype == IODNS_RECORD_AAAA) ? "6" : "4"), errbuf);
405                                         IOSOCKET_APPLY_COPYADDR(dest)
406                                         break;
407                                 }
408                                 usenum--;
409                         }
410                 }
411         } else
412                 iosock->dest.addr.addresslen = 0;
413         
414         iosocket_lookup_apply_end:
415         
416         if((iosock->socket_flags & IOSOCKETFLAG_DNSERROR)) {
417                 // TODO: trigger error
418                 iolog_trigger(IOLOG_ERROR, "error while trying to apply dns lookup information: %s", errbuf);
419                 
420                 if((iosock->socket_flags & IOSOCKETFLAG_PARENT_PUBLIC)) {
421                         //trigger event
422                         struct IOSocket *iosocket = iosock->parent;
423                         
424                         struct IOSocketEvent callback_event;
425                         callback_event.type = IOSOCKETEVENT_DNSFAILED;
426                         callback_event.socket = iosocket;
427                         callback_event.data.recv_str = errbuf;
428                         iosocket_trigger_event(&callback_event);
429                         
430                         iosocket_close(iosocket);
431                 } else {
432                         // TODO: IODNS Callback
433                 }
434                 return 0;
435         } else
436                 return 1;
437 }
438
439 static void socket_lookup_clear(struct _IOSocket *iosock) {
440         struct IOSocketDNSLookup *bind_lookup = ((iosock->socket_flags & IOSOCKETFLAG_DNSDONE_BINDDNS) ? iosock->bind.addrlookup : NULL);
441         struct IOSocketDNSLookup *dest_lookup = ((iosock->socket_flags & IOSOCKETFLAG_DNSDONE_DESTDNS) ? iosock->dest.addrlookup : NULL);
442         if(bind_lookup) {
443                 if(bind_lookup->result)
444                         iodns_free_result(bind_lookup->result);
445                 free(bind_lookup);
446                 iosock->bind.addrlookup = NULL;
447         }
448         if(dest_lookup) {
449                 if(dest_lookup->result)
450                         iodns_free_result(dest_lookup->result);
451                 free(dest_lookup);
452                 iosock->dest.addrlookup = NULL;
453         }
454 }
455
456 static void iosocket_prepare_fd(int sockfd) {
457         // prevent SIGPIPE
458         #ifndef WIN32
459         #if defined(SO_NOSIGPIPE)
460         {
461                 int set = 1;
462                 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
463         }
464         #else
465         signal(SIGPIPE, SIG_IGN);
466         #endif
467         #endif
468         
469         // make sockfd unblocking
470         #if defined(F_GETFL)
471         {
472                 int fcntl_flags;
473                 fcntl_flags = fcntl(sockfd, F_GETFL);
474                 fcntl(sockfd, F_SETFL, fcntl_flags|O_NONBLOCK);
475                 fcntl_flags = fcntl(sockfd, F_GETFD);
476                 fcntl(sockfd, F_SETFD, fcntl_flags|FD_CLOEXEC);
477         }
478         #elif defined(FIONBIO)
479         {
480                 unsigned long ulong = 1;
481                 ioctlsocket(sockfd, FIONBIO, &ulong);
482         }
483         #endif
484 }
485
486 static void iosocket_connect_finish(struct _IOSocket *iosock) {
487         int sockfd;
488         if((iosock->socket_flags & IOSOCKETFLAG_IPV6SOCKET))
489                 sockfd = socket(AF_INET6, SOCK_STREAM, 0);
490         else
491                 sockfd = socket(AF_INET, SOCK_STREAM, 0);
492         if(sockfd == -1) {
493                 iolog_trigger(IOLOG_ERROR, "could not create socket in %s:%d", __FILE__, __LINE__);
494                 // TODO: trigger error
495                 
496                 return;
497         }
498         
499         // set port and bind address
500         if((iosock->socket_flags & IOSOCKETFLAG_IPV6SOCKET)) {
501                 struct sockaddr_in6 *ip6 = (void*) iosock->dest.addr.address;
502                 ip6->sin6_family = AF_INET6;
503                 ip6->sin6_port = htons(iosock->port);
504                 
505                 if(iosock->bind.addr.addresslen) {
506                         struct sockaddr_in6 *ip6bind = (void*) iosock->bind.addr.address;
507                         ip6bind->sin6_family = AF_INET6;
508                         ip6bind->sin6_port = htons(0);
509                         
510                         bind(sockfd, (struct sockaddr*)ip6bind, sizeof(*ip6bind));
511                 }
512         } else {
513                 struct sockaddr_in *ip4 = (void*) iosock->dest.addr.address;
514                 ip4->sin_family = AF_INET;
515                 ip4->sin_port = htons(iosock->port);
516                 
517                 if(iosock->bind.addr.addresslen) {
518                         struct sockaddr_in *ip4bind = (void*) iosock->bind.addr.address;
519                         ip4bind->sin_family = AF_INET;
520                         ip4bind->sin_port = htons(0);
521                         
522                         bind(sockfd, (struct sockaddr*)ip4bind, sizeof(*ip4bind));
523                 }
524         }
525         
526         iosocket_prepare_fd(sockfd);
527         
528         int ret = connect(sockfd, iosock->dest.addr.address, iosock->dest.addr.addresslen); //returns EINPROGRESS here (nonblocking)
529         iolog_trigger(IOLOG_DEBUG, "connecting socket (connect: %d)", ret);
530         
531         iosock->fd = sockfd;
532         iosock->socket_flags |= IOSOCKETFLAG_CONNECTING;
533         
534         iosocket_activate(iosock);
535 }
536
537 static void iosocket_listen_finish(struct _IOSocket *iosock) {
538         int sockfd;
539         if((iosock->socket_flags & IOSOCKETFLAG_IPV6SOCKET))
540                 sockfd = socket(AF_INET6, SOCK_STREAM, 0);
541         else
542                 sockfd = socket(AF_INET, SOCK_STREAM, 0);
543         if(sockfd == -1) {
544                 iolog_trigger(IOLOG_ERROR, "could not create socket in %s:%d", __FILE__, __LINE__);
545                 // TODO: trigger error
546                 
547                 return;
548         }
549         
550         // set port and bind address
551         if((iosock->socket_flags & IOSOCKETFLAG_IPV6SOCKET)) {
552                 struct sockaddr_in6 *ip6bind = (void*) iosock->bind.addr.address;
553                 ip6bind->sin6_family = AF_INET6;
554                 ip6bind->sin6_port = htons(iosock->port);
555                 
556                 int opt = 1;
557                 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt));
558                 
559                 bind(sockfd, (struct sockaddr*)ip6bind, sizeof(*ip6bind));
560         } else {
561                 struct sockaddr_in *ip4bind = (void*) iosock->bind.addr.address;
562                 ip4bind->sin_family = AF_INET;
563                 ip4bind->sin_port = htons(iosock->port);
564                 
565                 int opt = 1;
566                 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt));
567                 
568                 bind(sockfd, (struct sockaddr*)ip4bind, sizeof(*ip4bind));
569         }
570         
571         iosocket_prepare_fd(sockfd);
572         
573         listen(sockfd, 1);
574         iosock->fd = sockfd;
575         
576         iosocket_activate(iosock);
577 }
578
579 struct _IOSocket *iosocket_accept_client(struct _IOSocket *iosock) {
580         struct IOSocket *new_iosocket = calloc(1, sizeof(*new_iosocket));
581         if(!new_iosocket) {
582                 iolog_trigger(IOLOG_ERROR, "could not allocate memory for IOSocket in %s:%d", __FILE__, __LINE__);
583                 close(accept(iosock->fd, NULL, 0)); // simply drop connection
584                 return NULL;
585         }
586         struct _IOSocket *new_iosock = _create_socket();
587         if(!new_iosock) {
588                 free(new_iosocket);
589                 close(accept(iosock->fd, NULL, 0)); // simply drop connection
590                 return NULL;
591         }
592         new_iosocket->iosocket = new_iosock;
593         new_iosocket->status = IOSOCKET_CONNECTED;
594         new_iosocket->data = iosock;
595         new_iosock->parent = new_iosocket;
596         new_iosock->socket_flags |= IOSOCKETFLAG_PARENT_PUBLIC | IOSOCKETFLAG_INCOMING | (iosock->socket_flags & IOSOCKETFLAG_IPV6SOCKET);
597         
598         struct sockaddr_storage addr;
599         socklen_t addrlen = sizeof(addr);
600         
601         //accept client
602         new_iosock->fd = accept(iosock->fd, (struct sockaddr *)&addr, &addrlen);
603         
604         //copy remote address
605         new_iosock->dest.addr.address = malloc(addrlen);
606         if(!new_iosock->dest.addr.address) {
607                 close(new_iosock->fd);
608                 free(new_iosock);
609                 free(new_iosock);
610                 iolog_trigger(IOLOG_ERROR, "could not allocate memory for sockaddr in %s:%d", __FILE__, __LINE__);
611                 return NULL;
612         }
613         memcpy(new_iosock->dest.addr.address, &addr, addrlen);
614         new_iosock->dest.addr.addresslen = addrlen;
615         
616         //copy local address
617         new_iosock->bind.addr.address = malloc(iosock->bind.addr.addresslen);
618         if(!new_iosock->bind.addr.address) {
619                 close(new_iosock->fd);
620                 free(new_iosock);
621                 free(new_iosock);
622                 iolog_trigger(IOLOG_ERROR, "could not allocate memory for sockaddr in %s:%d", __FILE__, __LINE__);
623                 return NULL;
624         }
625         memcpy(new_iosock->bind.addr.address, iosock->bind.addr.address, iosock->bind.addr.addresslen);
626         new_iosock->bind.addr.addresslen = iosock->bind.addr.addresslen;
627         
628         //prepare new socket fd
629         iosocket_prepare_fd(new_iosock->fd);
630         
631         if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {
632                 new_iosocket->ssl = 1;
633                 new_iosock->socket_flags |= IOSOCKETFLAG_SSLSOCKET;
634                 \r
635                 iossl_client_accepted(iosock, new_iosock);
636         }
637         
638         iosocket_activate(new_iosock);
639         return new_iosock;
640 }
641
642 /* public functions */
643
644 struct IOSocket *iosocket_connect(const char *hostname, unsigned int port, int ssl, const char *bindhost, iosocket_callback *callback) {
645         return iosocket_connect_flags(hostname, port, ssl, bindhost, callback, (IOSOCKET_ADDR_IPV4 | IOSOCKET_ADDR_IPV6));
646 }
647
648 struct IOSocket *iosocket_connect_flags(const char *hostname, unsigned int port, int ssl, const char *bindhost, iosocket_callback *callback, int flags) {
649         struct IOSocket *iodescriptor = calloc(1, sizeof(*iodescriptor));
650         if(!iodescriptor) {
651                 iolog_trigger(IOLOG_ERROR, "could not allocate memory for IOSocket in %s:%d", __FILE__, __LINE__);
652                 return NULL;
653         }
654         
655         struct _IOSocket *iosock = _create_socket();
656         if(!iosock) {
657                 free(iodescriptor);
658                 return NULL;
659         }
660         
661         iodescriptor->iosocket = iosock;
662         iodescriptor->status = IOSOCKET_CONNECTING;
663         iodescriptor->callback = callback;
664         iosock->parent = iodescriptor;
665         iosock->socket_flags |= IOSOCKETFLAG_PARENT_PUBLIC;
666         iosock->port = port;
667         if(ssl) {
668                 iodescriptor->ssl = 1;
669                 iosock->socket_flags |= IOSOCKETFLAG_SSLSOCKET;
670         }
671         
672         if(bindhost) {
673                 switch(iosocket_parse_address(bindhost, &iosock->bind.addr, flags)) {
674                 case -1:
675                         free(iosock);
676                         return NULL;
677                 case 0:
678                         /* start dns lookup */
679                         iosock->socket_flags |= IOSOCKETFLAG_PENDING_BINDDNS;
680                         iosocket_lookup_hostname(iosock, bindhost, flags, 1);
681                         break;
682                 case 1:
683                         /* valid address */
684                         break;
685                 }
686         }
687         switch(iosocket_parse_address(hostname, &iosock->dest.addr, flags)) {
688         case -1:
689                 free(iosock);
690                 return NULL;
691         case 0:
692                 /* start dns lookup */
693                 iosock->socket_flags |= IOSOCKETFLAG_PENDING_DESTDNS;
694                 iosocket_lookup_hostname(iosock, hostname, flags, 0);
695                 break;
696         case 1:
697                 /* valid address */
698                 break;
699         }
700         if((iosock->socket_flags & (IOSOCKETFLAG_PENDING_BINDDNS | IOSOCKETFLAG_PENDING_DESTDNS)) == 0) {
701                 iosocket_connect_finish(iosock);
702         }
703         return iodescriptor;
704 }
705
706 struct IOSocket *iosocket_listen(const char *hostname, unsigned int port, iosocket_callback *callback) {
707         return iosocket_listen_flags(hostname, port, callback, (IOSOCKET_ADDR_IPV4 | IOSOCKET_ADDR_IPV6));
708 }
709
710 struct IOSocket *iosocket_listen_flags(const char *hostname, unsigned int port, iosocket_callback *callback, int flags) {
711         struct IOSocket *iodescriptor = calloc(1, sizeof(*iodescriptor));
712         if(!iodescriptor) {
713                 iolog_trigger(IOLOG_ERROR, "could not allocate memory for IOSocket in %s:%d", __FILE__, __LINE__);
714                 return NULL;
715         }
716         
717         struct _IOSocket *iosock = _create_socket();
718         if(!iosock) {
719                 free(iodescriptor);
720                 return NULL;
721         }
722         
723         iodescriptor->iosocket = iosock;
724         iodescriptor->status = IOSOCKET_LISTENING;
725         iodescriptor->listening = 1;
726         iodescriptor->callback = callback;
727         iosock->parent = iodescriptor;
728         iosock->socket_flags |= IOSOCKETFLAG_PARENT_PUBLIC | IOSOCKETFLAG_LISTENING;
729         iosock->port = port;
730         
731         switch(iosocket_parse_address(hostname, &iosock->bind.addr, flags)) {
732         case -1:
733                 free(iosock);
734                 return NULL;
735         case 0:
736                 /* start dns lookup */
737                 iosock->socket_flags |= IOSOCKETFLAG_PENDING_BINDDNS;
738                 iosocket_lookup_hostname(iosock, hostname, flags, 1);
739                 break;
740         case 1:
741                 /* valid address */
742                 break;
743         }
744         if((iosock->socket_flags & IOSOCKETFLAG_PENDING_BINDDNS) == 0) {
745                 iosocket_listen_finish(iosock);
746         }
747         return iodescriptor;
748 }
749
750 struct IOSocket *iosocket_listen_ssl(const char *hostname, unsigned int port, const char *certfile, const char *keyfile, iosocket_callback *callback) {
751         return iosocket_listen_ssl_flags(hostname, port, certfile, keyfile, callback, (IOSOCKET_ADDR_IPV4 | IOSOCKET_ADDR_IPV6));
752 }
753
754 struct IOSocket *iosocket_listen_ssl_flags(const char *hostname, unsigned int port, const char *certfile, const char *keyfile, iosocket_callback *callback, int flags) {
755         struct IOSocket *iosocket = iosocket_listen_flags(hostname, port, callback, flags);\r
756         struct _IOSocket *iosock = iosocket->iosocket;\r
757         iosock->socket_flags |= IOSOCKETFLAG_SSLSOCKET;\r
758         iossl_listen(iosock, certfile, keyfile);
759         return iosocket;
760 }
761
762 void iosocket_close(struct IOSocket *iosocket) {
763         struct _IOSocket *iosock = iosocket->iosocket;
764         if(iosock == NULL) {
765                 iolog_trigger(IOLOG_WARNING, "called iosocket_close for destroyed IOSocket in %s:%d", __FILE__, __LINE__);
766                 return;
767         }
768         
769         iosock->socket_flags |= IOSOCKETFLAG_SHUTDOWN;
770         
771         if(iosock->writebuf.bufpos) {
772                 //try to send everything before closing
773 #if defined(F_GETFL)
774                 {
775                         int flags;
776                         flags = fcntl(iosock->fd, F_GETFL);
777                         fcntl(iosock->fd, F_SETFL, flags & ~O_NONBLOCK);
778                         flags = fcntl(iosock->fd, F_GETFD);
779                         fcntl(iosock->fd, F_SETFD, flags|FD_CLOEXEC);
780                 }
781 #else
782                 iosocket_deactivate(iosock);
783 #endif
784                 iosocket_try_write(iosock);
785         }
786         //close IOSocket
787         if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))
788                 iossl_disconnect(iosock);
789         if(iosock->fd)
790                 close(iosock->fd);
791         _free_socket(iosock);
792         iosocket->iosocket = NULL;
793         iosocket->status = IOSOCKET_CLOSED;
794         iogc_add(iosocket);
795 }
796
797 static int iosocket_try_write(struct _IOSocket *iosock) {
798         if(!iosock->writebuf.bufpos && !(iosock->socket_flags & IOSOCKETFLAG_SSL_WRITEHS)) \r
799                 return 0;
800         iolog_trigger(IOLOG_DEBUG, "write writebuf (%d bytes) to socket (fd: %d)", iosock->writebuf.bufpos, iosock->fd);
801         int res;
802         if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))
803                 res = iossl_write(iosock, iosock->writebuf.buffer, iosock->writebuf.bufpos);
804         else
805                 res = send(iosock->fd, iosock->writebuf.buffer, iosock->writebuf.bufpos, 0);
806         if(res < 0) {
807                 if (errno != EAGAIN && errno != EWOULDBLOCK)
808                         iolog_trigger(IOLOG_ERROR, "could not write to socket (fd: %d): %d - %s", iosock->fd, errno, strerror(errno));
809                 else
810                         res = 0;
811         } else {
812                 iosock->writebuf.bufpos -= res;
813                 if((iosock->socket_flags & (IOSOCKETFLAG_ACTIVE | IOSOCKETFLAG_SHUTDOWN)) == IOSOCKETFLAG_ACTIVE)
814                         engine->update(iosock);
815         }
816         return res;
817 }
818
819 void iosocket_send(struct IOSocket *iosocket, const char *data, size_t datalen) {
820         struct _IOSocket *iosock = iosocket->iosocket;
821         if(iosock == NULL) {
822                 iolog_trigger(IOLOG_WARNING, "called iosocket_close for destroyed IOSocket in %s:%d", __FILE__, __LINE__);
823                 return;
824         }
825         if(iosock->socket_flags & IOSOCKETFLAG_SHUTDOWN) {
826                 iolog_trigger(IOLOG_ERROR, "could not write to socket (socket is closing)");
827                 return;
828         }
829         iolog_trigger(IOLOG_DEBUG, "add %d to writebuf (fd: %d): %s", datalen, iosock->fd, data);
830         if(iosock->writebuf.buflen < iosock->writebuf.bufpos + datalen) {
831                 iolog_trigger(IOLOG_DEBUG, "increase writebuf (curr: %d) to %d (+%d bytes)", iosock->writebuf.buflen, iosock->writebuf.bufpos + datalen, (iosock->writebuf.bufpos + datalen - iosock->writebuf.buflen));
832                 iosocket_increase_buffer(&iosock->writebuf, iosock->writebuf.bufpos + datalen);
833                 if(iosock->writebuf.buflen < iosock->writebuf.bufpos + datalen) {
834                         iolog_trigger(IOLOG_ERROR, "increase writebuf (curr: %d) to %d (+%d bytes) FAILED", iosock->writebuf.buflen, iosock->writebuf.bufpos + datalen, (iosock->writebuf.bufpos + datalen - iosock->writebuf.buflen));
835                         return;
836                 }
837         }
838         memcpy(iosock->writebuf.buffer + iosock->writebuf.bufpos, data, datalen);
839         iosock->writebuf.bufpos += datalen;
840         if((iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
841                 engine->update(iosock);
842 }
843
844 void iosocket_write(struct IOSocket *iosocket, const char *line) {
845         size_t linelen = strlen(line);
846         iosocket_send(iosocket, line, linelen);
847 }
848
849 void iosocket_printf(struct IOSocket *iosocket, const char *text, ...) {
850         va_list arg_list;
851         char sendBuf[IOSOCKET_PRINTF_LINE_LEN];
852         int pos;
853         sendBuf[0] = '\0';
854         va_start(arg_list, text);
855         pos = vsnprintf(sendBuf, IOSOCKET_PRINTF_LINE_LEN - 1, text, arg_list);
856         va_end(arg_list);
857         if (pos < 0 || pos > (IOSOCKET_PRINTF_LINE_LEN - 1)) pos = IOSOCKET_PRINTF_LINE_LEN - 1;
858         sendBuf[pos] = '\0';
859         iosocket_send(iosocket, sendBuf, pos);
860 }
861
862
863 int iosocket_wants_reads(struct _IOSocket *iosock) {
864         if((iosock->socket_flags & (IOSOCKETFLAG_SSL_READHS | IOSOCKETFLAG_SSL_WRITEHS)))
865                 return ((iosock->socket_flags & IOSOCKETFLAG_SSL_WANTWRITE) ? 0 : 1);
866         if(!(iosock->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_RW))
867                 return 1;
868         else if((iosock->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_R))
869                 return 1;
870         return 0;
871 }
872 int iosocket_wants_writes(struct _IOSocket *iosock) {
873         if((iosock->socket_flags & (IOSOCKETFLAG_SSL_READHS | IOSOCKETFLAG_SSL_WRITEHS)))
874                 return ((iosock->socket_flags & IOSOCKETFLAG_SSL_WANTWRITE) ? 1 : 0);
875         if(!(iosock->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_RW)) {
876                 if(iosock->writebuf.bufpos || (iosock->socket_flags & IOSOCKETFLAG_CONNECTING))
877                         return 1;
878                 else
879                         return 0;
880         } else if((iosock->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_W))
881                 return 1;
882         return 0;
883 }
884
885
886 static void iosocket_trigger_event(struct IOSocketEvent *event) {
887         if(!event->socket->callback) 
888                 return;
889         iolog_trigger(IOLOG_DEBUG, "triggering event");
890         event->socket->callback(event);
891 }
892
893 void iosocket_events_callback(struct _IOSocket *iosock, int readable, int writeable) {
894         if((iosock->socket_flags & IOSOCKETFLAG_PARENT_PUBLIC)) {
895                 struct IOSocket *iosocket = iosock->parent;
896                 struct IOSocketEvent callback_event;
897                 callback_event.type = IOSOCKETEVENT_IGNORE;
898                 callback_event.socket = iosocket;
899                 
900                 if((iosock->socket_flags & IOSOCKETFLAG_SSL_HANDSHAKE)) {
901                         if(readable || writeable) {
902                                 if((iosock->socket_flags & IOSOCKETFLAG_INCOMING)) 
903                                         iossl_server_handshake(iosock);
904                                 else
905                                         iossl_client_handshake(iosock);
906                                 engine->update(iosock);\r
907                         } else if((iosock->socket_flags & IOSOCKETFLAG_LISTENING)) {\r
908                                 //TODO: SSL init error\r
909                         } else if((iosock->socket_flags & IOSOCKETFLAG_INCOMING)) {\r
910                                 if((iosock->socket_flags & IOSOCKETFLAG_SSL_ESTABLISHED)) {\r
911                                         //incoming SSL connection accepted\r
912                                         iosock->socket_flags &= ~IOSOCKETFLAG_SSL_HANDSHAKE;\r
913                                         callback_event.type = IOSOCKETEVENT_ACCEPT;\r
914                                         callback_event.data.accept_socket = iosock->parent;
915                                         struct _IOSocket *parent_socket = iosocket->data;
916                                         callback_event.socket = parent_socket->parent;
917                                         
918                                         //initialize readbuf
919                                         iosocket_increase_buffer(&iosock->readbuf, 1024);\r
920                                 } else {\r
921                                         //incoming SSL connection failed, simply drop\r
922                                         iosock->socket_flags |= IOSOCKETFLAG_DEAD;\r
923                                         iolog_trigger(IOLOG_ERROR, "SSL Handshake failed for incoming connection. Dropping fd %d", iosock->fd);\r
924                                 }
925                         } else {
926                                 // SSL Backend finished
927                                 if((iosock->socket_flags & IOSOCKETFLAG_SSL_ESTABLISHED)) {\r
928                                         iosocket->status = IOSOCKET_CONNECTED;\r
929                                         iosock->socket_flags &= ~IOSOCKETFLAG_SSL_HANDSHAKE;\r
930                                         callback_event.type = IOSOCKETEVENT_CONNECTED;\r
931                                         engine->update(iosock);\r
932                                         \r
933                                         //initialize readbuf\r
934                                         iosocket_increase_buffer(&iosock->readbuf, 1024);
935                                 } else {
936                                         callback_event.type = IOSOCKETEVENT_NOTCONNECTED;\r
937                                         iosock->socket_flags |= IOSOCKETFLAG_DEAD;
938                                 }
939                         }
940                 } else if((iosock->socket_flags & IOSOCKETFLAG_LISTENING)) {
941                         if(readable) {
942                                 //new client connected
943                                 struct _IOSocket *new_iosock = iosocket_accept_client(iosock);
944                                 if(!new_iosock)
945                                         return;
946                                 
947                                 if(!(new_iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {
948                                         callback_event.type = IOSOCKETEVENT_ACCEPT;
949                                         callback_event.data.accept_socket = new_iosock->parent;
950                                 }
951                         }
952                         
953                 } else if((iosock->socket_flags & IOSOCKETFLAG_CONNECTING)) {
954                         if(readable) { //could not connect
955                                 if((iosock->socket_flags & (IOSOCKETFLAG_IPV6SOCKET | IOSOCKETFLAG_RECONNECT_IPV4)) == (IOSOCKETFLAG_IPV6SOCKET | IOSOCKETFLAG_RECONNECT_IPV4)) {
956                                         iolog_trigger(IOLOG_DEBUG, "connecting to IPv6 host (%s) failed. trying to connect using IPv4.", iosock->dest.addrlookup->hostname);
957                                         iosocket_deactivate(iosock);
958                                         if(iosocket_lookup_apply(iosock, 1)) { //if ret=0 an error occured in iosocket_lookup_apply and we should stop here.
959                                                 iosocket_connect_finish(iosock);
960                                                 socket_lookup_clear(iosock);
961                                         }
962                                 } else {
963                                         callback_event.type = IOSOCKETEVENT_NOTCONNECTED;
964                                         /*
965                                         socklen_t arglen = sizeof(callback_event.data.errid);
966                                         if (getsockopt(iosock->fd, SOL_SOCKET, SO_ERROR, &callback_event.data.errid, &arglen) < 0)
967                                                 callback_event.data.errid = errno;
968                                         */
969                                         iosock->socket_flags |= IOSOCKETFLAG_DEAD;
970                                 }
971                         } else if(writeable) { //connection established
972                                 iosock->socket_flags &= ~IOSOCKETFLAG_CONNECTING;
973                                 socket_lookup_clear(iosock);
974                                 if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {\r
975                                         iolog_trigger(IOLOG_DEBUG, "SSL client socket connected. Stating SSL handshake...");
976                                         iossl_connect(iosock);
977                                         engine->update(iosock);
978                                         return;
979                                 }
980                                 iosocket->status = IOSOCKET_CONNECTED;
981                                 
982                                 callback_event.type = IOSOCKETEVENT_CONNECTED;
983                                 engine->update(iosock);
984                                 
985                                 //initialize readbuf
986                                 iosocket_increase_buffer(&iosock->readbuf, 1024);
987                         }
988                 } else {\r
989                         int ssl_rehandshake = 0;\r
990                         if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {\r
991                                 if((iosock->socket_flags & IOSOCKETFLAG_SSL_READHS))\r
992                                         ssl_rehandshake = 1;\r
993                                 else if((iosock->socket_flags & IOSOCKETFLAG_SSL_WRITEHS))\r
994                                         ssl_rehandshake = 2;\r
995                         }
996                         iosocketevents_callback_retry_read:
997                         if((readable && ssl_rehandshake == 0) || ssl_rehandshake == 1) {
998                                 int bytes;
999                                 if(iosock->readbuf.buflen - iosock->readbuf.bufpos >= 128) {
1000                                         int addsize;
1001                                         if(iosock->readbuf.buflen >= 2048)
1002                                                 addsize = 1024;
1003                                         else
1004                                                 addsize = iosock->readbuf.buflen;
1005                                         iosocket_increase_buffer(&iosock->readbuf, iosock->readbuf.buflen + addsize);
1006                                 }
1007                                 if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))
1008                                         bytes = iossl_read(iosock, iosock->readbuf.buffer + iosock->readbuf.bufpos, iosock->readbuf.buflen - iosock->readbuf.bufpos);
1009                                 else 
1010                                         bytes = recv(iosock->fd, iosock->readbuf.buffer + iosock->readbuf.bufpos, iosock->readbuf.buflen - iosock->readbuf.bufpos, 0);
1011                                 
1012                                 if(bytes <= 0) {\r
1013                                         if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_READHS)) == (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_READHS)) {\r
1014                                                 ssl_rehandshake = 1;\r
1015                                         } else if (errno != EAGAIN || errno != EWOULDBLOCK) {
1016                                                 iosock->socket_flags |= IOSOCKETFLAG_DEAD;
1017                                                 
1018                                                 callback_event.type = IOSOCKETEVENT_CLOSED;
1019                                                 callback_event.data.errid = errno;
1020                                         }
1021                                 } else {
1022                                         int i;
1023                                         iolog_trigger(IOLOG_DEBUG, "received %d bytes (fd: %d). readbuf position: %d", bytes, iosock->fd, iosock->readbuf.bufpos);
1024                                         iosock->readbuf.bufpos += bytes;
1025                                         int retry_read = (iosock->readbuf.bufpos == iosock->readbuf.buflen);
1026                                         callback_event.type = IOSOCKETEVENT_RECV;
1027                                         
1028                                         if(iosocket->parse_delimiter) {
1029                                                 int j, used_bytes = 0;
1030                                                 for(i = 0; i < iosock->readbuf.bufpos; i++) {
1031                                                         int is_delimiter = 0;
1032                                                         for(j = 0; j < IOSOCKET_PARSE_DELIMITERS_COUNT; j++) {
1033                                                                 if(iosock->readbuf.buffer[i] == iosocket->delimiters[j]) {
1034                                                                         is_delimiter = 1;
1035                                                                         break;
1036                                                                 }
1037                                                         }
1038                                                         if(is_delimiter) {
1039                                                                 iosock->readbuf.buffer[i] = 0;
1040                                                                 callback_event.data.recv_str = iosock->readbuf.buffer + used_bytes;
1041                                                                 iolog_trigger(IOLOG_DEBUG, "parsed line (%d bytes): %s", i - used_bytes, iosock->readbuf.buffer + used_bytes);
1042                                                                 used_bytes = i+1;
1043                                                                 if(iosock->readbuf.buffer[i-1] != 0 || iosocket->parse_empty)
1044                                                                         iosocket_trigger_event(&callback_event);
1045                                                         }
1046                                                         #ifdef IOSOCKET_PARSE_LINE_LIMIT
1047                                                         else if(i + 1 - used_bytes >= IOSOCKET_PARSE_LINE_LIMIT) {
1048                                                                 iosock->readbuf.buffer[i] = 0;
1049                                                                 callback_event.data.recv_str = iosock->readbuf.buffer + used_bytes;
1050                                                                 iolog_trigger(IOLOG_DEBUG, "parsed and stripped line (%d bytes): %s", i - used_bytes, iosock->readbuf.buffer + used_bytes);
1051                                                                 for(; i < iosock->readbuf.bufpos; i++) { //skip the rest of the line
1052                                                                         is_delimiter = 0;
1053                                                                         if(iosock->readbuf.buffer[i] == iosocket->delimiters[j])
1054                                                                                 break;
1055                                                                 }
1056                                                                 used_bytes = i+1;
1057                                                                 iosocket_trigger_event(&callback_event);
1058                                                         }
1059                                                         #endif
1060                                                 }
1061                                                 if(used_bytes) {
1062                                                         if(used_bytes == iosock->readbuf.bufpos) {
1063                                                                 iosock->readbuf.bufpos = 0;
1064                                                                 iolog_trigger(IOLOG_DEBUG, "readbuf fully processed (set buffer position to 0)");
1065                                                         } else {
1066                                                                 iolog_trigger(IOLOG_DEBUG, "readbuf rest: %d bytes (used %d bytes)", iosock->readbuf.bufpos - used_bytes, used_bytes);
1067                                                                 memmove(iosock->readbuf.buffer, iosock->readbuf.buffer + used_bytes, iosock->readbuf.bufpos - used_bytes);
1068                                                                 iosock->readbuf.bufpos -= used_bytes;
1069                                                         }
1070                                                 }
1071                                                 callback_event.type = IOSOCKETEVENT_IGNORE;
1072                                         } else
1073                                                 callback_event.data.recv_buf = &iosock->readbuf;
1074                                         if(retry_read)
1075                                                 goto iosocketevents_callback_retry_read;
1076                                 }
1077                         }
1078                         if((writeable && ssl_rehandshake == 0) || ssl_rehandshake == 2) {
1079                                 int bytes;
1080                                 bytes = iosocket_try_write(iosock);
1081                                 if(bytes < 0) {\r
1082                                         if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_WRITEHS)) == (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_WRITEHS)) {\r
1083                                                 ssl_rehandshake = 1;\r
1084                                         } else {
1085                                                 iosock->socket_flags |= IOSOCKETFLAG_DEAD;
1086                                                 
1087                                                 callback_event.type = IOSOCKETEVENT_CLOSED;
1088                                                 callback_event.data.errid = errno;\r
1089                                         }
1090                                 }
1091                         }\r
1092                         if(ssl_rehandshake) {
1093                                 engine->update(iosock);\r
1094                         }
1095                 }
1096                 if(callback_event.type != IOSOCKETEVENT_IGNORE)
1097                         iosocket_trigger_event(&callback_event);
1098                 if((iosock->socket_flags & IOSOCKETFLAG_DEAD))
1099                         iosocket_close(iosocket);
1100                 
1101         } else if((iosock->socket_flags & IOSOCKETFLAG_PARENT_DNSENGINE)) {
1102                 iodns_socket_callback(iosock, readable, writeable);
1103         }
1104 }
1105
1106 void iosocket_loop(int usec) {
1107         struct timeval timeout;
1108         timeout.tv_sec = usec / 1000000;
1109         timeout.tv_usec = usec % 1000000;
1110         engine->loop(&timeout);
1111 }