diff options
author | nirav <nirav@teisuu.com> | 2019-09-19 15:36:02 +0000 |
---|---|---|
committer | nirav <nirav@teisuu.com> | 2019-09-19 15:44:14 +0000 |
commit | d5f4022408249c5a513ae795b7b360854bd75a6c (patch) | |
tree | ad20cbe6aba24649647b7aa0520f25392571aeeb | |
parent | e985bfa6b8facac58da9a20c3c840498e2517bb5 (diff) | |
download | gopherd-d5f4022408249c5a513ae795b7b360854bd75a6c.tar.gz gopherd-d5f4022408249c5a513ae795b7b360854bd75a6c.zip |
Update
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | gopher.c | 56 | ||||
-rw-r--r-- | gopher.h | 7 | ||||
-rw-r--r-- | log.c | 2 | ||||
-rw-r--r-- | main.c | 53 |
6 files changed, 116 insertions, 15 deletions
@@ -1,2 +1,3 @@ +*.o tags gopherd @@ -1,12 +1,20 @@ +.POSIX: + CC=cc CFLAGS=-ansi -Wall -Wextra -pedantic all: gopherd -OBJ=main.o log.o +SRC=main.c log.c gopher.c +OBJ=$(SRC:.c=.o) gopherd: $(OBJ) $(CC) -o $@ $(OBJ) +tags: $(SRC) + ctags $(SRC) + clean: - rm -f gopherd *.o + rm -f gopherd + rm -f tags + rm -f *.o diff --git a/gopher.c b/gopher.c new file mode 100644 index 0000000..c1cb2eb --- /dev/null +++ b/gopher.c @@ -0,0 +1,56 @@ +#define _POSIX_C_SOURCE 200112L + +#include <sys/socket.h> + +#include <stdio.h> +#include <string.h> + +#include "log.h" + +static char *res = "1Entry 1 /entry1 localhost 3000\r\n\ +1Entry 2 /entry2 localhost 3000\r\n\ +1Entry 3 /entry3 localhost 3000\r\n\ +."; + +static char *res1 = "0SubEntry 1 /entry1 localhost 3000\r\n\ +0SubEntry 2 /entry2 localhost 3000\r\n\ +0SubEntry 3 /entry3 localhost 3000\r\n\ +."; + +static int +sendall(int fd, const char *buf, size_t len) +{ + size_t sent = 0; + ssize_t n; + + while (sent < len) { + n = send(fd, buf + sent, len - sent, 0); + if (n == -1) { + perror("send"); + return -1; + } + sent += n; + } + + return 0; +} + +int +handle_path(int fd, const char *path) +{ + const char *data; + + if (strcmp(path, "") == 0 || strcmp(path, "/") == 0) { + data = res; + } else if (strcmp(path, "/entry1") == 0) { + data = res1; + } else { + data = ""; + } + + if (sendall(fd, data, strlen(data)) == -1) { + logmsg(LOG_INFO, "failed to send data"); + return -1; + } + return 0; +} diff --git a/gopher.h b/gopher.h new file mode 100644 index 0000000..36155a3 --- /dev/null +++ b/gopher.h @@ -0,0 +1,7 @@ +#ifndef __GOPHER_H +#define __GOPHER_H + +int handle_path(int fd, const char *path); + +#endif + @@ -10,7 +10,7 @@ static int save; static time_t now; static struct tm *tm; -static char buf[25]; /* "2011-10-08T07:07:09+1111" */ +static char buf[25]; /* strlen("2011-10-08T07:07:09+1111") + 1 */ static va_list ap; static enum loglevel def_loglevel = LOG_DEBUG; @@ -14,6 +14,7 @@ #include <unistd.h> #include "log.h" +#include "gopher.h" #ifndef OPEN_MAX #define OPEN_MAX 1024 @@ -21,12 +22,15 @@ #define PORT "3000" #define BUFSIZE 1024 +#define HOSTMAX 1025 +#define SERVMAX 256 static int create_server(const char *port) { int fd, yes = 1; struct addrinfo *res, *p, hints; + char host[HOSTMAX], serv[SERVMAX]; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; @@ -56,38 +60,55 @@ create_server(const char *port) } if (bind(fd, p->ai_addr, p->ai_addrlen) == -1) { perror("bind"); + close(fd); continue; } break; } - freeaddrinfo(res); - if (p == NULL) { + freeaddrinfo(res); fprintf(stderr, "failed to bind\n"); return -1; } if (listen(fd, 32) == -1) { + freeaddrinfo(res); perror("listen"); return -1; } - logmsg(LOG_INFO, "listening on %s", port); + if (getnameinfo(p->ai_addr, p->ai_addrlen, host, sizeof(host), serv, + sizeof(serv), NI_NUMERICHOST) != 0) { + freeaddrinfo(res); + perror("getaddrinfo"); + return -1; + } + freeaddrinfo(res); + + logmsg(LOG_INFO, "listening on %s:%s", host, serv); return fd; } static int accept_connection(int s_fd) { + struct sockaddr_storage sa; + socklen_t salen; + char host[HOSTMAX]; int c_fd; - if ((c_fd = accept(s_fd, NULL, NULL)) == -1) { + if ((c_fd = accept(s_fd, (struct sockaddr *) & sa, &salen)) == -1) { if (errno != EWOULDBLOCK || errno != EAGAIN) { perror("accept"); exit(1); } return -1; } - logmsg(LOG_INFO, "connection accepted"); + if (getnameinfo((struct sockaddr *) & sa, salen, host, sizeof(host), + NULL, 0, NI_NUMERICHOST) != 0) { + perror("gethostname"); + return -1; + } + logmsg(LOG_INFO, "connection accepted from %s", host); return c_fd; } @@ -97,6 +118,7 @@ handle_client(int c_fd) { int n; char buf[BUFSIZE]; + char *lf; n = recv(c_fd, &buf, BUFSIZE - 1, 0); switch (n) { @@ -104,13 +126,20 @@ handle_client(int c_fd) if (errno != EWOULDBLOCK || errno != EAGAIN) { perror("recv"); } + break; case 0: logmsg(LOG_INFO, "connection closed by client"); + break; default: - buf[n] = '\0'; - if (send(c_fd, buf, n, 0) == -1) { - perror("send"); + lf = strchr(buf, '\r'); + if (lf == NULL || *lf != buf[n-2]) { + logmsg(LOG_INFO, "invalid request"); + break; } + *lf = '\0'; + + logmsg(LOG_INFO, "path: %s", buf); + handle_path(c_fd, buf); } close(c_fd); } @@ -166,14 +195,14 @@ main_loop(int s_fd) int main() { - int s_fd; + int fd; - s_fd = create_server(PORT); - if (s_fd == -1) { + fd = create_server(PORT); + if (fd == -1) { fprintf(stderr, "failed to create server\n"); exit(0); } - main_loop(s_fd); + main_loop(fd); return 0; } |