Separate out functions/structs/constants/globals to properly named
files.
This commit is contained in:
Stephen Seo 2024-08-29 15:38:44 +09:00
parent 8b0363a059
commit cadaf66cae
12 changed files with 249 additions and 151 deletions

View file

@ -9,7 +9,13 @@ else
endif endif
SOURCES = \ SOURCES = \
src/main.c src/main.c \
src/arg_parse.c \
src/big_endian.c \
src/tcp_socket.c \
src/signal_handling.c \
src/globals.c
OBJECT_DIR = objs OBJECT_DIR = objs
OBJECTS = $(addprefix ${OBJECT_DIR}/,$(patsubst %.c,%.c.o,${SOURCES})) OBJECTS = $(addprefix ${OBJECT_DIR}/,$(patsubst %.c,%.c.o,${SOURCES}))

42
src/arg_parse.c Normal file
View file

@ -0,0 +1,42 @@
#include "arg_parse.h"
// Standard library includes.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void print_usage(void) {
puts("Usage:");
puts(" -p <port> | --port <port>");
}
Args parse_args(int argc, char **argv) {
--argc;
++argv;
Args args;
memset(&args, 0, sizeof(Args));
while (argc > 0) {
if ((strcmp(argv[0], "-p") == 0 || strcmp(argv[0], "--port") == 0)
&& argc > 1) {
int value = atoi(argv[1]);
if (value >= 0 && value <= 0xFFFF) {
args.port = (unsigned short) value;
}
--argc;
++argv;
} else {
puts("ERROR: Invalid args!\n");
print_usage();
exit(1);
}
--argc;
++argv;
}
return args;
}
// vim: ts=2 sts=2 sw=2

15
src/arg_parse.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_ARG_PARSE_H_
#define SEODISPARATE_COM_C_SIMPLE_HTTP_ARG_PARSE_H_
typedef struct Args {
unsigned short flags;
unsigned short port;
} Args;
void print_usage(void);
Args parse_args(int argc, char **argv);
#endif
// vim: ts=2 sts=2 sw=2

20
src/big_endian.c Normal file
View file

@ -0,0 +1,20 @@
#include "big_endian.h"
int is_big_endian(void) {
union {
int i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1 ? 1 : 0;
}
unsigned short u16_be_swap(unsigned short value) {
if (is_big_endian()) {
return value;
} else {
return ((value >> 8) & 0xFF) | ((value << 8) & 0xFF00);
}
}
// vim: ts=2 sts=2 sw=2

10
src/big_endian.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_BIG_ENDIAN_H_
#define SEODISPARATE_COM_C_SIMPLE_HTTP_BIG_ENDIAN_H_
int is_big_endian(void);
unsigned short u16_be_swap(unsigned short value);
#endif
// vim: ts=2 sts=2 sw=2

5
src/globals.c Normal file
View file

@ -0,0 +1,5 @@
#include "globals.h"
int C_SIMPLE_HTTP_KEEP_RUNNING = 1;
// vim: ts=2 sts=2 sw=2

8
src/globals.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_GLOBALS_H_
#define SEODISPARATE_COM_C_SIMPLE_HTTP_GLOBALS_H_
extern int C_SIMPLE_HTTP_KEEP_RUNNING;
#endif
// vim: ts=2 sts=2 sw=2

View file

@ -4,161 +4,18 @@
#include <stdio.h> #include <stdio.h>
// Unix includes. // Unix includes.
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
#define C_SIMPLE_HTTP_TCP_SOCKET_BACKLOG 64 // Local includes.
#include "arg_parse.h"
#include "big_endian.h"
#include "tcp_socket.h"
#include "signal_handling.h"
#include "globals.h"
#define C_SIMPLE_HTTP_SLEEP_NANOS 1000000 #define C_SIMPLE_HTTP_SLEEP_NANOS 1000000
static int C_SIMPLE_HTTP_KEEP_RUNNING = 1;
void C_SIMPLE_HTTP_handle_sigint(int signal) {
if (signal == SIGINT) {
#ifndef NDEBUG
puts("Handling SIGINT");
#endif
C_SIMPLE_HTTP_KEEP_RUNNING = 0;
}
}
typedef struct Args {
unsigned short flags;
unsigned short port;
} Args;
int is_big_endian(void) {
union {
int i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1 ? 1 : 0;
}
unsigned short u16_be_swap(unsigned short value) {
if (is_big_endian()) {
return value;
} else {
return ((value >> 8) & 0xFF) | ((value << 8) & 0xFF00);
}
}
int create_tcp_socket(unsigned short port) {
struct sockaddr_in6 ipv6_addr;
memset(&ipv6_addr, 0, sizeof(struct sockaddr_in6));
ipv6_addr.sin6_family = AF_INET6;
ipv6_addr.sin6_port = u16_be_swap(port);
ipv6_addr.sin6_addr = in6addr_any;
int tcp_socket = socket(AF_INET6, SOCK_STREAM | SOCK_NONBLOCK, 6);
if (tcp_socket == -1) {
switch (errno) {
case EACCES:
puts("ERROR: Socket creation: EACCES");
break;
case EAFNOSUPPORT:
puts("ERROR: Socket creation: EAFNOSUPPORT");
break;
case EINVAL:
puts("ERROR: Socket creation: EINVAL");
break;
case EMFILE:
puts("ERROR: Socket creation: EMFILE");
break;
case ENOBUFS:
puts("ERROR: Socket creation: ENOBUFS");
break;
case ENOMEM:
puts("ERROR: Socket creation: ENOMEM");
break;
case EPROTONOSUPPORT:
puts("ERROR: Socket creation: EPROTONOSUPPORT");
break;
default:
puts("ERROR: Socket creation: Unknown Error");
break;
}
return -1;
}
int ret = bind(tcp_socket, (const struct sockaddr *)&ipv6_addr, sizeof(struct sockaddr_in6));
if (ret != 0) {
close(tcp_socket);
puts("ERROR: Failed to bind socket!");
return -1;
}
ret = listen(tcp_socket, C_SIMPLE_HTTP_TCP_SOCKET_BACKLOG);
if (ret == 0) {
return tcp_socket;
} else {
switch (errno) {
case EADDRINUSE:
puts("ERROR: Socket listen: EADDRINUSE");
break;
case EBADF:
puts("ERROR: Socket listen: EBADF");
break;
case ENOTSOCK:
puts("ERROR: Socket listen: ENOTSOCK");
break;
default:
puts("ERROR: Socket listen: Unknown Error");
break;
}
return -1;
}
}
void cleanup_tcp_socket(int *tcp_socket) {
if (tcp_socket && *tcp_socket != -1) {
close(*tcp_socket);
*tcp_socket = -1;
}
}
void print_usage(void) {
puts("Usage:");
puts(" -p <port> | --port <port>");
}
Args parse_args(int argc, char **argv) {
--argc;
++argv;
Args args;
memset(&args, 0, sizeof(Args));
while (argc > 0) {
if ((strcmp(argv[0], "-p") == 0 || strcmp(argv[0], "--port") == 0)
&& argc > 1) {
int value = atoi(argv[1]);
if (value >= 0 && value <= 0xFFFF) {
args.port = (unsigned short) value;
}
--argc;
++argv;
} else {
puts("ERROR: Invalid args!\n");
print_usage();
exit(1);
}
--argc;
++argv;
}
return args;
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
Args args = parse_args(argc, argv); Args args = parse_args(argc, argv);

21
src/signal_handling.c Normal file
View file

@ -0,0 +1,21 @@
#include "signal_handling.h"
// Standard library includes.
#include <stdio.h>
// Unix includes.
#include <signal.h>
// Local includes
#include "globals.h"
void C_SIMPLE_HTTP_handle_sigint(int signal) {
if (signal == SIGINT) {
#ifndef NDEBUG
puts("Handling SIGINT");
#endif
C_SIMPLE_HTTP_KEEP_RUNNING = 0;
}
}
// vim: ts=2 sts=2 sw=2

8
src/signal_handling.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_SIGNAL_HANDLING_H_
#define SEODISPARATE_COM_C_SIMPLE_HTTP_SIGNAL_HANDLING_H_
void C_SIMPLE_HTTP_handle_sigint(int signal);
#endif
// vim: ts=2 sts=2 sw=2

94
src/tcp_socket.c Normal file
View file

@ -0,0 +1,94 @@
#include "tcp_socket.h"
// Standard library includes.
#include <stdio.h>
#include <string.h>
// Unix includes.
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <unistd.h>
// Local includes.
#include "big_endian.h"
int create_tcp_socket(unsigned short port) {
struct sockaddr_in6 ipv6_addr;
memset(&ipv6_addr, 0, sizeof(struct sockaddr_in6));
ipv6_addr.sin6_family = AF_INET6;
ipv6_addr.sin6_port = u16_be_swap(port);
ipv6_addr.sin6_addr = in6addr_any;
int tcp_socket = socket(AF_INET6, SOCK_STREAM | SOCK_NONBLOCK, 6);
if (tcp_socket == -1) {
switch (errno) {
case EACCES:
puts("ERROR: Socket creation: EACCES");
break;
case EAFNOSUPPORT:
puts("ERROR: Socket creation: EAFNOSUPPORT");
break;
case EINVAL:
puts("ERROR: Socket creation: EINVAL");
break;
case EMFILE:
puts("ERROR: Socket creation: EMFILE");
break;
case ENOBUFS:
puts("ERROR: Socket creation: ENOBUFS");
break;
case ENOMEM:
puts("ERROR: Socket creation: ENOMEM");
break;
case EPROTONOSUPPORT:
puts("ERROR: Socket creation: EPROTONOSUPPORT");
break;
default:
puts("ERROR: Socket creation: Unknown Error");
break;
}
return -1;
}
int ret = bind(tcp_socket, (const struct sockaddr *)&ipv6_addr, sizeof(struct sockaddr_in6));
if (ret != 0) {
close(tcp_socket);
puts("ERROR: Failed to bind socket!");
return -1;
}
ret = listen(tcp_socket, C_SIMPLE_HTTP_TCP_SOCKET_BACKLOG);
if (ret == 0) {
return tcp_socket;
} else {
switch (errno) {
case EADDRINUSE:
puts("ERROR: Socket listen: EADDRINUSE");
break;
case EBADF:
puts("ERROR: Socket listen: EBADF");
break;
case ENOTSOCK:
puts("ERROR: Socket listen: ENOTSOCK");
break;
default:
puts("ERROR: Socket listen: Unknown Error");
break;
}
return -1;
}
}
void cleanup_tcp_socket(int *tcp_socket) {
if (tcp_socket && *tcp_socket != -1) {
close(*tcp_socket);
*tcp_socket = -1;
}
}
// vim: ts=2 sts=2 sw=2

12
src/tcp_socket.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_TCP_SOCKET_H_
#define SEODISPARATE_COM_C_SIMPLE_HTTP_TCP_SOCKET_H_
#define C_SIMPLE_HTTP_TCP_SOCKET_BACKLOG 64
int create_tcp_socket(unsigned short port);
void cleanup_tcp_socket(int *tcp_socket);
#endif
// vim: ts=2 sts=2 sw=2