#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
/* 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;
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) {
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: */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include "debug.h"
#include "server.h"
char *progname = NULL;
int port = 8080;
socket_t sock = INVALID_SOCKET;
+socket_t conn = INVALID_SOCKET;
/* help function */
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 */
}
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"));
/* 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;
}