[IOMultiplexerV2] started to implement c-ares backend
authorpk910 <philipp@zoelle1.de>
Sat, 8 Mar 2014 00:03:37 +0000 (01:03 +0100)
committerpk910 <philipp@zoelle1.de>
Sat, 8 Mar 2014 00:12:52 +0000 (01:12 +0100)
src/IOHandler/IODNSEngine_cares.c
src/IOHandler/IODNSEngine_default.c
src/IOHandler/IODNSLookup.c
src/IOHandler/IODNSLookup.h
src/IOHandler/IOEngine_select.c
src/IOHandler/IOSSLBackend.c
src/IOHandler/IOSockets.c
src/IOHandler/IOSockets.h
src/IOHandler/IOTimer.c
src/IOHandler/IOTimer.h
src/IOHandler_test/socket/iotest.c

index 2bbce18a7882f71f708065449c56032fed6c8710..447d8c1ccb6af408196c8faaa66c53334f5ef5ee 100644 (file)
 #include "IOInternal.h"
 #include "IOHandler.h"
 #include "IODNSLookup.h"
+#include "IOLog.h"
+#include "IOSockets.h"
+#include "IOTimer.h"
+
+#ifdef HAVE_ARES_H
+#include <ares.h>
+#include <string.h>
+#include <sys/time.h>
+#ifdef WIN32
+#define _WIN32_WINNT 0x501
+#include <windows.h>
+#include <winsock2.h>
+#elif defined HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+struct dnsengine_cares_socket {
+       struct _IOSocket *iosock;
+       int want_read : 1;
+       int want_write : 1;
+};
+
+static IOTIMER_CALLBACK(dnsengine_cares_timer_callback);
+
+static ares_channel dnsengine_cares_channel;
+static struct dnsengine_cares_socket dnsengine_cares_sockets[ARES_GETSOCK_MAXNUM];
+static struct IOTimerDescriptor *dnsengine_cares_timer = NULL;
 
 static int dnsengine_cares_init() {
-       /* TODO */
-    return 0;
+       int res;
+       
+       // zero dnsengine_cares_sockets array
+       memset(dnsengine_cares_sockets, 0, sizeof(*dnsengine_cares_sockets) * ARES_GETSOCK_MAXNUM);
+       
+       // initialize cares
+       if((res = ares_init(&dnsengine_cares_channel)) != ARES_SUCCESS) {
+               iolog_trigger(IOLOG_ERROR, "Failed to initialize c-ares in %s:%d", __FILE__, __LINE__);
+        return 0;
+    }
+    return 0; /* backend not completed */
+}
+
+static void dnsengine_cares_update_sockets() {
+       int ares_socks[ARES_GETSOCK_MAXNUM];
+       memset(ares_socks, 0, sizeof(*ares_socks) * ARES_GETSOCK_MAXNUM);
+       int sockreqs = ares_getsock(dnsengine_cares_channel, ares_socks, ARES_GETSOCK_MAXNUM);
+       int i, j, sockid, newsock, updatesock;
+       struct _IOSocket *iosock;
+       
+       //unregister "old" sockets
+       for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
+               if(!dnsengine_cares_sockets[i].iosock)
+                       continue;
+               
+               //search matching ares_socks
+               sockid = -1;
+               for(j = 0; j < ARES_GETSOCK_MAXNUM; j++) {
+                       if(dnsengine_cares_sockets[i].iosock->fd == ares_socks[j]) {
+                               sockid = j;
+                               break;
+                       }
+               }
+               if(sockid == -1) {
+                       //unregister socket
+                       _free_socket(dnsengine_cares_sockets[i].iosock);
+                       dnsengine_cares_sockets[i].iosock = NULL;
+               }
+       }
+       
+       //register new / update existing sockets
+       for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
+               if(!ares_socks[i])
+                       break;
+               
+               //search matching dnsengine_cares_socket
+               sockid = -1;
+               for(j = 0; j < ARES_GETSOCK_MAXNUM; j++) {
+                       if(dnsengine_cares_sockets[j].iosock && dnsengine_cares_sockets[j].iosock->fd == ares_socks[i]) {
+                               sockid = j;
+                               break;
+                       }
+               }
+               
+               if(sockid == -1) {
+                       //append new socket
+                       for(j = 0; j < ARES_GETSOCK_MAXNUM; j++) {
+                               if(!dnsengine_cares_sockets[j].iosock) {
+                                       sockid = j;
+                                       break;
+                               }
+                       }
+                       if(sockid == -1) {
+                               iolog_trigger(IOLOG_ERROR, "Error in dnsengine_cares_update_sockets: could not find free dnsengine_cares_socket in %s:%d", __FILE__, __LINE__);
+                               continue;
+                       }
+                       iosock = _create_socket();
+                       if(!iosock)
+                               continue;
+                       
+                       //set up iosock
+                       iosock->socket_flags |= IOSOCKETFLAG_PARENT_DNSENGINE | IOSOCKETFLAG_OVERRIDE_WANT_RW;
+                       iosock->fd = ares_socks[i];
+                       dnsengine_cares_sockets[sockid].want_read = 0;
+                       dnsengine_cares_sockets[sockid].want_write = 0;
+                       
+                       newsock = 1;
+               } else
+                       newsock = 0;
+               
+               updatesock = 0;
+               if(dnsengine_cares_sockets[sockid].want_read ^ ARES_GETSOCK_READABLE(sockreqs, i)) {
+                       if(ARES_GETSOCK_READABLE(sockreqs, i)) {
+                               dnsengine_cares_sockets[sockid].iosock->socket_flags |= IOSOCKETFLAG_OVERRIDE_WANT_R;
+                               dnsengine_cares_sockets[sockid].want_read = 1;
+                       } else {
+                               dnsengine_cares_sockets[sockid].iosock->socket_flags &= ~IOSOCKETFLAG_OVERRIDE_WANT_R;
+                               dnsengine_cares_sockets[sockid].want_read = 0;
+                       }
+                       updatesock = 1;
+               }
+               if(dnsengine_cares_sockets[sockid].want_write ^ ARES_GETSOCK_WRITABLE(sockreqs, i)) {
+                       if(ARES_GETSOCK_WRITABLE(sockreqs, i)) {
+                               dnsengine_cares_sockets[sockid].iosock->socket_flags |= IOSOCKETFLAG_OVERRIDE_WANT_W;
+                               dnsengine_cares_sockets[sockid].want_write = 1;
+                       } else {
+                               dnsengine_cares_sockets[sockid].iosock->socket_flags &= ~IOSOCKETFLAG_OVERRIDE_WANT_W;
+                               dnsengine_cares_sockets[sockid].want_write = 0;
+                       }
+                       updatesock = 1;
+               }
+               if(updatesock || newsock) {
+                       if(newsock)
+                               iosocket_activate(dnsengine_cares_sockets[sockid].iosock);
+                       else
+                               iosocket_update(dnsengine_cares_sockets[sockid].iosock);
+               }
+       }
+}
+
+static void dnsengine_cares_update_timeout() {
+       struct timeval timeout, now;
+       timeout.tv_sec = 60;
+       timeout.tv_usec = 0;
+       ares_timeout(dnsengine_cares_channel, &timeout, &timeout);
+       
+       gettimeofday(&now, NULL);
+       timeout.tv_sec += now.tv_sec;
+       timeout.tv_usec += now.tv_usec;
+       if(timeout.tv_usec > 1000000) {
+               timeout.tv_sec += 1;
+               timeout.tv_usec -= 1000000;
+       }
+       
+       if(dnsengine_cares_timer)
+               iotimer_set_timeout(dnsengine_cares_timer, &timeout);
+       else {
+               dnsengine_cares_timer = iotimer_create(&timeout);
+               iotimer_set_callback(dnsengine_cares_timer, dnsengine_cares_timer_callback);
+               iotimer_start(dnsengine_cares_timer);
+       }
+}
+
+static IOTIMER_CALLBACK(dnsengine_cares_timer_callback) {
+       dnsengine_cares_timer = NULL;
+       ares_process_fd(dnsengine_cares_channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
+       dnsengine_cares_update_timeout();
+       dnsengine_cares_update_sockets();
+}
+
+static void dnsengine_cares_socket_callback(struct _IOSocket *iosock, int wantread, int wantwrite) {
+       int socketfd = iosock->fd;
+       ares_process_fd(dnsengine_cares_channel, (wantread ? socketfd : ARES_SOCKET_BAD), (wantread ? socketfd : ARES_SOCKET_BAD));
+       dnsengine_cares_update_timeout();
+       dnsengine_cares_update_sockets();
 }
 
 static void dnsengine_cares_stop() {
-       /* TODO */
+       if(dnsengine_cares_timer)
+               iotimer_destroy(dnsengine_cares_timer);
 }
 
+
+
 static void dnsengine_cares_add(struct _IODNSQuery *iodns) {
     /* TODO */
 }
@@ -37,7 +210,7 @@ static void dnsengine_cares_remove(struct _IODNSQuery *iodns) {
 }
 
 static void dnsengine_cares_loop() {
-    /* TODO */
+    /* empty */
 }
 
 struct IODNSEngine dnsengine_cares = {
@@ -47,4 +220,19 @@ struct IODNSEngine dnsengine_cares = {
     .add = dnsengine_cares_add,
     .remove = dnsengine_cares_remove,
     .loop = dnsengine_cares_loop,
+       .socket_callback = dnsengine_cares_socket_callback,
 };
+
+#else
+
+struct IODNSEngine dnsengine_cares = {
+    .name = "c-ares",
+    .init = NULL,
+       .stop = NULL,
+    .add = NULL,
+    .remove = NULL,
+    .loop = NULL,
+       .socket_callback = NULL,
+};
+
+#endif
index b9f37641fe7f5e571ee58ecf4c6686dfe54e3d78..926a7d8c729549447cbdaffe72e88853bae1554b 100644 (file)
@@ -212,4 +212,5 @@ struct IODNSEngine dnsengine_default = {
     .add = dnsengine_default_add,
     .remove = dnsengine_default_remove,
     .loop = dnsengine_default_loop,
+       .socket_callback = NULL,
 };
index e39a9cfc0494a25d3598937a9418628f4dd0fdd7..71d014daf45d10270dfa132ef46f6f9984c08402 100644 (file)
@@ -90,6 +90,11 @@ void _stop_dnsquery(struct _IODNSQuery *query) {
                _free_dnsquery(query);
 }
 
+void iodns_socket_callback(struct _IOSocket *iosock, int wantread, int wantwrite) {
+       if(dnsengine && dnsengine->socket_callback)
+               dnsengine->socket_callback(iosock, wantread, wantwrite);
+}
+
 void iodns_event_callback(struct _IODNSQuery *query, enum IODNSEventType state) {
        if((query->flags & IODNSFLAG_PARENT_PUBLIC)) {
                struct IODNSQuery *descriptor = query->parent;
index 29574cba3185173f4bef1e1fb33f2bcb38023ad9..72ac5dc9110dcc27b499b7dbf212515d9bb1049b 100644 (file)
@@ -64,6 +64,7 @@ extern struct _IODNSQuery *iodnsquery_last;
 #define IODNSFLAG_PARENT_SOCKET  0x08
 
 struct IODNSResult;
+struct _IOSocket;
 
 struct _IODNSQuery {
        void *query;
@@ -89,6 +90,7 @@ struct IODNSEngine {
     void (*add)(struct _IODNSQuery *query);
     void (*remove)(struct _IODNSQuery *query);
     void (*loop)();
+       void (*socket_callback)(struct _IOSocket *iosock, int readable, int writeable);
 };
 
 void _init_iodns();
@@ -100,8 +102,8 @@ void _stop_dnsquery(struct _IODNSQuery *query);
 /* call only from engines! */
 enum IODNSEventType;
 void _free_dnsquery(struct _IODNSQuery *query);
+void iodns_socket_callback(struct _IOSocket *iosock, int wantread, int wantwrite);
 void iodns_event_callback(struct _IODNSQuery *query, enum IODNSEventType state);
-
 void iodns_poll();
 
 #endif
index 0d95116cd1303b2c15f5e10c2fa57d2a75345f57..b725572067b32c213e5cd62894b1021a43710ec3 100644 (file)
 
 #include <errno.h>
 #include <time.h>
+#include <string.h>
+#include <stdio.h>
 #ifdef WIN32
 #define _WIN32_WINNT 0x501
 #include <windows.h>
 #include <winsock2.h>
-#else
-#include <string.h>
-#include <stdio.h>
+#elif defined HAVE_SYS_SELECT_H
+#include <sys/select.h>
 #endif
 
 /* compat */
index 5fe568e37e83bc81fde5b6679c37b677b309f00c..6e595454eebd6e6a03c02198e123fa651f4d5362 100644 (file)
@@ -250,7 +250,7 @@ void iossl_init() {};
 void iossl_connect(struct _IOSocket *iosock) {};
 void iossl_listen(struct _IOSocket *iosock, const char *certfile, const char *keyfile) {};
 void iossl_client_handshake(struct _IOSocket *iosock) {};
-void iossl_client_accepted(struct _IOSocket *iosock, struct IODescriptor *client_iofd) {};
+void iossl_client_accepted(struct _IOSocket *iosock, struct _IOSocket *client_iofd) {};
 void iossl_server_handshake(struct _IOSocket *iosock) {};
 void iossl_disconnect(struct _IOSocket *iosock) {};
 int iossl_read(struct _IOSocket *iosock, char *buffer, int len) { return 0; };
index 4a7da99c6b8618c6df169a7ff65ce3775e3e0034..b844d64f8228240729807aa6fece42c7474dec3c 100644 (file)
@@ -20,6 +20,7 @@
 #include "IOSockets.h"
 #include "IOLog.h"
 #include "IODNSLookup.h"
+#include "IOSSLBackend.h"
 
 #ifdef WIN32
 #define _WIN32_WINNT 0x501
@@ -51,8 +52,6 @@ struct _IOSocket *iosocket_last = NULL;
 
 struct IOEngine *engine = NULL;
 
-static void iosocket_activate(struct _IOSocket *iosock);
-static void iosocket_deactivate(struct _IOSocket *iosock);
 static void iosocket_increase_buffer(struct IOSocketBuffer *iobuf, size_t required);
 static int iosocket_parse_address(const char *hostname, struct IODNSAddress *addr, int records);
 static int iosocket_lookup_hostname(struct _IOSocket *iosock, const char *hostname, int records, int bindaddr);
@@ -147,20 +146,26 @@ void _free_socket(struct _IOSocket *iosock) {
        free(iosock);
 }
 
-static void iosocket_activate(struct _IOSocket *iosock) {
+void iosocket_activate(struct _IOSocket *iosock) {
        if((iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
                return;
        iosock->socket_flags |= IOSOCKETFLAG_ACTIVE;
        engine->add(iosock);
 }
 
-static void iosocket_deactivate(struct _IOSocket *iosock) {
+void iosocket_deactivate(struct _IOSocket *iosock) {
        if(!(iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
                return;
        iosock->socket_flags &= ~IOSOCKETFLAG_ACTIVE;
        engine->remove(iosock);
 }
 
+void iosocket_update(struct _IOSocket *iosock) {
+       if(!(iosock->socket_flags & IOSOCKETFLAG_ACTIVE))
+               return;
+       engine->update(iosock);
+}
+
 static void iosocket_increase_buffer(struct IOSocketBuffer *iobuf, size_t required) {
        if(iobuf->buflen >= required) return;
        char *new_buf;
@@ -1056,7 +1061,7 @@ void iosocket_events_callback(struct _IOSocket *iosock, int readable, int writea
                        iosocket_close(iosocket);
                
        } else if((iosock->socket_flags & IOSOCKETFLAG_PARENT_DNSENGINE)) {
-               //TODO: IODNS callback
+               iodns_socket_callback(iosock, readable, writeable);
        }
 }
 
index f2d01e2afbe7f338f1dc74e9af7f3eeb5b6da04f..d38bcd7e6576b475919b5ce4c7db4f7543043b9f 100644 (file)
@@ -127,6 +127,12 @@ struct _IOSocket {
 };
 
 void _init_sockets();
+struct _IOSocket *_create_socket();
+void _free_socket(struct _IOSocket *iosock);
+void iosocket_activate(struct _IOSocket *iosock);
+void iosocket_deactivate(struct _IOSocket *iosock);
+void iosocket_update(struct _IOSocket *iosock);
+
 void iosocket_loop(int usec);
 void iosocket_lookup_callback(struct IOSocketDNSLookup *lookup, struct IODNSEvent *event);
 void iosocket_events_callback(struct _IOSocket *iosock, int readable, int writeable);
@@ -134,14 +140,14 @@ void iosocket_events_callback(struct _IOSocket *iosock, int readable, int writea
 #define iosocket_wants_reads(IOSOCK) \
 (\
        ((IOSOCK->socket_flags & (IOSOCKETFLAG_SSL_READHS | IOSOCKETFLAG_SSL_WRITEHS)) && !(IOSOCK->socket_flags & IOSOCKETFLAG_SSL_WANTWRITE)) || \
-       (!(IOSOCK->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_RW) || \
-       (IOSOCK->socket_flags & (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_R) == (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_R)) \
+       (!(IOSOCK->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_RW)) || \
+       ((IOSOCK->socket_flags & (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_R)) == (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_R)) \
 )\r
 #define iosocket_wants_writes(IOSOCK) \
 (\
-       (IOSOCK->socket_flags & (IOSOCKETFLAG_SSL_READHS | IOSOCKETFLAG_SSL_WRITEHS | IOSOCKETFLAG_SSL_WANTWRITE) > IOSOCKETFLAG_SSL_WANTWRITE) || \
+       ((IOSOCK->socket_flags & (IOSOCKETFLAG_SSL_READHS | IOSOCKETFLAG_SSL_WRITEHS | IOSOCKETFLAG_SSL_WANTWRITE)) > IOSOCKETFLAG_SSL_WANTWRITE) || \
        (!(IOSOCK->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_RW) && (IOSOCK->writebuf.bufpos || (IOSOCK->socket_flags & IOSOCKETFLAG_CONNECTING))) || \
-       (IOSOCK->socket_flags & (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_W) == (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_W)) \
+       ((IOSOCK->socket_flags & (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_W)) == (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_W)) \
 )
 
 #endif
index ec90d39304566da4e4abf31e6a6f742a40d63395..8c4adc7a0b5cdebcf2bfb0eb726e673df521fcfc 100644 (file)
@@ -80,6 +80,20 @@ void iotimer_set_autoreload(struct IOTimerDescriptor *descriptor, struct timeval
        }
 }
 
+void iotimer_set_timeout(struct IOTimerDescriptor *descriptor, struct timeval *timeout) {
+       struct _IOTimerDescriptor *timer = descriptor->iotimer;
+       if(timer == NULL) {
+               iolog_trigger(IOLOG_WARNING, "called iotimer_set_timeout for destroyed IOTimerDescriptor in %s:%d", __FILE__, __LINE__);
+               return;
+       }
+       if(!timeout) {
+               iolog_trigger(IOLOG_WARNING, "called iotimer_set_timeout without timeout given in %s:%d", __FILE__, __LINE__);
+               return;
+       }
+       timer->timeout = *timeout;
+       _rearrange_timer(timer);
+}
+
 void iotimer_set_callback(struct IOTimerDescriptor *descriptor, iotimer_callback *callback) {
        descriptor->callback = callback;
 }
index c173282bb3d1eb7904e86853461debbd7395d130..31576ccc67eb769ccb021f45845966ed061b5da7 100644 (file)
@@ -64,6 +64,7 @@ struct IOTimerDescriptor {
 struct IOTimerDescriptor *iotimer_create(struct timeval *timeout);
 void iotimer_start(struct IOTimerDescriptor *iotimer);
 void iotimer_set_autoreload(struct IOTimerDescriptor *iotimer, struct timeval *autoreload);
+void iotimer_set_timeout(struct IOTimerDescriptor *iotimer, struct timeval *timeout);
 void iotimer_set_callback(struct IOTimerDescriptor *iotimer, iotimer_callback *callback);
 void iotimer_destroy(struct IOTimerDescriptor *iotimer);
 
index 9da8b2be5a721bbee6f72529b400cdca231fa0c6..0069b02d29b135914d8d943c83b8435339f8b584 100644 (file)
@@ -51,7 +51,9 @@ static IOSOCKET_CALLBACK(io_callback) {
         case IOSOCKETEVENT_RECV:
                        {
                                struct IOSocketBuffer *recv_buf = event->data.recv_buf;
-                               write(1, recv_buf->buffer, recv_buf->bufpos);
+                               int i;
+                               for(i = 0; i < recv_buf->bufpos; i++)
+                                       putchar(recv_buf->buffer[i]);
                                recv_buf->bufpos = 0;
                                printf("\n");
             }