void tratarNuevoPersonaje(char* data) { char pId; pId = data[0]; log_info(logFile, "Creando Personaje %c", pId); CrearPersonaje(listaPersonajes, pId, 0, 0, 1, orden); orden++; dibujar(); }
int main(int argc, char* argv[]) { // Lo puse t0d0 en el llamado de abajo, no se porque y si se puede capturar 2 veces la señal como estaba hecho. // signal(SIGINT, notificarPersonajes); pthread_mutex_init(&semNiv, NULL); logger = logInit(argv, argv[1]); // Capturamos sigint y avisamos a los personajes para que cierren y cerramos el nivel. signal(SIGINT, cerrarForzado); t_config *configNivel; char** arrCaja; char* nom_nivel; char* ip_orq; char* port_orq; char* dir_orq; char ip[16]; int puerto; //--Creamos el config configNivel = config_try_create( //"nivel1.config" //Modo Debug argv[1], "Nombre,orquestador,TiempoChequeoDeadlock,Recovery,ip,puerto,Caja1"); ITEM_NIVEL *ListaItems = NULL; //--Creamos cada caja de recursos char* cajaAux; cajaAux = malloc(sizeof(char) * 6); sprintf(cajaAux, "Caja1"); //--Inicializa la lista con los personajes y sus recursos personajes = list_create(); personaje_t pjAux; int t = 1; int cols = 0; int rows = 0; int posXCaja = 0; int posYCaja = 0; nivel_gui_inicializar(); // Conseguimos el area del nivel char state = nivel_gui_get_area_nivel(&cols, &rows); // Validamos que no haya habido error if (state != EXIT_SUCCESS) { cerrarNivel("Error al intentar conseguir el area del nivel (GUI)."); exit(EXIT_FAILURE); } char* messageLimitErr; messageLimitErr = malloc(sizeof(char) * 100); //--Mientras pueda levantar el array while ((arrCaja = config_try_get_array_value(configNivel, cajaAux)) != NULL ) { posXCaja = atoi(arrCaja[3]); posYCaja = atoi(arrCaja[4]); // Validamos que la caja a crear esté dentro de los valores posibles del mapa if (posXCaja > rows || posYCaja > cols || posXCaja < 1 || posYCaja < 1) { sprintf(messageLimitErr, "La caja %c excede los limites de la pantalla. (%d,%d) - (%d,%d)", arrCaja[1][0], posXCaja, posYCaja, rows, cols); cerrarNivel(messageLimitErr); exit(EXIT_FAILURE); } // Si pasó la validacion, la creamos. CrearCaja(&ListaItems, arrCaja[1][0], atoi(arrCaja[3]), atoi(arrCaja[4]), atoi(arrCaja[2])); //--Rearma el cajaAux para la iteracion sprintf(cajaAux, "Caja%d", ++t); } free(cajaAux); //--Boludeces de los sockets message_t message; fd_set master, temp; struct sockaddr_in myAddress; struct sockaddr_in remoteAddress; int maxSock; int sockListener; int sockOrq; //--Saludo al orquestador //--Obetenemos el string del nombre y dirección del orquestador nom_nivel = config_get_string_value(configNivel, "Nombre"); dir_orq = config_get_string_value(configNivel, "orquestador"); puerto = config_get_int_value(configNivel, "puerto"); memcpy(ip, config_get_string_value(configNivel, "ip"), 16); // Conseguimos el tiempo de espera de chequeo int tiempoChequeo = config_get_int_value(configNivel, "TiempoChequeoDeadlock"); ip_orq = strtok(dir_orq, ":"); //--Separar ip port_orq = strtok(NULL, ":"); //--Separar puerto // Crear un socket: struct sockaddr_in socketInfo; if ((sockOrq = socket(AF_INET, SOCK_STREAM, 0)) != 0) { socketInfo.sin_family = AF_INET; socketInfo.sin_addr.s_addr = inet_addr(ip_orq); socketInfo.sin_port = htons(atoi(port_orq)); // Conectar el socket con la direccion 'socketInfo'. if (connect(sockOrq, (struct sockaddr*) &socketInfo, sizeof(socketInfo)) == -1) { perror("Connect"); exit(EXIT_FAILURE); } log_info(logger, "Conexión con orquestador."); orq_t orqMsj; orqMsj.type = NIVEL; orqMsj.detail = SALUDO; strcpy(orqMsj.name, nom_nivel); //memcpy(orqMsj.ip, &localhost->sin_addr.s_addr, 16); strcpy(orqMsj.ip, ip); orqMsj.port = puerto; //--Envía el "Saludo" para ser agregado if (send(sockOrq, &orqMsj, sizeof(orq_t), 0) == -1) { perror("Saludo"); exit(EXIT_FAILURE); } } // Definimos los threads pthread_t thr_interbloqueos; paramInterbloqueo_t parametros; parametros.numSock = sockOrq; parametros.tiempoChequeo = tiempoChequeo; parametros.recovery = config_get_int_value(configNivel, "Recovery"); // y los lanzamos if (pthread_create(&thr_interbloqueos, NULL, (void*) detectInterbloqueos, (void *) ¶metros)) { log_error(logger, strerror(errno)); exit(EXIT_FAILURE); } int maxRows, maxCols; int posX, posY; int posItemY, posItemX; int i; nivel_gui_get_area_nivel(&maxRows, &maxCols); nivel_gui_dibujar(ListaItems, nom_nivel); iniSocks(&master, &temp, &myAddress, remoteAddress, &maxSock, &sockListener, puerto, logger); while (1) { //--Gestiona un cliente ya conectado i = getSockChanged(&master, &temp, &maxSock, sockListener, &remoteAddress, &message, sizeof(message_t), logger); if (i != -1) { pthread_mutex_lock(&semNiv); int contPj; int contRec; char *auxRec; personaje_t *tempAux; //--Recibe mensaje y define comportamiento según el tipo switch (message.type) { case SALUDO: //--Agregamos personaje a la lista de items y a la de personajes/recursos CrearPersonaje(&ListaItems, i, message.name, INIX, INIY); pjAux.numSock = i; pjAux.chirimbolo = message.name; pjAux.blocked = false; pjAux.recursos = list_create(); list_add_new(personajes, &pjAux, sizeof(personaje_t)); //--Armamos la estrucura para enviar la posición inicial message.type = SALUDO; message.detail = INIX; message.detail2 = INIY; log_info(logger, "Se agregó el personaje %c con el socket %d", message.name, i); if (send(i, &message, sizeof(message), 0) == -1) perror("Respuesta posición inicial"); break; case POSICION: //--Obtiene posición del item pedido getPosRec(ListaItems, message.detail, &posX, &posY); //--Armamos la estrucura para enviar la posición del recurso pedido message.type = POSICION; message.detail = posX; message.detail2 = posY; if (send(i, &message, sizeof(message), 0) == -1) perror("Respuesta posición recurso"); break; case MOVIMIENTO: //--Devuelve las posiciones X e Y del item if (getPosPer(ListaItems, i, &posX, &posY) == -1) perror("GetPosItem"); switch (message.detail) { case ARRIBA: if (posY > 1) posY--; break; case ABAJO: if (posY < maxRows) posY++; break; case IZQUIERDA: if (posX > 1) posX--; break; case DERECHA: if (posX < maxCols) posX++; break; } //--Define confirmación y la devuelve message.type = MOVIMIENTO; message.detail2 = message.detail; message.detail = 1; if (send(i, &message, sizeof(message), 0) == -1) perror("Confirmacion"); //--Desbloquear en caso de que esté bloqueado for (contPj = 0; contPj < list_size(personajes); contPj++) { tempAux = list_get(personajes, contPj); if (tempAux->numSock == i && tempAux->blocked) tempAux->blocked = false; } MoverPersonaje(ListaItems, i, posX, posY); break; case PEDIDO: //--Obtiene posición del item pedido y del personaje getPosRec(ListaItems, message.detail, &posItemX, &posItemY); getPosPer(ListaItems, i, &posX, &posY); //--Valida si llegó al recurso if ((posItemX == posX) && (posItemY == posY)) { //-- Siempre le tiene que agregar a la lista de recursos, este o no bloqueado //--Agrega el recurso a la lista de recursos del personaje int contPj; personaje_t* tempAux; for (contPj = 0; contPj < list_size(personajes); contPj++) { tempAux = list_get(personajes, contPj); if (tempAux->numSock == i) { list_add_new(tempAux->recursos, &(message.detail), sizeof(message.detail)); break; } } //--Resta uno a la cantidad del item int result = restarQuantityRec(ListaItems, message.detail); if (result >= 0) { log_info(logger, "A %d se le da el recurso %c", i, message.detail); //--Si pudo restar la cantidad tempAux->blocked = false; //--Define confirmación y la devuelve message.detail = 1; if (send(i, &message, sizeof(message), 0) == -1) perror("Confirmacion"); } else { //--Si el recurso ya no tiene instacias tempAux->blocked = true; log_info(logger, "A %d se le niega el recurso %c", i, message.detail); //--Define rechazo y lo devuelve message.detail = 0; if (send(i, &message, sizeof(message), 0) == -1) perror("Confirmacion"); } } else { log_error(logger, "Posicion erronea al pedir recurso"); exit(EXIT_FAILURE); } break; case SALIR: for (contPj = 0; contPj < list_size(personajes); contPj++) { tempAux = list_get(personajes, contPj); if (tempAux->numSock == i) { //--Elimina y libera la lista de recursos de personaje for (contRec = 0; contRec < list_size(tempAux->recursos); contRec++) { auxRec = list_get(tempAux->recursos, contRec); //--Suma la cantidad de recursos que el personaje libera sumarQuantityRec(ListaItems, *auxRec, 1); } list_destroy_and_destroy_elements(tempAux->recursos, free); //--Elimina y libera al personaje de la lista de personajes list_remove_and_destroy_element(personajes, contPj, free); BorrarPer(&ListaItems, i); break; } } log_debug(logger, "%d se desconectó", i); break; } nivel_gui_dibujar(ListaItems, nom_nivel); pthread_mutex_unlock(&semNiv); } } nivel_gui_terminar(); return 0; }
void mensajesConPlataforma(int32_t socketEscucha) {//ATIENDE LA RECEPCION Y POSTERIOR RESPUESTA DE MENSAJES DEL ORQUESTADOR enum tipo_paquete unMensaje = PER_conexionNivel_ORQ; char* elMensaje=NULL; pthread_mutex_lock(&mutex_log); log_info(logger,"Voy a esperar recibir un mensaje de %d", socketEscucha); pthread_mutex_unlock(&mutex_log); pthread_mutex_lock(&mutex_mensajes); //(matyx) recibirMensaje(socketEscucha, &unMensaje,&elMensaje); pthread_mutex_unlock(&mutex_mensajes); sleep(1); pthread_mutex_lock(&mutex_log); log_info(logger, "Llego el tipo de paquete: %s .",obtenerNombreEnum(unMensaje)); log_info(logger, "Llego este mensaje: %s .",elMensaje); pthread_mutex_unlock(&mutex_log); switch (unMensaje) { case PLA_movimiento_NIV: {//graficar y actualizar la lista RECIBE "@,1,3" char ** mens = string_split(elMensaje,","); char idPers = mens[0][0]; if(huboCambios==true){ pthread_mutex_lock(&mutex_log); log_info(logger,"envio los cambios de configuracion"); pthread_mutex_unlock(&mutex_log); pthread_mutex_lock(&mutex_mensajes); enviarMensaje(socketDeEscucha, NIV_cambiosConfiguracion_PLA,buffer1); pthread_mutex_unlock(&mutex_mensajes); huboCambios=false; pthread_mutex_lock(&mutex_log); log_info(logger,"me preparo para recibir el ok"); pthread_mutex_unlock(&mutex_log); pthread_mutex_lock(&mutex_mensajes); recibirMensaje(socketEscucha, &unMensaje,&elMensaje); pthread_mutex_unlock(&mutex_mensajes); pthread_mutex_lock(&mutex_log); log_info(logger,"deberia haber recibido el OK1"); pthread_mutex_unlock(&mutex_log); if(unMensaje==OK1){ pthread_mutex_lock(&mutex_log); log_info(logger,"ya envie el cambio de configuracion, y me dieron el ok"); pthread_mutex_unlock(&mutex_log); if(existePersonajeEnListaItems(idPers)){ pthread_mutex_lock(&mutex_listas); MoverPersonaje(items, idPers,atoi(mens[1]), atoi(mens[2])); pthread_mutex_unlock(&mutex_listas); pthread_mutex_lock(&mutex_log); log_info(logger, "El personaje %s se movio a %s %s ",mens[0],mens[1],mens[2]); pthread_mutex_unlock(&mutex_log); if(graficar) nivel_gui_dibujar(items,nombre); } pthread_mutex_lock(&mutex_mensajes); enviarMensaje(socketEscucha,NIV_movimiento_PLA,"0"); //"0" SI ES VALIDO pthread_mutex_unlock(&mutex_mensajes); } else { pthread_mutex_lock(&mutex_log); log_info(logger,"no recibi OK1,recibi cualquiera"); pthread_mutex_unlock(&mutex_log); } } else { if(existePersonajeEnListaItems(idPers)){ pthread_mutex_lock(&mutex_listas); MoverPersonaje(items, elMensaje[0],atoi(mens[1]), atoi(mens[2])); pthread_mutex_unlock(&mutex_listas); pthread_mutex_lock(&mutex_log); log_info(logger, "El personaje %s se movio a %s %s ",mens[0],mens[1],mens[2]); pthread_mutex_unlock(&mutex_log); if(graficar) nivel_gui_dibujar(items,nombre); } pthread_mutex_lock(&mutex_log); log_info(logger, "Confirmo que el personaje %s puede moverse",mens[0]); pthread_mutex_unlock(&mutex_log); pthread_mutex_lock(&mutex_mensajes); enviarMensaje(socketEscucha,NIV_movimiento_PLA,"0"); //"0" SI ES VALIDO pthread_mutex_unlock(&mutex_mensajes); } break; } case PLA_personajeMuerto_NIV:{ //RECIBE "@" MUERTE POR ENEMIGOS char id=elMensaje[0]; t_personaje_niv1 * personaje = malloc(sizeof(t_personaje_niv1)); personaje = buscarPersonajeListaPersonajes(listaPersonajesRecursos,string_substring_until(elMensaje,1)); pthread_mutex_lock(&mutex_listas); // liberarRecursosDelPersonaje(personaje->recursosActuales); // tambien suma sus recursos a disponible borrarPersonajeListaPersonajes(listaPersonajesRecursos,elMensaje); pthread_mutex_unlock(&mutex_listas); pthread_mutex_lock(&mutex_log); log_info(logger, "El personaje %c ha muerto ",id); pthread_mutex_unlock(&mutex_log); break; } case PLA_nuevoPersonaje_NIV:{ //RECIBE "@" LA POSICION DE INICIO SERA SIEMPRE 0,0 POR LO QUE NO LA RECIBE char * simbolo = malloc(strlen(elMensaje)+1); strcpy(simbolo,elMensaje); pthread_mutex_lock(&mutex_listas); CrearPersonaje(items,elMensaje[0],0,0); pthread_mutex_unlock(&mutex_listas); //ACA CREO UNA LISTA DE PERSONAJES CON SUS RESPECTIVOS RECURSOS ASIGNADOS t_personaje_niv1 * personaje = malloc(sizeof(t_personaje_niv1)); personaje->simbolo = string_substring_until(elMensaje,1); personaje->recursosActuales = list_create(); personaje->recursoBloqueante = string_new(); personaje->posicion = posicion_create_pos(0,0); personaje->ingresoSistema = ingresoAlSistema; ingresoAlSistema++; pthread_mutex_lock(&mutex_listas); list_add(listaPersonajesRecursos,personaje); pthread_mutex_unlock(&mutex_listas); if(graficar) nivel_gui_dibujar(items,nombre); pthread_mutex_lock(&mutex_log); log_info(logger, "El nuevo personaje %c se dibujo en el mapa",elMensaje[0]); pthread_mutex_unlock(&mutex_log); break; } case PLA_posCaja_NIV:{ // RECIBE "F" SI ESTA SOLICITANDO UNA FLOR, POR EJEMPLO char * pos = string_new(); ITEM_NIVEL * caja = buscarRecursoEnLista(items, elMensaje); string_append(&pos, string_from_format("%d",caja->posx)); string_append(&pos, ","); string_append(&pos, string_from_format("%d",caja->posy)); pthread_mutex_lock(&mutex_log); log_info(logger,"enviare la posicion de la caja"); pthread_mutex_unlock(&mutex_log); pthread_mutex_lock(&mutex_mensajes); enviarMensaje(socketEscucha, NIV_posCaja_PLA,pos); //"X,Y" pthread_mutex_unlock(&mutex_mensajes); pthread_mutex_lock(&mutex_log); log_info(logger, "Envio posicion del recurso %s coordenadas %s ",elMensaje,pos); pthread_mutex_unlock(&mutex_log); free(pos); break; } case PLA_solicitudRecurso_NIV:{ // LE CONTESTO SI EL RECURSOS ESTA DISPONIBLE // El mensaje de ejemplo es : "@,H" char * rta; bool hayRecurso = determinarRecursoDisponible (string_substring_from(elMensaje, 2)); //SI ESTA EL RECURSO TMB LO RESTA t_personaje_niv1 * pers = buscarPersonajeListaPersonajes(listaPersonajesRecursos, string_substring_until(elMensaje,1)); if (hayRecurso){ rta = "0"; pthread_mutex_lock(&mutex_listas); list_add(pers->recursosActuales, string_substring_from(elMensaje, 2)); pers->recursoBloqueante = string_new(); pthread_mutex_unlock(&mutex_listas); }else{ pthread_mutex_lock(&mutex_listas); pers->recursoBloqueante = string_substring_from(elMensaje, 2); rta = "1"; pthread_mutex_unlock(&mutex_listas); } pthread_mutex_lock(&mutex_mensajes); enviarMensaje(socketEscucha, NIV_recursoConcedido_PLA,rta);//"0" CONCEDIDO, "1" NO CONCEDIDO pthread_mutex_unlock(&mutex_mensajes); break; } case PLA_personajesDesbloqueados_NIV:{//"5,@,#,....." recorro lista personaje recursos y actualizo recBloqueante a vacio char ** mens = string_split(elMensaje,","); int i; int cantPersonajes=atoi(mens[0]); for(i=1;i<=cantPersonajes;i++){ char * unPersDesbloqueado=mens[i]; t_personaje_niv1 * unPers=buscarPersonajeListaPersonajes(listaPersonajesRecursos,unPersDesbloqueado); pthread_mutex_lock(&mutex_listas); unPers->recursoBloqueante=string_new(); pthread_mutex_unlock(&mutex_listas); pthread_mutex_lock(&mutex_log); log_info(logger, "Personajes %s desbloqueados",mens[i]); pthread_mutex_unlock(&mutex_log); } break; } case PLA_actualizarRecursos_NIV:{ //"3;F,1;C,3;....." actualizo la lista de recursos sumandole esas cantidades char ** mens = string_split(elMensaje,";"); int cantRecursos= atoi(mens[0]); int i; pthread_mutex_lock(&mutex_log); log_info(logger, "Recursos desbloqueados: %s",elMensaje); pthread_mutex_unlock(&mutex_log); for(i=1;i<=cantRecursos;i++){ char** mensajeIndividual= string_split(mens[i],","); pthread_mutex_lock(&mutex_listas); int cantidad=atoi(mensajeIndividual[1]); sumarRecurso(items, mensajeIndividual[0][0],cantidad); pthread_mutex_unlock(&mutex_listas); if(graficar) nivel_gui_dibujar(items,nombre); } break; } case PLA_nivelFinalizado_NIV:{ //recibe personaje que termino el nivel ej: "@" char id=elMensaje[0]; t_personaje_niv1 * personaje = malloc(sizeof(t_personaje_niv1)); personaje = buscarPersonajeListaPersonajes(listaPersonajesRecursos,string_substring_until(elMensaje,1)); pthread_mutex_lock(&mutex_listas); // liberarRecursosDelPersonaje(personaje->recursosActuales); BorrarItem(items,id); borrarPersonajeListaPersonajes(listaPersonajesRecursos,elMensaje); pthread_mutex_unlock(&mutex_listas); pthread_mutex_lock(&mutex_log); log_info(logger, "El personaje %c ha terminado el nivel ",id); pthread_mutex_unlock(&mutex_log); if(graficar){ nivel_gui_dibujar(items,nombre); } break; } case PLA_perMuereInterbloqueo_NIV:{ char id=elMensaje[0]; t_personaje_niv1 * personaje = malloc(sizeof(t_personaje_niv1)); personaje = buscarPersonajeListaPersonajes(listaPersonajesRecursos,string_substring_until(elMensaje,1)); pthread_mutex_lock(&mutex_listas); // liberarRecursosDelPersonaje(personaje->recursosActuales); BorrarItem(items,id); borrarPersonajeListaPersonajes(listaPersonajesRecursos,elMensaje); pthread_mutex_unlock(&mutex_listas); pthread_mutex_lock(&mutex_log); log_info(logger, "El personaje %c ha muerto por interbloqueo ",id); pthread_mutex_unlock(&mutex_log); if(graficar) nivel_gui_dibujar(items,nombre); break; } case PLA_perMuereNaturalmente_NIV: { char id = elMensaje[0]; t_personaje_niv1 * personaje = malloc(sizeof(t_personaje_niv1)); personaje = buscarPersonajeListaPersonajes(listaPersonajesRecursos,string_substring_until(elMensaje, 1)); pthread_mutex_lock(&mutex_listas); liberarRecursosDelPersonaje(personaje->recursosActuales); BorrarItem(items, id); borrarPersonajeListaPersonajes(listaPersonajesRecursos, elMensaje); pthread_mutex_unlock(&mutex_listas); pthread_mutex_lock(&mutex_log); log_info(logger, "El personaje %c ha muerto por causas externas", id); pthread_mutex_unlock(&mutex_log); if (graficar) nivel_gui_dibujar(items, nombre); break; } { default: pthread_mutex_lock(&mutex_log); log_info(logger, "Recibi mensaje inexistente, la ejecucion del nivel finalizara"); pthread_mutex_unlock(&mutex_log); eliminarEstructuras(); break; } free(elMensaje); } }
void crearGuiPersonajes(void* item) { personaje* character = (personaje *) item; CrearPersonaje(&listaItems, *character->simbolo, character->lastPosition->x, character->lastPosition->y); }