575 lines
24 KiB
C
575 lines
24 KiB
C
/**************************************************************************/
|
||
/* */
|
||
/* 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... */
|