X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=server.c;h=b2a564d9767a23cb73921fa3c51c204125c24ecb;hb=refs%2Fheads%2Fmaster;hp=711f472072027be472342aa4f51b78beba70a1d9;hpb=06ec805762c1a44c6297b8b98ae7e3cc899ee6e3;p=webserver.git diff --git a/server.c b/server.c index 711f472..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,86 +24,252 @@ #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 */ +#define BACKLOG 5 #define BUFFER_SIZE 4096 +#define TIMEOUT 100000 /* 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; -socket_t open_listening_socket (int port) +/* stop server */ + +void stop_server (int sig) +{ + VERBOSE (INFO, PRINT ("Signal: %d\n", sig)); + terminate_network_context (); + exit (0); +} + +/* init network context */ + +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: %d\n", ERRNO)); - rc = closesocket (sock); - if (rc == SOCKET_ERROR) { - VERBOSE (ERROR, fprintf (stderr, "error: %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, "%s\n", "setsockopt/TCP_NODELAY")); - closesocket (sock); - if (rc == SOCKET_ERROR) { - VERBOSE (ERROR, fprintf (stderr, "error: %d\n", ERRNO)); - } - return -1; + VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY")); + _closesocket (_sock); + return 0; } - return sock; + rc = listen (_sock, BACKLOG); + if (rc < 0) { + VERBOSE (ERROR, PERROR ("error: %s\n", "listen")); + _closesocket (_sock); + return 0; + } + + sock = _sock; + + return 1; } -/* close listening socket */ -void close_listening_socket (socket_t sock) +/* accept incomming connection */ + +int accept_incoming_connection (void) { - int rc = closesocket (sock); - if (rc == SOCKET_ERROR) { - VERBOSE (ERROR, fprintf (stderr, "error: %d\n", ERRNO)); + if (sock == INVALID_SOCKET) { + VERBOSE (ERROR, PERROR ("Can't accept connection from closed socket\n")); + return 0; } -#ifdef _WIN32 /* Windows */ - WSACleanup (); + + 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 (_conn, F_SETFL, O_NONBLOCK); #endif + int val = 1; + int rc = setsockopt (_conn, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val)); + if (rc < 0) { + VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY")); + _closesocket (_conn); + return 0; + } + + conn = _conn; + + return 1; } -/* vim: set ts=4 sw=4 et: */ +/* close connection socket */ + +void close_connection (void) +{ + _closesocket (conn); + conn = INVALID_SOCKET; +} + +/* receive data from socket */ + +int receive_data (char **pdata) +{ + char buffer[BUFFER_SIZE] = {0}; + char *data = NULL; + int len = 0; + + if (conn == INVALID_SOCKET) { + VERBOSE (ERROR, PERROR ("Can't read data from closed socket\n")); + return 0; + } + + 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; + } + } + + 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: */