added SSL backend for IOMultiplexer
[TransparentIRC.git] / src / IOHandler.c
index 7a9f3b3d30e7aa4b098c7c83cae4dd031dbbe3dc..953340e506fb28ba5eae6748044fbc68fcb1b4ca 100644 (file)
@@ -16,6 +16,7 @@
  */
 #include "IOHandler.h"
 #include "IOEngine.h"
+#include "IOHandler_SSL.h"
 
 #define MAXLOG 1024
 
@@ -36,6 +37,7 @@ void iohandler_log(enum IOLogType type, char *text, ...) {
     
     //do something with logBuf
     //...
+    printf("%s", logBuf);
 }
 
 /* IO Engines */
@@ -46,6 +48,7 @@ extern struct IOEngine engine_epoll;
 struct IOEngine *engine = NULL;
 
 static void iohandler_init_engine() {
+    if(engine) return;
     //try other engines
     if(!engine && engine_kevent.init && engine_kevent.init())
         engine = &engine_kevent;
@@ -61,6 +64,7 @@ static void iohandler_init_engine() {
         }
     }
     iohandler_log(IOLOG_DEBUG, "using %s IO engine", engine->name);
+    iohandler_ssl_init();
 }
 
 static void iohandler_append(struct IODescriptor *descriptor) {
@@ -323,13 +327,14 @@ struct IODescriptor *iohandler_connect(const char *hostname, unsigned int port,
     }
     connect(sockfd, dstaddr, dstaddrlen); //returns EINPROGRESS here (nonblocking)
     descriptor->state = IO_CONNECTING;
+    descriptor->ssl = (ssl ? 1 : 0);
     descriptor->read_lines = 1;
     engine->update(descriptor);
     iohandler_log(IOLOG_DEBUG, "added client socket (%d) connecting to %s:%d", sockfd, hostname, port);
     return descriptor;
 }
 
-struct IODescriptor *iohandler_listen(const char *hostname, unsigned int port, int ssl, iohandler_callback *callback) {
+struct IODescriptor *iohandler_listen(const char *hostname, unsigned int port, iohandler_callback *callback) {
     int sockfd;
     struct addrinfo hints, *res, *freeres;
     struct sockaddr_in *ip4 = NULL;
@@ -449,7 +454,11 @@ void iohandler_printf(struct IODescriptor *iofd, const char *text, ...) {
 void iohandler_try_write(struct IODescriptor *iofd) {
     if(!iofd->writebuf.bufpos) return;
     iohandler_log(IOLOG_DEBUG, "write writebuf (%d bytes) to socket (fd: %d)", iofd->writebuf.bufpos, iofd->fd);
-    int res = send(iofd->fd, iofd->writebuf.buffer, iofd->writebuf.bufpos, 0);
+    int res;
+    if(iofd->ssl_active)
+        res = iohandler_ssl_write(iofd, iofd->writebuf.buffer, iofd->writebuf.bufpos);
+    else
+        res = send(iofd->fd, iofd->writebuf.buffer, iofd->writebuf.bufpos, 0);
     if(res < 0) {
         if (errno != EAGAIN) {
             iohandler_log(IOLOG_ERROR, "could not write to socket (fd: %d): %d - %s", iofd->fd, errno, strerror(errno));
@@ -481,6 +490,8 @@ void iohandler_close(struct IODescriptor *iofd) {
         iohandler_try_write(iofd);
     }
     //close IODescriptor
+    if(iofd->ssl)
+        iohandler_ssl_disconnect(iofd);
     if(iofd->type == IOTYPE_SERVER || iofd->type == IOTYPE_CLIENT || iofd->type == IOTYPE_STDIN)
         close(iofd->fd);
     iohandler_remove(iofd, engine_remove);
@@ -502,6 +513,15 @@ void iohandler_events(struct IODescriptor *iofd, int readable, int writeable) {
     callback_event.type = IOEVENT_IGNORE;
     callback_event.iofd = iofd;
     switch(iofd->state) {
+        case IO_SSLWAIT:
+            if(!readable && !writeable) {
+                callback_event.type = IOEVENT_SSLFAILED;
+                iofd->state = IO_CLOSED;
+            } else {
+                iohandler_log(IOLOG_DEBUG, "triggering iohandler_ssl_client_handshake for %s (fd: %d)", iohandler_iotype_name(iofd->type), iofd->fd);
+                iohandler_ssl_client_handshake(iofd);
+            }
+            break;
         case IO_CLOSED:
             if(iofd->type == IOTYPE_TIMER)
                 callback_event.type = IOEVENT_TIMEOUT;
@@ -525,6 +545,11 @@ void iohandler_events(struct IODescriptor *iofd, int readable, int writeable) {
                 iofd->state = IO_CLOSED;
                                engine->update(iofd);
             } else if(writeable) {
+                if(iofd->ssl && !iofd->ssl_active) {
+                    iohandler_log(IOLOG_DEBUG, "triggering iohandler_ssl_connect for %s (fd: %d)", iohandler_iotype_name(iofd->type), iofd->fd);
+                    iohandler_ssl_connect(iofd);
+                    return;
+                }
                 callback_event.type = IOEVENT_CONNECTED;
                 iofd->state = IO_CONNECTED;
                 engine->update(iofd);
@@ -533,7 +558,11 @@ void iohandler_events(struct IODescriptor *iofd, int readable, int writeable) {
         case IO_CONNECTED:
             if(readable) {
                 if(iofd->read_lines) {
-                    int bytes = recv(iofd->fd, iofd->readbuf.buffer + iofd->readbuf.bufpos, iofd->readbuf.buflen - iofd->readbuf.bufpos, 0);
+                    int bytes;
+                    if(iofd->ssl_active)
+                        bytes = iohandler_ssl_read(iofd, iofd->readbuf.buffer + iofd->readbuf.bufpos, iofd->readbuf.buflen - iofd->readbuf.bufpos);
+                    else
+                        bytes = recv(iofd->fd, iofd->readbuf.buffer + iofd->readbuf.bufpos, iofd->readbuf.buflen - iofd->readbuf.bufpos, 0);
                     if(bytes <= 0) {
                         if (errno != EAGAIN) {
                             iofd->state = IO_CLOSED;
@@ -631,6 +660,8 @@ char *iohandler_iostatus_name(enum IOStatus status) {
             return "IO_CONNECTING";
         case IO_CONNECTED:
             return "IO_CONNECTED";
+        case IO_SSLWAIT:
+            return "IO_SSLWAIT";
         default:
             return "(UNDEFINED)";
     }