1 /* IOSockets.c - IOMultiplexer v2
2 * Copyright (C) 2014 Philipp Kreil (pk910)
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.
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.
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/>.
17 #define _IOHandler_internals
18 #include "IOInternal.h"
19 #include "IOHandler.h"
20 #include "IOSockets.h"
22 #include "IODNSLookup.h"
23 #include "IOSSLBackend.h"
29 #define _WIN32_WINNT 0x501
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netinet/ip.h>
37 #include <arpa/inet.h>
41 #include "compat/inet.h"
50 #define EWOULDBLOCK EAGAIN
53 struct _IOSocket *iosocket_first = NULL;
54 struct _IOSocket *iosocket_last = NULL;
56 struct IOEngine *engine = NULL;
58 static void iosocket_increase_buffer(struct IOSocketBuffer *iobuf, size_t required);
59 static int iosocket_parse_address(const char *hostname, struct IODNSAddress *addr, int records);
60 static int iosocket_lookup_hostname(struct _IOSocket *iosock, const char *hostname, int records, int bindaddr);
61 static int iosocket_lookup_apply(struct _IOSocket *iosock, int noip6);
62 static void socket_lookup_clear(struct _IOSocket *iosock);
63 static void iosocket_connect_finish(struct _IOSocket *iosock);
64 static void iosocket_listen_finish(struct _IOSocket *iosock);
65 static int iosocket_try_write(struct _IOSocket *iosock);
66 static void iosocket_trigger_event(struct IOSocketEvent *event);
69 static int close(int fd) {
70 return closesocket(fd);
74 static void iosockets_init_engine() {
76 if(!engine && engine_kevent.init && engine_kevent.init())
77 engine = &engine_kevent;
78 if(!engine && engine_epoll.init && engine_epoll.init())
79 engine = &engine_epoll;
80 if(!engine && engine_win32.init && engine_win32.init())
81 engine = &engine_win32;
84 if(engine_select.init())
85 engine = &engine_select;
87 iolog_trigger(IOLOG_FATAL, "found no useable IO engine");
91 iolog_trigger(IOLOG_DEBUG, "using %s IOSockets engine", engine->name);
94 void _init_sockets() {
99 iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
101 iolog_trigger(IOLOG_ERROR, "WSAStartup returned error code: %d", iResult);
105 iosockets_init_engine();
\r
110 struct _IOSocket *_create_socket() {
111 struct _IOSocket *iosock = calloc(1, sizeof(*iosock));
113 iolog_trigger(IOLOG_ERROR, "could not allocate memory for _IOSocket in %s:%d", __FILE__, __LINE__);
117 iosocket_last->next = iosock;
119 iosocket_first = iosock;
120 iosock->prev = iosocket_last;
121 iosocket_last = iosock;
125 void _free_socket(struct _IOSocket *iosock) {
126 iosocket_deactivate(iosock);
128 iosock->prev->next = iosock->next;
130 iosocket_first = iosock->next;
132 iosock->next->prev = iosock->prev;
134 iosocket_last = iosock->prev;
136 if(iosock->bind.addr.addresslen)
137 free(iosock->bind.addr.address);
138 if(iosock->dest.addr.addresslen)
139 free(iosock->dest.addr.address);
140 if(iosock->bind.addrlookup || iosock->dest.addrlookup)
141 socket_lookup_clear(iosock);
142 if(iosock->readbuf.buffer)
143 free(iosock->readbuf.buffer);
144 if(iosock->writebuf.buffer)
145 free(iosock->writebuf.buffer);
146 if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))
\r
147 iossl_disconnect(iosock);
\r
152 void iosocket_activate(struct _IOSocket *iosock) {
153 if((iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
155 iosock->socket_flags |= IOSOCKETFLAG_ACTIVE;
159 void iosocket_deactivate(struct _IOSocket *iosock) {
160 if(!(iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
162 iosock->socket_flags &= ~IOSOCKETFLAG_ACTIVE;
163 engine->remove(iosock);
166 void iosocket_update(struct _IOSocket *iosock) {
167 if(!(iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
169 engine->update(iosock);
172 static void iosocket_increase_buffer(struct IOSocketBuffer *iobuf, size_t required) {
173 if(iobuf->buflen >= required) return;
176 new_buf = realloc(iobuf->buffer, required + 2);
178 new_buf = malloc(required + 2);
180 iobuf->buffer = new_buf;
181 iobuf->buflen = required;
185 static int iosocket_parse_address(const char *hostname, struct IODNSAddress *addr, int records) {
187 if((records & IOSOCKET_ADDR_IPV4)) {
188 struct sockaddr_in ip4addr;
189 ret = inet_pton(AF_INET, hostname, &(ip4addr.sin_addr));
191 addr->addresslen = sizeof(ip4addr);
192 addr->address = malloc(addr->addresslen);
194 iolog_trigger(IOLOG_ERROR, "could not allocate memory for sockaddr in %s:%d", __FILE__, __LINE__);
197 memcpy(addr->address, &ip4addr, sizeof(ip4addr));
201 if((records & IOSOCKET_ADDR_IPV6)) {
202 struct sockaddr_in6 ip6addr;
203 ret = inet_pton(AF_INET6, hostname, &(ip6addr.sin6_addr));
205 addr->addresslen = sizeof(ip6addr);
206 addr->address = malloc(addr->addresslen);
208 iolog_trigger(IOLOG_ERROR, "could not allocate memory for sockaddr in %s:%d", __FILE__, __LINE__);
211 memcpy(addr->address, &ip6addr, sizeof(ip6addr));
218 static int iosocket_lookup_hostname(struct _IOSocket *iosock, const char *hostname, int records, int bindaddr) {
219 struct IOSocketDNSLookup *lookup = calloc(1, sizeof(*lookup));
221 iolog_trigger(IOLOG_ERROR, "could not allocate memory for IOSocketDNSLookup in %s:%d", __FILE__, __LINE__);
225 struct _IODNSQuery *query = _create_dnsquery();
231 query->parent = lookup;
232 query->flags |= IODNSFLAG_PARENT_SOCKET;
233 lookup->iosocket = iosock;
234 lookup->query = query;
235 strncpy(lookup->hostname, hostname, sizeof(lookup->hostname));
236 lookup->hostname[sizeof(lookup->hostname)-1] = 0;
238 lookup->bindlookup = 1;
239 iosock->bind.addrlookup = lookup;
241 lookup->bindlookup = 0;
242 iosock->dest.addrlookup = lookup;
246 if((records & IOSOCKET_ADDR_IPV4))
247 dnsrecords |= IODNS_RECORD_A;
248 if((records & IOSOCKET_ADDR_IPV6))
249 dnsrecords |= IODNS_RECORD_AAAA;
251 query->request.host = strdup(hostname);
252 query->type = (dnsrecords & IODNS_FORWARD);
254 _start_dnsquery(query);
258 void iosocket_lookup_callback(struct IOSocketDNSLookup *lookup, struct IODNSEvent *event) {
259 lookup->query = NULL;
260 struct _IOSocket *iosock = lookup->iosocket;
264 if(event->type == IODNSEVENT_SUCCESS)
265 lookup->result = event->result;
267 lookup->result = NULL;
269 if(lookup->bindlookup) {
270 iosock->socket_flags &= ~IOSOCKETFLAG_PENDING_BINDDNS;
271 iosock->socket_flags |= IOSOCKETFLAG_DNSDONE_BINDDNS;
273 iosock->socket_flags &= ~IOSOCKETFLAG_PENDING_DESTDNS;
274 iosock->socket_flags |= IOSOCKETFLAG_DNSDONE_DESTDNS;
277 int dns_finished = 0;
278 if((iosock->socket_flags & (IOSOCKETFLAG_PENDING_BINDDNS | IOSOCKETFLAG_PENDING_DESTDNS)) == 0)
283 ret = iosocket_lookup_apply(iosock, 0);
284 if(ret) { //if ret=0 an error occured in iosocket_lookup_apply and we should stop here.
285 if((iosock->socket_flags & IOSOCKETFLAG_LISTENING)) {
286 socket_lookup_clear(iosock);
287 iosocket_listen_finish(iosock);
289 iosocket_connect_finish(iosock);
294 static int iosocket_lookup_apply(struct _IOSocket *iosock, int noip6) {
296 struct IOSocketDNSLookup *bind_lookup = ((iosock->socket_flags & IOSOCKETFLAG_DNSDONE_BINDDNS) ? iosock->bind.addrlookup : NULL);
297 struct IOSocketDNSLookup *dest_lookup = ((iosock->socket_flags & IOSOCKETFLAG_DNSDONE_DESTDNS) ? iosock->dest.addrlookup : NULL);
299 iolog_trigger(IOLOG_DEBUG, "all pending lookups finished. trying to apply lookup results...");
301 if(!bind_lookup && !dest_lookup) {
302 iosock->socket_flags |= IOSOCKETFLAG_DNSERROR;
303 sprintf(errbuf, "Internal Error");
304 iolog_trigger(IOLOG_ERROR, "trying to apply lookup results without any lookups processed in %s:%d", __FILE__, __LINE__);
305 goto iosocket_lookup_apply_end;
308 struct IODNSResult *result;
309 int bind_numip4 = 0, bind_numip6 = 0;
310 int dest_numip4 = 0, dest_numip6 = 0;
313 for(result = bind_lookup->result; result; result = result->next) {
314 if((result->type & IODNS_RECORD_A))
316 if((result->type & IODNS_RECORD_AAAA))
321 for(result = dest_lookup->result; result; result = result->next) {
322 if((result->type & IODNS_RECORD_A))
324 if((result->type & IODNS_RECORD_AAAA))
330 if(bind_lookup && (bind_numip6 == 0 && bind_numip4 == 0)) {
331 iosock->socket_flags |= IOSOCKETFLAG_DNSERROR;
332 sprintf(errbuf, "could not lookup bind address (%s)", bind_lookup->hostname);
333 goto iosocket_lookup_apply_end;
334 } else if(dest_lookup && (dest_numip6 == 0 && dest_numip4 == 0)) {
335 iosock->socket_flags |= IOSOCKETFLAG_DNSERROR;
336 sprintf(errbuf, "could not lookup destination address (%s)", dest_lookup->hostname);
337 goto iosocket_lookup_apply_end;
338 } else if(bind_lookup && dest_lookup) {
339 if(bind_numip6 > 0 && dest_numip6 > 0)
341 if(bind_numip4 > 0 && dest_numip4 > 0)
343 } else if(bind_lookup) {
348 } else if(dest_lookup) {
356 if(useip6 && !noip6) {
357 usetype = IODNS_RECORD_AAAA;
358 iosock->socket_flags |= IOSOCKETFLAG_IPV6SOCKET;
360 iosock->socket_flags |= IOSOCKETFLAG_RECONNECT_IPV4;
362 usetype = IODNS_RECORD_A;
363 iosock->socket_flags &= ~(IOSOCKETFLAG_IPV6SOCKET | IOSOCKETFLAG_RECONNECT_IPV4);
365 iosock->socket_flags |= IOSOCKETFLAG_DNSERROR;
366 sprintf(errbuf, "could not lookup adresses of the same IP family for bind and destination host. (bind: %d ip4, %d ip6 | dest: %d ip4, %d ip6)", bind_numip4, bind_numip6, dest_numip4, dest_numip6);
367 goto iosocket_lookup_apply_end;
370 #define IOSOCKET_APPLY_COPYADDR(type) \
371 iosock->type.addr.addresslen = result->result.addr.addresslen; \
372 iosock->type.addr.address = malloc(result->result.addr.addresslen); \
373 if(!iosock->type.addr.address) { \
374 iolog_trigger(IOLOG_ERROR, "could not allocate memory for sockaddr in %s:%d", __FILE__, __LINE__); \
375 iosock->type.addr.addresslen = 0; \
376 iosock->socket_flags |= IOSOCKETFLAG_DNSERROR; \
377 sprintf(errbuf, "could not allocate memory for dns information"); \
378 goto iosocket_lookup_apply_end; \
380 memcpy(iosock->type.addr.address, result->result.addr.address, result->result.addr.addresslen);
384 int usenum = ((usetype == IODNS_RECORD_AAAA) ? bind_numip6 : bind_numip4);
385 usenum = rand() % usenum;
386 for(result = bind_lookup->result; result; result = result->next) {
387 if((result->type & usetype)) {
389 inet_ntop(((usetype == IODNS_RECORD_AAAA) ? AF_INET6 : AF_INET), ((usetype == IODNS_RECORD_AAAA) ? (void *)(&((struct sockaddr_in6 *)result->result.addr.address)->sin6_addr) : (void *)(&((struct sockaddr_in *)result->result.addr.address)->sin_addr)), errbuf, sizeof(errbuf));
390 iolog_trigger(IOLOG_DEBUG, "using IPv%s Address (%s) as bind address", ((usetype == IODNS_RECORD_AAAA) ? "6" : "4"), errbuf);
391 IOSOCKET_APPLY_COPYADDR(bind)
398 iosock->bind.addr.addresslen = 0;
401 int usenum = ((usetype == IODNS_RECORD_AAAA) ? dest_numip6 : dest_numip4);
402 usenum = rand() % usenum;
403 for(result = dest_lookup->result; result; result = result->next) {
404 if((result->type & usetype)) {
406 inet_ntop(((usetype == IODNS_RECORD_AAAA) ? AF_INET6 : AF_INET), ((usetype == IODNS_RECORD_AAAA) ? (void *)(&((struct sockaddr_in6 *)result->result.addr.address)->sin6_addr) : (void *)(&((struct sockaddr_in *)result->result.addr.address)->sin_addr)), errbuf, sizeof(errbuf));
407 iolog_trigger(IOLOG_DEBUG, "using IPv%s Address (%s) as dest address", ((usetype == IODNS_RECORD_AAAA) ? "6" : "4"), errbuf);
408 IOSOCKET_APPLY_COPYADDR(dest)
415 iosock->dest.addr.addresslen = 0;
417 iosocket_lookup_apply_end:
419 if((iosock->socket_flags & IOSOCKETFLAG_DNSERROR)) {
420 // TODO: trigger error
421 iolog_trigger(IOLOG_ERROR, "error while trying to apply dns lookup information: %s", errbuf);
423 if((iosock->socket_flags & IOSOCKETFLAG_PARENT_PUBLIC)) {
425 struct IOSocket *iosocket = iosock->parent;
427 struct IOSocketEvent callback_event;
428 callback_event.type = IOSOCKETEVENT_DNSFAILED;
429 callback_event.socket = iosocket;
430 callback_event.data.recv_str = errbuf;
431 iosocket_trigger_event(&callback_event);
433 iosocket_close(iosocket);
435 // TODO: IODNS Callback
442 static void socket_lookup_clear(struct _IOSocket *iosock) {
443 struct IOSocketDNSLookup *bind_lookup = ((iosock->socket_flags & IOSOCKETFLAG_DNSDONE_BINDDNS) ? iosock->bind.addrlookup : NULL);
444 struct IOSocketDNSLookup *dest_lookup = ((iosock->socket_flags & IOSOCKETFLAG_DNSDONE_DESTDNS) ? iosock->dest.addrlookup : NULL);
446 if(bind_lookup->result)
447 iodns_free_result(bind_lookup->result);
449 iosock->bind.addrlookup = NULL;
452 if(dest_lookup->result)
453 iodns_free_result(dest_lookup->result);
455 iosock->dest.addrlookup = NULL;
459 static void iosocket_prepare_fd(int sockfd) {
462 #if defined(SO_NOSIGPIPE)
465 setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
468 signal(SIGPIPE, SIG_IGN);
472 // make sockfd unblocking
476 fcntl_flags = fcntl(sockfd, F_GETFL);
477 fcntl(sockfd, F_SETFL, fcntl_flags|O_NONBLOCK);
478 fcntl_flags = fcntl(sockfd, F_GETFD);
479 fcntl(sockfd, F_SETFD, fcntl_flags|FD_CLOEXEC);
481 #elif defined(FIONBIO)
483 unsigned long ulong = 1;
484 ioctlsocket(sockfd, FIONBIO, &ulong);
489 static void iosocket_connect_finish(struct _IOSocket *iosock) {
491 if((iosock->socket_flags & IOSOCKETFLAG_IPV6SOCKET))
492 sockfd = socket(AF_INET6, SOCK_STREAM, 0);
494 sockfd = socket(AF_INET, SOCK_STREAM, 0);
496 iolog_trigger(IOLOG_ERROR, "could not create socket in %s:%d", __FILE__, __LINE__);
497 // TODO: trigger error
502 // set port and bind address
503 if((iosock->socket_flags & IOSOCKETFLAG_IPV6SOCKET)) {
504 struct sockaddr_in6 *ip6 = (void*) iosock->dest.addr.address;
505 ip6->sin6_family = AF_INET6;
506 ip6->sin6_port = htons(iosock->port);
508 if(iosock->bind.addr.addresslen) {
509 struct sockaddr_in6 *ip6bind = (void*) iosock->bind.addr.address;
510 ip6bind->sin6_family = AF_INET6;
511 ip6bind->sin6_port = htons(0);
513 bind(sockfd, (struct sockaddr*)ip6bind, sizeof(*ip6bind));
516 struct sockaddr_in *ip4 = (void*) iosock->dest.addr.address;
517 ip4->sin_family = AF_INET;
518 ip4->sin_port = htons(iosock->port);
520 if(iosock->bind.addr.addresslen) {
521 struct sockaddr_in *ip4bind = (void*) iosock->bind.addr.address;
522 ip4bind->sin_family = AF_INET;
523 ip4bind->sin_port = htons(0);
525 bind(sockfd, (struct sockaddr*)ip4bind, sizeof(*ip4bind));
529 iosocket_prepare_fd(sockfd);
531 int ret = connect(sockfd, iosock->dest.addr.address, iosock->dest.addr.addresslen); //returns EINPROGRESS here (nonblocking)
532 iolog_trigger(IOLOG_DEBUG, "connecting socket (connect: %d)", ret);
535 iosock->socket_flags |= IOSOCKETFLAG_CONNECTING;
537 iosocket_activate(iosock);
540 static void iosocket_listen_finish(struct _IOSocket *iosock) {
542 if((iosock->socket_flags & IOSOCKETFLAG_IPV6SOCKET))
543 sockfd = socket(AF_INET6, SOCK_STREAM, 0);
545 sockfd = socket(AF_INET, SOCK_STREAM, 0);
547 iolog_trigger(IOLOG_ERROR, "could not create socket in %s:%d", __FILE__, __LINE__);
548 // TODO: trigger error
553 // set port and bind address
554 if((iosock->socket_flags & IOSOCKETFLAG_IPV6SOCKET)) {
555 struct sockaddr_in6 *ip6bind = (void*) iosock->bind.addr.address;
556 ip6bind->sin6_family = AF_INET6;
557 ip6bind->sin6_port = htons(iosock->port);
560 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt));
562 bind(sockfd, (struct sockaddr*)ip6bind, sizeof(*ip6bind));
564 struct sockaddr_in *ip4bind = (void*) iosock->bind.addr.address;
565 ip4bind->sin_family = AF_INET;
566 ip4bind->sin_port = htons(iosock->port);
569 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt));
571 bind(sockfd, (struct sockaddr*)ip4bind, sizeof(*ip4bind));
574 iosocket_prepare_fd(sockfd);
579 iosocket_activate(iosock);
582 struct _IOSocket *iosocket_accept_client(struct _IOSocket *iosock) {
583 struct IOSocket *new_iosocket = calloc(1, sizeof(*new_iosocket));
585 iolog_trigger(IOLOG_ERROR, "could not allocate memory for IOSocket in %s:%d", __FILE__, __LINE__);
586 close(accept(iosock->fd, NULL, 0)); // simply drop connection
589 struct _IOSocket *new_iosock = _create_socket();
592 close(accept(iosock->fd, NULL, 0)); // simply drop connection
595 new_iosocket->iosocket = new_iosock;
596 new_iosocket->status = IOSOCKET_CONNECTED;
597 new_iosocket->data = iosock;
598 new_iosock->parent = new_iosocket;
599 new_iosock->socket_flags |= IOSOCKETFLAG_PARENT_PUBLIC | IOSOCKETFLAG_INCOMING | (iosock->socket_flags & IOSOCKETFLAG_IPV6SOCKET);
601 struct sockaddr_storage addr;
602 socklen_t addrlen = sizeof(addr);
605 new_iosock->fd = accept(iosock->fd, (struct sockaddr *)&addr, &addrlen);
607 //copy remote address
608 new_iosock->dest.addr.address = malloc(addrlen);
609 if(!new_iosock->dest.addr.address) {
610 close(new_iosock->fd);
613 iolog_trigger(IOLOG_ERROR, "could not allocate memory for sockaddr in %s:%d", __FILE__, __LINE__);
616 memcpy(new_iosock->dest.addr.address, &addr, addrlen);
617 new_iosock->dest.addr.addresslen = addrlen;
620 new_iosock->bind.addr.address = malloc(iosock->bind.addr.addresslen);
621 if(!new_iosock->bind.addr.address) {
622 close(new_iosock->fd);
625 iolog_trigger(IOLOG_ERROR, "could not allocate memory for sockaddr in %s:%d", __FILE__, __LINE__);
628 memcpy(new_iosock->bind.addr.address, iosock->bind.addr.address, iosock->bind.addr.addresslen);
629 new_iosock->bind.addr.addresslen = iosock->bind.addr.addresslen;
631 //prepare new socket fd
632 iosocket_prepare_fd(new_iosock->fd);
634 if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {
635 new_iosocket->ssl = 1;
636 new_iosock->socket_flags |= IOSOCKETFLAG_SSLSOCKET;
638 iossl_client_accepted(iosock, new_iosock);
641 iosocket_increase_buffer(&iosock->readbuf, 1024);
644 iosocket_activate(new_iosock);
648 /* public functions */
650 struct IOSocket *iosocket_connect(const char *hostname, unsigned int port, int ssl, const char *bindhost, iosocket_callback *callback) {
651 return iosocket_connect_flags(hostname, port, ssl, bindhost, callback, (IOSOCKET_ADDR_IPV4 | IOSOCKET_ADDR_IPV6));
654 struct IOSocket *iosocket_connect_flags(const char *hostname, unsigned int port, int ssl, const char *bindhost, iosocket_callback *callback, int flags) {
655 struct IOSocket *iodescriptor = calloc(1, sizeof(*iodescriptor));
657 iolog_trigger(IOLOG_ERROR, "could not allocate memory for IOSocket in %s:%d", __FILE__, __LINE__);
661 struct _IOSocket *iosock = _create_socket();
667 iodescriptor->iosocket = iosock;
668 iodescriptor->status = IOSOCKET_CONNECTING;
669 iodescriptor->callback = callback;
670 iosock->parent = iodescriptor;
671 iosock->socket_flags |= IOSOCKETFLAG_PARENT_PUBLIC;
674 iodescriptor->ssl = 1;
675 iosock->socket_flags |= IOSOCKETFLAG_SSLSOCKET;
679 switch(iosocket_parse_address(bindhost, &iosock->bind.addr, flags)) {
684 /* start dns lookup */
685 iosock->socket_flags |= IOSOCKETFLAG_PENDING_BINDDNS;
686 iosocket_lookup_hostname(iosock, bindhost, flags, 1);
693 switch(iosocket_parse_address(hostname, &iosock->dest.addr, flags)) {
698 /* start dns lookup */
699 iosock->socket_flags |= IOSOCKETFLAG_PENDING_DESTDNS;
700 iosocket_lookup_hostname(iosock, hostname, flags, 0);
706 if((iosock->socket_flags & (IOSOCKETFLAG_PENDING_BINDDNS | IOSOCKETFLAG_PENDING_DESTDNS)) == 0) {
707 iosocket_connect_finish(iosock);
712 struct IOSocket *iosocket_listen(const char *hostname, unsigned int port, iosocket_callback *callback) {
713 return iosocket_listen_flags(hostname, port, callback, (IOSOCKET_ADDR_IPV4 | IOSOCKET_ADDR_IPV6));
716 struct IOSocket *iosocket_listen_flags(const char *hostname, unsigned int port, iosocket_callback *callback, int flags) {
717 struct IOSocket *iodescriptor = calloc(1, sizeof(*iodescriptor));
719 iolog_trigger(IOLOG_ERROR, "could not allocate memory for IOSocket in %s:%d", __FILE__, __LINE__);
723 struct _IOSocket *iosock = _create_socket();
729 iodescriptor->iosocket = iosock;
730 iodescriptor->status = IOSOCKET_LISTENING;
731 iodescriptor->listening = 1;
732 iodescriptor->callback = callback;
733 iosock->parent = iodescriptor;
734 iosock->socket_flags |= IOSOCKETFLAG_PARENT_PUBLIC | IOSOCKETFLAG_LISTENING;
737 switch(iosocket_parse_address(hostname, &iosock->bind.addr, flags)) {
742 /* start dns lookup */
743 iosock->socket_flags |= IOSOCKETFLAG_PENDING_BINDDNS;
744 iosocket_lookup_hostname(iosock, hostname, flags, 1);
750 if((iosock->socket_flags & IOSOCKETFLAG_PENDING_BINDDNS) == 0) {
751 iosocket_listen_finish(iosock);
756 struct IOSocket *iosocket_listen_ssl(const char *hostname, unsigned int port, const char *certfile, const char *keyfile, iosocket_callback *callback) {
757 return iosocket_listen_ssl_flags(hostname, port, certfile, keyfile, callback, (IOSOCKET_ADDR_IPV4 | IOSOCKET_ADDR_IPV6));
760 struct IOSocket *iosocket_listen_ssl_flags(const char *hostname, unsigned int port, const char *certfile, const char *keyfile, iosocket_callback *callback, int flags) {
761 struct IOSocket *iosocket = iosocket_listen_flags(hostname, port, callback, flags);
\r
762 struct _IOSocket *iosock = iosocket->iosocket;
\r
763 iosock->socket_flags |= IOSOCKETFLAG_SSLSOCKET;
\r
764 iossl_listen(iosock, certfile, keyfile);
768 void iosocket_close(struct IOSocket *iosocket) {
769 struct _IOSocket *iosock = iosocket->iosocket;
771 iolog_trigger(IOLOG_WARNING, "called iosocket_close for destroyed IOSocket in %s:%d", __FILE__, __LINE__);
775 iosock->socket_flags |= IOSOCKETFLAG_SHUTDOWN;
777 if(iosock->writebuf.bufpos) {
778 //try to send everything before closing
782 flags = fcntl(iosock->fd, F_GETFL);
783 fcntl(iosock->fd, F_SETFL, flags & ~O_NONBLOCK);
784 flags = fcntl(iosock->fd, F_GETFD);
785 fcntl(iosock->fd, F_SETFD, flags|FD_CLOEXEC);
788 iosocket_deactivate(iosock);
790 iosocket_try_write(iosock);
793 if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))
794 iossl_disconnect(iosock);
797 _free_socket(iosock);
798 iosocket->iosocket = NULL;
799 iosocket->status = IOSOCKET_CLOSED;
803 struct IODNSAddress *iosocket_get_remote_addr(struct IOSocket *iosocket) {
804 if(iosock->socket_flags & IOSOCKETFLAG_PENDING_DESTDNS)
806 if(!iosock->dest.addr.addresslen)
808 return &iosock->dest.addr;
811 struct IODNSAddress *iosocket_get_local_addr(struct IOSocket *iosocket) {
812 if(iosock->socket_flags & IOSOCKETFLAG_PENDING_BINDDNS)
814 if(!iosock->bind.addr.addresslen)
816 return &iosock->bind.addr;
819 static int iosocket_try_write(struct _IOSocket *iosock) {
820 if(!iosock->writebuf.bufpos && !(iosock->socket_flags & IOSOCKETFLAG_SSL_WRITEHS))
\r
822 iolog_trigger(IOLOG_DEBUG, "write writebuf (%d bytes) to socket (fd: %d)", iosock->writebuf.bufpos, iosock->fd);
824 if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))
825 res = iossl_write(iosock, iosock->writebuf.buffer, iosock->writebuf.bufpos);
827 res = send(iosock->fd, iosock->writebuf.buffer, iosock->writebuf.bufpos, 0);
829 if (errno != EAGAIN && errno != EWOULDBLOCK)
830 iolog_trigger(IOLOG_ERROR, "could not write to socket (fd: %d): %d - %s", iosock->fd, errno, strerror(errno));
834 iosock->writebuf.bufpos -= res;
835 if((iosock->socket_flags & (IOSOCKETFLAG_ACTIVE | IOSOCKETFLAG_SHUTDOWN)) == IOSOCKETFLAG_ACTIVE)
836 engine->update(iosock);
841 void iosocket_send(struct IOSocket *iosocket, const char *data, size_t datalen) {
842 struct _IOSocket *iosock = iosocket->iosocket;
844 iolog_trigger(IOLOG_WARNING, "called iosocket_close for destroyed IOSocket in %s:%d", __FILE__, __LINE__);
847 if(iosock->socket_flags & IOSOCKETFLAG_SHUTDOWN) {
848 iolog_trigger(IOLOG_ERROR, "could not write to socket (socket is closing)");
851 iolog_trigger(IOLOG_DEBUG, "add %d to writebuf (fd: %d): %s", datalen, iosock->fd, data);
852 if(iosock->writebuf.buflen < iosock->writebuf.bufpos + datalen) {
853 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));
854 iosocket_increase_buffer(&iosock->writebuf, iosock->writebuf.bufpos + datalen);
855 if(iosock->writebuf.buflen < iosock->writebuf.bufpos + datalen) {
856 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));
860 memcpy(iosock->writebuf.buffer + iosock->writebuf.bufpos, data, datalen);
861 iosock->writebuf.bufpos += datalen;
862 if((iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
863 engine->update(iosock);
866 void iosocket_write(struct IOSocket *iosocket, const char *line) {
867 size_t linelen = strlen(line);
868 iosocket_send(iosocket, line, linelen);
871 void iosocket_printf(struct IOSocket *iosocket, const char *text, ...) {
873 char sendBuf[IOSOCKET_PRINTF_LINE_LEN];
876 va_start(arg_list, text);
877 pos = vsnprintf(sendBuf, IOSOCKET_PRINTF_LINE_LEN - 1, text, arg_list);
879 if (pos < 0 || pos > (IOSOCKET_PRINTF_LINE_LEN - 1)) pos = IOSOCKET_PRINTF_LINE_LEN - 1;
881 iosocket_send(iosocket, sendBuf, pos);
885 int iosocket_wants_reads(struct _IOSocket *iosock) {
886 if((iosock->socket_flags & (IOSOCKETFLAG_SSL_READHS | IOSOCKETFLAG_SSL_WRITEHS)))
887 return ((iosock->socket_flags & IOSOCKETFLAG_SSL_WANTWRITE) ? 0 : 1);
888 if(!(iosock->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_RW))
890 else if((iosock->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_R))
894 int iosocket_wants_writes(struct _IOSocket *iosock) {
895 if((iosock->socket_flags & (IOSOCKETFLAG_SSL_READHS | IOSOCKETFLAG_SSL_WRITEHS)))
896 return ((iosock->socket_flags & IOSOCKETFLAG_SSL_WANTWRITE) ? 1 : 0);
897 if(!(iosock->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_RW)) {
898 if(iosock->writebuf.bufpos || (iosock->socket_flags & IOSOCKETFLAG_CONNECTING))
902 } else if((iosock->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_W))
908 static void iosocket_trigger_event(struct IOSocketEvent *event) {
909 if(!event->socket->callback)
911 iolog_trigger(IOLOG_DEBUG, "triggering event");
912 event->socket->callback(event);
915 void iosocket_events_callback(struct _IOSocket *iosock, int readable, int writeable) {
916 if((iosock->socket_flags & IOSOCKETFLAG_PARENT_PUBLIC)) {
917 struct IOSocket *iosocket = iosock->parent;
918 struct IOSocketEvent callback_event;
919 callback_event.type = IOSOCKETEVENT_IGNORE;
920 callback_event.socket = iosocket;
922 if((iosock->socket_flags & IOSOCKETFLAG_SSL_HANDSHAKE)) {
923 if(readable || writeable) {
924 if((iosock->socket_flags & IOSOCKETFLAG_INCOMING))
925 iossl_server_handshake(iosock);
927 iossl_client_handshake(iosock);
928 engine->update(iosock);
\r
929 } else if((iosock->socket_flags & IOSOCKETFLAG_LISTENING)) {
\r
930 //TODO: SSL init error
\r
931 } else if((iosock->socket_flags & IOSOCKETFLAG_INCOMING)) {
\r
932 if((iosock->socket_flags & IOSOCKETFLAG_SSL_ESTABLISHED)) {
\r
933 //incoming SSL connection accepted
\r
934 iosock->socket_flags &= ~IOSOCKETFLAG_SSL_HANDSHAKE;
\r
935 callback_event.type = IOSOCKETEVENT_ACCEPT;
\r
936 callback_event.data.accept_socket = iosock->parent;
937 struct _IOSocket *parent_socket = iosocket->data;
938 callback_event.socket = parent_socket->parent;
941 iosocket_increase_buffer(&iosock->readbuf, 1024);
\r
943 //incoming SSL connection failed, simply drop
\r
944 iosock->socket_flags |= IOSOCKETFLAG_DEAD;
\r
945 iolog_trigger(IOLOG_ERROR, "SSL Handshake failed for incoming connection. Dropping fd %d", iosock->fd);
\r
948 // SSL Backend finished
949 if((iosock->socket_flags & IOSOCKETFLAG_SSL_ESTABLISHED)) {
\r
950 iosocket->status = IOSOCKET_CONNECTED;
\r
951 iosock->socket_flags &= ~IOSOCKETFLAG_SSL_HANDSHAKE;
\r
952 callback_event.type = IOSOCKETEVENT_CONNECTED;
\r
953 engine->update(iosock);
\r
955 //initialize readbuf
\r
956 iosocket_increase_buffer(&iosock->readbuf, 1024);
958 callback_event.type = IOSOCKETEVENT_NOTCONNECTED;
\r
959 iosock->socket_flags |= IOSOCKETFLAG_DEAD;
962 } else if((iosock->socket_flags & IOSOCKETFLAG_LISTENING)) {
964 //new client connected
965 struct _IOSocket *new_iosock = iosocket_accept_client(iosock);
969 if(!(new_iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {
970 callback_event.type = IOSOCKETEVENT_ACCEPT;
971 callback_event.data.accept_socket = new_iosock->parent;
975 } else if((iosock->socket_flags & IOSOCKETFLAG_CONNECTING)) {
976 if(readable) { //could not connect
977 if((iosock->socket_flags & (IOSOCKETFLAG_IPV6SOCKET | IOSOCKETFLAG_RECONNECT_IPV4)) == (IOSOCKETFLAG_IPV6SOCKET | IOSOCKETFLAG_RECONNECT_IPV4)) {
978 iolog_trigger(IOLOG_DEBUG, "connecting to IPv6 host (%s) failed. trying to connect using IPv4.", iosock->dest.addrlookup->hostname);
979 iosocket_deactivate(iosock);
980 if(iosocket_lookup_apply(iosock, 1)) { //if ret=0 an error occured in iosocket_lookup_apply and we should stop here.
981 iosocket_connect_finish(iosock);
982 socket_lookup_clear(iosock);
985 callback_event.type = IOSOCKETEVENT_NOTCONNECTED;
987 socklen_t arglen = sizeof(callback_event.data.errid);
988 if (getsockopt(iosock->fd, SOL_SOCKET, SO_ERROR, &callback_event.data.errid, &arglen) < 0)
989 callback_event.data.errid = errno;
991 iosock->socket_flags |= IOSOCKETFLAG_DEAD;
993 } else if(writeable) { //connection established
994 iosock->socket_flags &= ~IOSOCKETFLAG_CONNECTING;
995 socket_lookup_clear(iosock);
996 if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {
\r
997 iolog_trigger(IOLOG_DEBUG, "SSL client socket connected. Stating SSL handshake...");
998 iossl_connect(iosock);
999 engine->update(iosock);
1002 iosocket->status = IOSOCKET_CONNECTED;
1004 callback_event.type = IOSOCKETEVENT_CONNECTED;
1005 engine->update(iosock);
1007 //initialize readbuf
1008 iosocket_increase_buffer(&iosock->readbuf, 1024);
1011 int ssl_rehandshake = 0;
\r
1012 if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {
\r
1013 if((iosock->socket_flags & IOSOCKETFLAG_SSL_READHS))
\r
1014 ssl_rehandshake = 1;
\r
1015 else if((iosock->socket_flags & IOSOCKETFLAG_SSL_WRITEHS))
\r
1016 ssl_rehandshake = 2;
\r
1018 iosocketevents_callback_retry_read:
1019 if((readable && ssl_rehandshake == 0) || ssl_rehandshake == 1) {
1021 if(iosock->readbuf.buflen - iosock->readbuf.bufpos <= 128) {
1023 if(iosock->readbuf.buflen >= 2048)
1026 addsize = iosock->readbuf.buflen;
1028 iolog_trigger(IOLOG_WARNING, "readbuf length is 0 when trying to read from fd %d", iosock->fd);
1031 iosocket_increase_buffer(&iosock->readbuf, iosock->readbuf.buflen + addsize);
1033 if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))
1034 bytes = iossl_read(iosock, iosock->readbuf.buffer + iosock->readbuf.bufpos, iosock->readbuf.buflen - iosock->readbuf.bufpos);
1036 bytes = recv(iosock->fd, iosock->readbuf.buffer + iosock->readbuf.bufpos, iosock->readbuf.buflen - iosock->readbuf.bufpos, 0);
1039 if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_READHS)) == (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_READHS)) {
\r
1040 ssl_rehandshake = 1;
\r
1041 } else if (errno != EAGAIN || errno != EWOULDBLOCK) {
1042 iosock->socket_flags |= IOSOCKETFLAG_DEAD;
1044 callback_event.type = IOSOCKETEVENT_CLOSED;
1045 callback_event.data.errid = errno;
1049 iolog_trigger(IOLOG_DEBUG, "received %d bytes (fd: %d). readbuf position: %d", bytes, iosock->fd, iosock->readbuf.bufpos);
1050 iosock->readbuf.bufpos += bytes;
1051 int retry_read = (iosock->readbuf.bufpos == iosock->readbuf.buflen);
1052 callback_event.type = IOSOCKETEVENT_RECV;
1054 if(iosocket->parse_delimiter) {
1055 int j, used_bytes = 0;
1056 for(i = 0; i < iosock->readbuf.bufpos; i++) {
1057 int is_delimiter = 0;
1058 for(j = 0; j < IOSOCKET_PARSE_DELIMITERS_COUNT; j++) {
1059 if(iosock->readbuf.buffer[i] == iosocket->delimiters[j]) {
1065 iosock->readbuf.buffer[i] = 0;
1066 callback_event.data.recv_str = iosock->readbuf.buffer + used_bytes;
1067 iolog_trigger(IOLOG_DEBUG, "parsed line (%d bytes): %s", i - used_bytes, iosock->readbuf.buffer + used_bytes);
1069 if(iosock->readbuf.buffer[i-1] != 0 || iosocket->parse_empty)
1070 iosocket_trigger_event(&callback_event);
1072 #ifdef IOSOCKET_PARSE_LINE_LIMIT
1073 else if(i + 1 - used_bytes >= IOSOCKET_PARSE_LINE_LIMIT) {
1074 iosock->readbuf.buffer[i] = 0;
1075 callback_event.data.recv_str = iosock->readbuf.buffer + used_bytes;
1076 iolog_trigger(IOLOG_DEBUG, "parsed and stripped line (%d bytes): %s", i - used_bytes, iosock->readbuf.buffer + used_bytes);
1077 for(; i < iosock->readbuf.bufpos; i++) { //skip the rest of the line
1079 if(iosock->readbuf.buffer[i] == iosocket->delimiters[j])
1083 iosocket_trigger_event(&callback_event);
1088 if(used_bytes == iosock->readbuf.bufpos) {
1089 iosock->readbuf.bufpos = 0;
1090 iolog_trigger(IOLOG_DEBUG, "readbuf fully processed (set buffer position to 0)");
1092 iolog_trigger(IOLOG_DEBUG, "readbuf rest: %d bytes (used %d bytes)", iosock->readbuf.bufpos - used_bytes, used_bytes);
1093 memmove(iosock->readbuf.buffer, iosock->readbuf.buffer + used_bytes, iosock->readbuf.bufpos - used_bytes);
1094 iosock->readbuf.bufpos -= used_bytes;
1097 callback_event.type = IOSOCKETEVENT_IGNORE;
1099 callback_event.data.recv_buf = &iosock->readbuf;
1101 goto iosocketevents_callback_retry_read;
1104 if((writeable && ssl_rehandshake == 0) || ssl_rehandshake == 2) {
1106 bytes = iosocket_try_write(iosock);
1108 if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_WRITEHS)) == (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_WRITEHS)) {
\r
1109 ssl_rehandshake = 1;
\r
1111 iosock->socket_flags |= IOSOCKETFLAG_DEAD;
1113 callback_event.type = IOSOCKETEVENT_CLOSED;
1114 callback_event.data.errid = errno;
\r
1118 if(ssl_rehandshake) {
1119 engine->update(iosock);
\r
1122 if(callback_event.type != IOSOCKETEVENT_IGNORE)
1123 iosocket_trigger_event(&callback_event);
1124 if((iosock->socket_flags & IOSOCKETFLAG_DEAD))
1125 iosocket_close(iosocket);
1127 } else if((iosock->socket_flags & IOSOCKETFLAG_PARENT_DNSENGINE)) {
1128 iodns_socket_callback(iosock, readable, writeable);
1132 void iosocket_loop(int usec) {
1133 struct timeval timeout;
1134 timeout.tv_sec = usec / 1000000;
1135 timeout.tv_usec = usec % 1000000;
1136 engine->loop(&timeout);