Threads and Scheduling
at main 121 lines 3.3 kB view raw
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