···88#include <string.h>
99#include <sys/socket.h>
10101111+// Macro para probar si un numero es negativo. En general, esta libreria
1212+// prefiere crashear el programa que dejar que el usuario arregle un error.
1113#define try(a) do { \
1214 if ((a) < 0) { \
1315 fprintf(stderr, "[ERROR]: %s:%d %s\n", __FILE__, __LINE__, strerror(errno)); \
···1921typedef uint16_t Port;
2022typedef uint8_t Byte;
21232424+// Buffer de bytes, lo puedes usar para lo que sea.
2225typedef struct {
2326 size_t len;
2427 Byte* buf;
2528} Buffer;
26293030+// Convierte un string de C a un buffer de bytes.
2731Buffer atob(const char* str);
28323333+3434+// Tipo para un IPv4. Ademas te ayuda convertir entre little endian y big
3535+// endian. La data de bytes aparece como bytes[3]bytes[2]bytes[1]bytes[0] en
3636+// memoria.
2937typedef union {
3038 Byte bytes[4];
3139 uint32_t ip;
3240} IPv4;
33414242+// Enchufe.
3443typedef struct {
3544 FD fd;
3645 struct sockaddr_in addr;
3746 socklen_t addrlen;
3847} Enchufe;
39484949+// Receptaculo.
4050typedef struct {
4151 struct sockaddr_in addr;
4252 socklen_t addrlen;
4353} Receptaculo;
44545555+// Crea un file descriptor nuevo para un enchufe.
4556inline FD nuevo() {
4657 FD fd = socket(PF_INET, SOCK_STREAM, 0);
4758 try (fd);
4859 return fd;
4960}
50616262+// Crea un receptaculo.
5163inline Receptaculo receptaculo(IPv4 ip, Port port) {
5264 struct sockaddr_in name = {
5365 .sin_family = AF_INET,
···6274 };
6375}
64767777+// Coge un file descriptor y un receptaculo y los junta. En otras palabras, los
7878+// aplasta. Un enchufe es basicamente, un file descriptor con un IP.
6579inline Enchufe aplasta(FD fd, Receptaculo rec) {
6680 return (Enchufe){
6781 .fd = fd,
···7084 };
7185}
72868787+// Esta funcion te crea un enchufe.
7388Enchufe enchufa(IPv4 ip, Port port);
8989+9090+// Esta funcion crea la conexion desde tu computadora hasta donde sea que este
9191+// el enchufe.
7492void conecta(Enchufe enchufe);
9393+9494+// Esta funcion amarra la direccion de IP que se le dio al enchufe, al file
9595+// descriptor. Hay casos donde no vas a querer que esten amarrados, como cuando
9696+// no te importa la direccion que tendra un cliente conectandose a un servidor,
9797+// por eso el default es que la funcion enchufa(ip, port) no amarre el file
9898+// descriptor al puerto.
7599void amarra(Enchufe enchufe);
100100+101101+// Le deja saber al enchufe cuantas conexiones se pueden hacer. El default es
102102+// que no se puedan hacer conexiones. Asi que si estas codificando un servidor,
103103+// tienes que llamar esta funcion.
76104void escucha(Enchufe enchufe, size_t len);
105105+106106+// Esta funcion bloquea el thread hasta que un cliente se conecte. Devuelve el
107107+// enchufe del cliente para poder comunicarse con el cliente. Tienes que
108108+// desenchufarlo cuando termines la direccion.
77109Enchufe acepta(Enchufe enchufe);
110110+111111+// Envia un buffer de bytes a un cliente.
78112void zumba(Enchufe enchufe, Buffer in_buf);
113113+114114+// Recibe un buffer de bytes de un cliente. Devuelve la cantidad de bytes que se
115115+// leyeron. Si devuelve 0, entonces el cliente cerro la conexion.
79116size_t recibe(Enchufe enchufe, Buffer out_buf);
117117+118118+// Esta funcion se encarga de liberar los recursos que ocupan los echufes.
80119void desenchufa(Enchufe enchufe);
8112082121#endif // ENCHUFE_H_ header
+16-6
src/lib/lib.c
···2121 if (str.len != calculated_len) {
2222 log(ERROR, "%s:%d String's length (%zu) is not equal to given length (%zu).", __FILE__, __LINE__, calculated_len, str.len);
23232424- printf("\n");
2424+ printf("\nBuffer contains: ");
2525 for (size_t i = 0; i < max_len; ++i) printf("[%d] ", str.buf[i]);
2626 printf("\n");
2727···3030 if (str.len > max_len) {
3131 log(ERROR, "%s:%d String's length (%zu) is larger than the buffer that contains it (%zu).\n", str.len, calculated_len);
32323333- printf("\n");
3333+ printf("\nBuffer contains: ");
3434 for (size_t i = 0; i < max_len; ++i) printf("[%d] ", str.buf[i]);
3535 printf("\n");
3636···3939 return str;
4040}
41414242-// Convertr the buffer received from a socket into an array of processes. The
4242+// Converts the buffer received from a socket into an array of processes. The
4343// user must free this memory.
4444Procs deserialize(Buffer out_buf, size_t msg_len) {
4545 Procs procs = {
···4848 };
4949 exists(procs.procs);
50505151+ // This loop will continue until all Proc's have been deserialized.
5152 size_t buf_idx = 0;
5253 for (size_t j = 0; buf_idx < msg_len; ++j) {
5354 // Reallocate new Proc if more than one proc was received.
···6465 size_t len = *(size_t*)(curr + sizeof(Time));
6566 Byte* str_buf = curr + sizeof(Time) + sizeof(size_t);
66676868+ // Validate the string in the buffer.
6769 Buffer program = validate_str((Buffer){.len = len, .buf = str_buf}, msg_len - buf_idx);
68707171+ // Insert everything into the proc list.
6972 procs.procs[j] = (Proc){
7073 .time = time,
7174 .program = bufcpy(program),
···7780 return procs;
7881}
79828383+// This function turns a proc into a buffer. In order to do that, this function
8484+// reinterprets everything on the proc as a sequence of bytes.
8085Buffer serialize(Proc proc) {
8686+ // First, determine how long the buffer has to be.
8187 size_t len = sizeof(Time) + sizeof(size_t) + proc.program.len + 1;
8888+8989+ // Allocate the bytes in the buffer.
8290 Buffer buf = {
8391 .len = len,
8492 .buf = (Byte*)calloc(len, sizeof(Byte)),
8593 };
8694 exists(buf.buf);
87959696+ // Copy everything in the buffer.
8897 memcpy((void*)buf.buf, (void*)&proc.time, sizeof(Time));
8998 memcpy((void*)(buf.buf + sizeof(Time)), (void*)&proc.program.len, sizeof(size_t));
9099 memcpy((void*)(buf.buf + sizeof(Time) + sizeof(size_t)), (void*)proc.program.buf, proc.program.len);
91100 return buf;
92101}
93102103103+// This function takes a string representing an IPv4 address and converts it
104104+// into an IPv4 type.
94105IPv4 parse_address(const char* str) {
9595- size_t len = strlen(str);
9696-9797- assert(len <= 15 && "What you have entered cannot possibly be an IP address.");
106106+ size_t len = safe_strlen(str, 15);
9810799108 IPv4 ip = {0};
100109 size_t curr_byte = 0;
···109118 return ip;
110119}
111120121121+// uses memchr to calculate strlen.
112122size_t safe_strlen(const char* str, size_t max_len) {
113123 return (size_t)memchr(str, '\0', max_len) - (size_t)str;
114124}
+17-2
src/lib/lib.h
···33#include "enchufe.h"
44#include <assert.h>
5566+// Macro para detectar si un pointer es NULL. Usa esta funcion si prefieres
77+// crashear el programa cuando encuetras un puntero NULL.
68#define exists(a) do { \
79 if ((a) == NULL) { \
810 fprintf(stderr, "[ERROR]: %s:%d Null pointer encountered, %s\n", __FILE__, __LINE__, strerror(errno)); \
···1012 } \
1113 } while(0)
12141515+// Esto es necesario por si prefieres que Proc aguante una unidad de tiempo
1616+// distinta.
1317typedef Byte Time;
14181919+// Esto sera lo que se envia y recibe por el socket.
1520typedef struct {
1621 Time time;
1722 Buffer program;
1823} Proc;
19242525+// Esto es para crear una lista dinamica de Procs.
2026typedef struct {
2127 Proc* procs;
2228 size_t len;
2329} Procs;
24302525-typedef Buffer SafeStr;
3131+// Esta funcion convierte un buffer en una lista de Proc's.
3232+Procs deserialize(Buffer out_buf, size_t msg_len);
26332727-Procs deserialize(Buffer out_buf, size_t msg_len);
3434+// Esta funcion convierte un Proc en un buffer.
2835Buffer serialize(Proc);
3636+3737+// Esta funcion convierte un string que representa un IPv4 en un IPv4.
2938IPv4 parse_address(const char* str);
3939+4040+// Esta funcion verifica que el string enviado por el socket sea valido.
3041Buffer validate_str(Buffer str, size_t max_len);
4242+4343+// Esta funcion crea una copia de un buffer en memoria y lo devuelve.
3144Buffer bufcpy(Buffer in);
4545+4646+// Esta funcion es mejor que strlen.
3247size_t safe_strlen(const char* str, size_t max_len);
33483449#endif // LIB_H_
+1
src/lib/log.c
···22#include <stdarg.h>
33#include "log.h"
4455+// LOGGGG
56void log(LogLevel level, const char* format, ...) {
67 FILE* out = stdout;
78
···11#include "pq.h"
22#include "log.h"
3344-#include <string.h>
44+// Just sets the head to NULL.
55PQ pq_init() {
66 return (PQ){.head = NULL};
77}
8899+// Goes node by node freeing all the memory.
910void pq_deinit(PQ* pq) {
1011 exists(pq);
1112 struct Node* curr = pq->head;
···1819 }
1920}
20212222+2323+// I spent way too long trying to implement this in C. . . So I tried it in
2424+// Haskell. The Haskell implementation looks like this:
2525+// insert :: a -> [a] -> [a]
2626+// insert p [] = [p]
2727+// insert p (x:xs) = if x > p then p:x:xs else x:insert p xs
2828+// The C implementation looks like this:
2129Node* n_insert(Proc proc, Node* node) {
2230 if (node == NULL) {
2331 Node* n = malloc(sizeof(Node));
···3947 }
4048}
41495050+// This function just calls n_insert.
4251void pq_insert(PQ* pq, Proc proc) {
4352 exists(pq);
44534554 pq->head = n_insert(proc, pq->head);
4655}
47565757+// Free node and buffer.
4858void pq_delete(PQ* pq) {
4959 exists(pq);
5060 if (pq->head != NULL) {
···5565 }
5666}
57676868+// This function creates a copy of the Proc.
5869Proc pq_access(PQ pq) {
5970 exists(pq.head);
6071 Proc proc = pq.head->proc;
···7081 };
7182}
72838484+// This function.
7385void pq_print(PQ pq) {
7486 struct Node* curr = pq.head;
7587 printf("\n");
···8799 printf("\n");
88100}
89101102102+// When the head is NULL the list is empty.
90103bool pq_empty(PQ pq) {
91104 return pq.head == NULL;
92105}
+19
src/lib/pq.h
···33#include "lib.h"
44#include <stdbool.h>
5566+// Nodo que aguanta cada proceso.
67struct Node {
78 Proc proc;
89 struct Node* next;
910};
1111+// Para crear un struct recursivo no se puede hacer un typedef. Aqui esta el
1212+// typedef.
1013typedef struct Node Node;
11141515+// Funcion helper para insertar un proceso en la lista y respetar el orden de
1616+// tiempo de procesos.
1217Node* n_insert(Proc proc, Node* node);
13181919+// La estructura para priority queue.
1420typedef struct {
1521 Node* head;
1622} PQ;
17232424+// Inicializar el prio queue.
1825PQ pq_init();
2626+2727+// La funcion para borrar el prio queue.
1928void pq_deinit(PQ* pq);
2929+3030+// La funcion para insertar en el prio queue.
2031void pq_insert(PQ* pq, Proc proc);
3232+3333+// la funcion para borrar el primer elemento del prio queue.
2134void pq_delete(PQ* pq);
3535+3636+// La funcion para accesar el tope del prio queue.
2237Proc pq_access(PQ pq);
3838+3939+// La funcion para imprimir el prio queue.
2340void pq_print(PQ pq);
4141+4242+// La funcion para verificar si el prio queue esta vacio.
2443bool pq_empty(PQ pq);
25442645#endif // PQ_H_