commit 26e3fc66a65026d6a5be21a76350dc8a6ef36924 Author: Marc Cane Date: Tue Apr 28 22:04:35 2026 +0200 Inicial diff --git a/P2P/CMakeLists.txt b/P2P/CMakeLists.txt new file mode 100644 index 0000000..66a4d27 --- /dev/null +++ b/P2P/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.5) +project(P2P) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + +set(SOURCE_FILES ../nodelumi2/MIp2-lumi.h ../nodelumi2/MIp2-lumi.c MIp2-p2p.c MIp2-mi.c MIp2-mi.h) +add_executable(P2P ${SOURCE_FILES}) \ No newline at end of file diff --git a/P2P/MIp2-mi.c b/P2P/MIp2-mi.c new file mode 100644 index 0000000..00c4d6a --- /dev/null +++ b/P2P/MIp2-mi.c @@ -0,0 +1,574 @@ +/**************************************************************************/ +/* */ +/* P1 - MI amb sockets TCP/IP - Part I */ +/* Fitxer mi.c que implementa la capa d'aplicació de MI, sobre la capa de */ +/* transport TCP (fent crides a la interfície de la capa TCP -sockets-). */ +/* */ +/* Autors: Marc Cané Salamià, Enric Rodríguez Galán */ +/* */ +/**************************************************************************/ + +/* Inclusió de llibreries, p.e. #include o #include "meu.h" */ +/* (si les funcions externes es cridessin entre elles, faria falta fer */ +/* un #include "MIp1v4-mi.h") */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "MIp2-mi.h" +#include + +/* Definició de constants, p.e., #define MAX_LINIA 150 */ + +#define TECLAT 0 +#define MAX_FD 2 +#define MAX_MESSAGE_SIZE 303 +#define NOM_INTERFICIE "lo" //Aquest valor s'ha de canviar si es vol fer funcionar la funcio MI_ObtenirInfoServidor() +#define IP_LENGTH 16 + +/* Declaració de funcions internes que es fan servir en aquest fitxer */ +/* (les seves definicions es troben més avall) per així fer-les conegudes */ +/* des d'aqui fins al final de fitxer. */ +int TCP_CreaSockClient(const char *IPloc, int portTCPloc); +int TCP_CreaSockServidor(const char *IPloc, int portTCPloc); +int TCP_DemanaConnexio(int Sck, const char *IPrem, int portTCPrem); +int TCP_AcceptaConnexio(int Sck, char *IPrem, int *portTCPrem); +int TCP_Envia(int Sck, const char *SeqBytes, int LongSeqBytes); +int TCP_Rep(int Sck, char *SeqBytes, int LongSeqBytes); +int TCP_TancaSock(int Sck); +int TCP_TrobaAdrSockLoc(int Sck, char *IPloc, int *portTCPloc); +int TCP_TrobaAdrSockRem(int Sck, char *IPrem, int *portTCPrem); +int HaArribatAlgunaCosa(const int *LlistaSck, int LongLlistaSck); +void MostraError(const char *text); + + +/* Definicio de funcions EXTERNES, és a dir, d'aquelles que en altres */ +/* fitxers externs es faran servir. */ +/* En termes de capes de l'aplicació, aquest conjunt de funcions externes */ +/* formen la interfície de la capa MI. */ + +/* Inicia l’escolta de peticions remotes de conversa a través d’un nou */ +/* socket TCP en el #port “portTCPloc” i una @IP local qualsevol (és a */ +/* dir, crea un socket “servidor” o en estat d’escolta – listen –). */ +/* Retorna -1 si hi ha error; l’identificador del socket d’escolta de MI */ +/* creat si tot va bé. */ +int MI_IniciaEscPetiRemConv(int portTCPloc) +{ + return TCP_CreaSockServidor("0.0.0.0", portTCPloc); +} + +/* Escolta indefinidament fins que arriba una petició local de conversa */ +/* a través del teclat o bé una petició remota de conversa a través del */ +/* socket d’escolta de MI d’identificador “SckEscMI” (un socket */ +/* “servidor”). */ +/* Retorna -1 si hi ha error; 0 si arriba una petició local; SckEscMI si */ +/* arriba una petició remota. */ +int MI_HaArribatPetiConv(int SckEscMI) +{ + int FDs[] = {TECLAT, SckEscMI}; + return HaArribatAlgunaCosa(FDs, MAX_FD); +} + +/* Crea una conversa iniciada per una petició local que arriba a través */ +/* del teclat: crea un socket TCP “client” (en un #port i @IP local */ +/* qualsevol), a través del qual fa una petició de conversa a un procés */ +/* remot, el qual les escolta a través del socket TCP ("servidor") d'@IP */ +/* “IPrem” i #port “portTCPrem” (és a dir, crea un socket “connectat” o */ +/* en estat establert – established –). Aquest socket serà el que es farà */ +/* servir durant la conversa. */ +/* Omple “IPloc*” i “portTCPloc*” amb, respectivament, l’@IP i el #port */ +/* TCP del socket del procés local. */ +/* El nickname local “NicLoc” i el nickname remot són intercanviats amb */ +/* el procés remot, i s’omple “NickRem*” amb el nickname remot. El procés */ +/* local és qui inicia aquest intercanvi (és a dir, primer s’envia el */ +/* nickname local i després es rep el nickname remot). */ +/* "IPrem" i "IPloc*" són "strings" de C (vectors de chars imprimibles */ +/* acabats en '\0') d'una longitud màxima de 16 chars (incloent '\0'). */ +/* "NicLoc" i "NicRem*" són "strings" de C (vectors de chars imprimibles */ +/* acabats en '\0') d'una longitud màxima de 300 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; l’identificador del socket de conversa de */ +/* MI creat si tot va bé. */ +int MI_DemanaConv(const char *IPrem, int portTCPrem, char *IPloc, int *portTCPloc, const char *NicLoc, char *NicRem) +{ + int sock; + + sock = TCP_CreaSockClient("0.0.0.0", 0); + if (sock == -1) return -1; + + if (TCP_DemanaConnexio(sock,IPrem, portTCPrem) == -1) return -1; + + if(TCP_TrobaAdrSockLoc(sock, IPloc, portTCPloc) == -1) return -1; + + if (MI_EnviaNickname(sock,NicLoc) == -1) + return -1; + + char buff[300]; + int long_nom = MI_RepLinia(sock,buff); + + if (long_nom == -1 ) return -1; + + //strncpy(NicRem, buff, long_nom); + strcpy(NicRem,buff); + //strcpy(NicRem,"setaci"); + + return sock; +} + +/* Crea una conversa iniciada per una petició remota que arriba a través */ +/* del socket d’escolta de MI d’identificador “SckEscMI” (un socket */ +/* “servidor”): accepta la petició i crea un socket (un socket */ +/* “connectat” o en estat establert – established –), que serà el que es */ +/* farà servir durant la conversa. */ +/* Omple “IPrem*”, “portTCPrem*”, “IPloc*” i “portTCPloc*” amb, */ +/* respectivament, l’@IP i el #port TCP del socket del procés remot i del */ +/* socket del procés local. */ +/* El nickname local “NicLoc” i el nickname remot són intercanviats amb */ +/* el procés remot, i s’omple “NickRem*” amb el nickname remot. El procés */ +/* remot és qui inicia aquest intercanvi (és a dir, primer es rep el */ +/* nickname remot i després s’envia el nickname local). */ +/* "IPrem*" i "IPloc*" són "strings" de C (vectors de chars imprimibles */ +/* acabats en '\0') d'una longitud màxima de 16 chars (incloent '\0'). */ +/* "NicLoc" i "NicRem*" són "strings" de C (vectors de chars imprimibles */ +/* acabats en '\0') d'una longitud màxima de 300 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; l’identificador del socket de conversa */ +/* de MI creat si tot va bé. */ +int MI_AcceptaConv(int SckEscMI, char *IPrem, int *portTCPrem, char *IPloc, int *portTCPloc, const char *NicLoc, char *NicRem) +{ + //if (TCP_TrobaAdrSockRem(SckEscMI, IPrem, portTCPrem) == -1) return -1; + + int sock; + + sock = TCP_AcceptaConnexio(SckEscMI,IPrem,portTCPrem); + if (sock == -1) + return -1; + + if (TCP_TrobaAdrSockLoc(sock, IPloc, portTCPloc) == -1) + return -1; + + if (TCP_TrobaAdrSockRem(sock, IPrem, portTCPrem) == -1) + return -1; + + char buff[300]; + int long_nom = MI_RepLinia(sock,buff); + + if (long_nom == -1 ) return -1; + + if (MI_EnviaNickname(sock,NicLoc) == -1) + return -1; + + //strncpy(NicRem, buff, long_nom); + strcpy(NicRem,buff); + + return sock; +} + +/* Escolta indefinidament fins que arriba una línia local de conversa a */ +/* través del teclat o bé una línia remota de conversa a través del */ +/* socket de conversa de MI d’identificador “SckConvMI” (un socket */ +/* "connectat”). */ +/* Retorna -1 si hi ha error; 0 si arriba una línia local; SckConvMI si */ +/* arriba una línia remota. */ +int MI_HaArribatLinia(int SckConvMI) +{ + int FDs[] = {TECLAT, SckConvMI}; + return HaArribatAlgunaCosa(FDs, MAX_FD); +} + +/* Envia a través del socket de conversa de MI d’identificador */ +/* “SckConvMI” (un socket “connectat”) la línia “Linia” escrita per */ +/* l’usuari local. */ +/* "Linia" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0'), no conté el caràcter fi de línia ('\n') i té una longitud */ +/* màxima de 300 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; el nombre de caràcters n de la línia */ +/* enviada (sense el ‘\0’) si tot va bé (0 <= n <= 299). */ +int MI_EnviaLinia(int SckConvMI, const char *Linia) +{ + char missatge[MAX_MESSAGE_SIZE+1], tipus = 'L'; + int miss_len = strlen(Linia); + sprintf(missatge,"%c%.3d%s",tipus,miss_len,Linia); + return TCP_Envia(SckConvMI, missatge, miss_len+4); +} + +/* Envia a través del socket de conversa de MI d’identificador */ +/* “SckConvMI” (un socket “connectat”) el nickname "Nick" escrit per */ +/* l’usuari local. */ +/* "Nick" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0'), no conté el caràcter fi de línia ('\n') i té una longitud */ +/* màxima de 300 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; el nombre de caràcters n del nickname */ +/* enviat (sense el ‘\0’) si tot va bé (0 <= n <= 299). */ +int MI_EnviaNickname(int SckConvMI, const char *Nick) +{ + char nickname[MAX_MESSAGE_SIZE+1], tipus = 'N'; + int miss_len = strlen(Nick); + sprintf(nickname,"%c%.3d%s",tipus,miss_len,Nick); + return TCP_Envia(SckConvMI, nickname, miss_len+4); +} + +/* Rep a través del socket de conversa de MI d’identificador “SckConvMI” */ +/* (un socket “connectat”) una línia escrita per l’usuari remot, amb la */ +/* qual omple “Linia”, o bé detecta l’acabament de la conversa per part */ +/* de l’usuari remot. */ +/* "Linia*" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0'), no conté el caràcter fi de línia ('\n') i té una longitud */ +/* màxima de 300 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; -2 si l’usuari remot acaba la conversa; el */ +/* nombre de caràcters n de la línia rebuda (sense el ‘\0’) si tot va bé */ +/* (0 <= n <= 299). */ +int MI_RepLinia(int SckConvMI, char *Linia) +{ + int res; + char buffer[MAX_MESSAGE_SIZE]; + + res = TCP_Rep(SckConvMI, buffer, sizeof(buffer)); + + if (res > 0){ + + char len[3]; + strncpy(len, buffer+1, sizeof(len)); + int long_miss = atoi(len); + + buffer[res]='\0'; + strcpy(Linia, buffer+4); + + res = long_miss; + } + else if (res == 0) res=-2; + + return res; +} + +/* Acaba la conversa associada al socket de conversa de MI */ +/* d’identificador “SckConvMI” (un socket “connectat”). */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int MI_AcabaConv(int SckConvMI) +{ + return TCP_TancaSock(SckConvMI); +} + +/* Acaba l’escolta de peticions remotes de conversa que arriben a través */ +/* del socket d’escolta de MI d’identificador “SckEscMI” (un socket */ +/* “servidor”). */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int MI_AcabaEscPetiRemConv(int SckEscMI) +{ + return TCP_TancaSock(SckEscMI); +} + +///******************************** FUNCIONS ADICIONALS DE LA CAPA MI ********************************/// + + +/* Donat un socket descriptor sock, ens troba la IP i el port a on es */ +/* troba. */ +/* "IPloc" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0') */ +/* Retorna -1 si algo ha anat malament, 0 si no hi ha hagut problemes */ +int MI_ObtenirInfoServidor(int sock, char *IPloc, int *portTCPloc){ + + if (TCP_TrobaAdrSockLoc(sock, IPloc, portTCPloc) == -1) return -1; //Aixo ens dona el port pero no la IP + + ///**** Fragment de codi extret de: https://stackoverflow.com/questions/20800319/how-do-i-get-my-ip-address-in-c-on-linux ****/// + + struct ifaddrs *addrs,*tmp; + + getifaddrs(&addrs); //funcio que ens retornara una llista encadenada d'interficies + + tmp = addrs; + int trobat = 0; + + while (tmp && !trobat) //Mentre ens quedin candidats i no el trobem + { + if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET) //Si la interficie es IPv4 + { + struct sockaddr_in *pAddr = (struct sockaddr_in *)tmp->ifa_addr; + if (strcmp(tmp->ifa_name,NOM_INTERFICIE) == 0) { //Si hem trobat la nostre interficie + strcpy(IPloc,inet_ntoa(pAddr->sin_addr)); + trobat = 1; + } + } + + tmp = tmp->ifa_next; + } + freeifaddrs(addrs); + + ///***************************************************************************************************************************/// + + return 0; +} + +/**************************************************************************/ +/* */ +/* P1 - MI amb sockets TCP/IP - Part I */ +/* Versio numero 1.337 */ +/* */ +/* Autors: Marc Cané Salamià, Enric Rodríguez Galán */ +/* */ +/**************************************************************************/ + + +/* Definicio de funcions */ + +/* Crea un socket TCP “client” a l’@IP “IPloc” i #port TCP “portTCPloc” */ +/* (si “IPloc” és “0.0.0.0” i/o “portTCPloc” és 0 es fa/farà una */ +/* assignació implícita de l’@IP i/o del #port TCP, respectivament). */ +/* "IPloc" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0') */ +/* Retorna -1 si hi ha error; l’identificador del socket creat si tot */ +/* va bé. */ +int TCP_CreaSockClient(const char *IPloc, int portTCPloc) +{ + int sockdesc; + if ((sockdesc = socket(AF_INET,SOCK_STREAM,0)) == -1){ + MostraError("Error creació socket client"); + return -1; + } + else{ + struct sockaddr_in adr; + + adr.sin_family = AF_INET; + adr.sin_addr.s_addr = inet_addr(IPloc); + adr.sin_port = htons(portTCPloc); + int i; + for(i=0;i<8;i++){adr.sin_zero[i]='0';} + + if (bind(sockdesc,(struct sockaddr*)&adr,sizeof(adr))==-1){ + MostraError("Error bind client"); + return -1; + } + } + return sockdesc; +} + +/* Crea un socket TCP “servidor” (o en estat d’escolta – listen –) a */ +/* l’@IP “IPloc” i #port TCP “portTCPloc” (si “IPloc” és “0.0.0.0” i/o */ +/* “portTCPloc” és 0 es fa una assignació implícita de l’@IP i/o del */ +/* #port TCP, respectivament). */ +/* "IPloc" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; l’identificador del socket creat si tot */ +/* va bé. */ +int TCP_CreaSockServidor(const char *IPloc, int portTCPloc) +{ + int sockdesc; + + if ((sockdesc = socket(AF_INET,SOCK_STREAM,0)) == -1){ + MostraError("Error creació socket servidor"); + return -1; + } + + struct sockaddr_in adr; + + adr.sin_family = AF_INET; + adr.sin_addr.s_addr = inet_addr(IPloc); + adr.sin_port = htons(portTCPloc); + int i; + for(i=0;i<8;i++){adr.sin_zero[i]='0';} + + if (bind(sockdesc,(struct sockaddr*)&adr,sizeof(adr))==-1){ + MostraError("Error bind servidor"); + return -1; + } + + if((listen(sockdesc,3))==-1){ + MostraError("Error bind servidor"); + return -1; + } + + return sockdesc; +} + +/* El socket TCP “client” d’identificador “Sck” demana una connexió al */ +/* socket TCP “servidor” d’@IP “IPrem” i #port TCP “portTCPrem” (si tot */ +/* va bé es diu que el socket “Sck” passa a l’estat “connectat” o */ +/* establert – established –). */ +/* "IPrem" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int TCP_DemanaConnexio(int Sck, const char *IPrem, int portTCPrem) +{ + struct sockaddr_in adr; + + adr.sin_family = AF_INET; + adr.sin_addr.s_addr = inet_addr(IPrem); + adr.sin_port = htons(portTCPrem); + int i; + for(i=0;i<8;i++){adr.sin_zero[i]='0';} + + if((connect(Sck,(struct sockaddr*)&adr,sizeof(adr)))==-1){ + char buff[100]; + snprintf(buff, sizeof(buff), "Error: no s'ha pogut connectar amb %s", IPrem); + MostraError(buff); + return -1; + } + + return 1; +} + +/* El socket TCP “servidor” d’identificador “Sck” accepta fer una */ +/* connexió amb un socket TCP “client” remot, i crea un “nou” socket, */ +/* que és el que es farà servir per enviar i rebre dades a través de la */ +/* connexió (es diu que aquest nou socket es troba en l’estat “connectat” */ +/* o establert – established –; el nou socket té la mateixa adreça que */ +/* “Sck”). */ +/* Omple “IPrem*” i “portTCPrem*” amb respectivament, l’@IP i el #port */ +/* TCP del socket remot amb qui s’ha establert la connexió. */ +/* "IPrem*" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; l’identificador del socket connectat creat */ +/* si tot va bé. */ + +int TCP_AcceptaConnexio(int Sck, char *IPrem, int *portTCPrem) +{ + struct sockaddr_in adr; + int scon; + + adr.sin_family = AF_INET; + adr.sin_addr.s_addr = inet_addr(IPrem); + adr.sin_port = htons(*portTCPrem); + int i; + for(i=0;i<8;i++){adr.sin_zero[i]='0';} + + size_t long_adr = sizeof(adr); + + if((scon=accept(Sck,(struct sockaddr*)&adr, &long_adr))==-1) + { + char buff[100]; + snprintf(buff, sizeof(buff), "Error: no s'ha pogut acceptar la connexio de %s", IPrem); + MostraError(buff); + return -1; + } + + return scon; +} + +/* Envia a través del socket TCP “connectat” d’identificador “Sck” la */ +/* seqüència de bytes escrita a “SeqBytes” (de longitud “LongSeqBytes” */ +/* bytes) cap al socket TCP remot amb qui està connectat. */ +/* "SeqBytes" és un vector de chars qualsevol (recordeu que en C, un */ +/* char és un enter de 8 bits) d'una longitud >= LongSeqBytes bytes. */ +/* Retorna -1 si hi ha error; el nombre de bytes enviats si tot va bé. */ +int TCP_Envia(int Sck, const char *SeqBytes, int LongSeqBytes) +{ + return write(Sck,SeqBytes,LongSeqBytes); +} + +/* Rep a través del socket TCP “connectat” d’identificador “Sck” una */ +/* seqüència de bytes que prové del socket remot amb qui està connectat, */ +/* i l’escriu a “SeqBytes*” (que té una longitud de “LongSeqBytes” bytes),*/ +/* o bé detecta que la connexió amb el socket remot ha estat tancada. */ +/* "SeqBytes*" és un vector de chars qualsevol (recordeu que en C, un */ +/* char és un enter de 8 bits) d'una longitud <= LongSeqBytes bytes. */ +/* Retorna -1 si hi ha error; 0 si la connexió està tancada; el nombre de */ +/* bytes rebuts si tot va bé. */ +int TCP_Rep(int Sck, char *SeqBytes, int LongSeqBytes) +{ + return read(Sck,SeqBytes,LongSeqBytes); +} + +/* S’allibera (s’esborra) el socket TCP d’identificador “Sck”; si “Sck” */ +/* està connectat es tanca la connexió TCP que té establerta. */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int TCP_TancaSock(int Sck) +{ + return close(Sck); +} + +/* Donat el socket TCP d’identificador “Sck”, troba l’adreça d’aquest */ +/* socket, omplint “IPloc*” i “portTCPloc*” amb respectivament, la seva */ +/* @IP i #port TCP. */ +/* "IPloc*" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int TCP_TrobaAdrSockLoc(int Sck, char *IPloc, int *portTCPloc) +{ + struct sockaddr_in adr; + socklen_t long_adr = sizeof(adr); + int res; + + if( (res = getsockname(Sck, (struct sockaddr*)&adr, &long_adr)) == -1){ + MostraError("Error al trobar la direccio local"); + return -1; + } + + strcpy(IPloc,inet_ntoa(adr.sin_addr)); + *portTCPloc = ntohs(adr.sin_port); + return res; +} + +/* Donat el socket TCP “connectat” d’identificador “Sck”, troba l’adreça */ +/* del socket remot amb qui està connectat, omplint “IPrem*” i */ +/* “portTCPrem*” amb respectivament, la seva @IP i #port TCP. */ +/* "IPrem*" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int TCP_TrobaAdrSockRem(int Sck, char *IPrem, int *portTCPrem) +{ + struct sockaddr_in adr; + socklen_t long_adr = sizeof(adr); + int res; + + if ( (res = getpeername(Sck, (struct sockaddr*)&adr, &long_adr)) == -1) { + MostraError("Error al trobar la direccio remota"); + return -1; + } + + strcpy(IPrem,inet_ntoa(adr.sin_addr)); + *portTCPrem = ntohs(adr.sin_port); + + return res; +} + +/* Examina simultàniament i sense límit de temps (una espera indefinida) */ +/* els sockets (poden ser TCP, UDP i stdin) amb identificadors en la */ +/* llista “LlistaSck” (de longitud “LongLlistaSck” sockets) per saber si */ +/* hi ha arribat alguna cosa per ser llegida. */ +/* "LlistaSck" és un vector d'enters d'una longitud >= LongLlistaSck */ +/* Retorna -1 si hi ha error; si arriba alguna cosa per algun dels */ +/* sockets, retorna l’identificador d’aquest socket. */ +int HaArribatAlgunaCosa(const int *LlistaSck, int LongLlistaSck) +{ + /*struct timeval timeout; + timeout.tv_sec = 30; + timeout.tv_usec = 0;*/ //estructura per definir un timeout de 30 segons al select + + fd_set set; + + FD_ZERO(&set); + + int i = 0; + + while (i o #include "meu.h" */ +/* Incloem "MIp1v4-mi.h" per poder fer crides a la interfície de MI */ +#include "MIp2-mi.h" +#include "../nodelumi2/MIp2-lumi.h" + +#include "stdio.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Definició de constants, p.e., #define MAX_LINIA 150 */ + +#define MAX_MISSATGE 300 +#define IP_LENGTH 16 +#define TECLAT 0 +#define MARCA_FI "/end" + +int main(int argc,char *argv[]) +{ + /* Declaració de variables, p.e., int n; */ + + /*int sesc, scon, slumi; //socket descriptor dels sockets + int port=0, port_loc, port_rem; //port: farà de port local o remot segons la situació. Les variables port_loc i port_rem son per claretat de codi. + char IPloc[IP_LENGTH], IPrem[IP_LENGTH]; //IPs local i remota + char adrLUMIloc[MAX_LEN_DOMINI+MAX_USER_NICK+1], adrLUMIrem[MAX_LEN_DOMINI+MAX_USER_NICK+1]; + char nickname_l[MAX_MISSATGE], nickname_r[MAX_MISSATGE]; //Nicknames local i remot + char vols_continuar; //Eleccio de l'usuari + int usuari_vol_conversa=1, connectat = 0; //Boolea per saber si l'usuari vol seguir parlant*/ + + int sesc, scon, slumi, desc; //descriptors dels sockets + int port_loc, port_rem; //port: farà de port local o remot segons la situació. Les variables port_loc i port_rem son per claretat de codi. + char IPloc[IP_LENGTH], IPrem[IP_LENGTH], IPnode[IP_LENGTH]; //IPs local i remota i del node + char adrLUMIloc[MAX_LEN_DOMINI+MAX_USER_NICK+1], adrLUMIrem[MAX_LEN_DOMINI+MAX_USER_NICK+1]; + char nickname_l[MAX_MISSATGE], nickname_r[MAX_MISSATGE]; //Nicknames local i remot + char domini_l[MAX_LEN_DOMINI], domini_r[MAX_LEN_DOMINI]; + char resposta[MAX_MISSATGE_PLUMI+1]; + char vols_continuar; //Eleccio de l'usuari + int fitxer_log; + int usuari_vol_conversa=1, connectat = 0, res; //Boolea per saber si l'usuari vol seguir parlant + int llistaDesc[3]; + + /* Expressions, estructures de control, crides a funcions, etc. */ + printf("Entra la teva @MI: "); + scanf("%s", adrLUMIloc); + printf("Quin nom d'usuari vols fer servir: "); + scanf("%s", nickname_l); + + //LUMI_DescodificarAdreca(adrLUMIloc,nickname_l,domini_l); + + if ((slumi = LUMI_InicialitzarAgent("0.0.0.0",0, &fitxer_log, adrLUMIloc, IPnode)) < 0){ + //Apagar tot + close(slumi); + return 1; + } + + res = LUMI_EnviaPeticioRegistre(slumi, adrLUMIloc); + if (res == 0) printf("S'ha rebut un missatge de confirmacio inesperat\n"); + else if (res == -1) printf("Error a l'hora d'enviar la peticio de registre\n"); + else if (res == -2) printf("Format del missatge de registre enviat incorrecte\n"); + else if (res == -3) printf("L'usuari que has indicat no existeix\n"); + else if (res == -4) printf("L'usuari que has indicat ja esta registrat\n"); + else if (res == -5) printf("Temps d'espera de peticio de registre esgotat\n"); + else if (res == -6) printf("Format del missatge de resposta incorrecte\n"); + else printf("Error desconegut\n"); + + while(usuari_vol_conversa){ + + connectat = 0; + + if ((sesc = MI_IniciaEscPetiRemConv(0)) == -1) return 1; + + if (MI_ObtenirInfoServidor(sesc,IPloc,&port_loc) == -1) return 1; + + //printf("\nLa IP necessaria per comunicar-se amb aquest terminal es: %s\nEl port assignat per comunicar-se amb aquest terminal es: %i\n\n", IPloc, port_loc); + + llistaDesc[0]=TECLAT; + llistaDesc[1]=sesc; + llistaDesc[2]=slumi; + + printf("Si vols iniciar conversa amb algu, entra la seva @MI, altrament espera:\n"); + + while(connectat==0){ + desc = HaArribatAlgunaCosaEnTemps(llistaDesc, 3, 0); + if(desc == slumi){ + res = LUMI_RepLiniaDe(slumi, NULL, NULL, resposta, sizeof(resposta)); + if(res==-2) printf("S'ha rebut una linia mal formatada\n"); + else if(res<=0) printf("S'ha produit un error al rebre un missatge de LUMI\n"); + res = LUMI_DescodificarMissatge(resposta[0], resposta, adrLUMIrem, NULL, NULL); + if(res==-1) printf("Error al descodificar un missatge LUMI\n"); + + if (resposta[0] == 'S') { + //printf("En markus ha respos a la peticio S\n"); + res = LUMI_EnviaRespostaServeiLocalitzacio(slumi, adrLUMIrem, IPloc, port_loc); + if(res<=0) printf("Error al respondre peticio de localitzacio\n"); + } + } + else{ + if (desc == -1){ //Si hi ha algun problema + printf("Error al escoltar\n"); + MI_AcabaEscPetiRemConv(sesc); + return 1; + } + else if(desc == TECLAT){ //Client + + scanf("%s", adrLUMIrem); + + if (strcmp(adrLUMIrem, "/end")!=0) { + + res = LUMI_EnviaPeticioLocalitzacio(slumi, adrLUMIloc, adrLUMIrem, IPrem, &port_rem); + + //printf("Nanu: %s, amb ip: %s i port %i, intenta parlar amb %s, amb ip: %s i port: %i\n", nickname_l, IPloc, port_loc, nickname_r, IPrem, port_rem); + + if (res == 1) { //ha arribat una C + scon = MI_DemanaConv(IPrem, port_rem, IPloc, &port_loc, nickname_l, nickname_r); + + if (scon == -1) return 1; + //printf("YES! Nanu: %s, amb ip: %s i port %i, intenta parlar amb %s, amb ip: %s i port: %i\n", nickname_l, IPloc, port_loc, nickname_r, IPrem, port_rem); + connectat = 1; + } + else { + if (res == 0) printf("S'ha rebut un missatge de confirmacio inesperat\n"); + else if (res == -1) printf("Error a l'hora d'enviar la peticio de localitzacio\n"); + else if (res == -2) printf("Format del missatge de localitzacio enviat incorrecte\n"); + else if (res == -3) printf("L'usuari que has indicat no existeix\n"); + else if (res == -4) printf("L'usuari que has indicat esta fora de linia\n"); + else if (res == -5) printf("Temps d'espera de peticio de localitzacio esgotat\n"); + else if (res == -6) printf("Format del missatge de resposta incorrecte\n"); + else if (res == -7) printf("L'usuari que has indicat esta ocupat. Prova mes tard\n"); + else printf("Error desconegut\n"); + } + } else{ + MI_AcabaEscPetiRemConv(sesc); + printf("Fins aviat!\n"); + return 0; + } + } + else{ //Servidor (sesc) + if ((scon = MI_AcceptaConv(sesc, IPrem, &port_rem, IPloc, &port_loc, nickname_l, nickname_r)) == -1) return 1; + + //printf() + printf("Has iniciat una conversa amb %s\n", nickname_r); + connectat = 1; + } + } + } + + MI_AcabaEscPetiRemConv(sesc); //Deixem d'escoltar, ja tenim un parell d'usuaris connectats + + llistaDesc[1]=scon; + + printf("\nConnexio establerta entre %s i %s\n\n", nickname_l, nickname_r); + printf("Dades de l'usuari local: \n\t @MI: %s \n\t IP: %s \n\t Port: %i \n\n", adrLUMIloc, IPloc, port_loc); + printf("Dades de l'usuari remot: \n\t @MI: %s \n\t IP: %s \n\t Port: %i \n\n", adrLUMIrem, IPrem, port_rem); + + int canal, fi = 0; //fi ens indica si s'ha de parar la execució del programa o no + char buffer[MAX_MISSATGE]; //Buffer on guardarem les linies que anem rebent + + while(!fi){ + + canal = HaArribatAlgunaCosaEnTemps(llistaDesc, 3, 0); //Obtenim el canal pel qual esta arribant una linia + + if(canal == TECLAT){ //Si el canal és teclat significa que nosaltres li volem dir algo al usuari remot + + int bytes_llegits = read(TECLAT,buffer,sizeof(buffer)); //Llegim el que li volem enviar i ho fiquem a un buffer + buffer[bytes_llegits-1] = '\0'; //Per protocol convertim aquesta tira entrada en una "String" de C + + if (bytes_llegits == -1) perror("Error al entrar per teclat"); + + if(strcmp(buffer,MARCA_FI) == 0){ //Pot ser que s'hagi indicat que es vol acabar, en aquest cas no s'envia cap linia al usuari remot + MI_AcabaConv(scon); //Tenca la conversa entre els dos + fi = 1; + } + else MI_EnviaLinia(scon,buffer); //Si no és la marca de fi li enviem el que s'ha escrit per teclat + + } + else if(canal == scon){ //Si el canal és scon significa que hem rebut una linia de l'usuari remot + + int estat_linia; //Variable que ens indica l'estat de la linia que connecta els dos usuaris, no confondre ammb la linia enviada + + estat_linia = MI_RepLinia(scon,buffer); //Es rep la linia enviada i es guarda al buffer + + if (estat_linia == -1){ //Si hi ha algun error en la recepció + perror("Error: s'ha tancat inesperadament la connexio"); + fi = 1; + MI_AcabaConv(scon); + } + else if (estat_linia == -2) { //L'altre ha finalitzat la conversa + fi = 1; + MI_AcabaConv(scon); + printf("L'usuari remot ha finalitzat la connexio\n"); + } + else printf("%s: %s\n", nickname_r, buffer); //Si no hi ha cap problema i no s'ha acabat la conversa mostrem la linia rebuda per pantalla + + } else if (canal == slumi){ + LUMI_RepLiniaDe(slumi, NULL, NULL, resposta, sizeof(resposta)); + char adrDESCrem[sizeof(adrLUMIrem)]; + LUMI_DescodificarMissatge(resposta[0], resposta, adrDESCrem, NULL, NULL); + + if (resposta[0] == 'S') { + LUMI_EnviaResposta(slumi, 'C', adrDESCrem, IPnode, 0); //li passem port 0 per indicar que es un socket UDP "connectat" + } + } + if (canal == -1){ //Si el canal rebut és -1 significa que hi ha algun error + perror("Error desconegut (select)"); + MI_AcabaConv(scon); + } + } + + printf("Vols parlar amb algu mes? (s/n)\n"); + scanf(" %c", &vols_continuar); + + usuari_vol_conversa = (vols_continuar == 's'); + } + + res = LUMI_EnviaPeticioDesregistre(slumi); + + if (res == 0) printf("S'ha rebut un missatge de confirmacio inesperat\n"); + else if (res == -1) printf("Error a l'hora d'enviar la peticio de desregistre\n"); + else if (res == -2) printf("Format del missatge de desregistre enviat incorrecte\n"); + else if (res == -3) printf("L'usuari que has indicat no existeix\n"); + else if (res == -4) printf("L'usuari que has indicat ja esta desregistrat\n"); + else if (res == -5) printf("Temps d'espera de peticio de desregistre esgotat\n"); + else if (res == -6) printf("Format del missatge de resposta incorrecte\n"); + else printf("Error desconegut\n"); + + LUMI_Desconnecta(slumi); + printf("Fins aviat!\n"); + + return 0; + } diff --git a/nodelumi2/CMakeLists.txt b/nodelumi2/CMakeLists.txt new file mode 100644 index 0000000..baa1bf2 --- /dev/null +++ b/nodelumi2/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.5) +project(nodelumi2) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + +set(SOURCE_FILES MIp2-lumi.h MIp2-lumi.c MIp2-nodelumi.c MIp2-nodelumi.cfg) +add_executable(nodelumi2 ${SOURCE_FILES}) \ No newline at end of file diff --git a/nodelumi2/MIp2-agelumi.c b/nodelumi2/MIp2-agelumi.c new file mode 100644 index 0000000..89ca9e7 --- /dev/null +++ b/nodelumi2/MIp2-agelumi.c @@ -0,0 +1,115 @@ +/**************************************************************************/ +/* */ +/* P1 - MI amb sockets TCP/IP - Part I */ +/* Fitxer p2p.c que implementa la interfície aplicació-usuari de */ +/* l'aplicació de MI, sobre la capa d'aplicació de MI (fent crides a la */ +/* interfície de la capa MI -fitxers mi.c i mi.h-). */ +/* */ +/* Autors: Marc Cané Salamià, Enric Rodríguez Galán */ +/* */ +/**************************************************************************/ + + +/* Inclusió de llibreries, p.e. #include o #include "meu.h" */ +/* Incloem "MIp1v4-mi.h" per poder fer crides a la interfície de MI */ +//#include "MIp2-mi.h" +#include "MIp2-lumi.h" + +#include "stdio.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Definició de constants, p.e., #define MAX_LINIA 150 */ + +#define MAX_MISSATGE 300 +#define IP_LENGTH 16 +#define TECLAT 0 +#define MARCA_FI "/end" + +int main(int argc,char *argv[]) +{ + /* Declaració de variables, p.e., int n; */ + + int sesc, scon, slumi; //socket descriptor dels sockets + int port=0, port_loc, port_rem; //port: farà de port local o remot segons la situació. Les variables port_loc i port_rem son per claretat de codi. + char IPloc[IP_LENGTH], IPrem[IP_LENGTH], IPnode[IP_LENGTH]; //IPs local i remota i del node + char adrLUMIloc[MAX_LEN_DOMINI+MAX_USER_NICK+1], adrLUMIrem[MAX_LEN_DOMINI+MAX_USER_NICK+1]; + char nickname_l[MAX_MISSATGE], nickname_r[MAX_MISSATGE]; //Nicknames local i remot + //char vols_continuar; //Eleccio de l'usuari + int fitxer_log; + int usuari_vol_conversa=1, connectat = 0, res; //Boolea per saber si l'usuari vol seguir parlant + + /* Expressions, estructures de control, crides a funcions, etc. */ + printf("Entra la teva @MI: "); + scanf("%s", adrLUMIloc); + //strcpy(adrLUMIloc,"Enric@localhost"); + + if ((slumi = LUMI_InicialitzarAgent("0.0.0.0",0, &fitxer_log, adrLUMIloc, IPnode)) < 0){ + //Apagar tot + close(slumi); + //close(sesc); + return 1; + } + //printf("Landmark"); + + res = LUMI_EnviaPeticioRegistre(slumi, adrLUMIloc); + if (res == -5) printf("El node esta 7at"); + else if(res < 0){ + close(slumi); + printf("FAIL%i\n",res); + //close(sesc); + return 1; + } else printf("Registrat correctament\n"); + + if (strcmp(adrLUMIloc,"Enric@localhost") != 0){ + int llista[] = {slumi}; + HaArribatAlgunaCosaEnTemps(llista, 1, 0); + char resposta[MAX_MISSATGE_PLUMI]; + + LUMI_RepLiniaDe(slumi, NULL, NULL, resposta, sizeof(resposta)); + LUMI_DescodificarMissatge(resposta[0], resposta, adrLUMIrem, NULL, NULL); + + printf("%s ens vol localitzar\n", adrLUMIrem); + int res2 = LUMI_EnviaRespostaServeiLocalitzacio(slumi, adrLUMIrem, "10.0.0.13", 1337); + + printf("Localitzacio: %i\n", res2); + } + else{ + + //scanf("%s", adrLUMIrem); + strcpy(adrLUMIrem,"Marc@localhost"); + + res = LUMI_EnviaPeticioLocalitzacio(slumi, adrLUMIloc, adrLUMIrem, IPrem, &port_rem, adrLUMIrem); + printf("Hola!\n"); + if (res == -5) printf("El node esta 7at"); + else if(res < 0){ + close(slumi); + //close(sesc); + return 1; + } + else printf("Localitzat correctament\n"); + + + } + res = LUMI_EnviaPeticioDesregistre(slumi); + if (res == -5) printf("El node esta 7at"); + else if(res < 0){ + close(slumi); + //close(sesc); + return 1; + } + else printf("Desregistrat correctament\n"); + + /*Localitzar(); + + Desregistrar();*/ + + return 0; + } diff --git a/nodelumi2/MIp2-lumi.c b/nodelumi2/MIp2-lumi.c new file mode 100755 index 0000000..45aae7a --- /dev/null +++ b/nodelumi2/MIp2-lumi.c @@ -0,0 +1,728 @@ + + +/**************************************************************************/ +/* */ +/* P2 - MI amb sockets TCP/IP - Part II */ +/* Fitxer lumi.c que implementa la capa d'aplicació de LUMI, sobre la */ +/* de transport UDP (fent crides a la interfície de la capa UDP */ +/* -sockets-). */ +/* */ +/* Autors: Marc Cané Salamià, Enric Rodríguez Galán */ +/* */ +/**************************************************************************/ + +/* Inclusió de llibreries, p.e. #include o #include "meu.h" */ +/* (si les funcions externes es cridessin entre elles, faria falta fer */ +/* un #include "MIp2-lumi.h") */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MIp2-lumi.h" + +/* Definició de constants, p.e., #define MAX_LINIA 150 */ + +#define RETRANSMISSIONS 10 +#define TIMEOUT 100 + +/* Declaració de funcions internes que es fan servir en aquest fitxer */ +/* (les seves definicions es troben més avall) per així fer-les conegudes */ +/* des d'aqui fins al final de fitxer. */ +/* Com a mínim heu de fer les següents funcions internes: */ + +int UDP_CreaSock(const char *IPloc, int portUDPloc); +int UDP_EnviaA(int Sck, const char *IPrem, int portUDPrem, const char *SeqBytes, int LongSeqBytes); +int UDP_RepDe(int Sck, char *IPrem, int *portUDPrem, char *SeqBytes, int LongSeqBytes); +int UDP_TancaSock(int Sck); +int UDP_TrobaAdrSockLoc(int Sck, char *IPloc, int *portUDPloc); +int UDP_DemanaConnexio(int Sck, const char *IPrem, int portUDPrem); +int UDP_Envia(int Sck, const char *SeqBytes, int LongSeqBytes); +int UDP_Rep(int Sck, char *SeqBytes, int LongSeqBytes); +int UDP_TrobaAdrSockRem(int Sck, char *IPrem, int *portUDPrem); +///int HaArribatAlgunaCosaEnTemps(const int *LlistaSck, int LongLlistaSck, int Temps); +///int ResolDNSaIP(const char *NomDNS, char *IP); +int Log_CreaFitx(const char *NomFitxLog); +int Log_Escriu(int FitxLog, const char *MissLog); +int Log_TancaFitx(int FitxLog); + +int LUMI_DescodificarSockTCPMissatgeC(const char * Missatge, char * IP, int * portTCP, char * adreca); + + +/* Definicio de funcions EXTERNES, és a dir, d'aquelles que en altres */ +/* fitxers externs es faran servir. */ +/* En termes de capes de l'aplicació, aquest conjunt de funcions externes */ +/* formen la interfície de la capa LUMI. */ +/* Les funcions externes les heu de dissenyar vosaltres... */ + +/* Definicio de funcions INTERNES, és a dir, d'aquelles que es faran */ +/* servir només en aquest mateix fitxer. */ + +/* Crea un socket UDP a l’@IP “IPloc” i #port UDP “portUDPloc” */ +/* (si “IPloc” és “0.0.0.0” i/o “portUDPloc” és 0 es fa/farà una */ +/* assignació implícita de l’@IP i/o del #port UDP, respectivament). */ +/* "IPloc" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0') */ +/* Retorna -1 si hi ha error; l’identificador del socket creat si tot */ +/* va bé. */ +int UDP_CreaSock(const char *IPloc, int portUDPloc) +{ + int sockdesc; + if ((sockdesc = socket(AF_INET,SOCK_DGRAM,0)) == -1){ + LUMI_MostraError("Error creació socket"); + return -1; + } + else{ + struct sockaddr_in adr; + + adr.sin_family = AF_INET; + adr.sin_addr.s_addr = inet_addr(IPloc); + adr.sin_port = htons(portUDPloc); + int i; + for(i=0;i<8;i++){adr.sin_zero[i]='0';} + + if (bind(sockdesc,(struct sockaddr*)&adr,sizeof(adr))==-1){ + LUMI_MostraError("Error bind"); + return -1; + } + } + return sockdesc; +} + +/* Envia a través del socket UDP d’identificador “Sck” la seqüència de */ +/* bytes escrita a “SeqBytes” (de longitud “LongSeqBytes” bytes) cap al */ +/* socket remot que té @IP “IPrem” i #port UDP “portUDPrem”. */ +/* "IPrem" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0') */ +/* "SeqBytes" és un vector de chars qualsevol (recordeu que en C, un */ +/* char és un enter de 8 bits) d'una longitud >= LongSeqBytes bytes */ +/* Retorna -1 si hi ha error; el nombre de bytes enviats si tot va bé. */ +int UDP_EnviaA(int Sck, const char *IPrem, int portUDPrem, const char *SeqBytes, int LongSeqBytes) +{ + struct sockaddr_in adrrem; + + adrrem.sin_family=AF_INET; + adrrem.sin_port=htons(portUDPrem); + adrrem.sin_addr.s_addr= inet_addr(IPrem); + int i; + for(i=0;i<8;i++){adrrem.sin_zero[i]='\0';} + + int bytes_llegits; + + if((bytes_llegits=sendto(Sck,SeqBytes,LongSeqBytes,0,(struct sockaddr*)&adrrem,sizeof(adrrem)))==-1) + { + perror("Error en sendto"); + close(Sck); + return(-1); + } + + return bytes_llegits; +} + +/* Rep a través del socket UDP d’identificador “Sck” una seqüència de */ +/* bytes que prové d'un socket remot i l’escriu a “SeqBytes*” (que té */ +/* una longitud de “LongSeqBytes” bytes). */ +/* Omple "IPrem*" i "portUDPrem*" amb respectivament, l'@IP i el #port */ +/* UDP del socket remot. */ +/* "IPrem*" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0') */ +/* "SeqBytes*" és un vector de chars qualsevol (recordeu que en C, un */ +/* char és un enter de 8 bits) d'una longitud <= LongSeqBytes bytes */ +/* Retorna -1 si hi ha error; el nombre de bytes rebuts si tot va bé. */ +int UDP_RepDe(int Sck, char *IPrem, int *portUDPrem, char *SeqBytes, int LongSeqBytes) +{ + struct sockaddr_in adrrem; + socklen_t ladrrem = sizeof(adrrem); + + int bytes_llegits; + + if((bytes_llegits=recvfrom(Sck,SeqBytes,LongSeqBytes,0,(struct sockaddr*)&adrrem,&ladrrem))==-1) + { + perror("Error recvfrom\n"); + close(Sck); + return -1; + } + + strcpy(IPrem, inet_ntoa(adrrem.sin_addr)); + *portUDPrem = ntohs(adrrem.sin_port); + + return bytes_llegits; +} + +/* S’allibera (s’esborra) el socket UDP d’identificador “Sck”. */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int UDP_TancaSock(int Sck) +{ + return close(Sck); +} + +/* Donat el socket UDP d’identificador “Sck”, troba l’adreça d’aquest */ +/* socket, omplint “IPloc*” i “portUDPloc*” amb respectivament, la seva */ +/* @IP i #port UDP. */ +/* "IPloc*" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0') */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int UDP_TrobaAdrSockLoc(int Sck, char *IPloc, int *portUDPloc) +{ + struct sockaddr_in sin; + socklen_t slen; + + slen = sizeof(sin); + if(getsockname(Sck, (struct sockaddr *)&sin, &slen)){ + LUMI_MostraError("Error al trobar la direccio local"); + return -1; + } + + *portUDPloc = ntohs(sin.sin_port); + strcpy(IPloc, inet_ntoa(sin.sin_addr)); + + return 1; +} + +/* El socket UDP d’identificador “Sck” es connecta al socket UDP d’@IP */ +/* “IPrem” i #port UDP “portUDPrem” (si tot va bé es diu que el socket */ +/* “Sck” passa a l’estat “connectat” o establert – established –). */ +/* Recordeu que a UDP no hi ha connexions com a TCP, i que això només */ +/* vol dir que es guarda localment l’adreça “remota” i així no cal */ +/* especificar-la cada cop per enviar i rebre. Llavors quan un socket */ +/* UDP està “connectat” es pot fer servir UDP_Envia() i UDP_Rep() (a més */ +/* de les anteriors UDP_EnviaA() i UDP_RepDe()) i UDP_TrobaAdrSockRem()). */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int UDP_DemanaConnexio(int Sck, const char *IPrem, int portUDPrem) +{ + struct sockaddr_in adr; + + adr.sin_family = AF_INET; + adr.sin_addr.s_addr = inet_addr(IPrem); + adr.sin_port = htons(portUDPrem); + int i; + for(i=0;i<8;i++){adr.sin_zero[i]='0';} + + if((connect(Sck,(struct sockaddr*)&adr,sizeof(adr)))==-1){ + char buff[100]; + snprintf(buff, sizeof(buff), "Error: no s'ha pogut connectar amb %s", IPrem); + LUMI_MostraError(buff); + return -1; + } + + return 0; +} + +/* Envia a través del socket UDP “connectat” d’identificador “Sck” la */ +/* seqüència de bytes escrita a “SeqBytes” (de longitud “LongSeqBytes” */ +/* bytes) cap al socket UDP remot amb qui està connectat. */ +/* "SeqBytes" és un vector de chars qualsevol (recordeu que en C, un */ +/* char és un enter de 8 bits) d'una longitud >= LongSeqBytes bytes. */ +/* Retorna -1 si hi ha error; el nombre de bytes enviats si tot va bé. */ +int UDP_Envia(int Sck, const char *SeqBytes, int LongSeqBytes) +{ + return send(Sck,SeqBytes,LongSeqBytes,0); +} + +/* Rep a través del socket UDP “connectat” d’identificador “Sck” una */ +/* seqüència de bytes que prové del socket remot amb qui està connectat, */ +/* i l’escriu a “SeqBytes*” (que té una longitud de “LongSeqBytes” bytes).*/ +/* "SeqBytes*" és un vector de chars qualsevol (recordeu que en C, un */ +/* char és un enter de 8 bits) d'una longitud <= LongSeqBytes bytes. */ +/* Retorna -1 si hi ha error; el nombre de bytes rebuts si tot va bé. */ +int UDP_Rep(int Sck, char *SeqBytes, int LongSeqBytes) +{ + return recv(Sck,SeqBytes,LongSeqBytes,0); +} + +/* Donat el socket UDP “connectat” d’identificador “Sck”, troba l’adreça */ +/* del socket remot amb qui està connectat, omplint “IPrem*” i */ +/* “portUDPrem*” amb respectivament, la seva @IP i #port UDP. */ +/* "IPrem*" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud màxima de 16 chars (incloent '\0'). */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int UDP_TrobaAdrSockRem(int Sck, char *IPrem, int *portUDPrem) +{ + struct sockaddr_in adr; + socklen_t long_adr = sizeof(adr); + int res; + + if ( (res = getpeername(Sck, (struct sockaddr*)&adr, &long_adr)) == -1) { + LUMI_MostraError("Error al trobar la direccio remota"); + return -1; + } + + strcpy(IPrem,inet_ntoa(adr.sin_addr)); + *portUDPrem = ntohs(adr.sin_port); + + return res; +} + +/* Examina simultàniament durant "Temps" (en [ms] els sockets (poden ser */ +/* TCP, UDP i stdin) amb identificadors en la llista “LlistaSck” (de */ +/* longitud “LongLlistaSck” sockets) per saber si hi ha arribat alguna */ +/* cosa per ser llegida. Si Temps és -1, s'espera indefinidament fins que */ +/* arribi alguna cosa. */ +/* "LlistaSck" és un vector d'enters d'una longitud >= LongLlistaSck */ +/* Retorna -1 si hi ha error; retorna -2 si passa "Temps" sense que */ +/* arribi res; si arriba alguna cosa per algun dels sockets, retorna */ +/* l’identificador d’aquest socket. */ +int HaArribatAlgunaCosaEnTemps(const int *LlistaSck, int LongLlistaSck, int Temps) +{ + struct timeval timeout; + timeout.tv_sec = Temps/1000; + timeout.tv_usec = (Temps%1000)*1000; //estructura per definir un timeout al select + + fd_set set; + + FD_ZERO(&set); + + int i = 0; + + while (i 0){ + int res; + if ((res = select(smax,&set,NULL,NULL,&timeout)) == -1){ + LUMI_MostraError("Error a la espera d'arribar alguna cosa"); + return -1; + } + if(res == 0) return 0; + } + else if (select(smax,&set,NULL,NULL,NULL) == -1){ + LUMI_MostraError("Error a la espera d'arribar alguna cosa"); + return -1; + } + + int ifd=0; + + while( ifd < LongLlistaSck && !FD_ISSET(LlistaSck[ifd],&set) ) ifd++; + + return LlistaSck[ifd]; +} + +/* Donat el nom DNS "NomDNS" obté la corresponent @IP i l'escriu a "IP*" */ +/* "NomDNS" és un "string" de C (vector de chars imprimibles acabat en */ +/* '\0') d'una longitud qualsevol, i "IP*" és un "string" de C (vector de */ +/* chars imprimibles acabat en '\0') d'una longitud màxima de 16 chars */ +/* (incloent '\0'). */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé */ +int ResolDNSaIP(const char *NomDNS, char *IP) +{ + struct addrinfo hints, *infoptr; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; // AF_INET perquè només volem adreces IPv4 + + int result = getaddrinfo(NomDNS, NULL, &hints, &infoptr); + if (result != 0) { + fprintf(stderr, "Error a getaddrinfo\n%s\n",gai_strerror(result)); + return(-1); + } + + struct addrinfo *p; + char host[256]; + + p = infoptr; + result = getnameinfo(p->ai_addr, p->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST); + if (result != 0) { + fprintf(stderr, "Error a getnameinfo\n"); + return(-1); + } + strcpy(IP, host); + + freeaddrinfo(infoptr); + return 0; +} + +/* Crea un fitxer de "log" de nom "NomFitxLog". */ +/* "NomFitxLog" és un "string" de C (vector de chars imprimibles acabat */ +/* en '\0') d'una longitud qualsevol. */ +/* Retorna -1 si hi ha error; l'identificador del fitxer creat si tot va */ +/* bé. */ +int Log_CreaFitx(const char *NomFitxLog) +{ + int filedesc = open(NomFitxLog, O_APPEND|O_CREAT, 0666); + if (filedesc < 0){ + LUMI_MostraError("Error al crear el fitxer Log"); + return -1; + } + return filedesc; +} + +/* Escriu al fitxer de "log" d'identificador "FitxLog" el missatge de */ +/* "log" "MissLog". */ +/* "MissLog" és un "string" de C (vector de chars imprimibles acabat */ +/* en '\0') d'una longitud qualsevol. */ +/* Retorna -1 si hi ha error; el nombre de caràcters del missatge de */ +/* "log" (sense el '\0') si tot va bé */ +int Log_Escriu(int FitxLog, const char *MissLog) +{ + int lMiss = strlen(MissLog); + char buff[lMiss]; + strcpy(buff,MissLog); + //buff[lMiss-1] = '\n'; + /*int res = write(FitxLog,MissLog,strlen(MissLog)-1); + if (res < 0) return res;*/ + return write(FitxLog,buff,sizeof(buff)); +} + +/* Tanca el fitxer de "log" d'identificador "FitxLog". */ +/* Retorna -1 si hi ha error; un valor positiu qualsevol si tot va bé. */ +int Log_TancaFitx(int FitxLog) +{ + return close(FitxLog); +} + +void LUMI_MostraError(const char *text) +{ + fprintf(stderr, "%s\n", text); +} + +/* Si ho creieu convenient, feu altres funcions... */ + +int LUMI_InicialitzarNode(const char * fitxer_log){ + //printf("%s\n",fitxer_log); + LUMI_Fitxer_Log = Log_CreaFitx(fitxer_log); //el nom del fitxer ha de portar el nom del domini + return UDP_CreaSock("0.0.0.0",UDP_PORT); +} + +int LUMI_InicialitzarAgent(const char * IP, int portUDP, int * fitxer_log, const char * adrLUMI, char * IPnode){ + int res = UDP_CreaSock(IP,portUDP); + if (res < 0 ) return res; + + char nickname[MAX_USER_NICK], domini[MAX_LEN_DOMINI]; + LUMI_DescodificarAdreca(adrLUMI, nickname, domini); + //printf("nick: %s, domini: %s",nickname,domini); + if (ResolDNSaIP(domini, IPnode) < 0) return -1; + + if (UDP_DemanaConnexio(res, IPnode, UDP_PORT) < 0) return -1; + + char nom_fitxer[MAX_NOM_FITXER]; + LUMI_ResolNomFitxerLog('A', nom_fitxer, adrLUMI); + if ( (*fitxer_log = Log_CreaFitx(nom_fitxer)) < 0 ) return -2; + + return res; +} + +int LUMI_ResolNomFitxerLog(char tipus, char * fitxer_log, const char * buffer){ + if (tipus == 'A' ) strcpy(fitxer_log, NOM_FITXER_AGENT); + else if (tipus == 'N') strcpy(fitxer_log, NOM_FITXER_NODE); + else return 1; + strcat(fitxer_log, buffer); + strcat(fitxer_log, EXT_FITXER_LOG); + return 0; +} + +int LUMI_EnviaFiable(int Sck, const char * Missatge, char * resposta, int timeout){ + int intents = 0, enviat = 0, res, retorn; + int llist[] = {Sck}; + while(!enviat && intents 0 ){ //Si hem rebut algo, comprovem si es una A (resposta) + char buff[MAX_MISSATGE_PLUMI]; + int longitud = UDP_Rep(Sck, buff, sizeof(buff)); + buff[longitud]='\0'; + if(LUMI_ComprovarFormat(buff) != 0) return -6; + if (buff[0] == 'A'){ + switch(buff[1]){ + case 'K': + retorn = 0; + break; + case 'I': + retorn = -2; + break; + case 'N': + retorn = -3; + break; + case 'C': + retorn = -7; + break; + default: + retorn = -4; + break; + } + enviat = 1; //Si es una resposta, vol dir que el destinatari ha rebut be el paquet + } else if (buff[0]== 'C') {retorn = 1; enviat = 1;} + if (resposta != NULL) strcpy(resposta, buff); + }//else printf("%s. Intent %i\n", "TIMEOUT EXPIRED", intents);//LUMI_MostraError("TIMEOUT EXPIRED\n"); + intents++; + } + + if (enviat == 0){ + /*Log_Escriu(LUMI_Fitxer_Log,"Ha fallat l'enviament del seguent missatge: \n\t"); + Log_Escriu(LUMI_Fitxer_Log,Missatge); + Log_Escriu(LUMI_Fitxer_Log,"\n\n");*/ + return -5; + } + else{ + /*Log_Escriu(LUMI_Fitxer_Log,"S'ha enviat correctament el seguent missatge: \n\t"); + Log_Escriu(LUMI_Fitxer_Log,Missatge); + Log_Escriu(LUMI_Fitxer_Log,"\n\n");*/ + return retorn; + } +} + +int LUMI_EnviaLiniaA(int Sck, const char * IP, int portUDPrem, const char * buffer){ + return UDP_EnviaA(Sck, IP, portUDPrem, buffer, strlen(buffer)); +} + +int LUMI_EnviaPeticioRegistre(int Sck, char * adrLUMI){ + char buffer[MAX_MISSATGE_PLUMI+1]; + sprintf(buffer,"R%s",adrLUMI); + return LUMI_EnviaFiable(Sck, buffer, NULL, TIMEOUT); +} + +int LUMI_EnviaPeticioDesregistre(int Sck){ + return LUMI_EnviaFiable(Sck, "D", NULL, TIMEOUT); +} + +int LUMI_EnviaResposta(int Sck, char tipus, const char * adrLUMI, const char * IP, int portUDPrem){ + char buffer[MAX_MISSATGE_PLUMI+1]; + + if(adrLUMI==NULL) sprintf(buffer,"A%c",tipus); + else sprintf(buffer,"A%c%s",tipus, adrLUMI); + + if(portUDPrem==0) return UDP_Envia(Sck, buffer, strlen(buffer)); + else return UDP_EnviaA(Sck, IP, portUDPrem, buffer, strlen(buffer)); +} + +int LUMI_EnviaPeticioLocalitzacio(int Sck, const char * adrLUMIloc, const char * adrLUMIrem, char * IPlocalitzat, int * portTCP){ + char buffer[MAX_MISSATGE_PLUMI+1]; + sprintf(buffer,"L%s#%s", adrLUMIrem, adrLUMIloc); + char resposta[MAX_MISSATGE_PLUMI+1]; + int res = LUMI_EnviaFiable(Sck, buffer, resposta, TIMEOUT*2); + //printf("%s\n", resposta); + if (res <= 0) return res; + else if (res == 1){ + LUMI_DescodificarSockTCPMissatgeC(resposta,IPlocalitzat,portTCP, NULL); + return res; + } +} + +int LUMI_EnviaPeticioServeiLocalitzacio(int Sck, const char * adrLUMI, const char * IP, int portUDPrem){ + char buffer[MAX_MISSATGE_PLUMI+1]; + sprintf(buffer,"S%s",adrLUMI); + return UDP_EnviaA(Sck, IP, portUDPrem, buffer, strlen(buffer)); +} + +int LUMI_EnviaRespostaServeiLocalitzacio(int Sck, const char * adrLUMI, const char * IP, int portTCPrem){ + char buffer[MAX_MISSATGE_PLUMI+1]; + sprintf(buffer,"C%s#%i#%s",IP, portTCPrem, adrLUMI); + //printf("%s\n", buffer); + return UDP_Envia(Sck, buffer, strlen(buffer)); +} + +int LUMI_DescodificarAdreca(const char * adr, char * nickname, char * domini){ + int i=0; + while (adr[i]!='@') i++; + if (domini != NULL) strcpy(domini, adr+i+1); + if (nickname != NULL){ + strncpy(nickname, adr, i); + nickname[i]='\0'; + } + return 0; +} + +int LUMI_DescodificarMissatge(char tipus, const char * Missatge, char * adreca, char * domini, char * nom_usuari){ + if (tipus == 'R'){ + strcpy(adreca,Missatge+1); + LUMI_DescodificarAdreca(adreca, nom_usuari, domini); + } + else if (tipus == 'L'){ + char buffer[MAX_USER_NICK+MAX_LEN_DOMINI+2]; + int i=1; + while (Missatge[i]!='#') i++; + strncpy(buffer, Missatge+1, i-1); + buffer[i-1]='\0'; + LUMI_DescodificarAdreca(buffer,nom_usuari,domini); + strcpy(adreca, Missatge+i+1); + } + else if (tipus == 'A'){ + int longitud = strlen(Missatge); + if (longitud > 2) { + strcpy(adreca,Missatge+2); + LUMI_DescodificarAdreca(adreca, nom_usuari, domini); + } + } + else if (tipus == 'S'){ + strcpy(adreca,Missatge+1); + LUMI_DescodificarAdreca(adreca, nom_usuari, domini); + } + else if(tipus == 'C'){ + int i, j=1; + for(i = 1; i < 3; i++){ //ens saltem els dos primers # i ens posicionem sobre el tercer + while (Missatge[j]!='#') j++; + j++; + } + strcpy(adreca,Missatge+j); + //printf("%s\n", adreca); + LUMI_DescodificarAdreca(adreca, nom_usuari, domini); + } + else if (tipus == 'D') return 0; + else return -1; + + return 0; +} + +int LUMI_DescodificarSockTCPMissatgeC(const char * Missatge, char * IP, int * portTCP, char * adreca){ + int i=1, j; + char buffer[6]; + while (Missatge[i]!='#') i++; + strncpy(IP,Missatge+1,i-1); //aixo esta mal + IP[i-1]='\0'; + j=i+1; + while (Missatge[j]!='#') j++; + strncpy(buffer,Missatge+i+1,j-i-1); + *portTCP=atoi(buffer); + if (adreca != NULL) strcpy(adreca, Missatge+j+1); + return 0; +} + +int comprovarIP(const char * IP){ //aka "la fàbrica de bugs" + int i=0, mida=strlen(IP), punts=0, old=-1, temp; + char buff[16]; + char c; + while(i='0')) return 2; + i++; + } + i=0; + while(i255) return 1; + old=i; + i++; + punts++; + } + if (punts != 4 || IP[mida-1]=='.') return -1; + return 0; +} + +int validarAdreca(const char * adreca, int longAdr){ + int i = 0; + while( i < longAdr && adreca[i]!='#' && adreca[i]!='@') i++; + if(i == longAdr || adreca[i]=='#') return 1; + else return 0; +} + +int LUMI_ComprovarFormat(const char * buffer){ + int mida=strlen(buffer), i=1, j; + char tipus = buffer[0]; + switch(tipus){ + case 'R': + case 'S': + if (mida == 1) return 1; + else{ + if (validarAdreca(buffer+1,mida-1) == 1) return 1; + } + break; + case 'D': + if (mida > 1) return 1; + break; + case 'L': + if(mida == 1) return 1; + + while (buffer[i]!='@' && buffer[i]!='#' && i2){ + while (buffer[i]!='@' && i IP_LENGTH || i-1 <7 ) return 1; + /*C222.222.222.222# + 01234567891111111 + 0123456*/ + char ip[IP_LENGTH]; + strncpy(ip, buffer+1, i-1); + ip[i-1] = '\0'; + + //if(comprovarIP(ip) == 1) return 1; //millor que no estigues implementada + + j= i+1; + while (buffer[j]!='#' && j MAX_PORT) return 1; //comprobem que el port es un nuumero compres entre 0 i 65535 + + if(validarAdreca(buffer+j+1,mida-j) == 1) return 1; + + break; + default: + return 1; + break; + } + return 0; +} + +int LUMI_RepLiniaDe(int Sck, char * IPrem, int * portUDP, char * buffer, int mida_buffer){ + + int res; + if (IPrem != NULL && portUDP != NULL) res = UDP_RepDe(Sck, IPrem, portUDP, buffer, mida_buffer); + else res = UDP_Rep(Sck,buffer,mida_buffer); + if (res <= 0) return res; + buffer[res]='\0'; + + if(LUMI_ComprovarFormat(buffer) == 1){ + LUMI_EnviaResposta(Sck,'I', NULL, IPrem, *portUDP); + return -2; + } + + return res; +} + +int LUMI_EscriureFitxerLog(int fitxer, const char * linia){ + return 0; +} + +int LUMI_Desconnecta(int Sck){ + close(Sck); +} diff --git a/nodelumi2/MIp2-lumi.h b/nodelumi2/MIp2-lumi.h new file mode 100755 index 0000000..9421748 --- /dev/null +++ b/nodelumi2/MIp2-lumi.h @@ -0,0 +1,73 @@ +/**************************************************************************/ +/* */ +/* P2 - MI amb sockets TCP/IP - Part II */ +/* Fitxer capçalera de lumi.c */ +/* */ +/* Autors: Marc Cané Salamià, Enric Rodríguez Galán */ +/* */ +/**************************************************************************/ + +#define UDP_PORT 7189 +#define IP_LENGTH 16 +#define MAX_USER_NICK 20 +#define MAX_MISSATGE_PLUMI 150 +#define MAX_LEN_DOMINI 100 +#define MAX_PORT 65535 +#define INTENTS 5 + +#define MAX_NOM_FITXER 100 +#define NOM_FITXER_NODE "MIp2-nodelumi-" +#define NOM_FITXER_CONFIG "MIp2-nodelumi.cfg" +#define NOM_FITXER_AGENT "MIp2-agelumi-" +#define EXT_FITXER_LOG ".log" + +/* Declaració de funcions externes de lumi.c, és a dir, d'aquelles que es */ +/* faran servir en un altre fitxer extern, p.e., MIp2-p2p.c, */ +/* MIp2-nodelumi.c, o MIp2-agelumic.c. El fitxer extern farà un #include */ +/* del fitxer .h a l'inici, i així les funcions seran conegudes en ell. */ +/* En termes de capes de l'aplicació, aquest conjunt de funcions externes */ +/* formen la interfície de la capa LUMI. */ +/* Les funcions externes les heu de dissenyar vosaltres... */ +//int LUMI_FuncioExterna(arg1, arg2...); + +struct usuari; + +int LUMI_Fitxer_Log; + +void LUMI_MostraError(const char *text); + +int LUMI_ComprovarFormat(const char * buffer); + +int LUMI_DescodificarAdreca(const char * adr, char * nickname, char * domini); + +int LUMI_ResolNomFitxerLog(char tipus, char * fitxer_log, const char * buffer); + +int LUMI_RepLiniaDe(int Sck, char * IPrem, int * portUDP, char * buffer, int mida_buffer); + +int LUMI_EnviaFiable(int Sck, const char * Missatge, char * resposta, int timeout); + +int LUMI_EnviaLiniaA(int Sck, const char * IP, int portUDPrem, const char * buffer); + +int LUMI_EnviaPeticioRegistre(int Sck, char * adrLUMI); + +int LUMI_EnviaPeticioDesregistre(int Sck); + +int LUMI_EnviaResposta(int Sck, char tipus, const char * adrLUMI, const char * IP, int portUDPrem); + +int LUMI_EnviaPeticioLocalitzacio(int Sck, const char * adrLUMIloc, const char * adrLUMIrem, char * IPlocalitzat, int * portTCP); + +int LUMI_EnviaPeticioServeiLocalitzacio(int Sck, const char * adrLUMI, const char * IP, int portUDPrem); + +int LUMI_EnviaRespostaServeiLocalitzacio(int Sck, const char * adrLUMI, const char * IP, int portTCPrem); + +int LUMI_DescodificarMissatge(char tipus, const char * Missatge, char * adreca, char * domini, char * nom_usuari); + +int LUMI_InicialitzarNode(const char * fitxer_log); + +int LUMI_InicialitzarAgent(const char * IP, int portUDP, int * fitxer_log, const char * adrLUMI, char * IPnode); + +int HaArribatAlgunaCosaEnTemps(const int *LlistaSck, int LongLlistaSck, int Temps); + +int ResolDNSaIP(const char *NomDNS, char *IP); + +int LUMI_Desconnecta(int Sck); \ No newline at end of file diff --git a/nodelumi2/MIp2-nodelumi.c b/nodelumi2/MIp2-nodelumi.c new file mode 100644 index 0000000..6cd6880 --- /dev/null +++ b/nodelumi2/MIp2-nodelumi.c @@ -0,0 +1,304 @@ +/**************************************************************************/ +/* */ +/* P2 - MI amb sockets TCP/IP - Part II */ +/* Fitxer nodelumi.c que implementa la interfície aplicació-administrador */ +/* d'un node de LUMI, sobre la capa d'aplicació de LUMI (fent crides a la */ +/* interfície de la capa LUMI -fitxers lumi.c i lumi.h-). */ +/* */ +/* Autors: Marc Cané Salamià, Enric Rodríguez Galán */ +/* */ +/**************************************************************************/ + +/* Inclusió de llibreries, p.e. #include o #include "meu.h" */ +/* Incloem "MIp2-lumi.h" per poder fer crides a la interfície de LUMI */ +#include "MIp2-lumi.h" +#include +#include +#include +#include +#include +#include +#include + +/* Definició de constants, p.e., #define MAX_LINIA 150 */ + +struct usuari{ + char nom[MAX_USER_NICK]; + char IP[IP_LENGTH]; + int UDP_port; +}; + +int ObrirFitxLectura(const char *NomFitx) +{ + int filedesc = open(NomFitx, O_RDONLY); + if (filedesc < 0){ + LUMI_MostraError("Error al obrir el fitxer de configuracio"); + return -1; + } + return filedesc; +} + +//Pre: buff apunta a un buffer del màxim de caràcters que pot tenir una línia +//Post: retorna 1 si no s'ha arribat a la marca de fi de fitxer, 0 altrament +int LlegirLinia(int fitxer, char * buff){ + char c=0; + int byte_llegit=1, i=0; + + while(byte_llegit!=0 && c!='\n'){ + byte_llegit=read(fitxer,&c,1); + buff[i]=c; + i++; + } + buff[i-1]='\0'; + return byte_llegit; +} + +char DOMINI[MAX_LEN_DOMINI]; + +void InicialitzarTaulaUsuaris(struct usuari ** taula_usuaris, int n){ + *taula_usuaris = (struct usuari *) malloc(sizeof(struct usuari)*n); +} + +int CercarUsuariPerNom(struct usuari * taula_usuaris, const char * NomUsuari, int n_usuaris){ + /*int trobat = 0, mig, esq=0 , dret = n_usuaris-1 , comparacio; + while(trobat == 0 && esq<=dret){ + mig = (dret + esq) / 2; + comparacio = strcmp(taula_usuaris[mig].nom, NomUsuari); + if (comparacio == 0) trobat = 1; + else{ + if (comparacio < 0) esq=mig+1; + else dret=mig-1; + } + } + if (trobat == 1) return mig; + else return (-1)*mig;*/ + int i=0, trobat=0; + while(i 0) { + //LUMI_MostraError("Error: l'usuari %s ja esta donat d'alta", NomUsuari); + return -1; + } + else{ + /*int i; + posicio*=-1; + for(i = n_usuaris-1; i>posicio; i--) intercanviar(taula_usuaris,i,i-1); //potser aixo peta*/ + posicio = n_usuaris; + strcpy(taula_usuaris[posicio].nom, NomUsuari); + taula_usuaris[posicio].UDP_port=-1; + } + return 1; +} + +int LlegirTaulaDesdeFitxer(const char * file_name, struct usuari ** taula_usuaris){ + int fitxer = ObrirFitxLectura(file_name); + if (fitxer == -1) return -1; + + char buff[100]; + int byte_llegit, total_usuaris=0, alta_usuaris=0; + + LlegirLinia(fitxer,buff); //llegim el nom del domini + strcpy(DOMINI,buff); + + LlegirLinia(fitxer,buff); //llegim el nombre d'usuaris del domini + total_usuaris=atoi(buff); + + InicialitzarTaulaUsuaris(taula_usuaris, total_usuaris); + + byte_llegit = LlegirLinia(fitxer,buff); //legir primer usuari + //printf("%i", (*taula_usuaris)[0].UDP_port); + + while(byte_llegit!=0 && alta_usuaris= 0){ + strcpy(IPrem,taula_usuaris[user].IP); + portUDPrem = taula_usuaris[user].UDP_port; + LUMI_EnviaLiniaA(Sck, IPrem, portUDPrem, buffer); //sense retransmissions + } + else { + LUMI_MostraError("Problema al reenviar una peticio: L'usuari no existeix"); + } + } + else{ + if (ResolDNSaIP(domini_usuari, IPrem) < 0) + LUMI_MostraError("Error al resoldre direccio dns"); + else { + LUMI_EnviaLiniaA(Sck, IPrem, UDP_PORT, buffer); //sense retransmissions + } + } + break; + default: + //Error en el format + break; + } + } + + canal = HaArribatAlgunaCosaEnTemps(llistaSck, 1, 0); + + bytes_rebuts = LUMI_RepLiniaDe(Sck,IPrem,&portUDPrem, buffer, sizeof(buffer)); //encarregat d'enviar el AI si el format es erroni + } + + close(Sck); + return 0; + } diff --git a/nodelumi2/MIp2-nodelumi.cfg b/nodelumi2/MIp2-nodelumi.cfg new file mode 100755 index 0000000..e0f9b7c --- /dev/null +++ b/nodelumi2/MIp2-nodelumi.cfg @@ -0,0 +1,13 @@ +localhost +11 +pepito +maria +el7at +pere.pi +7uring +lindefinit +crazyfrog +eustaki +mr.xarxes +Marc +Enric