best makefile
[webserver.git] / server.c
index 4f3b24f1c56374d326079c9d904b45e42b4e2504..b2a564d9767a23cb73921fa3c51c204125c24ecb 100644 (file)
--- a/server.c
+++ b/server.c
@@ -1,8 +1,5 @@
-/* depend: */
-/* cflags: */
-/* linker: color.o debug.o */
-
 #include <assert.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
-//#include <sys/types.h>
-//#include <sys/socket.h>
 #include <sys/select.h>
 #endif
+#include <unistd.h>
 
 #include "debug.h"
 
 #include "server.h"
 
-/* compat */
+/* types */
 
 #ifdef _WIN32 /* Windows */
-#define PF_INET AF_INET
-#define ERRNO (WSAGetLastError ())
+typedef SOCKET socket_t;
 #else /* Posix */
-#define closesocket close
-#define ERRNO errno
-#define SOCKET_ERROR -1
+typedef int socket_t;
 #endif
 
-/* types */
-
 /* constants */
 
 #define BACKLOG 5
 
 /* 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 */
 
+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 */
 
 void init_network_context (void)
@@ -54,15 +67,35 @@ 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
+
+#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
@@ -70,137 +103,135 @@ void terminate_network_context (void)
 
 /* open listening socket */
 
-socket_t open_listening_socket (int port)
+int open_listening_socket (int port)
 {
     int val = 1;
 
-    VERBOSE (DEBUG, fprintf (stdout, "Opening socket\n"));
+    VERBOSE (DEBUG, PRINT ("Opening socket\n"));
     //socket_t sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
-    socket_t sock = socket (AF_INET, SOCK_STREAM, 0);
-    if (sock == INVALID_SOCKET) {
-        return -1;
+    _closesocket (sock);
+    socket_t _sock = socket (AF_INET, SOCK_STREAM, 0);
+    if (_sock == INVALID_SOCKET) {
+        return 0;
     }
 
     struct sockaddr_in addr = {0};
-    bzero (&addr, sizeof (addr));
+    //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"));
-    //setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val));
-    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
-    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;
+
+    return 1;
 }
 
 /* accept incomming connection */
 
-socket_t accept_incoming_connection (socket_t sock)
+int accept_incoming_connection (void)
 {
-    socket_t connection = accept (sock, NULL, 0);
-    if (connection < 0) {
-        return INVALID_SOCKET;
+    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;
-    int 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 INVALID_SOCKET;
+        VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY"));
+        _closesocket (_conn);
+        return 0;
     }
 
-    return connection;
+    conn = _conn;
+
+    return 1;
 }
 
-/* close listening socket */
+/* close connection socket */
 
-void close_socket (socket_t sock)
+void close_connection (void)
 {
-    int rc = closesocket (sock);
-    if (rc == SOCKET_ERROR) {
-        VERBOSE (ERROR, fprintf (stderr, "error: %d\n", ERRNO));
-    }
+    _closesocket (conn);
+    conn = INVALID_SOCKET;
 }
 
 /* receive data from socket */
 
-int receive_data (socket_t sock, unsigned char **pdata)
+int receive_data (char **pdata)
 {
-    unsigned char buffer[BUFFER_SIZE] = {0};
-    unsigned char *data = NULL;
+    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 (sock, &rfds);
+        FD_SET (conn, &rfds);
 
-        int retval = select (sock + 1, &rfds, NULL, NULL, &tv);
+        int retval = select (conn + 1, &rfds, NULL, NULL, &tv);
         if (retval != 1) { /* 0 or SOCKET_ERROR */
             break;
         }
 
         /* read from socket */
-        int rc = read (sock, buffer, BUFFER_SIZE);
+        int rc = recv (conn, buffer, BUFFER_SIZE, 0);
+        VERBOSE (DEBUG, PRINT ("rc: %d\nerrno: %d\n", rc, ERRNO));
 
-        if (rc == 0) { /* sock closed */
+        if (rc == 0) { /* sock closed or error */
             if (data) {
                 free (data);
                 data = NULL;
-                len  = 0;
             }
-            break;
-
-        } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */
-            if (data) {
-                free (data);
-                data = NULL;
-            }
-            len  = -1;
+            len  = (rc < 0) ? -1 : 0;
             break;
 
         } else if (rc > 0) {
@@ -218,18 +249,20 @@ int receive_data (socket_t sock, unsigned char **pdata)
 
 /* send data onto socket */
 
-int send_data (socket_t sock, unsigned char *data, int len)
+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 = write (sock, data + index, len - index);
+        int rc = send (conn, data + index, len - index, 0);
 
-        if (rc == 0) { /* sock closed */
-            index = 0;
-            break;
-        } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */
-            index = -1;
+        if (rc <= 0) { /* sock closed or error */
+            index = (rc < 0) ? -1 : 0;
             break;
         } else if (rc > 0) {
             index += rc;