summaryrefslogtreecommitdiff
path: root/C/netCode
diff options
context:
space:
mode:
authorCarlos Maiolino <[email protected]>2025-07-10 22:55:07 +0200
committerCarlos Maiolino <[email protected]>2025-07-10 22:56:55 +0200
commitd98f46ce647846b0aa30b2e16a30fd4e152a1bf5 (patch)
tree267474fcc77cf20b428f6f4c7f768ca09f4cfe0e /C/netCode
parent869e68986aa8f69af6e7842260a68d1e5c6f796f (diff)
Add new code
Signed-off-by: Carlos Maiolino <[email protected]>
Diffstat (limited to 'C/netCode')
-rw-r--r--C/netCode/.gitignore2
-rw-r--r--C/netCode/client.c66
-rw-r--r--C/netCode/server.c202
-rw-r--r--C/netCode/types.h26
4 files changed, 296 insertions, 0 deletions
diff --git a/C/netCode/.gitignore b/C/netCode/.gitignore
new file mode 100644
index 0000000..f2ad853
--- /dev/null
+++ b/C/netCode/.gitignore
@@ -0,0 +1,2 @@
+client
+server
diff --git a/C/netCode/client.c b/C/netCode/client.c
new file mode 100644
index 0000000..dafd1e8
--- /dev/null
+++ b/C/netCode/client.c
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include "types.h"
+
+void handle_client(int fd)
+{
+ char buf[4096] = {0};
+ int *data;
+ proto_hdr_t *hdr = (proto_hdr_t*)buf;
+
+
+ read(fd, buf, sizeof(proto_hdr_t) + sizeof(int));
+
+ hdr->type = ntohl(hdr->type);
+ hdr->len = ntohs(hdr->len);
+
+ data = (int *)&hdr[1];
+ *data = ntohl(*data);
+
+ if (hdr->type != PROTO_HELLO)
+ printf("Protocol mismatch\n");
+
+ if (*data != 1)
+ printf("Protocol version mismatch\n");
+
+ printf("Client connected - proto: %d ver: %d payload: %d\n",
+ hdr->type, hdr->len, *data);
+}
+
+int main(int argc, char *argv[])
+{
+ int err;
+ struct sockaddr_in serverInfo = {0};
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (argc != 2) {
+ printf("Usage: ./client <ip>\n");
+ exit(1);
+ }
+
+ serverInfo.sin_family = AF_INET;
+ serverInfo.sin_addr.s_addr = inet_addr(argv[1]);;
+ serverInfo.sin_port = htons(SERVER_PORT);
+
+ if (fd < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ err = connect(fd, (struct sockaddr*)&serverInfo, sizeof(serverInfo));
+ if (err < 0) {
+ perror("connect");
+ close(fd);
+ exit(1);
+ }
+
+ handle_client(fd);
+ close(fd);
+ return 0;
+}
diff --git a/C/netCode/server.c b/C/netCode/server.c
new file mode 100644
index 0000000..0b951eb
--- /dev/null
+++ b/C/netCode/server.c
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include "types.h"
+
+clientstate_t clientStates[MAX_CLIENTS];
+
+void init_clients(void) {
+ int i;
+
+ for (i = 0; i < MAX_CLIENTS; i++) {
+ /* -1 means client slot is free */
+ clientStates[i].fd = -1;
+ clientStates[i].state = STATE_NEW;
+ memset(&clientStates[i].buffer, 0, BUF_SIZE);
+ }
+}
+
+int find_free_client(void) {
+ int i = 0;
+
+ for (i = 0; i < MAX_CLIENTS; i++)
+ if (clientStates[i].fd == -1)
+ return i;
+
+ return -1;
+}
+
+int find_slot_by_fd(int fd)
+{
+ int i;
+ for (i = 0; i < MAX_CLIENTS; i++) {
+ if (clientStates[i].fd == fd)
+ return i;
+ }
+ return -1;
+}
+
+void handle_client(int fd)
+{
+ char buf[4096] = {0};
+ proto_hdr_t *hdr = (proto_hdr_t*)buf;
+ int *data;
+ int reallen;
+
+ hdr->type = htonl(PROTO_HELLO);
+ reallen = sizeof(int);
+ hdr->len = htons(reallen);
+
+ data = (int *)&hdr[1];
+ *data = htonl(1);
+
+ printf("hdr_ptr: %p data_ptr: %p\n", hdr, data);
+ write(fd, hdr, sizeof(proto_hdr_t) + reallen);
+
+}
+
+
+int main(void)
+{
+ int err;
+ int listen_fd, conn_fd, nfds, freeSlot;
+ struct sockaddr_in serverInfo = {0};
+ struct sockaddr_in clientInfo = {0};
+ socklen_t csize;
+ int opt = 1;
+
+ struct pollfd fds[MAX_CLIENTS + 1];
+
+ memset(fds, 9, sizeof(fds));
+ serverInfo.sin_family = AF_INET;
+ serverInfo.sin_addr.s_addr = 0; /* bind to all IPs */
+ serverInfo.sin_port = htons(SERVER_PORT);
+
+ init_clients();
+
+ listen_fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (listen_fd < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ err = bind(listen_fd,
+ (struct sockaddr *)&serverInfo,
+ sizeof(serverInfo));
+
+ if (err < 0) {
+ perror("bind");
+ close(listen_fd);
+ exit(1);
+ }
+
+ err = listen(listen_fd, 0);
+ if (err < 0) {
+ perror("listen");
+ close(listen_fd);
+ exit(1);
+ }
+
+ if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
+ perror("setsockopt");
+ close(listen_fd);
+ exit(1);
+ }
+
+ printf("Server listening to port: %d\n", SERVER_PORT);
+
+ csize = sizeof(clientInfo);
+
+ fds[0].fd = listen_fd;
+ fds[0].events = POLLIN;
+ nfds = 1;
+
+ while (1) {
+ int i, j;
+ int nevents;
+
+ /* fds is initialized with MAX_CLIENTS + 1 */
+ for (i = 0, j = 1; i < MAX_CLIENTS; i++, j++) {
+ if (clientStates[i].fd != -1) {
+ /* Add open fd to the poll */
+ fds[j].fd = clientStates[i].fd;
+ fds[j].events = POLLIN;
+ printf("FD %d added to poll\n", clientStates[i].fd);
+ }
+ }
+
+ nevents = poll(fds, nfds, -1);
+
+ if (nevents == -1) {
+ perror("poll");
+ exit(1);
+ }
+
+ /* if listen_fd is ready, accept it */
+ if (fds[0].revents & POLLIN) {
+ conn_fd = accept(listen_fd,
+ (struct sockaddr*)&clientInfo,
+ &csize);
+
+ if (conn_fd < 0) {
+ perror("accept");
+ continue;
+ }
+
+ printf("New connection from: %s:%d\n",
+ inet_ntoa(clientInfo.sin_addr),
+ ntohs(clientInfo.sin_port));
+
+ freeSlot = find_free_client();
+ if (freeSlot < 0) {
+ printf("Server full - closing connection\n");
+ close(conn_fd);
+ } else {
+ clientStates[freeSlot].fd = conn_fd;
+ clientStates[freeSlot].state = STATE_CONNECTED;
+ nfds++;
+ printf("Adding fd %d to slot %d\n",
+ conn_fd, freeSlot);
+ }
+ nevents--;
+ }
+
+ printf("NFDS: %d\n", nfds);
+ for (i = 1; i <= nfds && nevents > 0; i++) {
+ int fd, slot;
+ ssize_t bytes_read;
+
+ if (fds[i].revents & POLLIN) {
+ nevents--;
+
+ fd = fds[i].fd;
+ slot = find_slot_by_fd(fd);
+ bytes_read = read(fd,
+ &clientStates[slot].buffer,
+ sizeof(clientStates[slot].buffer));
+ if (bytes_read <= 0) {
+ close(fd);
+ printf("Connection error\n");
+ if (slot == -1) {
+ printf("Trying to close an invalid fd\n");
+ } else {
+ clientStates[slot].fd = -1;
+ clientStates[slot].state = STATE_DISCONNECTED;
+ printf("Client disconnected or error\n");
+ nfds--;
+ }
+ } else {
+ printf("Data received: %s\n", clientStates[slot].buffer);
+ }
+ }
+
+ }
+ }
+ return 0;
+}
diff --git a/C/netCode/types.h b/C/netCode/types.h
new file mode 100644
index 0000000..e70974e
--- /dev/null
+++ b/C/netCode/types.h
@@ -0,0 +1,26 @@
+#define SERVER_PORT 5555
+#define MAX_CLIENTS 5
+#define BUF_SIZE 4096
+
+typedef enum {
+ PROTO_HELLO,
+} proto_type_e;
+
+/* Type-Length-Value */
+typedef struct {
+ proto_type_e type;
+ unsigned short len;
+} proto_hdr_t;
+
+typedef enum {
+ STATE_NEW,
+ STATE_CONNECTED,
+ STATE_DISCONNECTED,
+} state_e;
+
+typedef struct {
+ int fd;
+ state_e state;
+ char buffer[BUF_SIZE];
+} clientstate_t;
+