/*####################################################################################### # Class One S.L. Software Trademark # #---------------------------------------------------------------------------------------# # # # Programa: hot9ceri.c # # Programador: Pedro Amoedo # # Descripcion: Interface de centralita de telefono con CHAR-IP y ROOM-STATUS # # Fecha Ultima Modificacion: 28-09-2006 # # # #######################################################################################*/ #include #include #include #include #include #include #include #include #include //Definiciones de tipos de estandar POSIX. #include //Tipos para el uso de sockets y prototipos de las funciones necesarias para su manejo. #include //Constantes definidas para sistemas internet. #include //Rutinas de translacion de direcciones IP. #include //Rutina para modificacion de parametros del socket /***************************************CONSTANTES**********************************************/ # define HOTEL "[AGIR]" # define CFGFILE "hot91ctf.cfg" # define DATAFILE "hot91ctf.dat" # define HISTFILE "hot91ctf.his" # define STX 02 # define ETX 03 # define ACK 06 /**********************************VARIABLES A UTILIZAR**********************************************/ int sockfd; //Identificador del socket int longitud; //variable con el tamaņo de la estructura destino. char mensaje_enviar[128]; //Mensaje a enviar a la centralita. char mensaje_recibir[128]; //Mensaje a enviar a la centralita. char msj_tmp[128],hab[3],cod_rs[1]; char direccion [16]; //Direccion de la centralita. char puerto_centralita[10]; int puerto; //puerto centralita. int c; //Mantengo el valor de las funciones, para CONTROLAR los errores. struct sockaddr_in origen; //Estructura origen. struct sockaddr_in destino; //Estructura destino. int i, j; // multiple purpouse counter char ent[128]; // empty string to store the incoming bytes extern int errno; /* system defined internal error */ int fin,result,iof=-1; char e; FILE *fd1; // Configuracion FILE *fd3; // Datos de salida FILE *fd4; // Historico /********************************************FUNCION PRINCIPAL*****************************************/ int main (void) { struct timeval timeout; //Estructura para el timeout del select fd_set readset; //Conjunto de sockets para lectura timeout.tv_sec=60; //segundos timeout.tv_usec=0; //microsegundos //Apertura del fichero .cfg para cojer la configuracion fd1 = fopen (CFGFILE,"r"); if (fd1 == NULL) { puts ("ERROR: no puedo abrir fichero " CFGFILE); printf ("reason: %s\n", strerror (errno)); exit (1); } if (fgets (direccion, sizeof(direccion), fd1) == NULL) { puts ("ERROR: no puedo leer desde " CFGFILE); printf ("reason: %s\n", strerror (errno)); exit (1); } if (fgets (puerto_centralita, sizeof(puerto_centralita), fd1) == NULL) { puts ("ERROR: no puedo leer desde " CFGFILE); printf ("reason: %s\n", strerror (errno)); exit (1); } puerto= atoi(puerto_centralita); fclose (fd1); /************************************************** * ABRO LOS FICHEROS DE OUTPUT * hot91ctf.dat : graba un solo registro de la trama * hot91ctf.his : historico de registros **************************************************/ if ( ( fd3 = fopen(DATAFILE, "w") ) == NULL ) { puts ("ERROR: no puedo abrir " DATAFILE); printf ("reason: %s\n", strerror (errno) ); exit (1); } if ( ( fd4 = fopen(HISTFILE, "a+") ) == NULL ) { puts ("ERROR: no puedo abrir " HISTFILE); printf ("reason: %s\n", strerror (errno) ); exit (1); } /* Creacion del socket TCP */ sockfd = socket (AF_INET,SOCK_STREAM,0); if (sockfd == -1) { perror("Error al crearse el socket.\n"); exit(1); } /************************************************************************/ /* Preparar un nombre local en un puerto cualquiera:el nombre local se */ /* prepara con la propia direccion de Internet y el puerto se deja a la */ /* eleccion de la maquina */ /************************************************************************/ origen.sin_family=AF_INET; origen.sin_port= htons(0); origen.sin_addr.s_addr=htonl(INADDR_ANY); /* Asignar nombre local al socket:asignacion de una direccion local */ c = bind(sockfd,(struct sockaddr*)&origen,sizeof(origen)); if (c == -1) { perror("Error al asignar un nombre local al socket\n"); exit(2); } /************************************************************************/ /* Preparar el nombre de la maquina remota:la direccion remota hay que */ /* convertirla a binario con la funcion "inet.addr" y el numero de */ /* puerto remoto hay que ponerlo en formato de red con htons. */ /************************************************************************/ c=inet_addr(direccion); if (c == -1) { perror("Error, la direccion no es valida"); exit(3); } destino.sin_family=AF_INET; destino.sin_port=htons(puerto); destino.sin_addr.s_addr=inet_addr(direccion); /* Establecer la conexion con el servidor*/ c = connect (sockfd,(struct sockaddr*)&destino, sizeof(destino)); if (c == -1) { perror("Error al conectarse al servidor."); exit(4); } fin=0; do{ printf ("\n%s ESPERANDO LLAMADAS... \n", HOTEL); //Funciones de inicializacion necesarias para el select FD_ZERO(&readset); //limpia el conjunto de descriptores FD_SET(sockfd,&readset); //asocia el socket con el conjunto /*La funcion select nos permite monitorear un conjunto de sockets antes de tomar una decision bloqueante como recv*/ result=select(sockfd + 1,&readset,NULL,NULL,&timeout); if (result > 0) //Hay datos { /* El socket tiene datos disponibles para ser leidos */ if ((iof=fcntl(sockfd, F_GETFL, 0)) != -1) /*Aun sabiendo que el socket tiene datos, lo configuramos como no bloqueante con la funcion fcntl para evitar un bloqueo inesperado por parte de la funcion recv*/ fcntl(sockfd, F_SETFL, iof | O_NONBLOCK); c=recv(sockfd,mensaje_recibir,sizeof(mensaje_recibir),0); if (c == -1) { perror("Error al recibir el mensaje:\n"); exit(3); } //Una vez leidos los datos devolvemos al socket su configuracion bloqueante if (iof != -1) fcntl(sockfd, F_SETFL, iof); }else if (result == 0) exit(3); //Timeout del select if (result < 0) printf("Error",errno); //Error mensaje_recibir[c]='\0'; printf("Mensaje recibido:%s\n", mensaje_recibir); //Envio del ACK //e=ACK; //c=send(sockfd,&e,sizeof(e),0); //if (c == -1){ // perror("Error al enviar mensaje:\n"); // exit(4); //} //printf("ACK enviado.\n"); if (mensaje_recibir[1]!= 'T' && mensaje_recibir[1]!= 'R' && mensaje_recibir[1]!= 'A' && mensaje_recibir[1]!= 'C'){ printf("La trama recibida no es correcta, el TIPO DE INFORMACION es distinto de T, R, A y C.\n"); // fputs ("Trama erronea:", fd4); // fputs (mensaje_recibir, fd4); // fputc('\n',fd4); fin=0; } else { if (mensaje_recibir[0]!= STX && mensaje_recibir[49]!= ETX){ printf("La trama recibida no es correcta, no posee STX o ETX.\n"); fin=0; } else { fin=1; } } }while(fin == 0); //Recomposicion de trama a modelo Room-Status adecuado para cobol if (mensaje_recibir[1] == 'R') { //inicio e=STX; strcat(msj_tmp,&e); strcat(msj_tmp,"R "); //habitacion msj_tmp[3]=mensaje_recibir[3]; msj_tmp[4]=mensaje_recibir[4]; msj_tmp[5]=mensaje_recibir[5]; msj_tmp[6]=mensaje_recibir[6]; //fecha msj_tmp[7]=mensaje_recibir[7]; msj_tmp[8]=mensaje_recibir[8]; msj_tmp[9]=mensaje_recibir[9]; msj_tmp[10]=mensaje_recibir[10]; msj_tmp[11]=mensaje_recibir[11]; msj_tmp[12]=mensaje_recibir[12]; //hora msj_tmp[13]=mensaje_recibir[13]; msj_tmp[14]=mensaje_recibir[14]; msj_tmp[15]=mensaje_recibir[15]; msj_tmp[16]=mensaje_recibir[16]; //codigo room-status(2 digitos) cod_rs[0]=mensaje_recibir[17]; cod_rs[1]=mensaje_recibir[18]; strcat(msj_tmp," R"); strcat(msj_tmp,cod_rs); //fin e=ETX; strcat(msj_tmp,&e); strcpy(mensaje_recibir,msj_tmp); } //Almacenar la trama en el fichero .dat fputs(mensaje_recibir, fd3); //Se almacena la trama recibida en el fichero historico fputs (mensaje_recibir, fd4); fputc('\n',fd4); //Se cierra el fichero de datos if (fclose (fd3) == EOF) { puts ("ERROR: no se pudo cerrar el fichero de datos."); printf ("reason: %s\n", strerror (errno) ); exit (1); } //Se cierra el historico if (fclose (fd4) == EOF) { puts ("ERROR: no se pudo cerrar el fichero historico."); printf ("reason: %s\n", strerror (errno) ); exit (1); } //Se cierra el socket close(sockfd); return (0); } //FIN DEL ALGORITMO