shttp

A small http server written in C

git clone git://git.janzachar.dev/shttp.git


0#include "super.h"
1
2#include <arpa/inet.h>
3#include <pthread.h>
4#include <unistd.h>
5#include <signal.h>
6#include <string.h>
7#include <stdlib.h>
8#include <stdio.h>
9
10#define serror(sock, err) { \
11	perror((err)); \
12	close((sock)->fd); \
13	exit(EXIT_FAILURE); \
14}
15
16
17void sock_fill(struct sock *sock, const char *addr, int port)
18{
19	memset(sock, 0, sizeof(*sock));
20	sock->len = sizeof(sock->addr);
21
22	sock->addr.sin_family = AF_INET;
23	sock->addr.sin_port = htons(port);
24
25	switch (inet_pton(AF_INET, addr, &sock->addr.sin_addr)) {
26	default: break;
27	case 0: 
28		printe("Not a valid address '%s'!\n", addr);
29		close(sock->fd);
30		exit(EXIT_FAILURE);
31	case -1:
32		serror(sock, "inet_pton()");
33	}
34}
35
36
37void sock_open(struct sock *sock)
38{
39	sock->fd = socket(AF_INET, SOCK_STREAM, 0);
40
41	int opt = 1;
42	if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
43		serror(sock, "setsockopt() reuse address");
44
45	if (bind(sock->fd, (struct sockaddr*)&sock->addr, sizeof(sock->addr)))
46		serror(sock, "bind()");
47
48	if (listen(sock->fd, LISTEN_COUNT))
49		serror(sock, "listen()");
50}
51
52
53int _sock;
54void sigint(int)
55{
56	close(_sock);
57	_sock = 0;
58}
59
60void sock_on(struct sock *sock, int (*func)(int))
61{
62	_sock = sock->fd;
63	signal(SIGINT, sigint);
64	
65	while (_sock) {
66		int fd = accept(sock->fd, (struct sockaddr*)&sock->addr, &sock->len);
67		if (!_sock) break;
68		if (fd < 0) 
69			serror(sock, "accept()");
70
71		struct timeval timeout = {
72			.tv_sec = 0,
73			.tv_usec = 0
74		};
75
76		if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)))
77			serror(sock, "setsockopt() receive timeout");
78
79		if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)))
80			serror(sock, "setsockopt() send timeout");
81
82		int out = func(fd);
83		close(fd);
84		if (out) break;
85	}
86
87	if (_sock) close(_sock);
88}
89
90