backbone server is ready
[webserver.git] / server.c
index 711f472072027be472342aa4f51b78beba70a1d9..574e54a53830b2dc24029dac66f1d015a9ac2518 100644 (file)
--- a/server.c
+++ b/server.c
@@ -5,6 +5,7 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #ifdef _WIN32 /* Windows */
 #include <winsock2.h>
 #include <ws2tcpip.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"
 
-/* types */
+/* compat */
 
 #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
 
+/* types */
+
 /* constants */
 
+#define BACKLOG 5
 #define BUFFER_SIZE 4096
+#define TIMEOUT 100000
 
 /* macros */
 
 /* gobal variables */
 
-/* open listening socket */
+/* init network context */
 
-socket_t open_listening_socket (int port)
+void init_network_context (void)
 {
 #ifdef _WIN32 /* Windows */
     WSADATA WSAData;
@@ -53,40 +58,69 @@ socket_t open_listening_socket (int port)
     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);
+/* terminate network context */
+
+void terminate_network_context (void)
+{
+#ifdef _WIN32 /* Windows */
+    WSACleanup ();
+#endif
+}
+
+/* open listening socket */
+
+socket_t open_listening_socket (int port)
+{
+    int val = 1;
+
+    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;
     }
 
     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"));
+    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));
+        VERBOSE (ERROR, PERROR ("error: bind %d\n", ERRNO));
         rc = closesocket (sock);
         if (rc == SOCKET_ERROR) {
-            VERBOSE (ERROR, fprintf (stderr, "error: %d\n", ERRNO));
+            VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
         }
         return -1;
     }
 
-    VERBOSE (DEBUG, fprintf (stdout, "Configuring socket\n"));
+    VERBOSE (DEBUG, PRINT ("Configuring socket\n"));
 #ifndef _WIN32 /* Posix */
     fcntl (sock, F_SETFL, O_NONBLOCK);
 #endif
-    int val = 1;
     rc = setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
     if (rc < 0) {
-        VERBOSE (ERROR, fprintf (stderr, "%s\n", "setsockopt/TCP_NODELAY"));
+        VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY"));
+        closesocket (sock);
+        if (rc == SOCKET_ERROR) {
+            VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
+        }
+        return -1;
+    }
+
+    rc = listen (sock, BACKLOG);
+    if (rc < 0) {
+        VERBOSE (ERROR, PERROR ("error: %s\n", "listen"));
         closesocket (sock);
         if (rc == SOCKET_ERROR) {
-            VERBOSE (ERROR, fprintf (stderr, "error: %d\n", ERRNO));
+            VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
         }
         return -1;
     }
@@ -94,18 +128,116 @@ socket_t open_listening_socket (int port)
     return sock;
 }
 
+/* accept incomming connection */
+
+socket_t accept_incoming_connection (socket_t sock)
+{
+    socket_t connection = accept (sock, NULL, 0);
+    if (connection == INVALID_SOCKET) {
+        return INVALID_SOCKET;
+    }
+
+#ifndef _WIN32 /* POSIX */
+    fcntl (connection, F_SETFL, O_NONBLOCK);
+#endif
+    int val = 1;
+    int rc = setsockopt (connection, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
+    if (rc < 0) {
+        VERBOSE (ERROR, PERROR ("error: %s\n", "setsockopt/TCP_NODELAY"));
+        closesocket (connection);
+        if (rc == SOCKET_ERROR) {
+            VERBOSE (ERROR, PERROR ("error: close %d\n", ERRNO));
+        }
+        return INVALID_SOCKET;
+    }
+
+    return connection;
+}
+
 /* close listening socket */
-void close_listening_socket (socket_t sock)
+
+void close_socket (socket_t sock)
 {
     int rc = closesocket (sock);
     if (rc == SOCKET_ERROR) {
-        VERBOSE (ERROR, fprintf (stderr, "error: %d\n", ERRNO));
+        VERBOSE (ERROR, PERROR ("error: %d\n", ERRNO));
     }
-#ifdef _WIN32 /* Windows */
-    WSACleanup ();
-#endif
 }
 
-/* vim: set ts=4 sw=4 et: */
+/* receive data from socket */
+
+int receive_data (socket_t sock, unsigned char **pdata)
+{
+    unsigned char buffer[BUFFER_SIZE] = {0};
+    unsigned char *data = NULL;
+    int len = 0;
+
+    while (1) {
+
+        /* timeout management */
+        fd_set rfds;
+        struct timeval tv = { 0, TIMEOUT };
+        FD_ZERO (&rfds);
+        FD_SET (sock, &rfds);
+
+        int retval = select (sock + 1, &rfds, NULL, NULL, &tv);
+        if (retval != 1) { /* 0 or SOCKET_ERROR */
+            break;
+        }
+
+        /* read from socket */
+        int rc = read (sock, buffer, BUFFER_SIZE);
+
+        if (rc == 0) { /* sock closed */
+            if (data) {
+                free (data);
+                data = NULL;
+                len  = 0;
+            }
+            break;
+
+        } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */
+            if (data) {
+                free (data);
+                data = NULL;
+            }
+            len  = -1;
+            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 (socket_t sock, unsigned char *data, int len)
+{
+    int index = 0;
+
+    while (index < len) {
+        int rc = write (sock, data + index, len - index);
+
+        if (rc == 0) { /* sock closed */
+            index = 0;
+            break;
+        } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */
+            index = -1;
+            break;
+        } else if (rc > 0) {
+            index += rc;
+        }
+    }
+
+    return index;
+}
 
 /* vim: set ts=4 sw=4 et: */