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