void add_new_personaje_in_plataforma(tSimbolo simbolo){ int i; bool encontrado=false; for(i=0; i < list_size(personajes_jugando); i++){ t_estado_personaje * personaje = list_get(personajes_jugando, i); if(personaje->simbolo == simbolo){ encontrado =true; break; } } if(!encontrado){ t_estado_personaje personaje; personaje.simbolo = simbolo; personaje.estado = false; list_add_new(personajes_jugando, &personaje, sizeof(t_estado_personaje)); } }
void detectInterbloqueos(void* argumentos) { t_list* bloqueados; paramInterbloqueo_t parametros; memcpy(¶metros, argumentos, sizeof(paramInterbloqueo_t)); int cantBloq, marcados; // Iteramos infinitamente while (1) { pthread_mutex_lock(&semNiv); cantBloq = 0; marcados = 0; bloqueados = list_create(); //log_trace(logger, "Initializing locking sysem activatinasdqu..,"); int contPer1, contPer2; personaje_t* levantador1, *levantador2; //--Recorrer los personajes for (contPer1 = 0; contPer1 < list_size(personajes); contPer1++) { levantador1 = list_get(personajes, contPer1); //--marca a los que no estan bloqueados if (levantador1->blocked) { levantador1->marcado = false; cantBloq++; } else { levantador1->marcado = true; marcados++; } } for (; cantBloq >= 0; cantBloq--) { //(En el peor de los casos, tiene que asignar 2n-1 veces) //Por cada pj no marcado for (contPer1 = 0; contPer1 < list_size(personajes); contPer1++) { levantador1 = list_get(personajes, contPer1); if (!levantador1->marcado) { //Si necesita un recurso de uno marcado for (contPer2 = 0; contPer2 < list_size(personajes); contPer2++) { levantador2 = list_get(personajes, contPer2); if (levantador2->marcado && tieneLoQueNecesito(levantador2, levantador1)) { log_trace(logger, "Marque a %c", levantador1->chirimbolo); levantador1->marcado = true; marcados++; break; } } } } }; //Estan en DeadLock los que no esten marcados for (contPer1 = 0; contPer1 < list_size(personajes); contPer1++) { levantador1 = list_get(personajes, contPer1); if (!levantador1->marcado) { list_add_new(bloqueados, levantador1, sizeof(personaje_t)); log_trace(logger, "%c esta en Deadlock", levantador1->chirimbolo); } } //--Si la lista tiene más de 1 deadlockeados, se la mandamos al orquestador if ((list_size(bloqueados) > 1) && (parametros.recovery)) { //--Envía un header con la cantidad de personajes orq_t header; header.type = NIVEL; header.detail = HAYINTERBLOQUEO; header.port = list_size(bloqueados); if (send(parametros.numSock, &header, sizeof(header), 0) == -1) { log_error(logger, "Send: %s", strerror(errno)); exit(EXIT_FAILURE); } log_trace(logger, "Header: cantidad: %d", list_size(bloqueados)); //--Envía los personajes message_t message; personaje_t* levantadorBlk; while (list_size(bloqueados) != 0) { levantadorBlk = list_remove(bloqueados, 0); message.name = levantadorBlk->chirimbolo; if (send(parametros.numSock, &message, sizeof(message), 0) == -1) { log_error(logger, "Send: %s", strerror(errno)); exit(EXIT_FAILURE); } log_trace(logger, "\tPersonaje: %c", message.name); } list_destroy_and_destroy_elements(bloqueados, free); } // Mandamos el proceso a dormir para que espere el tiempo definido por archivo de config. pthread_mutex_unlock(&semNiv); sleep(parametros.tiempoChequeo); log_trace(logger, ">>>Revisando DL<<<"); } }
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* planificador(void* argumentos) { int q = 1; //En que parte del quantum esta int contIndex = 0; int proxPj = 0; nivel_t argu; memcpy(&argu, argumentos, sizeof(nivel_t)); message_t mensaje; personaje_t pjAuxiliar; //--Este sirve para crear los personajes nuevos personaje_t* pjLevantador = malloc(sizeof(personaje_t)); //--Este sirve para levantar de la lista y usar //--Boludeces de los sockets fd_set master, temp; struct sockaddr_in myAddress; struct sockaddr_in remoteAddress; int maxSock; int sockListener; int i, contPj; _Bool encontrado = false, pedirNoRequiereQuantum; //para forzar el turno si se desbloquea iniSocks(&master, &temp, &myAddress, remoteAddress, &maxSock, &sockListener, argu.puertoPlan, logger); while (1) { i = getSockChanged(&master, &temp, &maxSock, sockListener, &remoteAddress, &mensaje, sizeof(mensaje), logger); if (i != -1) { //Conexcion que cambia pthread_mutex_lock(&semNiv); switch (mensaje.type) { case SALUDO: pjAuxiliar.name = mensaje.name; pjAuxiliar.sockID = i; pjAuxiliar.index = ++contIndex; pjAuxiliar.recursos = list_create(); //Arma la lista delos recursos list_add_new(argu.l_personajesRdy, &pjAuxiliar, sizeof(personaje_t)); log_trace(logger, "Se agrego %c a la lista (%d)", mensaje.name, list_size(argu.l_personajesRdy)); imprimirLista(argu.nombre, argu.l_personajesRdy, argu.l_personajesBlk, proxPj); if (list_size(argu.l_personajesRdy) == 1) { //--Mandar primer turno al primero mensaje.type = PERSONAJE; mensaje.detail = TURNO; if (send(pjAuxiliar.sockID, &mensaje, sizeof(message_t), 0) == -1) { log_error(logger, "send: %s", strerror(errno)); exit(EXIT_FAILURE); } } break; case TURNO: pedirNoRequiereQuantum = true; if (mensaje.detail2 != NADA) { //--Agregar recurso pedido a su lista de recursos // (se lo agregamos aca, para saber poque recurso esta bloqueado, antes de mandarlo a la lista de bloqueados) list_add_new(pjLevantador->recursos, &(mensaje.detail2), sizeof(mensaje.detail2)); pedirNoRequiereQuantum = false; if (mensaje.detail == BLOCK) { //Si volvió bloqueado, marcar personaje como bloqueado log_info(logger, "Personaje: %c esta bloquado por: %c", pjLevantador->name, mensaje.detail2); //-- Lo saca de listos, y lo pone en bloquados list_add(argu.l_personajesBlk, list_remove(argu.l_personajesRdy, proxPj)); //Para que pase al otro PJ proxPj--; imprimirLista(argu.nombre, argu.l_personajesRdy, argu.l_personajesBlk, proxPj); q = Quantum + 1; } q--; } if (list_size(argu.l_personajesRdy) != 0) { //--Si ya terminó su quantum if (q >= Quantum) { proxPj++; //Solo avanza en la lista si se le acabo el Qauntum proxPj = abs(proxPj) % list_size(argu.l_personajesRdy); q = 1; } else { q++; } //--Cachear pj pjLevantador = list_get(argu.l_personajesRdy, proxPj); //--Si hay a quien enviarle el próximo turno mensaje.type = PERSONAJE; mensaje.detail = TURNO; if (pedirNoRequiereQuantum) usleep(delay); log_trace(logger, "Turno para %c", pjLevantador->name); if (send(pjLevantador->sockID, &mensaje, sizeof(message_t), 0) == -1) { log_error(logger, "send: %s", strerror(errno)); } } break; case REINICIAR: mensaje.detail = DIEPOTATO; // Enviar mensaje de muerte al personaje, porque solicitó reiniciar. if (send(i, &mensaje, sizeof(mensaje), 0) == -1) { log_error(logger, "send: %s", strerror(errno)); exit(EXIT_FAILURE); } break; case SALIR: encontrado = false; for (contPj = 0; contPj < list_size(argu.l_personajesBlk); contPj++) { //Cicla los personajes pjLevantador = list_get(argu.l_personajesBlk, contPj); if (pjLevantador->sockID == i) { encontrado = true; //Si lo encontras en Blk list_remove(argu.l_personajesBlk, contPj); //y sacarlo de la lista break; } } //Si no lo encuentra if (!encontrado) { //Si no lo encontras, buscarlo en rdy for (contPj = 0; contPj < list_size(argu.l_personajesRdy); contPj++) { //Cicla los personajes pjLevantador = list_get(argu.l_personajesRdy, contPj); if (pjLevantador->sockID == i) { list_remove(argu.l_personajesRdy, contPj); //y sacarlo de la lista break; } } } //Jamas deveria pasar que no lo encuentre int contRec; char* recurso; int j; personaje_t* pjLevantadorBlk = malloc(sizeof(personaje_t)); //Si esta seteado "encontrado" es porque estaba bloqueado, entonces el ultimo recurso de la lista no es un recurso real. for (contRec = 0; contRec < list_size(pjLevantador->recursos) - (encontrado ? 1 : 0); contRec++) { recurso = list_get(pjLevantador->recursos, contRec); for (j = 0; j < list_size(argu.l_personajesBlk); j++) { //--Cicla los personajes bloqueados pjLevantadorBlk = list_get(argu.l_personajesBlk, j); //Si el ultimo recurso, es el que libera char* recursoLevantado = list_get(pjLevantadorBlk->recursos, list_size(pjLevantadorBlk->recursos) - 1); if (*recursoLevantado == *recurso) { log_trace(logger, "Se desbloqueo %c por %c recurso", pjLevantadorBlk->name, *recurso); //Desbloquear list_add(argu.l_personajesRdy, pjLevantadorBlk); list_remove(argu.l_personajesBlk, j); imprimirLista(argu.nombre, argu.l_personajesRdy, argu.l_personajesBlk, proxPj - 1); break; } } } //Limpia las cosas, porque se fue list_destroy_and_destroy_elements(pjLevantador->recursos, free); // forzar un mensaje de turno para volver a multiplexar if (list_size(argu.l_personajesRdy) > 0) { proxPj--; proxPj = abs(proxPj) % list_size(argu.l_personajesRdy); q = 1; imprimirLista(argu.nombre, argu.l_personajesRdy, argu.l_personajesBlk, proxPj); //--Cachear pj usleep(delay); mensaje.detail = TURNO; pjLevantador = list_get(argu.l_personajesRdy, proxPj); log_trace(logger, "Turno para %c", pjLevantador->name); if (send(pjLevantador->sockID, &mensaje, sizeof(message_t), 0) == -1) { log_error(logger, "send: %s", strerror(errno)); } } if (mensaje.detail2 == FOSHIZZLE) { mensaje.detail2 = NADA; //Cuando un PJ termina tod0 su plan, se fija si hay otros PJs dando vueltas, o termina orqTerminoTodo(); //<-- Aca esta el execve } //End case SALIR break; } pthread_mutex_unlock(&semNiv); } } return NULL ; }
void orquestador(void) { //Tirar hilos pthread_t threads[20]; //Solo 20 planificadores concurrentemente int cantidadHilos = 0; //Para que cuando sume empieze en 0; l_niveles = list_create(); orq_t orqMsj; int lastPlan = PUERTO_PLAN; //--Boludeces de los sockets fd_set master, temp; struct sockaddr_in myAddress; struct sockaddr_in remoteAddress; int maxSock; int sockListener; int i; _Bool nivelEncontrado; iniSocks(&master, &temp, &myAddress, remoteAddress, &maxSock, &sockListener, PUERTO_ORQ, logger); while (1) { i = getSockChanged(&master, &temp, &maxSock, sockListener, &remoteAddress, &orqMsj, sizeof(orqMsj), logger); if (i != -1) { //Solo lo hace si el select esta levantando un socket que ya tenia. La primera vuelta sale con -700 nivel_t nivel; // = (nivel_t*) malloc(sizeof(nivel_t)); char* nombrePJ = malloc(sizeof(char)); nivel_t* aux; int indList; int indListPers; pthread_mutex_lock(&semNiv); //--Switch según quien envió el mensaje switch (orqMsj.type) { case NIVEL: //--Switch según el tipo de mensaje switch (orqMsj.detail) { case SALUDO: //--Armar estructura nueva strcpy(nivel.ip, orqMsj.ip); strcpy(nivel.nombre, orqMsj.name); nivel.puerto = orqMsj.port; lastPlan = lastPlan + 15; nivel.puertoPlan = lastPlan; nivel.l_personajesRdy = list_create(); nivel.l_personajesBlk = list_create(); nivel.sock = i; list_add_new(l_niveles, (void*) &nivel, sizeof(nivel_t)); log_trace(logger, "Se conectó el nivel: %s, IP: %s, Puerto: %d", orqMsj.name, orqMsj.ip, orqMsj.port); //Tira el nuevo hilo if (pthread_create(&threads[cantidadHilos++], NULL, planificador, (void *) &nivel)) { //-- Mandamos al hilo t0do el nivel log_error(logger, "pthread_create: %s", strerror(errno)); exit(EXIT_FAILURE); } log_debug(logger, "Nuevo hilo de '%s' que atiende puerto: %d", orqMsj.name, lastPlan); break; case SALIR: for (indList = 0; indList < list_size(l_niveles); ++indList) { //Cicla en la lista niveles aux = (nivel_t*) list_get(l_niveles, indList); if (aux->sock == i) { //Cuando lo encuentra, la borra list_remove(l_niveles, indList); break; } } break; //----------------------------REGION CRITICA-------------------- case HAYINTERBLOQUEO: log_trace(logger, "Llego mensaje de deadlock en nivel de socket %d", i); for (indList = 0; indList < list_size(l_niveles); ++indList) { //Cicla en la lista niveles aux = (nivel_t*) list_get(l_niveles, indList); if ((aux->sock == i) && (list_size(aux->l_personajesBlk) != 0)) { // Busca el nivel y si tiene algun personaje bloqueado message_t message; personaje_t *levantadorPJ; personaje_t victima; victima.index = 0; int contPjDLk, tope; tope = orqMsj.port; //--Ciclo que recibe todos los personajes del deadlock for (contPjDLk = 1; contPjDLk <= tope; contPjDLk++) { if (recv(i, &message, sizeof(message), 0) == -1) { log_error(logger, "Recv: %s", strerror(errno)); exit(EXIT_FAILURE); } //--Buscar el personaje que nos mandaron int contPjBlk; for (contPjBlk = 0; contPjBlk < list_size(aux->l_personajesBlk); contPjBlk++) { levantadorPJ = list_get(aux->l_personajesBlk, contPjBlk); //--Si lo encuentra, sale del ciclo if (levantadorPJ->name == message.name) break; } //--Si el índice es mayor, setear nueva víctima if (victima.index < levantadorPJ->index) victima = *levantadorPJ; } log_info(logger, "\n>>>>>VICTIMA: %c\n", victima.name); message.detail = DIEPOTATO; //--Matar víctima if (send(victima.sockID, &message, sizeof(message), 0) == -1) { log_error(logger, "Send: %s", strerror(errno)); exit(EXIT_FAILURE); } break; } } break; //****************REGION CRITICA******************************* } break; case PERSONAJE: //--Switch según el tipo de mensaje switch (orqMsj.detail) { case SALUDO: nivelEncontrado = false; //--Busca en la lista de niveles, el nivel pedido for (indList = 0; indList < list_size(l_niveles); ++indList) { //Cicla en la lista de niveles aux = (nivel_t*) list_get(l_niveles, indList); if (string_equals_ignore_case(aux->nombre, orqMsj.name)) { nivelEncontrado = true; log_trace(logger, "Se conectó el personaje: %c, Pide: %s", orqMsj.ip[0], orqMsj.name); //Cuando la encuentra, arma la estructura con la información del NIVEL y la envía. orqMsj.port = aux->puerto; strcpy(orqMsj.ip, aux->ip); if (send(i, &orqMsj, sizeof(orq_t), 0) == -1) { log_error(logger, "send: %s", strerror(errno)); exit(EXIT_FAILURE); } //--Arma la estructura con la información del PLANIFICADOR de ese nivel y la envía //strcpy(orqMsj.ip, ipOrq); orqMsj.port = aux->puertoPlan; if (send(i, &orqMsj, sizeof(orq_t), 0) == -1) { log_error(logger, "send: %s", strerror(errno)); exit(EXIT_FAILURE); } break; } } if (!nivelEncontrado) { //Si no encontro el nivel, decirselo orqMsj.detail = NADA; if (send(i, &orqMsj, sizeof(orq_t), 0) == -1) { log_error(logger, "send: %s", strerror(errno)); exit(EXIT_FAILURE); } } break; case SALIR: //--Busca en la lista de niveles, el nivel pedido for (indList = 0; indList < list_size(l_niveles); ++indList) { //Cicla en la lista de niveles aux = (nivel_t*) list_get(l_niveles, indList); if (!strcmp(aux->nombre, orqMsj.name)) { for (indListPers = 0; indListPers < list_size(aux->l_personajesRdy); ++indListPers) { //--Busca al personaje en la lista del nivel. nombrePJ = list_get(aux->l_personajesRdy, indListPers); if (orqMsj.ip[0] == *nombrePJ) list_remove(aux->l_personajesRdy, indListPers); break; } } } break; } break; } pthread_mutex_unlock(&semNiv); } } }