From f6d435bd2fb5b11d12cc1df11f6d5e31d8d8738d Mon Sep 17 00:00:00 2001 From: Marcel Poul Date: Mon, 14 Nov 2011 12:50:20 +0000 Subject: [PATCH] simple server (wo ssl) added --- emi.canl.canl-c/src/canl.c | 151 ++++++++++++++++++++++++------- emi.canl.canl-c/src/canl_sample_server.c | 23 +++-- 2 files changed, 136 insertions(+), 38 deletions(-) diff --git a/emi.canl.canl-c/src/canl.c b/emi.canl.canl-c/src/canl.c index 009db72..58623b8 100644 --- a/emi.canl.canl-c/src/canl.c +++ b/emi.canl.canl-c/src/canl.c @@ -2,12 +2,16 @@ #include #include #include +#include #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) { diff --git a/emi.canl.canl-c/src/canl_sample_server.c b/emi.canl.canl-c/src/canl_sample_server.c index 6f1f88d..96ff765 100644 --- a/emi.canl.canl-c/src/canl_sample_server.c +++ b/emi.canl.canl-c/src/canl_sample_server.c @@ -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); -- 1.8.2.3