summaryrefslogtreecommitdiff
path: root/C
diff options
context:
space:
mode:
Diffstat (limited to 'C')
-rw-r--r--C/OOP/Makefile18
-rw-r--r--C/OOP/README4
-rw-r--r--C/OOP/animal/animal.c72
-rw-r--r--C/OOP/cat/cat.c41
-rw-r--r--C/OOP/include/animal_p.h23
-rw-r--r--C/OOP/include/animal_priv.h19
-rw-r--r--C/OOP/include/cat_p.h19
-rw-r--r--C/OOP/main.c30
-rw-r--r--C/Pointers/addr.c47
-rw-r--r--C/Pointers/multi_indirection.c42
-rw-r--r--C/README.md3
-rwxr-xr-xC/enumbin0 -> 12568 bytes
-rw-r--r--C/enum.c17
-rw-r--r--C/final-project-z2h/Makefile22
-rw-r--r--C/final-project-z2h/README.md1
-rw-r--r--C/final-project-z2h/fdbbin0 -> 1044 bytes
-rw-r--r--C/final-project-z2h/include/common.h8
-rw-r--r--C/final-project-z2h/include/file.h7
-rw-r--r--C/final-project-z2h/include/parse.h26
-rw-r--r--C/final-project-z2h/src/file.c39
-rw-r--r--C/final-project-z2h/src/main.c108
-rw-r--r--C/final-project-z2h/src/parse.c162
-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
26 files changed, 1004 insertions, 0 deletions
diff --git a/C/OOP/Makefile b/C/OOP/Makefile
new file mode 100644
index 0000000..478ddab
--- /dev/null
+++ b/C/OOP/Makefile
@@ -0,0 +1,18 @@
+oop_prog: main.o animal.o cat.o
+ gcc -Wall -o oop_prog main.o cat/cat.o animal/animal.o
+
+main.o: main.c
+ gcc -I./include -c main.c
+
+animal.o: animal/animal.c
+ gcc -I./include -c animal/animal.c -o animal/animal.o
+
+cat.o: cat/cat.c
+ gcc -I./include -c cat/cat.c -o cat/cat.o
+
+
+clean:
+ rm animal/*.o
+ rm cat/*.o
+ rm main.o
+ rm oop_prog
diff --git a/C/OOP/README b/C/OOP/README
new file mode 100644
index 0000000..4aab525
--- /dev/null
+++ b/C/OOP/README
@@ -0,0 +1,4 @@
+This is a simple example on how to write Object-oriented code in C.
+
+The structure here is simple, we have a 'parent' class named Animal,
+and its sub-classes based on different animals.
diff --git a/C/OOP/animal/animal.c b/C/OOP/animal/animal.c
new file mode 100644
index 0000000..01934d7
--- /dev/null
+++ b/C/OOP/animal/animal.c
@@ -0,0 +1,72 @@
+/* Animal class implementation */
+
+#define MAX_NAME_LEN 10
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "animal_priv.h"
+
+
+struct animal * animal_new() {
+ return (struct animal *)malloc(sizeof(struct animal));
+}
+
+/*
+ * By passing the custom sound function to the constructor, we prevent the need to expose the
+ * Animal's private interface to the sub-class
+ *
+ * This is an attempt to get as much abstraction as possible of a C program.
+ * The sub-class has no business in understanding the inner functionality of the parent class,
+ * so, this is an attempt to hide the animal implementation as much as possible from the sub-class.
+ */
+void animal_ctor(struct animal *animal,
+ void (*sound_fn)(void))
+{
+ animal->name = malloc(MAX_NAME_LEN * sizeof(char));
+
+ if (sound_fn)
+ animal->make_sound = sound_fn;
+ else
+ animal->make_sound = NULL;
+}
+
+void animal_dtor(struct animal *animal)
+{
+ free(animal->name);
+}
+
+void animal_get_name(struct animal *animal, char *name)
+{
+ strncpy(name, animal->name, MAX_NAME_LEN);
+}
+
+void animal_set_name(struct animal *animal, const char *name)
+{
+ if (strlen(name) >= MAX_NAME_LEN)
+ strncpy(animal->name, "\0", 1);
+ else
+ strncpy(animal->name, name, MAX_NAME_LEN);
+}
+
+/*
+ * To be able to access the object specific implementation of make_sound(),
+ * this function should somehow access the function pointer to the
+ * object-specific implementation.
+ *
+ * This could be done in two ways:
+ * - By having the Animal object embedded within the sub-class, so both
+ * the Animal object and the Sub-Class object will share the same address
+ * in memory, or:
+ * - We add an 'ops' field in the Animal object, which should be populated
+ * by the sub-class.
+ *
+ * In both ways, there is no way to really hide the Animal implementation from
+ * the sub-class, as in one way or another, we'll need to have access to the
+ * Animal class fields, so we can override the functions.
+ */
+void animal_sound(struct animal *animal)
+{
+ if (animal->make_sound)
+ animal->make_sound();
+}
diff --git a/C/OOP/cat/cat.c b/C/OOP/cat/cat.c
new file mode 100644
index 0000000..c513bb6
--- /dev/null
+++ b/C/OOP/cat/cat.c
@@ -0,0 +1,41 @@
+/*
+ * Cat class.
+ *
+ * This is a subclass of the animal class
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "animal_priv.h"
+#include "animal_p.h"
+
+/*
+ * We need access to animal's definition, so we can embbed it
+ * within our sub-class
+ */
+struct cat {
+ struct animal animal;
+};
+
+void __cat_sound(void)
+{
+ printf("The cat makes MEOOOOOW\n");
+}
+
+struct cat *cat_new(void)
+{
+ return (struct cat*)malloc(sizeof(struct cat));
+}
+
+void cat_ctor(struct cat *cat)
+{
+ animal_ctor((struct animal *)cat,
+ __cat_sound);
+ printf("cat_ctor: cat: %p animal: %p\n", cat, &cat->animal);
+}
+
+void cat_dtor(struct cat *cat)
+{
+ animal_dtor((struct animal *)cat);
+}
diff --git a/C/OOP/include/animal_p.h b/C/OOP/include/animal_p.h
new file mode 100644
index 0000000..e09aa7c
--- /dev/null
+++ b/C/OOP/include/animal_p.h
@@ -0,0 +1,23 @@
+/* Animal class public interface */
+
+#ifndef ANIMAL_P_H
+#define ANIMAL_P_H
+
+/* Forward declaration */
+struct animal;
+
+/* Alloc new object */
+struct animal* animal_new(void);
+
+/* Constructor - make_sound may be NULL*/
+void animal_ctor(struct animal*, void (*make_sound)(void));
+
+/* Destructor */
+void animal_dtor(struct animal*);
+
+/* Behavior */
+void animal_get_name(struct animal*, char*);
+void animal_set_name(struct animal*, const char*);
+void animal_sound(void *);
+
+#endif /* ANIMAL_P_H */
diff --git a/C/OOP/include/animal_priv.h b/C/OOP/include/animal_priv.h
new file mode 100644
index 0000000..78a83c1
--- /dev/null
+++ b/C/OOP/include/animal_priv.h
@@ -0,0 +1,19 @@
+/* Animal class private definition */
+
+#ifndef ANIMAL_PRIV_H
+#define ANIMAL_PRIV_H
+
+/*
+ * We use a "private" definition as a way to encapsulate it, hiding
+ * it from the users.
+ *
+ * Access to its private definition is only allowed to its sub-classes.
+ *
+ * We could enforce it by moving here the allocator and constructors
+ */
+struct animal {
+ char *name;
+ void (*make_sound) (void);
+};
+
+#endif /* ANIMAL_PRIV_H */
diff --git a/C/OOP/include/cat_p.h b/C/OOP/include/cat_p.h
new file mode 100644
index 0000000..82bcfb1
--- /dev/null
+++ b/C/OOP/include/cat_p.h
@@ -0,0 +1,19 @@
+/* Cat class public interface */
+
+#ifndef CAT_P_H
+#define CAT_P_H
+
+struct cat;
+
+/* Allocator */
+struct cat *cat_new(void);
+
+/* Constructor */
+void cat_ctor(struct cat *);
+
+/* Destructor */
+void cat_dtor(struct cat *);
+
+/* Behavior functions inherited from Animal class */
+
+#endif /* CAT_P_H */
diff --git a/C/OOP/main.c b/C/OOP/main.c
new file mode 100644
index 0000000..7943580
--- /dev/null
+++ b/C/OOP/main.c
@@ -0,0 +1,30 @@
+/*
+ * Simple program exemplifying the usage of Animal class
+ * and its sub-classes
+ */
+#include <stdio.h>
+
+/*
+ * The main program here, only need access to the public interfaces
+ * but the sub-classes will need access to the animal's private interface
+ */
+#include "animal_p.h"
+#include "cat_p.h"
+
+int main(void) {
+
+ /* We don't need to know how the cat object is implemented */
+ struct cat *myCat = cat_new();
+
+ cat_ctor(myCat);
+
+ /*
+ * For us to have the Animal class definition hidden, the animal_sound()
+ * should have a way to defer the parent Animal class, from the cat class.
+ *
+ * See its implementation within animal.c
+ */
+ animal_sound((struct animal *)myCat);
+ return 0;
+}
+
diff --git a/C/Pointers/addr.c b/C/Pointers/addr.c
new file mode 100644
index 0000000..f77a9c6
--- /dev/null
+++ b/C/Pointers/addr.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+
+int main (void)
+{
+ /*
+ * Arrays in C are just sequential data items
+ * stored in a memory location
+ * The address of the array, is the same as the first
+ * element in the array
+ * The name of the array is also the address of the array.
+ */
+
+ char str1[] = "Hello cruel world"; /* \0 is automatically added */
+
+ /* Those variables look the same, but they are not. */
+
+ /* This is an array */
+
+ /*
+ * str2, is the address of the "ARRAY" which the characters
+ * of the string are stored
+ * str2 is not a 'pointer' to the location of the Hello char array
+ * str2 IS THE LOCATION of the array.
+ */
+ char str2[] = "Hello";
+
+ /*
+ * This is a pointer.
+ *
+ * Whose value is not the string, but the - address of that string -
+ *
+ */
+ char *str3 = "Goodbye";
+
+ str3 = NULL;
+ str2 = NULL;
+ /*
+ * &str1, &str1[0] and str1, all points to the very same address.
+ *
+ * The array name, str1, is also the address of the array.
+ * */
+ printf("%s, %c, %d, %d %d\n", str1, str1[0], &str1, &str1[0], str1);
+
+ printf("%p %p %s\n", &str2, str2, str2);
+ printf("%p %p %s\n", &str3, str3, str3);
+
+}
diff --git a/C/Pointers/multi_indirection.c b/C/Pointers/multi_indirection.c
new file mode 100644
index 0000000..92b677c
--- /dev/null
+++ b/C/Pointers/multi_indirection.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+char *words[3];
+
+int main(void)
+{
+ char *pc;
+ char **ppc;
+ int i;
+ char *foo, *bar;
+
+ printf("multiple indirection example\n");
+
+ words[0] = "zero";
+ foo = "FOO";
+ words[1] = "one";
+ bar = "BAR";
+ words[2] = "two";
+
+ for (int i = 0; i < 3; i++)
+ printf("%s\n", words[i]);
+
+ printf("Print each char in each string...\n");
+
+ ppc = words;
+
+ printf("Addr of array head %p\n", words);
+ for (i = 0; i < 3; i ++) {
+ ppc = words + i;
+ pc = *ppc;
+
+ printf("array %d -> loc %p -> deref: %p\n", i, &words[i], *ppc);
+ while (*pc != 0) {
+ printf("addr: %p - content: %c \n", pc, *pc);
+ pc += 1;
+ }
+
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/C/README.md b/C/README.md
new file mode 100644
index 0000000..8b8d49d
--- /dev/null
+++ b/C/README.md
@@ -0,0 +1,3 @@
+### Random C code ###
+
+Just a bunch of random C code with no specific purpose
diff --git a/C/enum b/C/enum
new file mode 100755
index 0000000..dda68f7
--- /dev/null
+++ b/C/enum
Binary files differ
diff --git a/C/enum.c b/C/enum.c
new file mode 100644
index 0000000..f177efa
--- /dev/null
+++ b/C/enum.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+enum names {
+ BAR = 5,
+ FOO,
+ RONALDO
+};
+
+int main(void) {
+ enum names myName;
+
+ myName = BAR;
+ printf("Enum: %d\n", myName);
+ myName = 99;
+
+ return myName;
+}
diff --git a/C/final-project-z2h/Makefile b/C/final-project-z2h/Makefile
new file mode 100644
index 0000000..be3cefa
--- /dev/null
+++ b/C/final-project-z2h/Makefile
@@ -0,0 +1,22 @@
+TARGET = bin/dbview
+SRC = $(wildcard src/*.c)
+OBJ = $(patsubst src/%.c, obj/%.o, $(SRC))
+
+run: clean default
+ ./$(TARGET) -f ./mynewdb.db -n
+ ./$(TARGET) -f ./mynewdb.db -a "Timmy H.,123 Sheshire Ln.,120"
+
+default: $(TARGET)
+
+clean:
+ rm -f obj/*.o
+ rm -f bin/*
+ rm -f *.db
+
+$(TARGET): $(OBJ)
+ gcc -o $@ $?
+
+obj/%.o : src/%.c
+ gcc -c $< -o $@ -Iinclude
+
+
diff --git a/C/final-project-z2h/README.md b/C/final-project-z2h/README.md
new file mode 100644
index 0000000..560d92e
--- /dev/null
+++ b/C/final-project-z2h/README.md
@@ -0,0 +1 @@
+# This is a readme file
diff --git a/C/final-project-z2h/fdb b/C/final-project-z2h/fdb
new file mode 100644
index 0000000..394b7fb
--- /dev/null
+++ b/C/final-project-z2h/fdb
Binary files differ
diff --git a/C/final-project-z2h/include/common.h b/C/final-project-z2h/include/common.h
new file mode 100644
index 0000000..839cc6f
--- /dev/null
+++ b/C/final-project-z2h/include/common.h
@@ -0,0 +1,8 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#define STATUS_ERROR -1
+#define STATUS_SUCCESS 0
+
+
+#endif
diff --git a/C/final-project-z2h/include/file.h b/C/final-project-z2h/include/file.h
new file mode 100644
index 0000000..73fd2a7
--- /dev/null
+++ b/C/final-project-z2h/include/file.h
@@ -0,0 +1,7 @@
+#ifndef FILE_H
+#define FILE_H
+
+int create_db_file(char *filename);
+int open_db_file(char *filename);
+
+#endif
diff --git a/C/final-project-z2h/include/parse.h b/C/final-project-z2h/include/parse.h
new file mode 100644
index 0000000..edcda9b
--- /dev/null
+++ b/C/final-project-z2h/include/parse.h
@@ -0,0 +1,26 @@
+#ifndef PARSE_H
+#define PARSE_H
+
+#define HEADER_MAGIC 0x4c4c4144
+
+struct dbheader_t {
+ unsigned int magic;
+ unsigned short version;
+ unsigned short count;
+ unsigned int filesize;
+};
+
+struct employee_t {
+ char name[256];
+ char address[256];
+ unsigned int hours;
+};
+
+int create_db_header(int fd, struct dbheader_t **headerOut);
+int validate_db_header(int fd, struct dbheader_t **headerOut);
+int read_employees(int fd, struct dbheader_t *, struct employee_t **employeesOut);
+int output_file(int fd, struct dbheader_t *, struct employee_t *employees);
+void list_employees(struct dbheader_t *dbhdr, struct employee_t *employees);
+int add_employee(struct dbheader_t *dbhdr, struct employee_t *employees, char *addstring);
+
+#endif
diff --git a/C/final-project-z2h/src/file.c b/C/final-project-z2h/src/file.c
new file mode 100644
index 0000000..fcdb036
--- /dev/null
+++ b/C/final-project-z2h/src/file.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "file.h"
+#include "common.h"
+
+
+int create_db_file(char *filename) {
+ int fd = open(filename, O_RDWR);
+ if (fd != -1) {
+ close(fd);
+ printf("File already exists\n");
+ return STATUS_ERROR;
+ }
+
+ fd = open(filename, O_RDWR | O_CREAT, 0644);
+ if (fd == -1) {
+ perror("open");
+ return STATUS_ERROR;
+ }
+
+ return fd;
+}
+
+int open_db_file(char *filename) {
+ int fd = open(filename, O_RDWR, 0644);
+ if (fd == -1) {
+ perror("open");
+ return STATUS_ERROR;
+ }
+
+ return fd;
+}
+
+
diff --git a/C/final-project-z2h/src/main.c b/C/final-project-z2h/src/main.c
new file mode 100644
index 0000000..09cbde1
--- /dev/null
+++ b/C/final-project-z2h/src/main.c
@@ -0,0 +1,108 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "file.h"
+#include "parse.h"
+
+void print_usage(char *argv[]) {
+ printf("Usage: %s -n -f <database file>\n", argv[0]);
+ printf("\t -n - create new database file\n");
+ printf("\t -f - (required) path to database file\n");
+ return;
+}
+
+int main(int argc, char *argv[]) {
+ char *filepath = NULL;
+ char *portarg = NULL;
+ unsigned short port = 0;
+ bool newfile = false;
+ bool list = false;
+ char *addstring = NULL;
+ int c;
+
+ int dbfd = -1;
+ struct dbheader_t *dbhdr = NULL;
+ struct employee_t *employees = NULL;
+
+ while ((c = getopt(argc, argv, "nf:a:l")) != -1) {
+ switch (c) {
+ case 'n':
+ newfile = true;
+ break;
+ case 'f':
+ filepath = optarg;
+ break;
+ case 'p':
+ portarg = optarg;
+ break;
+ case 'a':
+ addstring = optarg;
+ break;
+ case 'l':
+ list = true;
+ break;
+ case '?':
+ printf("Unknown option -%c\n", c);
+ break;
+ default:
+ return -1;
+
+ }
+ }
+
+ if (filepath == NULL) {
+ printf("Filepath is a required argument\n");
+ print_usage(argv);
+
+ return 0;
+ }
+
+
+ if (newfile) {
+ dbfd = create_db_file(filepath);
+ if (dbfd == STATUS_ERROR) {
+ printf("Unable to create database file\n");
+ return -1;
+ }
+
+ if (create_db_header(dbfd, &dbhdr) == STATUS_ERROR) {
+ printf("Failed to create database header\n");
+ return -1;
+ }
+ } else {
+ dbfd = open_db_file(filepath);
+ if (dbfd == STATUS_ERROR) {
+ printf("Unable to open database file\n");
+ return -1;
+ }
+
+ if (validate_db_header(dbfd, &dbhdr) == STATUS_ERROR) {
+ printf("Failed to validate database header\n");
+ return -1;
+ }
+ }
+
+ if (read_employees(dbfd, dbhdr, &employees) != STATUS_SUCCESS) {
+ printf("Failed to read employees");
+ return 0;
+ }
+
+ if (addstring) {
+ dbhdr->count++;
+ employees = realloc(employees, dbhdr->count*(sizeof(struct employee_t)));
+ add_employee(dbhdr, employees, addstring);
+ }
+
+ if (list) {
+ list_employees(dbhdr, employees);
+ }
+
+
+ output_file(dbfd, dbhdr, employees);
+
+
+ return 0;
+}
diff --git a/C/final-project-z2h/src/parse.c b/C/final-project-z2h/src/parse.c
new file mode 100644
index 0000000..0f9b8e7
--- /dev/null
+++ b/C/final-project-z2h/src/parse.c
@@ -0,0 +1,162 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "common.h"
+#include "parse.h"
+
+void list_employees(struct dbheader_t *dbhdr, struct employee_t *employees) {
+ int i = 0;
+ for (; i < dbhdr->count; i++) {
+ printf("Employee %d\n", i);
+ printf("\tName: %s\n", employees[i].name);
+ printf("\tAddress: %s\n", employees[i].address);
+ printf("\tHours: %d\n", employees[i].hours);
+ }
+}
+
+int add_employee(struct dbheader_t *dbhdr, struct employee_t *employees, char *addstring) {
+ printf("%s\n", addstring);
+
+ char *name = strtok(addstring, ",");
+
+ char *addr = strtok(NULL, ",");
+
+ char *hours = strtok(NULL, ",");
+
+ printf("%s %s %s\n", name, addr, hours);
+
+
+ strncpy(employees[dbhdr->count-1].name, name, sizeof(employees[dbhdr->count-1].name));
+ strncpy(employees[dbhdr->count-1].address, addr, sizeof(employees[dbhdr->count-1].address));
+
+ employees[dbhdr->count-1].hours = atoi(hours);
+
+
+ return STATUS_SUCCESS;
+}
+
+int read_employees(int fd, struct dbheader_t *dbhdr, struct employee_t **employeesOut) {
+ if (fd < 0) {
+ printf("Got a bad FD from the user\n");
+ return STATUS_ERROR;
+ }
+
+
+ int count = dbhdr->count;
+
+ struct employee_t *employees = calloc(count, sizeof(struct employee_t));
+ if (employees == (void*)-1) {
+ printf("Malloc failed\n");
+ return STATUS_ERROR;
+ }
+
+ read(fd, employees, count*sizeof(struct employee_t));
+
+ int i = 0;
+ for (; i < count; i++) {
+ employees[i].hours = ntohl(employees[i].hours);
+ }
+
+ *employeesOut = employees;
+ return STATUS_SUCCESS;
+
+}
+
+int output_file(int fd, struct dbheader_t *dbhdr, struct employee_t *employees) {
+ if (fd < 0) {
+ printf("Got a bad FD from the user\n");
+ return STATUS_ERROR;
+ }
+
+ int realcount = dbhdr->count;
+
+ dbhdr->magic = htonl(dbhdr->magic);
+ dbhdr->filesize = htonl(sizeof(struct dbheader_t) + (sizeof(struct employee_t) * realcount));
+ dbhdr->count = htons(dbhdr->count);
+ dbhdr->version = htons(dbhdr->version);
+
+ lseek(fd, 0, SEEK_SET);
+
+ write(fd, dbhdr, sizeof(struct dbheader_t));
+
+ int i = 0;
+ for (; i < realcount; i++) {
+ employees[i].hours = htonl(employees[i].hours);
+ write(fd, &employees[i], sizeof(struct employee_t));
+ }
+
+ return STATUS_SUCCESS;
+
+}
+
+int validate_db_header(int fd, struct dbheader_t **headerOut) {
+ if (fd < 0) {
+ printf("Got a bad FD from the user\n");
+ return STATUS_ERROR;
+ }
+
+ struct dbheader_t *header = calloc(1, sizeof(struct dbheader_t));
+ if (header == (void*)-1) {
+ printf("Malloc failed create a db header\n");
+ return STATUS_ERROR;
+ }
+
+ if (read(fd, header, sizeof(struct dbheader_t)) != sizeof(struct dbheader_t)) {
+ perror("read");
+ free(header);
+ return STATUS_ERROR;
+ }
+
+ header->version = ntohs(header->version);
+ header->count = ntohs(header->count);
+ header->magic = ntohl(header->magic);
+ header->filesize = ntohl(header->filesize);
+
+ if (header->magic != HEADER_MAGIC) {
+ printf("Impromper header magic\n");
+ free(header);
+ return -1;
+ }
+
+
+ if (header->version != 1) {
+ printf("Impromper header version\n");
+ free(header);
+ return -1;
+ }
+
+ struct stat dbstat = {0};
+ fstat(fd, &dbstat);
+ if (header->filesize != dbstat.st_size) {
+ printf("Corrupted database\n");
+ free(header);
+ return -1;
+ }
+
+ *headerOut = header;
+}
+
+int create_db_header(int fd, struct dbheader_t **headerOut) {
+ struct dbheader_t *header = calloc(1, sizeof(struct dbheader_t));
+ if (header == (void*)-1) {
+ printf("Malloc failed to create db header\n");
+ return STATUS_ERROR;
+ }
+
+ header->version = 0x1;
+ header->count = 0;
+ header->magic = HEADER_MAGIC;
+ header->filesize = sizeof(struct dbheader_t);
+
+ *headerOut = header;
+
+ return STATUS_SUCCESS;
+}
+
+
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;
+