summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornirav <nirav@teisuu.com>2019-09-19 15:36:02 +0000
committernirav <nirav@teisuu.com>2019-09-19 15:44:14 +0000
commitd5f4022408249c5a513ae795b7b360854bd75a6c (patch)
treead20cbe6aba24649647b7aa0520f25392571aeeb
parente985bfa6b8facac58da9a20c3c840498e2517bb5 (diff)
downloadgopherd-d5f4022408249c5a513ae795b7b360854bd75a6c.tar.gz
gopherd-d5f4022408249c5a513ae795b7b360854bd75a6c.zip
Update
-rw-r--r--.gitignore1
-rw-r--r--Makefile12
-rw-r--r--gopher.c56
-rw-r--r--gopher.h7
-rw-r--r--log.c2
-rw-r--r--main.c53
6 files changed, 116 insertions, 15 deletions
diff --git a/.gitignore b/.gitignore
index b7e5ac2..9ce25c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
+*.o
tags
gopherd
diff --git a/Makefile b/Makefile
index a989775..9debc82 100644
--- a/Makefile
+++ b/Makefile
@@ -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
+
diff --git a/log.c b/log.c
index c543238..eab204c 100644
--- a/log.c
+++ b/log.c
@@ -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;
diff --git a/main.c b/main.c
index 466ab83..0d45d46 100644
--- a/main.c
+++ b/main.c
@@ -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;
}