simple server (wo ssl) added
authorMarcel Poul <marcel.poul@cern.ch>
Mon, 14 Nov 2011 12:50:20 +0000 (12:50 +0000)
committerMarcel Poul <marcel.poul@cern.ch>
Mon, 14 Nov 2011 12:50:20 +0000 (12:50 +0000)
emi.canl.canl-c/src/canl.c
emi.canl.canl-c/src/canl_sample_server.c

index 009db72..58623b8 100644 (file)
@@ -2,12 +2,16 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <arpa/inet.h>
+#include <unistd.h>
 #include "canl.h"
 #include "canl_locl.h"
 #include "sys/socket.h"
 #include "string.h"
 
+#define BACKLOG 10 //TODO just for testing - max incoming connections
+
 static void io_clean(canl_ctx cc, canl_io_handler io);
+static int init_io_content(io_handler *io);
 
 canl_ctx canl_create_ctx()
 {
@@ -68,6 +72,7 @@ end:
 canl_io_handler canl_create_io_handler(canl_ctx cc)
 {
     io_handler *new_io_h = NULL;
+    int err = 0;
 
     if (!cc) {
         goto end;
@@ -77,17 +82,57 @@ canl_io_handler canl_create_io_handler(canl_ctx cc)
     new_io_h = (io_handler *) malloc(sizeof(*new_io_h));
     if (!new_io_h)
         //set_error(ctx->err_msg);
-        goto end;
+        return NULL;
 
     /*read cc and set io_handler accordingly ...*/
     new_io_h->ar = NULL;
     new_io_h->s_addr = NULL;
     new_io_h->sock = -1;
 
+    /* allocate memory and initialize io content*/
+    if (init_io_content(new_io_h)){
+        err = 1;
+        goto end;
+    }
+
 end:
+    if (err) {
+        canl_io_destroy(cc, (canl_io_handler)new_io_h);
+        new_io_h = NULL;
+    }
     return new_io_h;
 }
 
+static int init_io_content(io_handler *io)
+{
+    int err = 0;
+    if (!io) {
+        err = 1;
+        goto end;
+    }
+
+    io->ar = (asyn_result *) calloc(1, sizeof(*(io->ar)));
+    if (!io->ar) {
+        err = 1;
+        goto end;
+    }
+
+    io->ar->ent = (struct hostent *) calloc(1, sizeof(struct hostent));
+    if (!io->ar->ent) {
+        err=1;
+        goto end;
+    }
+
+    io->s_addr = (struct sockaddr *) calloc(1, sizeof(struct sockaddr));
+    if (!io->s_addr) {
+        err = 1;
+        goto end;
+    }
+
+end:
+    return err;
+}
+
 int canl_io_connect(canl_ctx cc, canl_io_handler io, char * host, int port, 
         int flags, cred_handler ch, struct timeval *timeout)
 {
@@ -103,37 +148,17 @@ int canl_io_connect(canl_ctx cc, canl_io_handler io, char * host, int port,
         goto end;
     }
 
-    if (!io) {
-        err = 1;
-        goto end;
-    }
-    if (io_cc->ar) {
-        free (io_cc->ar);
-        io_cc->ar = NULL;
-    }
-    io_cc->ar = (asyn_result *) malloc(sizeof(*(io_cc->ar)));
-    if (!io_cc->ar) {
+    if (!io_cc || !io_cc->ar || !io_cc->ar->ent || !io_cc->s_addr) {
         err = 1;
         goto end;
     }
-    io_cc->ar->ent = (struct hostent *) calloc (1, sizeof(struct hostent));
-    if (!io_cc->ar->ent) {
-        err=1;
-        goto end;
-    }
 
     /*dns TODO - wrap it for using ipv6 and ipv4 at the same time*/
     err = asyn_getservbyname(AF_INET, io_cc->ar, host, NULL);
     if (err)
         goto end;
     
-    io_cc->s_addr = (struct sockaddr *) malloc(sizeof(struct sockaddr));
-    if (!io_cc->s_addr) {
-        err = 1;
-        goto end;
-    }
     sa_in = (struct sockaddr_in *) io_cc->s_addr;
-    
 
     /*open socket TODO just for testing purpose*/
     sock = socket(AF_INET, SOCK_STREAM, 0);
@@ -146,6 +171,8 @@ int canl_io_connect(canl_ctx cc, canl_io_handler io, char * host, int port,
     memcpy(&sa_in->sin_addr.s_addr, io_cc->ar->ent->h_addr, sizeof(struct in_addr));
     err = connect(io_cc->sock, (struct sockaddr*) sa_in, sizeof(*sa_in));
 
+    /*TODO Maybe continue with select()*/
+
     /*call openssl */
 
     /*write succes or failure to cc, io*/
@@ -164,24 +191,82 @@ int canl_io_accept(canl_ctx cc, canl_io_handler io, int port,
         int flags, cred_handler ch, struct timeval *timeout, 
         canl_io_handler *new_io)
 {
-    int err;
+    int err = 0, sockfd = 0, new_fd = 0;
     io_handler *io_cc = (io_handler*) io;
     glb_ctx *glb_cc = (glb_ctx*) cc;
+    io_handler **io_new_cc = (io_handler**) new_io;
+
+    struct addrinfo hints, *servinfo, *p;
+    socklen_t sin_size;
+    int yes=1;
+    int rv;
+    char * PORT = "4321"; //TODO for testing purposes only
 
     /*check cc and io*/
-    if (!cc) {
-        err = 1;
+    if (!cc) 
+        return -1;
+
+    if (!io_cc || !io_cc->ar || !io_cc->ar->ent || !io_cc->s_addr) {
+        err = -1;
         goto end;
     }
-
-    if (!io) {
-        //set_error(ctx->err_msg);
-        err = 1;
+    if (!*io_new_cc || !(*io_new_cc)->ar || !(*io_new_cc)->ar->ent 
+            || !(*io_new_cc)->s_addr) {
+        err = -1;
         goto end;
     }
-    /*check cc and io*/
+
+    memset(&hints, 0, sizeof hints);
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_PASSIVE; // use my IP
+
+    if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
+        // set err - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
+        return -1;
+    }
+    for(p = servinfo; p != NULL; p = p->ai_next) {
+        if ((sockfd = socket(p->ai_family, p->ai_socktype,
+                        p->ai_protocol)) == -1) {
+            // set err - perror("server: socket");
+            continue;
+        }
+        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
+                    sizeof(int)) == -1) {
+            // set err - perror("setsockopt");
+            return -1;
+        }
+        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
+            close(sockfd);
+            // set err - perror("server: bind");
+            continue;
+        }
+        break;
+    }
+
+    if (p == NULL) {
+        // set err - fprintf(stderr, "server: failed to bind\n");
+        return -2;
+    }
+
+    freeaddrinfo(servinfo); // all done with this structure
+
+    if (listen(sockfd, BACKLOG) == -1) {
+        // set err - perror("listen");
+        return -1;
+    }
 
     /*wait for client*/
+    printf("server: waiting for connections...\n");
+    sin_size = sizeof((*io_new_cc)->s_addr);
+    new_fd = accept(sockfd, (*io_new_cc)->s_addr, &sin_size);
+    if (new_fd == -1) 
+        // set err - perror("accept");
+        return -1;
+
+    /* TODO everything fine - set new_io_cc according to their_addr*/
+
+    return new_fd; //TODO compare return value with API
 
     /*call openssl to make a secured connection, optional?*/
 
@@ -232,10 +317,12 @@ static void io_clean(canl_ctx cc, canl_io_handler io)
         return;
     }
 
-    // delete io_handle content
+    // delete io_handler content
     if (io_cc->ar) {
-        free_hostent(io_cc->ar->ent);
+        if (io_cc->ar->ent)
+            free_hostent(io_cc->ar->ent);
         io_cc->ar->ent = NULL;
+        free (io_cc->ar);
         io_cc->ar = NULL;
     }
     if (io_cc->s_addr) {
index 6f1f88d..96ff765 100644 (file)
@@ -5,6 +5,7 @@ int main()
 {
     canl_ctx my_ctx;
     canl_io_handler my_io_h;
+    canl_io_handler my_new_io_h;
     int err = 0;
     char *err_msg = NULL;
 
@@ -19,17 +20,17 @@ int main()
         //set_error("io handler cannot be created\n");
         goto end;
     }
-
-    err = canl_io_accept(my_ctx, my_io_h, 1234, 0, NULL, NULL, NULL);
-    if (err) {
-        //set_error("cannot make a connection");
+    
+    my_new_io_h = canl_create_io_handler(my_ctx);
+    if (!my_new_io_h) {
+        //set_error("io handler cannot be created\n");
         goto end;
     }
 
-    err = canl_io_connect(my_ctx, my_io_h, "", 1234, 0, NULL, NULL);
+    /* canl_create_io_handler has to be called for my_new_io_h and my_io_h*/
+    err = canl_io_accept(my_ctx, my_io_h, 4321, 0, NULL, NULL, &my_new_io_h);
     if (err) {
         //set_error("cannot make a connection");
-        canl_io_destroy(my_ctx, my_io_h);
         goto end;
     }
 
@@ -52,6 +53,16 @@ int main()
     if (err){
         //set_error ("cannot destroy io");
     }
+    
+    err = canl_io_close(my_ctx, my_new_io_h);
+    if (err){
+        //set_error ("cannot close io");
+    }
+
+    err = canl_io_destroy(my_ctx, my_new_io_h);
+    if (err){
+        //set_error ("cannot destroy io");
+    }
 
 end:
     canl_get_error(my_ctx, &err_msg);