buggy code (2)
authorLaurent Mazet <mazet@softndesign.org>
Sun, 14 May 2023 14:46:16 +0000 (16:46 +0200)
committerLaurent Mazet <mazet@softndesign.org>
Sun, 14 May 2023 14:46:16 +0000 (16:46 +0200)
server.c
server.h
webserver.c

index 10517ca72b32ece41ace52565c2146e2ac8cc851..1535ef39e5157480fdd73f5cf5beaa3fa1524d20 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 "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
@@ -45,9 +47,9 @@ typedef int socket_t;
 
 /* 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;
@@ -55,7 +57,21 @@ socket_t open_listening_socket (int port)
     assert (INVALID_SOCKET == (socket_t)-1);
     assert (SOCKET_ERROR == -1);
 #endif
+}
+
+/* terminate network context */
+
+void terminate_network_context (void)
+{
+#ifdef _WIN32 /* Windows */
+    WSACleanup ();
+#endif
+}
 
+/* open listening socket */
+
+socket_t open_listening_socket (int port)
+{
     VERBOSE (DEBUG, fprintf (stdout, "Opening socket\n"));
     socket_t sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (sock == INVALID_SOCKET) {
@@ -106,73 +122,116 @@ socket_t open_listening_socket (int port)
     return 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
-}
-
 /* accept incomming connection */
 
-int accept_incoming_connection (socket_t sock)
+socket_t accept_incoming_connection (socket_t sock)
 {
-    int connection = accept (sock, NULL, 0);
+    socket_t connection = accept (sock, NULL, 0);
     if (connection < 0) {
-        return connection;
+        return INVALID_SOCKET;
     }
 
 #ifndef _WIN32 /* POSIX */
     fcntl (connection, F_SETFL, O_NONBLOCK);
 #endif
     int val = 1;
-    rc = setsockopt (connection, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof (val));
+    int rc = setsockopt (connection, 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;
+        return INVALID_SOCKET;
     }
 
     return connection;
 }
 
-/* receive data */
-int receive_data (socket_t sock, unsigned char data, int maxlen)
+/* close listening socket */
+
+void close_socket (socket_t sock)
 {
+    int rc = closesocket (sock);
+    if (rc == SOCKET_ERROR) {
+        VERBOSE (ERROR, fprintf (stderr, "error: %d\n", ERRNO));
+    }
+}
 
-    /* timeout management */
-    fd_set rfds;
-    struct timeval tv = { 0, TIMEOUT };
-    FD_ZERO (&rfds);
-    FD_SET (sock, &rfds);
+/* receive data from socket */
 
-    int retval = select (sock + 1, &rfds, NULL, NULL, &tv);
-    if (retval != 1)
-        return retval; /* 0 or SOCKET_ERROR */
+int receive_data (socket_t sock, unsigned char **pdata)
+{
+    unsigned char buffer[BUFFER_SIZE] = {0};
+    unsigned char *data = NULL;
+    int len = 0;
 
-    /* read from socket */
-    int len = read (sock, data, maxlen);
+    while (1) {
 
-    if (rc = 0) { /* sock closed */
-        return 0;
-    } else if ((rc < 0) && (ERRNO != EAGAIN)) { /* error */
-        return -1;
-    } else if (rc > 0) {
-        return len;
-    }
+        /* 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;
+        }
 
-    /* do we retry ? */
+        /* 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;
+        }
+    }
 
-    return -2;
+    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: */
index 0738e5a41f9832f96a861c93d3510effeb443437..679ef462bb44b548d76a0bb9b2ebddb33b6995ef 100644 (file)
--- a/server.h
+++ b/server.h
@@ -9,8 +9,16 @@ typedef int socket_t;
 #define INVALID_SOCKET -1
 #endif
 
+void init_network_context (void);
+void terminate_network_context (void);
+
 socket_t open_listening_socket (int port);
-void close_listening_socket (socket_t sock);
+socket_t accept_incoming_connection (socket_t sock);
+
+void close_socket (socket_t sock);
+
+int receive_data (socket_t sock, unsigned char **pdata);
+int send_data (socket_t sock, unsigned char *data, int len);
 
 #endif /* __SERVER_H__ */
 
index 9861836fc5abcdcff7b1649f27cc8003e93ae2b5..5de4db83effcc5c8c90acb7066421aba74059c2e 100644 (file)
@@ -5,6 +5,7 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 #include "debug.h"
 #include "server.h"
@@ -23,6 +24,7 @@
 char *progname = NULL;
 int port = 8080;
 socket_t sock = INVALID_SOCKET;
+socket_t conn = INVALID_SOCKET;
 
 /* help function */
 
@@ -39,10 +41,14 @@ int usage (int ret)
 
 void stop_server (__attribute__((unused)) int sig)
 {
+    if (conn != INVALID_SOCKET) {
+        close_socket (conn);
+    }
     if (sock != INVALID_SOCKET) {
-        close_listening_socket (sock);
-        exit (0);
+        close_socket (sock);
     }
+    terminate_network_context ();
+    exit (0);
 }
 
 /* main function */
@@ -100,6 +106,7 @@ int main (int argc, char *argv[])
     }
 
     VERBOSE (DEBUG, fprintf (stdout, "Initializing socket\n"));
+    init_network_context ();
     sock = open_listening_socket (port);
     if (sock == INVALID_SOCKET) {
         VERBOSE (ERROR, fprintf (stderr, "Can't open listening socket\n"));
@@ -109,49 +116,43 @@ int main (int argc, char *argv[])
 
     /* main loop */
     while (1) {
-        int connection = accept_incoming_connection (sock);
-        if ((connection < 0) && (errno == EAGAIN)) {
-            accept_nonblock_ok = 1;
-        }
-        if (connection < 0) {
-            sleep (1);
+        conn = accept_incoming_connection (sock);
+        if (conn == INVALID_SOCKET) {
+            usleep (1e5);
             continue;
         }
 
         VERBOSE (DEBUG, fprintf (stdout, "Server connected, waiting for data\n"));
 
-        while (1) {
-            unsigned char data[BUFFER_SIZE] = {0};
-            int len = 0;
+        unsigned char *data = {0};
 
-            len = receive_data (connection, data, size (data));
-            if (len == 0) {
-                // nonblocking connection
-                sleep (1);
-                continue;
-            }
-            if (len < 0) {
-                VERBOSE (WARNING, fprintf (stdout, "Connection closed by peer\n"));
-                close_connection (connection);
-                break;
-            }
+        int len = receive_data (conn, &data);
+        if (len == 0) {
+            VERBOSE (WARNING, fprintf (stdout, "Connection closed by peer (rx)\n"));
+        } else if (len < 0) {
+            VERBOSE (WARNING, fprintf (stdout, "Connection in error (rx)\n"));
+        } else {
 
             // processing
-            
-            len = send_data (connection, data, size (data));
-            if (len < 0) {
-                VERBOSE (WARNING, fprintf (stdout, "Connection closed by peer\n"));
-                close_connection (connection);
-                break;
+
+            int rc = send_data (conn, data, len);
+            if (rc == 0) {
+                VERBOSE (WARNING, fprintf (stdout, "Connection closed by peer (tx)\n"));
+            } else if (rc < 0) {
+                VERBOSE (WARNING, fprintf (stdout, "Connection in error (tx)\n"));
             }
+        }
 
-            /* sleep so that we go trhough remaining data in receive buffer */
-            usleep (1e5);
+        if (data) {
+            free (data);
         }
+        close_socket (conn);
+        conn = INVALID_SOCKET;
     }
-
+    
     VERBOSE (DEBUG, fprintf (stdout, "Closing socket\n"));
-    close_listening_socket (sock);
+    close_socket (sock);
+    terminate_network_context ();
 
     return 2;
 }