Skip to content

Instantly share code, notes, and snippets.

@vinikira
Created January 19, 2022 14:35
Show Gist options
  • Save vinikira/179c421f8db743e05dbc1dae2c0c1a38 to your computer and use it in GitHub Desktop.
Save vinikira/179c421f8db743e05dbc1dae2c0c1a38 to your computer and use it in GitHub Desktop.
HTTP server using only system sockets in C
#!/bin/sh
set -xe
cc -Wall -Werror -std=c11 -pedantic -c common.c
cc -Wall -Werror -std=c11 -pedantic -o main main.c common.o
#include "common.h"
void err_n_die(const char *fmt, ...) {
int errno_save = errno;
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
fflush(stderr);
if (errno_save != 0) {
fprintf(stderr, "(errno = %d): %s\n", errno_save, strerror(errno_save));
fprintf(stderr, "\n");
fflush(stderr);
}
va_end(ap);
exit(1);
}
char *bin2hex(const unsigned char *input, size_t len) {
char *result;
char *hexits = "0123456789ABCDEF";
if (input == NULL || len <= 0) {
return NULL;
}
int resultlength = (len * 3) + 1;
result = malloc(resultlength);
bzero(result, resultlength);
for (size_t i = 0; i < len; i++) {
int idx = i * 3;
result[idx] = hexits[input[i] >> 4];
result[idx + 1] = hexits[input[i] & 0x0F];
result[idx + 2] = ' ';
}
return result;
}
#ifndef _COMMON_H_
#define _COMMON_H_
#include <sys/socket.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdarg.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <netdb.h>
#define SERVER_PORT 18000
#define MAXLINE 4096
void err_n_die(const char *fmt, ...);
char *bin2hex(const unsigned char *input, size_t len);
#endif /* _COMMON_H_ */
#include "common.h"
#define USE_TCP 0
#define CONNECTIONS_QUEUE_SIZE 10
int main(void) {
int listenfd;
int connfd;
int n;
struct sockaddr_in servaddr;
uint8_t buff[MAXLINE + 1];
uint8_t recvline[MAXLINE + 1];
if ((listenfd = socket(AF_INET, SOCK_STREAM, USE_TCP)) < 0) {
err_n_die("socket error");
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERVER_PORT);
if ((bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0) {
err_n_die("bind error.");
}
if ((listen(listenfd, CONNECTIONS_QUEUE_SIZE)) < 0 ) {
err_n_die("listen error.");
}
while (1) {
printf("Waiting for a connection on port %d", SERVER_PORT);
fflush(stdout);
connfd = accept(listenfd, (struct sockaddr *) NULL, NULL);
memset(recvline, 0, MAXLINE);
while ((n = read(connfd, recvline, MAXLINE - 1)) > 0) {
fprintf(stdout, "\n%s\n\n%s", bin2hex(recvline, n), recvline);
if (recvline[n - 1] == '\n') {
break;
}
memset(recvline, 0, MAXLINE);
}
if (n < 0) {
err_n_die("read error.");
}
snprintf((char *) buff, sizeof(buff), "HTTP/1.0 200 OK\r\n\r\nHello");
write(connfd, (char *) buff, strlen((char *) buff));
close(connfd);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment