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