#include "socktools.h"
#include <unistd.h>
#include <pthread.h>
#include <string.h>

extern int PORT, NMAX;

static int somme  = 0, nbproc=0;

pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

typedef struct loft {
  pthread_t t;
  struct loft * next;
} *threadlist, threadenr;

threadlist actifs = NULL;

void  newthread ( void )
{ threadlist aux;
  aux = (threadlist) malloc( sizeof( threadenr ) );
  aux->next = actifs;
  actifs = aux;
}

void delthread ( void )
{ threadlist aux;
  aux = actifs;
  actifs = aux->next;
  free(aux);
}



void* tache( void * parms);

typedef struct task {
  int val;
  struct sockaddr client;
} argtask;

void* tache( void * parms)
{ int sd, res;
  argtask arg; 
  arg = *( ( argtask *) parms ); 
  sd = socket( AF_INET, SOCK_DGRAM, 0);
  printfrom( &arg.client );
  printf(" thread  sub->%d", arg.val);
  fflush(stdout);
  sendpaquetto( sd,  & arg.client, arg.val);
  res = recvpaquetfrom( sd, & arg.client );
  pthread_mutex_lock( & mymutex );
  somme += res;
  nbproc--;
  pthread_mutex_unlock( & mymutex );
  pthread_exit( NULL );
}

void sdcnet( int sd, int n )
{ int ret, val;
  struct task arg; 
  while ( n ) {
    val = recvpaquetfrom( sd, & arg.client ); 
    arg.val = n;
    pthread_mutex_lock( & mymutex );
    nbproc++;
    printf("\nval=%d actif=%d", n, nbproc);
    pthread_mutex_unlock( & mymutex );
    newthread();
    ret = pthread_create( & (actifs->t) , NULL, tache, (void *) & arg );
    if ( ret ) erreur("thread");
    n = n - 1;
  }
  while ( actifs ) {
    pthread_join( actifs->t , NULL);
    delthread();
  }
}


int main(int argc, char *argv[])
{ int   sd;
  struct sockaddr_in serv; 
  
  if ( ! argok( argc, argv ) ) return 1;

  sd = socket( AF_INET, SOCK_DGRAM, 0);
  if ( sd < 0 ) erreur("socket");

  serv = sockaddrinlocal( PORT );
  if ( bind( sd, (struct sockaddr *) &serv, sizeof(serv)) < 0 )
    erreur("bind");

  sdcnet( sd , NMAX);
  printf("\nSomme %d premiers carres : %d", NMAX, somme);
  close(sd);
  return 0;
}
