lumi-practica-xarxes-udg/P2P/MIp2-p2p.c

249 lines
10 KiB
C

/**************************************************************************/
/* */
/* 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;
}