summaryrefslogtreecommitdiffstats
path: root/nserver
diff options
context:
space:
mode:
authorrsiddharth <s@ricketyspace.net>2019-08-24 19:26:17 -0400
committerrsiddharth <s@ricketyspace.net>2020-04-17 20:56:33 -0400
commit0c5b08ea58f88252e950ecaf40125a22b79fa83c (patch)
tree89508d0e0d6afc6cb6379bde9139777af5341160 /nserver
Add nserver.
For now it contains only "statserve".
Diffstat (limited to 'nserver')
-rw-r--r--nserver/LICENSE15
-rw-r--r--nserver/Makefile63
-rw-r--r--nserver/README.md11
-rw-r--r--nserver/bin/statserve.c118
-rw-r--r--nserver/src/dbg.h43
-rw-r--r--nserver/tests/minunit.h33
-rw-r--r--nserver/tests/runtests.sh19
7 files changed, 302 insertions, 0 deletions
diff --git a/nserver/LICENSE b/nserver/LICENSE
new file mode 100644
index 0000000..9601066
--- /dev/null
+++ b/nserver/LICENSE
@@ -0,0 +1,15 @@
+Copyright 2019 rsiddharth <s@ricketyspace.net>
+
+Permission to use, copy, modify, and/or distribute this software for
+any purpose with or without fee is hereby granted, provided that the
+above copyright notice and this permission notice appear in all
+copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
diff --git a/nserver/Makefile b/nserver/Makefile
new file mode 100644
index 0000000..c6a12a8
--- /dev/null
+++ b/nserver/Makefile
@@ -0,0 +1,63 @@
+CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
+LIBS=-ldl $(OPTLIBS)
+PREFIX?=/usr/local
+CTAGS=`which ectags`
+
+SOURCES=$(wildcard src/**/*.c src/*.c)
+OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
+
+TEST_SRC=$(wildcard tests/*_tests.c)
+TESTS=$(patsubst %.c,%,$(TEST_SRC))
+
+PROGRAMS_SRC=$(wildcard bin/*.c)
+PROGRAMS=$(patsubst %.c,%,$(PROGRAMS_SRC))
+
+TARGET=build/libnserve.a
+SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
+
+# The Target Build
+all: $(PROGRAMS) TAGS
+
+dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
+dev: all
+
+$(TARGET): CFLAGS += -fPIC
+$(TARGET): build $(OBJECTS)
+ ar rcs $@ $(OBJECTS)
+ ranlib $@
+$(SO_TARGET): $(TARGET) $(OBJECTS)
+ $(CC) -shared -o $@ $(OBJECTS)
+
+$(PROGRAMS): LDLIBS += -lm
+
+build:
+ @mkdir -p build
+ @mkdir -p bin
+
+# The Unit Tests
+.PHONY: tests
+tests: CFLAGS += $(TARGET)
+tests: $(TESTS)
+ sh ./tests/runtests.sh
+
+# The Cleaner
+clean:
+ rm -rf build $(OBJECTS) $(TESTS)
+ rm -f tests/tests.log
+ find . -name "*.gc" -exec rm {} \;
+ rm -rf `find . -name "*.dSYM" -print`
+
+# The Install
+install: all
+ install -d $(DESTDIR)/$(PREFIX)/lib/
+ install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
+
+# Generate TAGS file
+TAGS: $(SOURCES) $(TEST_SRC)
+ find ./ -type f -name '*.h' -or -name '*.c' | $(CTAGS) -e -L -
+
+# The Checker
+check:
+ @echo Files with potentially dangerous functions.
+ @egrep '[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)\
+ |stpn?cpy|a?sn?printf|byte_)' $(SOURCES) || true
diff --git a/nserver/README.md b/nserver/README.md
new file mode 100644
index 0000000..7c0cac9
--- /dev/null
+++ b/nserver/README.md
@@ -0,0 +1,11 @@
+# nserver
+
+## statserve
+
+To start this server, do:
+
+```
+./bin/statserve
+```
+
+It'll be listening on port 7899.
diff --git a/nserver/bin/statserve.c b/nserver/bin/statserve.c
new file mode 100644
index 0000000..d62622a
--- /dev/null
+++ b/nserver/bin/statserve.c
@@ -0,0 +1,118 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include <dbg.h>
+
+#define PORT "7899"
+#define BACKLOG 10
+
+int echo(int sock, char *buf, int len)
+{
+ int bytes = 0;
+
+ bytes = send(sock, buf, len, 0);
+ check(bytes >= 0, "statserv: send failed");
+
+ return bytes;
+ error:
+ return -1;
+}
+
+void serve(int sock)
+{
+ int rc = 0;
+ int buf_len = 1000;
+ char buf[buf_len];
+ ssize_t bytes;
+
+ do {
+ bytes = recv(sock, buf, buf_len, 0);
+ check(bytes >= 0, "statserv: recv failed");
+
+ if (bytes < 1) {
+ break;
+ }
+
+ rc = echo(sock, buf, bytes);
+ check(rc != -1, "statserv: echo failed");
+ } while(1);
+
+ rc = close(sock);
+ check(rc == 0, "statserv: close failed");
+
+ exit(0);
+ error:
+ rc = close(sock);
+ check(rc == 0, "statserv: close failed");
+ exit(1);
+}
+
+int main(void)
+{
+ int rc = 0;
+ int sockfd_s = 0, sockfd_c = 0;
+ struct addrinfo hints;
+ struct addrinfo *servinfo = NULL;
+ struct sockaddr sockaddr_c;
+ socklen_t sockaddr_c_len;
+ pid_t pidc;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+
+ rc = getaddrinfo(NULL, PORT, &hints, &servinfo);
+ check(rc == 0, "statserve: getaddrinfo failed");
+
+ sockfd_s = socket(servinfo->ai_family, servinfo->ai_socktype,
+ servinfo->ai_protocol);
+ check(sockfd_s != 0, "statserve: socket failed");
+
+ rc = bind(sockfd_s, servinfo->ai_addr, servinfo->ai_addrlen);
+ check(rc == 0, "statserve: bind failed");
+
+ rc = listen(sockfd_s, BACKLOG);
+ check(rc == 0, "statserve: listen failed");
+
+ do {
+ printf("Waiting for connection...\n");
+ sockfd_c = accept(sockfd_s, &sockaddr_c, &sockaddr_c_len);
+
+ pidc = fork();
+ check(pidc != -1, "statserve: fork failed");
+
+ if (pidc == 0) {
+ serve(sockfd_c);
+ }
+
+ rc = close(sockfd_c);
+ check(rc == 0, "statserv: close failed");
+ } while(1);
+
+ // Clean up.
+ freeaddrinfo(servinfo);
+
+ rc = close(sockfd_s);
+ check(rc == 0, "statserv: close failed");
+
+ return 0;
+
+ error:
+ if (servinfo)
+ freeaddrinfo(servinfo);
+ if (sockfd_s) {
+ rc = close(sockfd_s);
+ check(rc == 0, "statserv: close failed");
+ }
+ if (sockfd_c) {
+ rc = close(sockfd_c);
+ check(rc == 0, "statserv: close failed");
+ }
+
+ return -1;
+}
diff --git a/nserver/src/dbg.h b/nserver/src/dbg.h
new file mode 100644
index 0000000..67ebe77
--- /dev/null
+++ b/nserver/src/dbg.h
@@ -0,0 +1,43 @@
+#ifndef __dbg_h__
+#define __dbg_h__
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#ifdef NDEBUG
+#define debug(M, ...)
+#else
+#define debug(M, ...) fprintf(stderr, "DEBUG %s:%s:%d: " M "\n", \
+ __FILE__, __FUNCTION__, __LINE__, \
+ ##__VA_ARGS__)
+#endif
+
+#define clean_errno() (errno == 0 ? "None" : strerror(errno))
+
+#define log_err(M, ...) fprintf(stderr, \
+ "[ERROR] (%s:%s:%d: errno: %s) " M "\n", __FILE__, \
+ __FUNCTION__, __LINE__, \
+ clean_errno(), ##__VA_ARGS__)
+
+#define log_warn(M, ...) fprintf(stderr, \
+ "[WARN] (%s:%s:%d: errno: %s) " M "\n", \
+ __FILE__, __FUNCTION__, __LINE__, \
+ clean_errno(), ##__VA_ARGS__)
+
+#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%s:%d) " M "\n", \
+ __FILE__, __FUNCTION__, __LINE__, \
+ ##__VA_ARGS__)
+
+#define check(A, M, ...) if(!(A)) {\
+ log_err(M, ##__VA_ARGS__); errno=0; goto error; }
+
+#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__);\
+ errno=0; goto error; }
+
+#define check_mem(A) check((A), "Out of memory.")
+
+#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__);\
+ errno=0; goto error; }
+
+#endif
diff --git a/nserver/tests/minunit.h b/nserver/tests/minunit.h
new file mode 100644
index 0000000..a7cb280
--- /dev/null
+++ b/nserver/tests/minunit.h
@@ -0,0 +1,33 @@
+#undef NDEBUG
+#ifndef _minunit_h
+#define _minunit_h
+
+#include <stdio.h>
+#include <dbg.h>
+#include <stdlib.h>
+
+#define mu_suite_start() char *message = NULL
+
+#define mu_assert(test, message) if (!(test)) {\
+ log_err(message); return message; }
+#define mu_run_test(test) debug("\n-----%s", " " #test); \
+ message = test(); tests_run++; if (message) return message;
+
+#define RUN_TESTS(name) int main(int argc, char *argv[]) {\
+ argc = 1; \
+ debug("----- RUNNING: %s", argv[0]); \
+ printf("----\nRUNNING: %s\n", argv[0]);\
+ char *result = name();\
+ if (result != 0) {\
+ printf("FAILED: %s\n", result); \
+ }\
+ else {\
+ printf("ALL TESTS PASSED\n");\
+ }\
+ printf("Tests run: %d\n", tests_run);\
+ exit(result != 0);\
+ }
+
+int tests_run;
+
+#endif
diff --git a/nserver/tests/runtests.sh b/nserver/tests/runtests.sh
new file mode 100644
index 0000000..ff579a3
--- /dev/null
+++ b/nserver/tests/runtests.sh
@@ -0,0 +1,19 @@
+echo "Running unit tests:"
+
+for i in tests/*_tests
+do
+ if test -f $i
+ then
+ if $VALGRIND ./$i 2>> tests/tests.log
+ then
+ echo $i PASS
+ else
+ echo "ERROR in test $i: here's tests/tests.log"
+ echo "------"
+ tail tests/tests.log
+ exit 1
+ fi
+ fi
+done
+
+echo ""