Skip to content

Instantly share code, notes, and snippets.

@dmaynor
Created February 25, 2025 15:51
Show Gist options
  • Save dmaynor/7578bc52c6150f0b18e6a216e2c5bf9e to your computer and use it in GitHub Desktop.
Save dmaynor/7578bc52c6150f0b18e6a216e2c5bf9e to your computer and use it in GitHub Desktop.
/* LINUX KERNEL STYLE */ /* SEI CERT STYLE */
/** /**
* Simple socket server example * Simple socket server example following
* following Linux Kernel style * SEI CERT secure coding practices
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <errno.h>
#include <stdbool.h>
#define PORT 8080 #define PORT 8080
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
#define MAX_CLIENTS 5 #define MAX_CLIENTS 5
/**
* Handles client communication securely
* @param client_fd Client socket file descriptor
* @return true on success, false on error
*/
static void handle_client(int client_fd) bool HandleClient(const int client_fd) {
{
char buffer[BUFFER_SIZE] = {0}; char buffer[BUFFER_SIZE];
memset(buffer, 0, sizeof(buffer));
int bytes_read; /* Bounds checking and error handling */
ssize_t bytes_read = read(client_fd, buffer,
BUFFER_SIZE - 1);
bytes_read = read(client_fd, buffer, if (bytes_read < 0) {
BUFFER_SIZE); fprintf(stderr, "Error reading from socket: %s\n",
if (bytes_read < 0) { strerror(errno));
perror("read failed"); return false;
return; }
}
/* Ensure null termination regardless of client input */
buffer[bytes_read] = '\0';
printf("Message received: %s\n", buffer); printf("Message received: %s\n", buffer);
char *response = "Message received"; const char* response = "Message received";
send(client_fd, response, strlen(response),
0); /* Check return value of send() */
ssize_t bytes_sent = send(client_fd, response,
strlen(response), 0);
if (bytes_sent < 0) {
fprintf(stderr, "Error sending response: %s\n",
strerror(errno));
return false;
}
} return true;
}
int main(void) int main(void) {
{
int server_fd, client_fd; int server_fd = -1;
int client_fd = -1;
struct sockaddr_in address; struct sockaddr_in address;
int opt = 1; int opt = 1;
int addrlen = sizeof(address); socklen_t addrlen = sizeof(address);
bool keep_running = true;
/* Create socket file descriptor */ /* Create socket with explicit error checking */
if ((server_fd = socket(AF_INET, server_fd = socket(AF_INET, SOCK_STREAM, 0);
SOCK_STREAM, 0)) < 0) { if (server_fd < 0) {
perror("socket failed"); fprintf(stderr, "Socket creation failed: %s\n",
exit(EXIT_FAILURE); strerror(errno));
} return EXIT_FAILURE;
}
/* Set socket options */ /* Set socket options with explicit error checking */
if (setsockopt(server_fd, SOL_SOCKET, if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR,
SO_REUSEADDR, &opt, &opt, sizeof(opt)) != 0) {
sizeof(opt))) { fprintf(stderr, "Setsockopt failed: %s\n",
perror("setsockopt failed"); strerror(errno));
exit(EXIT_FAILURE); close(server_fd);
} return EXIT_FAILURE;
}
/* Initialize address structure */
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET; address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY; address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT); address.sin_port = htons(PORT);
/* Bind socket to the port */ /* Bind with explicit error checking */
if (bind(server_fd, (struct sockaddr *) if (bind(server_fd, (struct sockaddr *)&address,
&address, sizeof(address)) < 0) { sizeof(address)) != 0) {
perror("bind failed"); fprintf(stderr, "Bind failed: %s\n",
exit(EXIT_FAILURE); strerror(errno));
} close(server_fd);
return EXIT_FAILURE;
}
/* Listen for connections */ /* Listen with explicit error checking */
if (listen(server_fd, MAX_CLIENTS) < 0) { if (listen(server_fd, MAX_CLIENTS) != 0) {
perror("listen failed"); fprintf(stderr, "Listen failed: %s\n",
exit(EXIT_FAILURE); strerror(errno));
} close(server_fd);
return EXIT_FAILURE;
}
printf("Server listening on port %d\n", printf("Server listening on port %d\n", PORT);
PORT);
/* Main server loop */ /* Main server loop with defensive programming */
while (1) { while (keep_running) {
printf("Waiting for connection...\n"); printf("Waiting for connection...\n");
if ((client_fd = accept(server_fd, client_fd = accept(server_fd, (struct sockaddr *)
(struct sockaddr *)&address, &address, &addrlen);
(socklen_t*)&addrlen)) < 0) { if (client_fd < 0) {
perror("accept failed"); fprintf(stderr, "Accept failed: %s\n",
continue; strerror(errno));
} continue;
}
/* Handle client connection */ /* Handle client with error checking */
handle_client(client_fd); if (!HandleClient(client_fd)) {
close(client_fd); fprintf(stderr, "Client handling failed\n");
} }
/* Always close client socket even if errors occurred */
close(client_fd);
client_fd = -1;
}
/* Clean up resources */
if (server_fd >= 0) {
close(server_fd);
}
return 0; return EXIT_SUCCESS;
} }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment