<commit_before>#include "servidor.h"

// Inicia el servidor con los parametros especificados.
int inicializar_servidor(fd_set * master, fd_set * read_fds, int * listener, int * fdmax,int max_conexiones, int puerto)
{
	struct sockaddr_in selfAddress;
	
	int yes = 1; // para setsockopt() SO_REUSEADDR, mas abajo
			
        // borra los conjuntos maestro y temporal						
	FD_ZERO(master); 
	FD_ZERO(read_fds); 
		
	// obtener socket a la escucha
	if ((*listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		return ERROR_SOCKET;		
	}
	// obviar el mensaje "address already in use" (la direccion ya se esta usando)
	if (setsockopt(*listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))== -1)
	{
		return ADDR_IN_USE;
	}

	// enlazar
	selfAddress.sin_family = AF_INET;
	selfAddress.sin_addr.s_addr = INADDR_ANY;
	selfAddress.sin_port = htons(puerto);
	memset(&(selfAddress.sin_zero), '\0', 8);

	if (bind(*listener, (struct sockaddr *) &selfAddress, sizeof(selfAddress)) == -1) 
	{
		return ERROR_BIND;
	}

	// escuchar	
	if (listen(*listener, max_conexiones) == -1) {
		return ERROR_LISTEN;
	}
	
	// agregar listener al conjunto maestro	
	FD_SET(*listener, master);

	// Seguir la pista del descriptor de fichero mayor
	*fdmax = *listener;
	
	return SUCCESS;
}

void servidor(void (*manejadorDeDatos)(struct NIPC datos, int socket), int puerto, int maxConecciones)
{  	
  struct sockaddr_in remoteaddr;	
  int connectionIndex = 0;
  int estadoDatosCliente;
  struct NIPC datosRecibidos;			  

  int * listener = malloc(sizeof(int));
  int * fdmax = malloc(sizeof(int));
  fd_set * master = malloc(sizeof(fd_set));
  fd_set * read_fds = malloc(sizeof(fd_set));

  datosRecibidos.Length = 0;
  datosRecibidos.Payload = malloc(0);
  datosRecibidos.Type = 0;
      
  inicializar_servidor(master, read_fds, listener, fdmax, maxConecciones, puerto);    


	for (;;) 
	{
		*read_fds = *master; // copiarlo
		if (select(*fdmax + 1, read_fds, NULL, NULL, NULL ) == -1) {
			perror(" error en el select");
			break;
		}

		// explorar conexiones existentes en busca de datos que leer
		for (connectionIndex = 0; connectionIndex <= *fdmax; connectionIndex++) {
			if (FD_ISSET(connectionIndex, read_fds)) //tenemos datos!!
			{
				if (connectionIndex == *listener) 
				{
					// Handle new connections!
					handleConnection(&remoteaddr, *listener, fdmax, master);
				}
				else
				{					
					estadoDatosCliente = handleClientDataRecieved(connectionIndex, master,*fdmax, *listener, &datosRecibidos);						
					if(estadoDatosCliente != ERROR_RECEIVE_SERV)
					{
					  manejadorDeDatos(datosRecibidos, connectionIndex);
				          free(datosRecibidos.Payload);
					}
				}
			}
		}
	}    


  // Liberar los datos allocados. 
  free(listener);
  free(fdmax);
  free(master);
  free(read_fds);

}


// Gestionar nuevas conexiones
void handleConnection(struct sockaddr_in * remoteaddr,int listener, int * fdmax, fd_set * master)
{    
  int addrlen = sizeof(*remoteaddr);
  int newfd; // descriptor de socket de nueva conexión aceptada
  
  if ((newfd = accept(listener,(struct sockaddr*) remoteaddr, (socklen_t *) &addrlen)) == -1) 
  {
	  perror("accept");
  }
  else 
  {
	  FD_SET(newfd, master); // agregar al conjunto maestro
	  if (newfd > *fdmax)
	  {
		  // actualizar el maximo
		  *fdmax = newfd;
	  }
  }  

}

// Gestionar datos de un cliente
int handleClientDataRecieved(int cliente, fd_set * master, int fdmax, int listener, struct NIPC * datos)
{
  int nbytes;  
  char buffer[BUFFSIZE]; // buffer para datos del cliente	        
  char * orden;
  struct Paquete paqueteRecibido;     
  
  if ((nbytes = recv(cliente, buffer, BUFFSIZE, 0)) <= 0) 
  {
    // error o conexion cerrada por el cliente
    close(cliente);
    FD_CLR(cliente, master); // eliminar del conjunto maestro       
    return ERROR_RECEIVE_SERV;
  }
  else 
  { 
    // tenemos datos del cliente           
    orden = malloc(nbytes+1);
    memcpy(orden,buffer,nbytes);
    orden[nbytes] = '\0';    
    paqueteRecibido.Serializado = orden;
    paqueteRecibido.Length = nbytes;
    *datos = Deserializar(paqueteRecibido.Serializado); 
    free(orden);
  }
  
  return SUCCESS;  
}


/*
int mandarMensaje(char * mensaje,int tipoMensaje,int socket)
{
	struct Paquete recibido;
	struct NIPC paqueteAMandar; 		
	
	paqueteAMandar.Type = tipoMensaje;
	paqueteAMandar.Length = strlen(mensaje);
	paqueteAMandar.Payload = mensaje;
	recibido = Serializar(paqueteAMandar);
	if(send(socket,recibido.Serializado , recibido.Length , 0)== -1) 
	{	  
	  return ERROR_SEND;
	}
	
	return SUCCESS;
}
*/
// cierra la conexion y borra los conjuntos maestro y temporal
void cerrar_servidor(int socket, fd_set * master, fd_set * read_fds)
{
  close(socket); 
  FD_ZERO(master); 
  FD_ZERO(read_fds);
}<commit_msg>Correcciones de legibilidad:   - Indentación: 2 espacios en lugar de 4.   - Corchetes de funcion en su propia linea.   - Comentarios útiles.<commit_after>#include "servidor.h"

// Inicia el servidor con los parametros especificados.
int inicializar_servidor(fd_set * master, fd_set * read_fds, int * listener, int * fdmax,int max_conexiones, int puerto)
{

  struct sockaddr_in selfAddress;	
  int yes = 1;
			
  // Borra los conjuntos maestro y temporal						
  FD_ZERO(master); 
  FD_ZERO(read_fds); 
		
  // Obtener socket a la escucha
  if ((*listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  {
    return ERROR_SOCKET;		
  }
	
  // Obviar el mensaje "address already in use" (la direccion ya se esta usando)
  if (setsockopt(*listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))== -1)
  {
    return ADDR_IN_USE;
  }

  // Enlazar
  selfAddress.sin_family = AF_INET;
  selfAddress.sin_addr.s_addr = INADDR_ANY;
  selfAddress.sin_port = htons(puerto);
  memset(&(selfAddress.sin_zero), '\0', 8);

  if (bind(*listener, (struct sockaddr *) &selfAddress, sizeof(selfAddress)) == -1) 
  {
    return ERROR_BIND;
  }

  // Escuchar	
  if (listen(*listener, max_conexiones) == -1) 
  {
    return ERROR_LISTEN;
  }
	
  // Agregar listener al conjunto maestro.
  FD_SET(*listener, master);

  // Seguir la pista del descriptor de fichero mayor
  *fdmax = *listener;
	
  return SUCCESS;
}

// Ejecuta la logica del servidor, iterando infinitamente.
void servidor(void (*manejadorDeDatos)(struct NIPC datos, int socket), int puerto, int maxConecciones)
{  
	
  struct sockaddr_in remoteaddr;	
  int connectionIndex = 0;
  int estadoDatosCliente;
  struct NIPC datosRecibidos;			  

  int * listener = malloc(sizeof(int));
  int * fdmax = malloc(sizeof(int));
  fd_set * master = malloc(sizeof(fd_set));
  fd_set * read_fds = malloc(sizeof(fd_set));

  datosRecibidos.Length = 0;
  datosRecibidos.Payload = NULL;
  datosRecibidos.Type = 0;
      
  inicializar_servidor(master, read_fds, listener, fdmax, maxConecciones, puerto);    

  for (;;) 
  {

    *read_fds = *master; // Copiar conjunto maestro.
    if (select(*fdmax + 1, read_fds, NULL, NULL, NULL ) == -1)
    {
      perror(" error en el select");
      break;
    }
    
    // explorar conexiones existentes en busca de datos que leer
    for (connectionIndex = 0; connectionIndex <= *fdmax; connectionIndex++)
    {
      if (FD_ISSET(connectionIndex, read_fds)) //tenemos datos!!
      {
        if (connectionIndex == *listener) 
        {
          // Handle new connections!
          handleConnection(&remoteaddr, *listener, fdmax, master);
        }
        else
        {					
          estadoDatosCliente = handleClientDataRecieved(connectionIndex, master,*fdmax, *listener, &datosRecibidos); 						
          if(estadoDatosCliente != ERROR_RECEIVE_SERV)
          {
            manejadorDeDatos(datosRecibidos, connectionIndex);
            free(datosRecibidos.Payload);
          }
        }
      }
    }
  }
    
  // Cerrar la conexion en el socket de escucha (del servidor) y borrar los conjuntos maestro y temporal.
  close(*listener); 
  FD_ZERO(master); 
  FD_ZERO(read_fds);

  // Liberar los datos allocados. 
  free(listener);
  free(fdmax);
  free(master);
  free(read_fds);

}

// Gestionar nuevas conexiones
void handleConnection(struct sockaddr_in * remoteaddr,int listener, int * fdmax, fd_set * master)
{   
 
  int addrlen = sizeof(*remoteaddr);
  int newfd; // descriptor de socket de nueva conexión aceptada
  
  if ((newfd = accept(listener,(struct sockaddr*) remoteaddr, (socklen_t *) &addrlen)) == -1) 
  {
	  perror("accept");
  }
  else 
  {
    FD_SET(newfd, master); // Agregar descriptor al conjunto maestro.
    if (newfd > *fdmax)
    {
      // Actualizar el maximo.
      *fdmax = newfd;
    }
  }  
}

// Gestionar datos de un cliente
int handleClientDataRecieved(int cliente, fd_set * master, int fdmax, int listener, struct NIPC * datos)
{

  int nbytes;  
  char buffer[BUFFSIZE]; // buffer para datos del cliente	        
  char * orden;
  struct Paquete paqueteRecibido;     
  
  if ((nbytes = recv(cliente, buffer, BUFFSIZE, 0)) <= 0) 
  {
    // Error o conexion cerrada por el cliente.
    close(cliente);
    FD_CLR(cliente, master); // Eliminar del conjunto maestro 
      
    return ERROR_RECEIVE_SERV;
  }
  else 
  { 
    // Tenemos datos del cliente.           
    orden = malloc(nbytes+1);
    memcpy(orden,buffer,nbytes);
    orden[nbytes] = '\0';    
    paqueteRecibido.Serializado = orden;
    paqueteRecibido.Length = nbytes;
    *datos = Deserializar(paqueteRecibido.Serializado); 
    free(orden);
  }
  
  return SUCCESS;  
}

/*
int mandarMensaje(char * mensaje,int tipoMensaje,int socket)
{
  struct Paquete recibido;
  struct NIPC paqueteAMandar; 		

  paqueteAMandar.Type = tipoMensaje;
  paqueteAMandar.Length = strlen(mensaje);
  paqueteAMandar.Payload = mensaje;
  recibido = Serializar(paqueteAMandar);
  if(send(socket,recibido.Serializado , recibido.Length , 0)== -1) 
  {	  
    return ERROR_SEND;
  }
 
  return SUCCESS;
}
*/
{'fraction_non_alphanumeric': 0.11201381131309028, 'fraction_numerical': 0.004569919772519549, 'mean_word_length': 3.167583580194668, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5236368', 'n_tokens_mistral': 3796, 'n_tokens_neox': 3576, 'n_words': 825}