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