Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: alcatraz en 11 Junio 2010, 15:35 pm



Título: Servidor SSL con Pthreads
Publicado por: alcatraz en 11 Junio 2010, 15:35 pm
Hola, estaba haciendo un pequeño servidor SSL que pudiese atender a multiples clientes a la vez. Cogí un ejemplo que encontre por internet y trabaje sobre el:
Código:
#define NUM_THREADS 5


//−−− S e r v i d o r −−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−
// R e a l i z a r e l p r o c e d i m i e n t o s e r v i c i o −−−−−−−−−−−−−−−

void *Servidor(void *threadarg){
      char buf[1024];
      char reply[1024];
      int sd, bytes;
      const char* HTMLecho="Esto solo es el mensaje de mi servidor SSL multihilo";


       

     // Estructura donde se guardan los parametros de los threads
      struct thread_data *my_data;
      int taskid;
      // Parser de los datos de la estructura a variables
      my_data=(struct thread_data*)threadarg;
      taskid=my_data->thread_id;
      SSL *ssl=my_data->message;

      HTMLecho=my_data->reto;

      printf("Inicia Servidor\n");
      if(SSL_accept(ssl)==FAIL){
               printf("Hubo un error en el SSL accept\n");
               ERR_print_errors_fp(stderr);
      } else{
               printf("SSL accept fue exitoso\n");
               //MostrarCertificados(ssl);
               bytes=SSL_read(ssl,buf,sizeof(buf));
               if(bytes>0){
                       buf[bytes]=0;
                       printf("Mensaje cliente [%d]: %s\n", taskid,buf);


                       sprintf(reply,HTMLecho,buf);
                 sleep (30);

                       //SSL_write(ssl,reply,strlen(reply));
SSL_write(ssl,reply,20);
               }
               else
                       ERR_print_errors_fp(stderr);
      }
      sd=SSL_get_fd(ssl);
      SSL_free(ssl);
      close(sd);
}


//−−− Main −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
// Se e n c a r g a de c r e a r e l s e r v i d o r


int main(int count, char *strings[]){
     //Arreglo de hilos
     pthread_t threads[NUM_THREADS];
     struct thread_data thread_data_array[NUM_THREADS];
     int t=0;
     int rc;
     SSL_CTX *ctx;
     int server;
     char *portnum;
     SSL_library_init();
     if(count!= 2){
             printf("Uso : %s <portnum>\n", strings[0]);
             exit(0);
     }

//Genero el reto
printf("Generando reto...\n");
   /* Longitud del reto */
unsigned short int length = 20;
char reto[20];
    /* Seed number for rand() */
srand((unsigned int) time(0) + getpid());
    /* ASCII characters 33 to 126 */
int aux=0;
    while(length--) {
        reto[aux]=putchar(rand() % 94 + 33);
        srand(rand());
aux++;
    }
reto[aux]='\0';
    printf("\n");
//imprimirReto(reto);
const char* HTMLecho;
HTMLecho=reto;


     portnum = strings [1];
     ctx=IniciarCTXServidor();
     CargarCertificados(ctx,"/home/xabi/Escritorio/examples/ssl/proyecto/certificados/servidor/server.crt","/home/xabi/Escritorio/examples/ssl/proyecto/certificados/servidor/server.key");//Certificado y clave
     server=CrearSocket(atoi(portnum));
     printf("Esperando por conexiones[%d]\n", server);
     printf("Inicia a aceptar conexiones\n");
     while(1){
         struct sockaddr_in addr;
         SSL *ssl;
             int len=sizeof(addr);
             int client=accept(server,(struct sockaddr*)&addr,&len);
             printf("Connection: %d %d\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
             ssl=SSL_new(ctx);
         // Se crea contexto
             SSL_set_fd(ssl,client);
       t++;
             // Se da numero de pthread
       thread_data_array[t].thread_id=t;
       // Se le da el id del thread al thread
           thread_data_array[t].message=ssl;
       // Se le da el asigna el contexto de la conexion al thread


     thread_data_array[t].reto=(char *)HTMLecho;

             rc=pthread_create(&threads[t],NULL,Servidor,(void *)&thread_data_array[t]);
             // Se crea el hilo y se le manda la estructura llenada previamente


if(t==NUM_THREADS){ //DUDA!!!!!!!!!
sleep(5);
t=0;
}

  }
  close(server);
  SSL_CTX_free(ctx);
}


Como veis para cada peticion que llega crea un hilo que atiende esta petición y tengo definido un máximo de 5 peticiones. De esta forma funcionaba, pero después de la 5 petcion , al llegar la 6 lógicaente da un error de segmentacion. Así que decidi poner, si llega a la 5 petición pongo el contador a 0 y que siga creando hilos, perono estoy seguro de que este bien ya que vuelvo a crear un hilo con id=0 por ejemplo igual que el otro hilo id=0 que no se si acabo o no y supongo que puede darme problemas de concurrecia en el futuro.

Alguna idea de como mejorar esto? Gracias