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:
| A | socket.c | | | 133 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | socket.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 */
+