lumi-practica-xarxes-udg/nodelumi2/MIp2-lumi.c

729 lines
24 KiB
C
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**************************************************************************/
/* */
/* 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; lidentificador 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 didentificador “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 didentificador “Sck” una seqüència de */
/* bytes que prové d'un socket remot i lescriu 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;
}
/* Sallibera (sesborra) el socket UDP didentificador “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 didentificador “Sck”, troba ladreça daquest */
/* 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 didentificador “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 lestat “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 ladreç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” didentificador “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” didentificador “Sck” una */
/* seqüència de bytes que prové del socket remot amb qui està connectat, */
/* i lescriu 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” didentificador “Sck”, troba ladreç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 */
/* lidentificador daquest 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);
}