729 lines
24 KiB
C
Executable File
729 lines
24 KiB
C
Executable File
|
||
|
||
/**************************************************************************/
|
||
/* */
|
||
/* 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);
|
||
}
|