summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornirav <nirav@teisuu.com>2019-09-15 09:26:41 +0000
committernirav <nirav@teisuu.com>2019-09-15 09:26:41 +0000
commite985bfa6b8facac58da9a20c3c840498e2517bb5 (patch)
treee38c1b5d9eed792d770ccb3deff9f4dd29be41be
downloadgopherd-e985bfa6b8facac58da9a20c3c840498e2517bb5.tar.gz
gopherd-e985bfa6b8facac58da9a20c3c840498e2517bb5.zip
Initial commit
-rw-r--r--.gitignore2
-rw-r--r--Makefile12
-rw-r--r--log.c36
-rw-r--r--log.h12
-rw-r--r--main.c179
5 files changed, 241 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b7e5ac2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+tags
+gopherd
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a989775
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+CC=cc
+CFLAGS=-ansi -Wall -Wextra -pedantic
+
+all: gopherd
+
+OBJ=main.o log.o
+
+gopherd: $(OBJ)
+ $(CC) -o $@ $(OBJ)
+
+clean:
+ rm -f gopherd *.o
diff --git a/log.c b/log.c
new file mode 100644
index 0000000..c543238
--- /dev/null
+++ b/log.c
@@ -0,0 +1,36 @@
+#define _POSIX_C_SOURCE 200112L
+
+#include <time.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "log.h"
+
+static int save;
+static time_t now;
+static struct tm *tm;
+static char buf[25]; /* "2011-10-08T07:07:09+1111" */
+static va_list ap;
+static enum loglevel def_loglevel = LOG_DEBUG;
+
+void
+logmsg(enum loglevel level, const char *format,...)
+{
+ if (def_loglevel < level) {
+ return;
+ }
+ save = errno;
+
+ time(&now);
+ tm = localtime(&now);
+ strftime(buf, sizeof buf, "%FT%T%z", tm);
+
+ printf("%s ", buf);
+ va_start(ap, format);
+ vprintf(format, ap);
+ va_end(ap);
+ printf("\n");
+
+ errno = save;
+}
diff --git a/log.h b/log.h
new file mode 100644
index 0000000..b9f56b6
--- /dev/null
+++ b/log.h
@@ -0,0 +1,12 @@
+#ifndef __LOG_H
+#define __LOG_H
+
+enum loglevel {
+ LOG_NONE,
+ LOG_INFO,
+ LOG_DEBUG
+};
+
+void logmsg(enum loglevel level, const char *format,...);
+
+#endif
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..466ab83
--- /dev/null
+++ b/main.c
@@ -0,0 +1,179 @@
+#define _POSIX_C_SOURCE 200112L
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "log.h"
+
+#ifndef OPEN_MAX
+#define OPEN_MAX 1024
+#endif
+
+#define PORT "3000"
+#define BUFSIZE 1024
+
+static int
+create_server(const char *port)
+{
+ int fd, yes = 1;
+ struct addrinfo *res, *p, hints;
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+
+ if (getaddrinfo(NULL, port, &hints, &res) != 0) {
+ perror("getaddrinfo");
+ return -1;
+ }
+ for (p = res; p != NULL; p = p->ai_next) {
+ if ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol))
+ == -1) {
+ perror("socket");
+ continue;
+ }
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes,
+ sizeof(int)) == -1) {
+ perror("setsockopt");
+ close(fd);
+ return -1;
+ }
+ if (ioctl(fd, FIONBIO, &yes) == -1) {
+ perror("ioctl");
+ close(fd);
+ return -1;
+ }
+ if (bind(fd, p->ai_addr, p->ai_addrlen) == -1) {
+ perror("bind");
+ continue;
+ }
+ break;
+ }
+
+ freeaddrinfo(res);
+
+ if (p == NULL) {
+ fprintf(stderr, "failed to bind\n");
+ return -1;
+ }
+ if (listen(fd, 32) == -1) {
+ perror("listen");
+ return -1;
+ }
+ logmsg(LOG_INFO, "listening on %s", port);
+ return fd;
+}
+
+static int
+accept_connection(int s_fd)
+{
+ int c_fd;
+
+ if ((c_fd = accept(s_fd, NULL, NULL)) == -1) {
+ if (errno != EWOULDBLOCK || errno != EAGAIN) {
+ perror("accept");
+ exit(1);
+ }
+ return -1;
+ }
+ logmsg(LOG_INFO, "connection accepted");
+
+ return c_fd;
+}
+
+static void
+handle_client(int c_fd)
+{
+ int n;
+ char buf[BUFSIZE];
+
+ n = recv(c_fd, &buf, BUFSIZE - 1, 0);
+ switch (n) {
+ case -1:
+ if (errno != EWOULDBLOCK || errno != EAGAIN) {
+ perror("recv");
+ }
+ case 0:
+ logmsg(LOG_INFO, "connection closed by client");
+ default:
+ buf[n] = '\0';
+ if (send(c_fd, buf, n, 0) == -1) {
+ perror("send");
+ }
+ }
+ close(c_fd);
+}
+
+static void
+main_loop(int s_fd)
+{
+ int i, rc, end_server = 0;
+ int c_fd, nfds = 1, curr_size = 0;
+ struct pollfd pfds[OPEN_MAX];
+
+ memset(pfds, 0, sizeof(pfds));
+ pfds[0].fd = s_fd;
+ pfds[0].events = POLLIN;
+
+ do {
+ rc = poll(pfds, nfds, -1);
+ if (rc == -1) {
+ perror("poll");
+ break;
+ }
+ if (rc == 0) {
+ fprintf(stderr, "poll timeout\n");
+ break;
+ }
+ curr_size = nfds;
+ for (i = 0; i < curr_size; i++) {
+ if (pfds[i].revents == 0)
+ continue;
+
+ if (pfds[i].revents != POLLIN) {
+ logmsg(LOG_INFO, "revents not POLLIN\n");
+ end_server = 1;
+ break;
+ }
+ if (pfds[i].fd == s_fd) {
+ do {
+ c_fd = accept_connection(s_fd);
+ if (c_fd != -1) {
+ pfds[nfds].fd = c_fd;
+ pfds[nfds].events = POLLIN;
+ nfds++;
+ }
+ } while (c_fd != -1);
+ } else {
+ handle_client(pfds[i].fd);
+ pfds[i].fd = -1;
+ }
+ }
+ } while (end_server == 0);
+}
+
+int
+main()
+{
+ int s_fd;
+
+ s_fd = create_server(PORT);
+ if (s_fd == -1) {
+ fprintf(stderr, "failed to create server\n");
+ exit(0);
+ }
+ main_loop(s_fd);
+
+ return 0;
+}