Inicial
commit
26e3fc66a6
|
|
@ -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})
|
||||
|
|
@ -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 <sys/types.h> o #include "meu.h" */
|
||||
/* (si les funcions externes es cridessin entre elles, faria falta fer */
|
||||
/* un #include "MIp1v4-mi.h") */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include "MIp2-mi.h"
|
||||
#include <ifaddrs.h>
|
||||
|
||||
/* 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<LongLlistaSck){
|
||||
FD_SET(LlistaSck[i],&set);
|
||||
i++;
|
||||
}
|
||||
int smax = LlistaSck[i-1]+1;
|
||||
|
||||
if (select(smax,&set,NULL,NULL,NULL) == -1){
|
||||
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];
|
||||
}
|
||||
|
||||
/* Escriu un missatge de text al flux d’error estàndard stderr, format */
|
||||
/* pel text “Text”, un “:”, un espai en blanc, un text que descriu el */
|
||||
/* darrer error produït en una crida de sockets, i un canvi de línia. */
|
||||
void MostraError(const char *text)
|
||||
{
|
||||
fprintf(stderr, "%s: %s\n", text, strerror(errno));
|
||||
}
|
||||
|
||||
/* Si ho creieu convenient, feu altres funcions... */
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/**************************************************************************/
|
||||
/* */
|
||||
/* P1 - MI amb sockets TCP/IP - Part I */
|
||||
/* Fitxer capçalera de mi.c */
|
||||
/* */
|
||||
/* Autors: Marc Cané Salamià, Enric Rodríguez Galán */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/* Declaració de funcions externes de mi.c, és a dir, d'aquelles que es */
|
||||
/* faran servir en un altre fitxer extern, p.e., MIp1-p2p.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 MI. */
|
||||
int MI_IniciaEscPetiRemConv(int portTCPloc);
|
||||
int MI_HaArribatPetiConv(int SckEscMI);
|
||||
int MI_DemanaConv(const char *IPrem, int portTCPrem, char *IPloc, int *portTCPloc, const char *NicLoc, char *NicRem);
|
||||
int MI_AcceptaConv(int SckEscMI, char *IPrem, int *portTCPrem, char *IPloc, int *portTCPloc, const char *NicLoc, char *NicRem);
|
||||
int MI_HaArribatLinia(int SckConvMI);
|
||||
int MI_EnviaLinia(int SckConvMI, const char *Linia);
|
||||
int MI_EnviaNickname(int SckConvMI, const char *Linia);
|
||||
int MI_RepLinia(int SckConvMI, char *Linia);
|
||||
int MI_AcabaConv(int SckConvMI);
|
||||
int MI_AcabaEscPetiRemConv(int SckEscMI);
|
||||
int MI_ObtenirInfoServidor(int sock, char *IPloc, int *portTCPloc);
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 <stdio.h> 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 <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
|
@ -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})
|
||||
|
|
@ -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 <stdio.h> 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 <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
|
@ -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 <sys/types.h> o #include "meu.h" */
|
||||
/* (si les funcions externes es cridessin entre elles, faria falta fer */
|
||||
/* un #include "MIp2-lumi.h") */
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#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<LongLlistaSck){
|
||||
FD_SET(LlistaSck[i],&set);
|
||||
i++;
|
||||
}
|
||||
|
||||
int smax = 0;
|
||||
i=0;
|
||||
while(i<LongLlistaSck){
|
||||
if (smax<LlistaSck[i]) smax = LlistaSck[i];
|
||||
i++;
|
||||
}
|
||||
smax++;
|
||||
|
||||
if (Temps > 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<INTENTS){
|
||||
UDP_Envia(Sck,Missatge,strlen(Missatge));
|
||||
res = HaArribatAlgunaCosaEnTemps(llist,1,timeout);
|
||||
if (res < 0){
|
||||
LUMI_MostraError("Error al esperar EnviaFiable");
|
||||
return -1;
|
||||
}
|
||||
else if (res > 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<mida){
|
||||
c=IP[i];
|
||||
if(c!='.' && !(c<='9' && c>='0')) return 2;
|
||||
i++;
|
||||
}
|
||||
i=0;
|
||||
while(i<mida){
|
||||
while(IP[i]!='.' && i<mida) i++;
|
||||
strncpy(buff, IP+old+1, i-old-1);
|
||||
buff[i-old-1]='\0';
|
||||
temp=atoi(buff);
|
||||
if(temp<=0 || temp>255) 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]!='#' && i<mida) i++;//busquem la primera @
|
||||
if(buffer[i]=='#' && i == mida) return 1; //si no la trobem abans que un # o que el fi del missatge
|
||||
|
||||
while (buffer[i]!='#' && i<mida) i++;//busquem el #
|
||||
if (i == mida) return 1;//si no el trobem abans que el fi del missatge
|
||||
|
||||
while (buffer[i]!='@' && i<mida) i++; //busquem la segona @
|
||||
if(i == mida) return 1; //si no la trobem
|
||||
|
||||
break;
|
||||
case 'A':
|
||||
if(mida>2){
|
||||
while (buffer[i]!='@' && i<mida) i++;
|
||||
if(i == mida) return 1;
|
||||
}
|
||||
else if (mida == 2){
|
||||
if (buffer[1] != 'K' && buffer[1] != 'I' && buffer[1] != 'N') return 1;
|
||||
}
|
||||
else return 1;
|
||||
break;
|
||||
case 'C':
|
||||
if(mida == 1) return 1;
|
||||
|
||||
while (buffer[i]!='#' && i<mida) i++;// busuquem el primer #
|
||||
if(i == mida) return 1;
|
||||
|
||||
if(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<mida) j++;//busquem la segona marca #
|
||||
|
||||
char port[6];
|
||||
strncpy(port,buffer+i+1,j-i-1);
|
||||
port[j-i-1]='\0';
|
||||
|
||||
int res=atoi(port);
|
||||
if(res == 0 || res > 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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
@ -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 <stdio.h> o #include "meu.h" */
|
||||
/* Incloem "MIp2-lumi.h" per poder fer crides a la interfície de LUMI */
|
||||
#include "MIp2-lumi.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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<n_usuaris && !trobat){
|
||||
if(strcmp(taula_usuaris[i].nom, NomUsuari)==0)
|
||||
trobat=1;
|
||||
else i++;
|
||||
}
|
||||
return trobat?i:-1*i;
|
||||
}
|
||||
|
||||
int CercarUsuariPerIPiPort(struct usuari * taula_usuaris, const char * IP, int port, int n_usuaris){
|
||||
int trobat = 0, i = 0;
|
||||
while (i<n_usuaris && !trobat) {
|
||||
if ((strcmp(taula_usuaris[i].IP, IP) == 0) && (taula_usuaris[i].UDP_port == port)) trobat = 1;
|
||||
else i++;
|
||||
}
|
||||
return trobat?i:-1*i;
|
||||
}
|
||||
|
||||
void intercanviar(struct usuari * taula_usuaris, int i, int j){
|
||||
struct usuari aux = taula_usuaris[i];
|
||||
taula_usuaris[i] = taula_usuaris[j];
|
||||
taula_usuaris[j] = aux;
|
||||
}
|
||||
//n _usuaris < max_usuaris sempre
|
||||
int DonardAltaUsuari(struct usuari * taula_usuaris, const char * NomUsuari, int n_usuaris, int max_usuaris){
|
||||
|
||||
if (n_usuaris == max_usuaris) return -1;
|
||||
|
||||
int posicio = CercarUsuariPerNom(taula_usuaris, NomUsuari, n_usuaris);
|
||||
if (posicio > 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<total_usuaris){
|
||||
if ( DonardAltaUsuari(*taula_usuaris,buff,alta_usuaris,total_usuaris) == -1){
|
||||
//error l'usuari ja exisita, s'ha de ficar al fitxer log
|
||||
} else alta_usuaris++;
|
||||
byte_llegit = LlegirLinia(fitxer,buff);
|
||||
}
|
||||
|
||||
return alta_usuaris;
|
||||
}
|
||||
|
||||
int desregistrarUsuari(struct usuari * taula_usuaris, int usuari){
|
||||
taula_usuaris[usuari].UDP_port = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int registrarUsuari(struct usuari * taula_usuaris, int usuari, const char * IP, int portUDP){
|
||||
strcpy(taula_usuaris[usuari].IP,IP);
|
||||
taula_usuaris[usuari].UDP_port = portUDP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
/* Declaració de variables, p.e., int n; */
|
||||
int fi_execucio = 0, user, n_usuaris, portUDPrem, bytes_rebuts, Sck=0, canal;
|
||||
struct usuari * taula_usuaris = NULL;
|
||||
char buffer[MAX_MISSATGE_PLUMI+1], tipus_missatge, IPrem[IP_LENGTH], adr_preguntador[MAX_USER_NICK+MAX_LEN_DOMINI+2];
|
||||
char nickname[MAX_USER_NICK], domini_usuari[MAX_LEN_DOMINI], fitxer_log[MAX_NOM_FITXER];
|
||||
char buffer2[300];
|
||||
/* Expressions, estructures de control, crides a funcions, etc. */
|
||||
|
||||
printf("Estic al pas 1\n");
|
||||
|
||||
if ((n_usuaris = LlegirTaulaDesdeFitxer("/home/markus/ClionProjects/nodelumi2/MIp2-nodelumi.cfg"/*NOM_FITXER_CONFIG*/, &taula_usuaris)) == -1 ){
|
||||
//LUMI_EscriureFitxerLog(NOM_FITXER_LOG, "Error al llegir el fitxer de configuracio");
|
||||
//Apagar tots
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Falta encapsular
|
||||
|
||||
printf("Estic al pas 2\n");
|
||||
|
||||
//LUMI_ResolNomFitxerLog('N', fitxer_log, DOMINI);
|
||||
strcpy(fitxer_log, "temporal.log");
|
||||
Sck = LUMI_InicialitzarNode(fitxer_log);
|
||||
|
||||
int llistaSck[] = {Sck};
|
||||
|
||||
canal = HaArribatAlgunaCosaEnTemps(llistaSck, 1, 0);
|
||||
|
||||
printf("Estic al pas 3");
|
||||
|
||||
bytes_rebuts = LUMI_RepLiniaDe(Sck,IPrem,&portUDPrem, buffer, sizeof(buffer)); //encarregat d'enviar el AI si el format es erroni
|
||||
|
||||
while(fi_execucio!=1){
|
||||
|
||||
if (bytes_rebuts <= 0){ //si hi ha hagut error
|
||||
if(bytes_rebuts == -1){ //si s'ha produit un error inesperat
|
||||
close(Sck);
|
||||
return 1;
|
||||
}
|
||||
else if (bytes_rebuts == 0) return 1; //si s'ha tancat el socket
|
||||
//si bytes_rebuts == -2 només volem omitir la linia rebuda, aixi que no fem res
|
||||
}
|
||||
else{
|
||||
buffer[bytes_rebuts] = '\0';
|
||||
tipus_missatge = buffer[0];
|
||||
LUMI_DescodificarMissatge(tipus_missatge, buffer, adr_preguntador, domini_usuari, nickname);
|
||||
switch(tipus_missatge){
|
||||
case 'R':
|
||||
printf("nick=%s\n",nickname);
|
||||
if (strcmp(DOMINI,domini_usuari) != 0) { //no es del nostre domini
|
||||
LUMI_EnviaResposta(Sck, 'N', adr_preguntador, IPrem, portUDPrem);
|
||||
} else{ //L'usuari a registrar es del nostre domini
|
||||
user = CercarUsuariPerNom(taula_usuaris, nickname, n_usuaris);
|
||||
if (user < 0){//L'usuari no esta a la taula
|
||||
LUMI_EnviaResposta(Sck, 'N', NULL, IPrem, portUDPrem);
|
||||
}
|
||||
else //L'usuari existeix dins la taula
|
||||
{
|
||||
if(taula_usuaris[user].UDP_port!=-1) { //evitem suplantació d'identitat
|
||||
registrarUsuari(taula_usuaris, user, IPrem, portUDPrem);
|
||||
sprintf(buffer2, "L'usuari %s amb IP %s i portUDP %i s'ha registrar correctament", taula_usuaris[user].nom, taula_usuaris[user].IP, taula_usuaris[user].UDP_port);
|
||||
printf("%s\n", buffer2);
|
||||
LUMI_EnviaResposta(Sck, 'K', NULL, IPrem, portUDPrem);
|
||||
}
|
||||
else{
|
||||
LUMI_EnviaResposta(Sck,'O',adr_preguntador,IPrem,portUDPrem);
|
||||
printf("No s'ha pogut registrar l'usuari %s, ja estava registrat\n", nickname);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
user = CercarUsuariPerIPiPort(taula_usuaris,IPrem, portUDPrem, n_usuaris);
|
||||
if (user < 0){//L'usuari no esta a la taula
|
||||
LUMI_EnviaResposta(Sck, 'N', NULL, IPrem, portUDPrem);
|
||||
}
|
||||
else //L'usuari existeix dins la taula
|
||||
{
|
||||
desregistrarUsuari(taula_usuaris, user);
|
||||
sprintf(buffer2, "L'usuari %s amb IP %s s'ha desregistrat correctament", taula_usuaris[user].nom, taula_usuaris[user].IP, taula_usuaris[user].UDP_port);
|
||||
printf("%s\n",buffer2);
|
||||
LUMI_EnviaResposta(Sck, 'K', NULL, IPrem, portUDPrem);
|
||||
}
|
||||
break;
|
||||
case 'L': //Aqui els buffers domini i nickname contenen la informació de l'usuari que es vol localitzar.
|
||||
|
||||
if(strcmp(domini_usuari, DOMINI) == 0)
|
||||
{
|
||||
sprintf(buffer2, "L'usuari %s intenta localitzar a algu", adr_preguntador);
|
||||
printf("%s\n",buffer2);
|
||||
user = CercarUsuariPerNom(taula_usuaris, nickname, n_usuaris); //farà referencia al usuari que es vol localitzar
|
||||
if (user < 0) {
|
||||
LUMI_EnviaResposta(Sck, 'N', adr_preguntador, IPrem, portUDPrem);
|
||||
}
|
||||
else if (taula_usuaris[user].UDP_port == -1){
|
||||
LUMI_EnviaResposta(Sck, 'O', adr_preguntador, IPrem, portUDPrem); ///AIXO NO HA DE PORTAR ADR PREGUNTADOR
|
||||
}
|
||||
else{
|
||||
LUMI_EnviaPeticioServeiLocalitzacio(Sck, adr_preguntador, taula_usuaris[user].IP, taula_usuaris[user].UDP_port);
|
||||
}
|
||||
}
|
||||
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;
|
||||
case 'C':
|
||||
case 'A': //En ambdos casos s'actua de la mateixa manera
|
||||
if(strcmp(domini_usuari, DOMINI) == 0){
|
||||
user = CercarUsuariPerNom(taula_usuaris, nickname, n_usuaris);
|
||||
if (user >= 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
localhost
|
||||
11
|
||||
pepito
|
||||
maria
|
||||
el7at
|
||||
pere.pi
|
||||
7uring
|
||||
lindefinit
|
||||
crazyfrog
|
||||
eustaki
|
||||
mr.xarxes
|
||||
Marc
|
||||
Enric
|
||||
Loading…
Reference in New Issue