X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=server.c;h=b2a564d9767a23cb73921fa3c51c204125c24ecb;hb=refs%2Fheads%2Fmaster;hp=10517ca72b32ece41ace52565c2146e2ac8cc851;hpb=04a2223db2463c9c66c7f5eb24aab0d8da3dfa16;p=webserver.git diff --git a/server.c b/server.c index 10517ca..b2a564d 100644 --- a/server.c +++ b/server.c @@ -1,10 +1,8 @@ -/* depend: */ -/* cflags: */ -/* linker: color.o debug.o */ - #include +#include #include #include +#include #ifdef _WIN32 /* Windows */ #include #include @@ -14,9 +12,9 @@ #include #include #include -//#include -//#include +#include #endif +#include #include "debug.h" @@ -26,13 +24,8 @@ #ifdef _WIN32 /* Windows */ typedef SOCKET socket_t; -#define PF_INET AF_INET -#define ERRNO (WSAGetLastError ()) #else /* Posix */ typedef int socket_t; -#define closesocket close -#define ERRNO errno -#define SOCKET_ERROR -1 #endif /* constants */ @@ -43,136 +36,240 @@ typedef int socket_t; /* macros */ +#ifdef _WIN32 /* Windows */ +#define PF_INET AF_INET +#define ERRNO (WSAGetLastError ()) +#else /* Posix */ +#define closesocket close +#define ERRNO errno +#define SOCKET_ERROR -1 +#define INVALID_SOCKET -1 +#endif + /* gobal variables */ -/* open listening socket */ +socket_t sock = INVALID_SOCKET; +socket_t conn = INVALID_SOCKET; + +/* stop server */ + +void stop_server (int sig) +{ + VERBOSE (INFO, PRINT ("Signal: %d\n", sig)); + terminate_network_context (); + exit (0); +} + +/* init network context */ -socket_t open_listening_socket (int port) +void init_network_context (void) { #ifdef _WIN32 /* Windows */ WSADATA WSAData; WSAStartup (MAKEWORD(2,0), &WSAData); + assert (INVALID_SOCKET == (socket_t)-1); assert (SOCKET_ERROR == -1); #endif - VERBOSE (DEBUG, fprintf (stdout, "Opening socket\n")); - socket_t sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock == INVALID_SOCKET) { - return -1; +#ifndef _WIN32 /* Posix */ + signal (SIGINT, &stop_server); +#endif + signal (SIGABRT, &stop_server); + signal (SIGSEGV, &stop_server); + signal (SIGTERM, &stop_server); +} + +/* terminate network context */ + +void _closesocket (socket_t sock) +{ + if (sock != INVALID_SOCKET) { + int rc = closesocket (sock); + if (rc == SOCKET_ERROR) { + VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO)); + } + } +} + +void terminate_network_context (void) +{ + _closesocket (sock); + _closesocket (conn); +#ifdef _WIN32 /* Windows */ + WSACleanup (); +#endif +} + +/* open listening socket */ + +int open_listening_socket (int port) +{ + int val = 1; + + VERBOSE (DEBUG, PRINT ("Opening socket\n")); + //socket_t sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + _closesocket (sock); + socket_t _sock = socket (AF_INET, SOCK_STREAM, 0); + if (_sock == INVALID_SOCKET) { + return 0; } struct sockaddr_in addr = {0}; - addr.sin_family = PF_INET; + //bzero (&addr, sizeof (addr)); + //addr.sin_family = PF_INET; + addr.sin_family = AF_INET; addr.sin_port = htons (port); addr.sin_addr.s_addr = htonl (INADDR_ANY); - VERBOSE (DEBUG, fprintf (stdout, "Binding socket\n")); - int rc = bind (sock, (struct sockaddr *)&addr, sizeof (addr)); + VERBOSE (DEBUG, PRINT ("Binding socket\n")); + //setsockopt (_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val)); + int rc = bind (_sock, (struct sockaddr *)&addr, sizeof (addr)); if (rc == SOCKET_ERROR) { - VERBOSE (ERROR, fprintf (stderr, "error: bind %d\n", ERRNO)); - rc = closesocket (sock); - if (rc == SOCKET_ERROR) { - VERBOSE (ERROR, fprintf (stderr, "error: close %d\n", ERRNO)); - } - return -1; + VERBOSE (ERROR, PERROR ("error: bind %d\n", ERRNO)); + _closesocket (_sock); + return 0; } - VERBOSE (DEBUG, fprintf (stdout, "Configuring socket\n")); + VERBOSE (DEBUG, PRINT ("Configuring socket\n")); #ifndef _WIN32 /* Posix */ - fcntl (sock, F_SETFL, O_NONBLOCK); + fcntl (_sock, F_SETFL, O_NONBLOCK); #endif - int val = 1; - rc = setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val)); + rc = setsockopt (_sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val)); if (rc < 0) { - VERBOSE (ERROR, fprintf (stderr, "error: %s\n", "setsockopt/TCP_NODELAY")); - closesocket (sock); - if (rc == SOCKET_ERROR) { - VERBOSE (ERROR, fprintf (stderr, "error: close %d\n", ERRNO)); - } - return -1; + VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY")); + _closesocket (_sock); + return 0; } - rc = listen (sock, BACKLOG); + rc = listen (_sock, BACKLOG); if (rc < 0) { - VERBOSE (ERROR, fprintf (stderr, "error: %s\n", "listen")); - closesocket (sock); - if (rc == SOCKET_ERROR) { - VERBOSE (ERROR, fprintf (stderr, "error: close %d\n", ERRNO)); - } - return -1; + VERBOSE (ERROR, PERROR ("error: %s\n", "listen")); + _closesocket (_sock); + return 0; } - return sock; -} + sock = _sock; -/* close listening socket */ -void close_listening_socket (socket_t sock) -{ - int rc = closesocket (sock); - if (rc == SOCKET_ERROR) { - VERBOSE (ERROR, fprintf (stderr, "error: %d\n", ERRNO)); - } -#ifdef _WIN32 /* Windows */ - WSACleanup (); -#endif + return 1; } /* accept incomming connection */ -int accept_incoming_connection (socket_t sock) +int accept_incoming_connection (void) { - int connection = accept (sock, NULL, 0); - if (connection < 0) { - return connection; + if (sock == INVALID_SOCKET) { + VERBOSE (ERROR, PERROR ("Can't accept connection from closed socket\n")); + return 0; + } + + if (conn != INVALID_SOCKET) { + _closesocket (conn); + conn = INVALID_SOCKET; + } + socket_t _conn = accept (sock, NULL, 0); + if (_conn == INVALID_SOCKET) { + return 0; } #ifndef _WIN32 /* POSIX */ - fcntl (connection, F_SETFL, O_NONBLOCK); + fcntl (_conn, F_SETFL, O_NONBLOCK); #endif int val = 1; - rc = setsockopt (connection, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val)); + int rc = setsockopt (_conn, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val)); if (rc < 0) { - VERBOSE (ERROR, fprintf (stderr, "error: %s\n", "setsockopt/TCP_NODELAY")); - closesocket (connection); - if (rc == SOCKET_ERROR) { - VERBOSE (ERROR, fprintf (stderr, "error: close %d\n", ERRNO)); - } - return -1; + VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY")); + _closesocket (_conn); + return 0; } - return connection; + conn = _conn; + + return 1; } -/* receive data */ -int receive_data (socket_t sock, unsigned char data, int maxlen) -{ +/* close connection socket */ - /* timeout management */ - fd_set rfds; - struct timeval tv = { 0, TIMEOUT }; - FD_ZERO (&rfds); - FD_SET (sock, &rfds); +void close_connection (void) +{ + _closesocket (conn); + conn = INVALID_SOCKET; +} - int retval = select (sock + 1, &rfds, NULL, NULL, &tv); - if (retval != 1) - return retval; /* 0 or SOCKET_ERROR */ +/* receive data from socket */ - /* read from socket */ - int len = read (sock, data, maxlen); +int receive_data (char **pdata) +{ + char buffer[BUFFER_SIZE] = {0}; + char *data = NULL; + int len = 0; - if (rc = 0) { /* sock closed */ + if (conn == INVALID_SOCKET) { + VERBOSE (ERROR, PERROR ("Can't read data from closed socket\n")); return 0; - } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */ - return -1; - } else if (rc > 0) { - return len; } - /* do we retry ? */ + while (1) { + + /* timeout management */ + fd_set rfds; + struct timeval tv = { 0, TIMEOUT }; + FD_ZERO (&rfds); + FD_SET (conn, &rfds); + + int retval = select (conn + 1, &rfds, NULL, NULL, &tv); + if (retval != 1) { /* 0 or SOCKET_ERROR */ + break; + } + + /* read from socket */ + int rc = recv (conn, buffer, BUFFER_SIZE, 0); + VERBOSE (DEBUG, PRINT ("rc: %d\nerrno: %d\n", rc, ERRNO)); + + if (rc == 0) { /* sock closed or error */ + if (data) { + free (data); + data = NULL; + } + len = (rc < 0) ? -1 : 0; + break; + + } else if (rc > 0) { + data = realloc (data, len + rc); + memcpy (data + len, buffer, rc); + len += rc; + } + } - return -2; + if (pdata != NULL) { + *pdata = data; + } + return len; } +/* send data onto socket */ + +int send_data (char *data, int len) +{ + int index = 0; + + if (conn == INVALID_SOCKET) { + VERBOSE (ERROR, PERROR ("Can't read data from closed socket\n")); + return 0; + } + + while (index < len) { + int rc = send (conn, data + index, len - index, 0); + + if (rc <= 0) { /* sock closed or error */ + index = (rc < 0) ? -1 : 0; + break; + } else if (rc > 0) { + index += rc; + } + } + + return index; +} /* vim: set ts=4 sw=4 et: */