From 89f0e084c2855dce141b64278a1bd5ed9eba7a5a Mon Sep 17 00:00:00 2001 From: Laurent Mazet Date: Sun, 14 May 2023 16:46:16 +0200 Subject: [PATCH] buggy code (2) --- server.c | 145 ++++++++++++++++++++++++++++++++++++---------------- server.h | 10 +++- webserver.c | 65 +++++++++++------------ 3 files changed, 144 insertions(+), 76 deletions(-) diff --git a/server.c b/server.c index 10517ca..1535ef3 100644 --- a/server.c +++ b/server.c @@ -5,6 +5,7 @@ #include #include #include +#include #ifdef _WIN32 /* Windows */ #include #include @@ -16,25 +17,26 @@ #include //#include //#include +#include #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: */ diff --git a/server.h b/server.h index 0738e5a..679ef46 100644 --- 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__ */ diff --git a/webserver.c b/webserver.c index 9861836..5de4db8 100644 --- a/webserver.c +++ b/webserver.c @@ -5,6 +5,7 @@ #include #include #include +#include #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; } -- 2.30.2