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

305 lines
10 KiB
C

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