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