Threads and Scheduling
1#ifndef ENCHUFE_H_
2#define ENCHUFE_H_
3#include <errno.h>
4#include <netinet/in.h>
5#include <stdint.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <sys/socket.h>
10
11// Macro para probar si un numero es negativo. En general, esta libreria
12// prefiere crashear el programa que dejar que el usuario arregle un error.
13#define try(a) do { \
14 if ((a) < 0) { \
15 fprintf(stderr, "[ERROR]: %s:%d %s\n", __FILE__, __LINE__, strerror(errno)); \
16 exit (EXIT_FAILURE); \
17 } \
18 } while(0)
19
20typedef int FD; // short for FileDescriptor
21typedef uint16_t Port;
22typedef uint8_t Byte;
23
24// Buffer de bytes, lo puedes usar para lo que sea.
25typedef struct {
26 size_t len;
27 Byte* buf;
28} Buffer;
29
30// Convierte un string de C a un buffer de bytes.
31Buffer atob(const char* str);
32
33
34// Tipo para un IPv4. Ademas te ayuda convertir entre little endian y big
35// endian. La data de bytes aparece como bytes[3]bytes[2]bytes[1]bytes[0] en
36// memoria.
37typedef union {
38 Byte bytes[4];
39 uint32_t ip;
40} IPv4;
41
42// Enchufe.
43typedef struct {
44 FD fd;
45 struct sockaddr_in addr;
46 socklen_t addrlen;
47} Enchufe;
48
49// Receptaculo.
50typedef struct {
51 struct sockaddr_in addr;
52 socklen_t addrlen;
53} Receptaculo;
54
55// Crea un file descriptor nuevo para un enchufe.
56inline FD nuevo() {
57 FD fd = socket(PF_INET, SOCK_STREAM, 0);
58 try (fd);
59 return fd;
60}
61
62// Crea un receptaculo.
63inline Receptaculo receptaculo(IPv4 ip, Port port) {
64 struct sockaddr_in name = {
65 .sin_family = AF_INET,
66 .sin_port = port,
67 .sin_addr = {
68 .s_addr = ip.ip,
69 },
70 };
71 return (Receptaculo){
72 .addr = name,
73 .addrlen = sizeof(name),
74 };
75}
76
77// Coge un file descriptor y un receptaculo y los junta. En otras palabras, los
78// aplasta. Un enchufe es basicamente, un file descriptor con un IP.
79inline Enchufe aplasta(FD fd, Receptaculo rec) {
80 return (Enchufe){
81 .fd = fd,
82 .addr = rec.addr,
83 .addrlen = rec.addrlen,
84 };
85}
86
87// Esta funcion te crea un enchufe.
88Enchufe enchufa(IPv4 ip, Port port);
89
90// Esta funcion crea la conexion desde tu computadora hasta donde sea que este
91// el enchufe.
92void conecta(Enchufe enchufe);
93
94// Esta funcion amarra la direccion de IP que se le dio al enchufe, al file
95// descriptor. Hay casos donde no vas a querer que esten amarrados, como cuando
96// no te importa la direccion que tendra un cliente conectandose a un servidor,
97// por eso el default es que la funcion enchufa(ip, port) no amarre el file
98// descriptor al puerto.
99void amarra(Enchufe enchufe);
100
101// Le deja saber al enchufe cuantas conexiones se pueden hacer. El default es
102// que no se puedan hacer conexiones. Asi que si estas codificando un servidor,
103// tienes que llamar esta funcion.
104void escucha(Enchufe enchufe, size_t len);
105
106// Esta funcion bloquea el thread hasta que un cliente se conecte. Devuelve el
107// enchufe del cliente para poder comunicarse con el cliente. Tienes que
108// desenchufarlo cuando termines la direccion.
109Enchufe acepta(Enchufe enchufe);
110
111// Envia un buffer de bytes a un cliente.
112void zumba(Enchufe enchufe, Buffer in_buf);
113
114// Recibe un buffer de bytes de un cliente. Devuelve la cantidad de bytes que se
115// leyeron. Si devuelve 0, entonces el cliente cerro la conexion.
116size_t recibe(Enchufe enchufe, Buffer out_buf);
117
118// Esta funcion se encarga de liberar los recursos que ocupan los echufes.
119void desenchufa(Enchufe enchufe);
120
121#endif // ENCHUFE_H_ header