s-httpd

mildly suckless httpd
Log | Files | Refs | README | LICENSE

commit 5ecb627c682083b5334e61f0fb3846afb16ba33f
parent d836adcff75c25e29ad9f60a97bc78870b1d008c
Author: Mario Rosell R. Martinez <mario@mariorosell.es>
Date:   Fri, 27 Mar 2026 20:03:11 +0100

serve/socket: add low level socket handling

Diffstat:
Asocket.c | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asocket.h | 27+++++++++++++++++++++++++++
2 files changed, 160 insertions(+), 0 deletions(-)

diff --git a/socket.c b/socket.c @@ -0,0 +1,133 @@ +/* + * socket.c -- low-level socket code + */ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <arpa/inet.h> +#include <sys/types.h> +#include <sys/socket.h> + +int +sock_create(const char* ip, int port) +{ + int srvfd = socket(AF_INET, SOCK_STREAM, 0); + if (srvfd < 0) { + perror("socket"); + return -1; + } + + int opt = 1; + if (setsockopt(srvfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { + perror("setsockopt"); + close(srvfd); + return -1; + } + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + if (ip == NULL) { + addr.sin_addr.s_addr = INADDR_ANY; /* accept requests from anywhere */ + } else { + if (inet_pton(AF_INET, ip, &addr.sin_addr) <= 0) { + perror("inet_pton"); + close(srvfd); + return -1; + } + } + + if (bind(srvfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("bind"); + close(srvfd); + return -1; + } + + if (listen(srvfd, 128) < 0) { + perror("listen"); + close(srvfd); + return -1; + } + + return srvfd; +} + +int +sock_accept(int fd) +{ + struct sockaddr_in client; + socklen_t len = sizeof(client); + + int cfd = accept(fd, (struct sockaddr*)&client, &len); + if (cfd < 0) { + perror("accept"); + return -1; + } + + return cfd; +} + +void +sock_close(int fd) +{ + close(fd); +} + +int +sock_connect(const char* ip, int port) +{ + int fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) { + perror("socket"); + return -1; + } + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + if (inet_pton(AF_INET, ip, &addr.sin_addr) <= 0) { + perror("inet_pton"); + close(fd); + return -1; + } + + if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("connect"); + close(fd); + return -1; + } + + return fd; +} + +int +sock_send(int fd, const char* data, size_t len) +{ + ssize_t sent = send(fd, data, len, 0); + if (sent < 0) { + perror("send"); + return -1; + } + + return (int)sent; +} + +int +sock_recv(int fd, char* buf, size_t len) +{ + ssize_t recvd = recv(fd, buf, len, 0); + if (recvd < 0) { + perror("recv"); + return -1; + } + + return (int)recvd; +} + diff --git a/socket.h b/socket.h @@ -0,0 +1,27 @@ +/* + * socket.h -- low-level socket defs + */ + +#ifndef SOCKET_H +#define SOCKET_H + +#include <stddef.h> + +typedef struct socket { + int fd; +} Socket; + +/* serving */ +int sock_create(const char* ip, int port); /* make a socket */ +int sock_accept(int fd); /* accept a connection from a client */ +void sock_close(int fd); /* close a server socket */ + +/* client */ +int sock_connet(const char* ip, int port); /* connet to the server */ + +/* i/o */ +int sock_send(int fd, const char* data, size_t len); /* send data to client */ +int sock_recv(int fd, char* buf, size_t len); /* recieve data from client */ + +#endif /* SOCKET_H */ +