/* cflags: */
/* linker: color.o debug.o */
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
+#ifdef _WIN32 /* Windows */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else /* Posix */
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
#include "debug.h"
+/* types */
+
+#ifdef _WIN32 /* Windows */
+typedef SOCKET socket_t;
+#else /* Posix */
+typedef int socket_t;
+#endif
+
/* constants */
#define BUFFER_SIZE 4096
return ret;
}
+/* open listening socket */
+
+socket_t open_listening_socket (int port)
+{
+#ifdef _WIN32 /* Windows */
+ WSADATA WSAData;
+ WSAStartup (MAKEWORD(2,0), &WSAData);
+ assert (INVALID_SOCKET == (socket_t)-1);
+#endif
+
+ VERBOSE (DEBUG, fprintf (stdout, "Opening socket\n"));
+#ifdef _WIN32 /* Windows */
+ socket_t sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock == INVALID_SOCKET)
+ return -1;
+#else /* Posix */
+ socket_t sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (socket < 0)
+ return -1;
+#endif
+
+ struct sockaddr_in addr = {0};
+#ifdef _WIN32 /* Windows */
+ addr.sin_family = AF_INET;
+#else /* Posix */
+ addr.sin_family = PF_INET;
+#endif
+ addr.sin_port = htons (port);
+ addr.sin_addr.s_addr = htonl (INADDR_ANY);
+
+ VERBOSE (DEBUG, fprintf (stdout, "Binding socket\n"));
+ int rc = bind (sock, (struct sockaddr *)&addr, sizeof (addr));
+#ifdef _WIN32 /* Windows */
+ if (rc == SOCKET_ERROR) {
+ VERBOSE (ERROR, fprintf (stderr, "error: %d\n", WSAGetLastError ()));
+ if (closesocket (sock) == SOCKET_ERROR) {
+ VERBOSE (ERROR, fprintf (stderr, "error: %d\n", WSAGetLastError ()));
+ }
+#else /* Posix */
+ if (socket < 0) {
+ VERBOSE (ERROR, fprintf (stderr, "error: %d\n", errno));
+ close (sock);
+#endif
+ return -1;
+ }
+
+ VERBOSE (DEBUG, fprintf (stdout, "Configuring socket\n"));
+#ifdef _WIN32 /* Windows */
+#else /* 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"));
+#ifdef _WIN32 /* Windows */
+ closesocket (sock);
+#else /* Posix */
+ close (sock);
+#endif
+ return -1;
+ }
+
+ return sock;
+}
+
+/* close listening socket */
+void close_listening_socket (socket_t sock)
+{
+#ifdef _WIN32 /* Windows */
+ closesocket (sock);
+ WSACleanup ();
+#else /* Posix */
+ close (sock);
+#endif
+}
+
/* main function */
int main (int argc, char *argv[])
}
}
+ VERBOSE (DEBUG, fprintf (stdout, "Initializing socket\n"));
+ socket_t sock = open_listening_socket (port);
+ if (sock == (socket_t)-1) {
+ VERBOSE (ERROR, fprintf (stderr, "Can't open listening socket\n"));
+ return 1;
+ }
+
+ VERBOSE (INFO, fprintf (stdout, "Listening socket on port %d\n", port));
+ sleep (2);
+
+ VERBOSE (DEBUG, fprintf (stdout, "Closing socket\n"));
+ close_listening_socket (sock);
+
return ret;
}
// test: webserver.exe -v 2>&1 | grep -q 'missing verbose level'
// test: webserver.exe -p 2>&1 | grep -q 'missing port number'
// test: webserver.exe -p -1 2>&1 | grep -q 'incorrect port number'
+// test: webserver.exe | grep -q 'Listening socket on port 8080'
+// test: webserver.exe -p 8000 | grep -q 'Listening socket on port 8000'
/* vim: set ts=4 sw=4 et: */