void delete_user_from_users(int descriptor){
  int ret;
  ret= sem_wait(&users_sem);
  ERROR_HELPER(ret,"error on sem_wait to users_sem");
  int i;
  for(i=0; i<num_users; i++){
    if(users[i]->socket==descriptor){
      free(users[i]);
      for(;i<num_users-1; i++){
        users[i]= users[i+1];
      }
      break;
    }
  }
  if(i<num_users){
    printf("Utente elimato da array utenti");
    users[num_users-1]=NULL;
    num_users-=1;
    ret= sem_post(&users_sem);
    ERROR_HELPER(ret,"error on sem_post to users_sem");
    printf("\n");
    print_stats_users();
  }
  else{
    ret= sem_post(&users_sem);
    ERROR_HELPER(ret,"error on sem_post to users_sem");
    printf("Utente non ancora registrato. connessione chiusa\n");
  }

  close(descriptor);
}
Channel* add_lastChannel(Channel* channel,User* user){
  int i,ret;
  ret= sem_wait(&channels_sem);
  ERROR_HELPER(ret,"error on sem_wait to channels_sem");

  for(i=0; i<MAX_CHANNEL; i++){
    if(channels[i]==NULL){
      channels[i]= (Channel*) malloc (sizeof(Channel));
      memcpy(channels[i],channel,sizeof(Channel));
      user->user_channel=channels[i];
      Channel* temp=channels[i];
      num_channels++;
      ret= sem_post(&channels_sem);
      ERROR_HELPER(ret,"error on sem_post to channels_sem");

      printf("Lo user %s ha creato il canale %s\n",user->username,user->user_channel->channel_name );
      return temp;
    }
  }
  ret= sem_post(&channels_sem);
  ERROR_HELPER(ret,"error on sem_post to channels_sem");

  printf("Numero canali massimo superato\n");
  return NULL;
}
int delete_channel(Channel* ch,int descriptor){
  int ret;
  ret= sem_wait(&channels_sem);
  ERROR_HELPER(ret,"error on sem_wait to channels_sem");

  closed_by_admin(ch,descriptor);
  int i;
  for(i=0; i<num_channels; i++){
    if(strcmp(ch->channel_name,channels[i]->channel_name)==0){
      free(channels[i]);
      for(;i<num_channels-1; i++){
        channels[i]= channels[i+1];
      }
      num_channels-=1;
      channels[num_channels]= NULL;

      ret= sem_post(&channels_sem);
      ERROR_HELPER(ret,"error on sem_post to channels_sem");

      printf("Canale %s cancellato\n", ch->channel_name);
      print_stats_channels();
      return 1;
    }
  }
  ret= sem_post(&channels_sem);
  ERROR_HELPER(ret,"error on sem_post to channels_sem");
  return -1;
}
Channel* join_chat(User* user){
  int descriptor=user->socket;
  char buffer[BUFFER_SIZE];
  char str[BUFFER_SIZE];
  int ret;
  snprintf(str,sizeof(str),"%s",print_channel());
  int i,while_flag=1;

  while(while_flag){
  ret= send_message(descriptor,str,NULL);
  ret= receive_message(descriptor,buffer);

  if(buffer[0]=='$'){
    memset(buffer,0,sizeof(buffer));
    snprintf(buffer,sizeof(buffer),"%s",QUIT_CLIENT);
    send_message(user->socket,buffer,strlen(buffer));
    return NULL;
  }

  ret= sem_wait(&channels_sem);
  ERROR_HELPER(ret,"error on sem_wait to channels_sem");

  for(i=0; i<num_channels; i++){
    if(strcmp(buffer,channels[i]->channel_name)==0){
      while_flag=0;
      break;
    }
  }
  if(while_flag==0){
    memset(buffer,0,sizeof(buffer));
    memset(str,0,sizeof(str));
    break;
  }
  memset(str,0,sizeof(str));
  snprintf(str,sizeof(str),"%s",ERR_CHAT);
  strcat(str, print_channel());
  ret= sem_post(&channels_sem);
  ERROR_HELPER(ret,"error on sem_post to channels_sem");
  }

  channels[i]->subscribers[channels[i]->sub_num]= (User*) malloc(sizeof(User));
  memcpy(channels[i]->subscribers[channels[i]->sub_num],user,sizeof(User));
  channels[i]->sub_num+=1;
  user->user_channel= channels[i];
  printf("Aggiunto user %s con descrittore %d alla chat %s\n", channels[i]->subscribers[channels[i]->sub_num-1]->username,channels[i]->subscribers[channels[i]->sub_num-1]->socket,user->user_channel->channel_name);

  return channels[i];
}
//-----FUNCTIONS----
int already_exists(char buffer[]){
  int ret;

  ret= sem_wait(&channels_sem);
  ERROR_HELPER(ret,"error on sem_wait to channels_sem");

  int i;
  for(i=0;i<num_channels;i++){
    if(strcmp(channels[i]->channel_name,buffer)==0){
      snprintf(buffer,BUFFER_SIZE,"%s","Chat name already in use.Type another name.\n");
      ret= sem_post(&channels_sem);
      ERROR_HELPER(ret,"error on sem_post to channels_sem");

      return 1;
    }
  }
  ret= sem_post(&channels_sem);
  ERROR_HELPER(ret,"error on sem_post to channels_sem");

  return 0;
}
int add_lastUser(User* user){
  int ret;

  ret= sem_wait(&users_sem);
  ERROR_HELPER(ret,"error on sem_wait to users_sem");

  int i;
  for(i=0;i<MAX_USERS;i++){
    if(users[i]==NULL){
      users[i]= (User*) malloc(sizeof(User));
      memcpy(users[i],user,sizeof(User));
      num_users++;
      ret= sem_post(&users_sem);
      ERROR_HELPER(ret,"error on sem_post to users_sem");
      return i;
    }
  }
  ret= sem_post(&users_sem);
  ERROR_HELPER(ret,"error on sem_post to users_sem");
  printf("Numero utenti massimo superato\n" );
  return -1;
}
void delete_user_from_channel(int descriptor,Channel* channel){
  int ret;
  if(channel==NULL){
    printf("Utente in nessun canale.Connessione chiusa.\n");
    return;
  }
  ret= sem_wait(&channels_sem);
  ERROR_HELPER(ret,"error on sem_wait to channels_sem");

  if(isAdmin(descriptor,channel) && channel->sub_num>1){
    char buffer[BUFFER_SIZE];
    int descriptor= channel->subscribers[1]->socket;
    channel->admin= descriptor;
    memset(buffer,0, sizeof(buffer));
    snprintf(buffer,sizeof(buffer),"%s","You're the new admin of the chat.\n");
    send_message(descriptor,buffer,strlen(buffer));
  }

  int i;
  for(i=0; i<channel->sub_num; i++){
    if(channel->subscribers[i]->socket==descriptor){
      free(channel->subscribers[i]);
      for(;i<channel->sub_num-1; i++){
        channel->subscribers[i]= channel->subscribers[i+1];
      }
      break;
    }
  }
  channel->sub_num-=1;

  if(channel->sub_num==0) delete_channel_by_server(channel);
  ret= sem_post(&channels_sem);
  ERROR_HELPER(ret,"error on sem_post to channels_sem");

  printf("E' stato eseguito un delete_user\n\n");
  print_stats_channels();
}
int receive_message(int descriptor, char* buffer){

  memset(buffer,0,sizeof(buffer));
  int ret;
  while((ret= recv(descriptor, buffer, BUFFER_SIZE-1, MSG_NOSIGNAL))<=0){
    if (errno == EWOULDBLOCK || errno == EPIPE || ret==0){
      printf("RECV: User with descriptor %d has crashed. He will be deleted from everything\n",descriptor);
      delete_user_from_users(descriptor);
      delete_user_from_channel(descriptor,find_channel(descriptor));
      pthread_exit(NULL);
    }
    else if (errno == EINTR) continue;
    else ERROR_HELPER(ret,"error receiving from client");
  }
  buffer[ret]= '\0';
  printf("Ricevuto: %s da %d\n", buffer, descriptor);
  return ret;
}
int send_message(int descriptor, char* buffer, int size){
  int ret= BUFFER_SIZE;
  if(size!=NULL) ret= size+1;
  char msg[ret];
  snprintf(msg,sizeof(msg),"%s",buffer);

  size_t msg_size= strlen(buffer);
  while((ret= send(descriptor,msg,msg_size,MSG_NOSIGNAL))<=0){
    if (errno == EWOULDBLOCK || errno == EPIPE){
      printf("SEND: User with descriptor %d has crashed. He will be deleted from everything\n",descriptor);
      delete_user_from_users(descriptor);
      delete_user_from_channel(descriptor,find_channel(descriptor));
      return errno;
    }
    else if (errno == EINTR) continue;
    else ERROR_HELPER(ret,"Error with send function from server");
  }
  return ret;
}
Exemple #10
0
void chat_session(int socket_desc) {
    int ret;

    pthread_t chat_threads[2];

    ret = pthread_create(&chat_threads[0], NULL, receiveMessage, (void*)socket_desc);
    GENERIC_ERROR_HELPER(ret, ret, "Cannot create thread for receiving messages");

    ret = pthread_create(&chat_threads[1], NULL, sendMessage, (void*)socket_desc);
    GENERIC_ERROR_HELPER(ret, ret, "Cannot create thread for sending messages");

    // wait for termination
    ret = pthread_join(chat_threads[0], NULL);
    GENERIC_ERROR_HELPER(ret, ret, "Cannot join on thread for receiving messages");

    ret = pthread_join(chat_threads[1], NULL);
    GENERIC_ERROR_HELPER(ret, ret, "Cannot join on thread for sending messages");

    // close socket
    ret = close(socket_desc);
    ERROR_HELPER(ret, "Cannot close socket");
}
Exemple #11
0
void* invia(void* arg) {
    struct_arg_client* args = (struct_arg_client*) arg;

    int ret;
    char buf[1024];

    while (1) {
        //printf("send: ");
        fgets(buf, 1024, stdin); //fgets prende anche il carattere invio
        size_t buf_len = strlen(buf);
        
        if (buf_len == 1) continue;
        buf[buf_len - 1] = '\0';
        
        //--buf_len; // remove '\n' from the end of the message
        
        while ((ret = send(args->desc, buf, buf_len, 0)) < 0) {
            if (errno == EINTR) continue;
            if(ret==0) exit(0);
            ERROR_HELPER(-1, "Cannot write to the socket");
        }
 
    }
}
Exemple #12
0
int main(int argc, char **argv){
  //-----SIGNALS HANDLING---

  struct sigaction sigint, sighup, sigquit, sigsegv, sigterm, sigpipe;

  sigemptyset(&sigint.sa_mask);
  sigint.sa_handler= generic_handler;
  sigint.sa_flags= SA_SIGINFO;

  sigaction(SIGINT,&sigint,0);

  sigemptyset(&sigquit.sa_mask);
  sigquit.sa_handler= generic_handler;
  sigquit.sa_flags= SA_SIGINFO;

  sigaction(SIGQUIT,&sigquit,0);

  sigemptyset(&sighup.sa_mask);
  sighup.sa_handler= generic_handler;
  sighup.sa_flags= SA_SIGINFO;

  sigaction(SIGHUP,&sighup,0);


  sigemptyset(&sigsegv.sa_mask);
  sigsegv.sa_handler= generic_handler;
  sigsegv.sa_flags= SA_SIGINFO;

  sigaction(SIGSEGV,&sigsegv,0);


  sigemptyset(&sigterm.sa_mask);
  sigterm.sa_handler= generic_handler;
  sigterm.sa_flags= SA_SIGINFO;

  sigaction(SIGTERM,&sigterm,0);

  //-----------------------
  char buffer[BUFFER_SIZE];
  int ret;
  int receive_sock;
  struct sockaddr_in server;
  struct sockaddr_in client;
  pthread_t tid;
  //------------------------
  if (argc != 2) {
      printf("Sintassi: <port_number>\n");
      exit(EXIT_FAILURE);
  }

  num_users=0;
  num_channels=0;
  ret= sem_init(&users_sem,0,1);
  ret= sem_init(&channels_sem,0,1);
  ERROR_HELPER(ret, "error creating users semaphore");
  users=(User**) malloc(MAX_USERS*sizeof(User*));
  channels=(Channel**) malloc(MAX_CHANNEL*sizeof(Channel*));
  int i;
  for(i=0;i<MAX_USERS;i++){
    users[i]=NULL;
  }
  for(i=0;i<MAX_CHANNEL;i++){
    channels[i]=NULL;
  }
  long tmp= strtol(argv[1],NULL, 0);



  server_sock= socket(AF_INET, SOCK_STREAM,0);
  ERROR_HELPER(server_sock,"Error creating the socket");
  server.sin_family= AF_INET;
  server.sin_port= htons(tmp);
  server.sin_addr.s_addr= htonl(INADDR_ANY);
  int true = 1;
  setsockopt(server_sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int));
  struct timeval timeout;
  timeout.tv_sec= 300;
  timeout.tv_usec= 0;

  ret= bind(server_sock,(struct sockaddr*) &server,sizeof(server));
  ERROR_HELPER(ret,"Error binding the socket");

  ret= listen(server_sock,BACKLOG);
  ERROR_HELPER(ret,"Error in listen");

  int size_client= sizeof(client);
  printf("Server running...\n");

  while(1){
    if( (receive_sock= accept(server_sock,(struct sockaddr *)&client,&size_client)) <0){
      if(errno==EINTR) continue;
      else ERROR_HELPER(receive_sock,"Error while accept");
    }

    if(setsockopt(receive_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout))<0){
      printf("errore sock option rcvtimeo\n");
      exit(EXIT_FAILURE);
    }

    Params* tmp= (Params*) malloc(sizeof(Params));
    tmp->descriptor= receive_sock;
    inet_ntop(AF_INET, &(client.sin_addr), tmp->address, INET_ADDRSTRLEN);
    ret= pthread_create(&tid,NULL,init_chat,(void*) tmp);
    ERROR_HELPER(ret,"Error creating the thread");
    pthread_detach(tid);
  }

  return 0;

}
Exemple #13
0
void* init_chat(void* in){

  int ret;

  Params* parameters= (Params*) malloc(sizeof(Params));
  parameters= (Params*) in;

  int descriptor= parameters->descriptor;
  char address[INET_ADDRSTRLEN];
  char buffer[BUFFER_SIZE];

  snprintf(address,sizeof(address),"%s",parameters->address);
  snprintf(buffer,sizeof(buffer),"%s\n",WELCOME_MESSAGE);

  do{
    ret= send_message(descriptor,buffer,NULL);
    ret= receive_message(descriptor,buffer);
    if(buffer[0]=='\n' || strlen(buffer)==0 || strlen(buffer)>USERNAME_LENGTH)
    snprintf(buffer,sizeof(buffer),"%s\n","Not valid username! It has to be at least 1 character and at last 20 characters long\n");
    else if(strcmp(buffer,QUIT_COMMAND)==0){
      send_message(descriptor,QUIT_INIT,strlen(QUIT_INIT));
      ERROR_HELPER(ret,"error with sem_post in init_chat");
      pthread_exit(NULL);
    }
    else break;
  } while(1);

  User* tmp_us= createUser(buffer,descriptor,address);
  ret=add_lastUser(tmp_us);

  if(ret==-1){
    snprintf(buffer,sizeof(buffer),"%s","Chat is full.Try again later :(");
    send_message(descriptor,buffer,strlen(buffer));
    close(descriptor);
    pthread_exit(NULL);
  }

  printf("Utente %s creato e ret è %d\n", users[ret]->username,ret);

  while(1){
    int user_input= choose_operation(tmp_us);
    ERROR_HELPER(user_input,"errore choose operation");

    switch (user_input) {
      case 0:
        print_stats_users();
        Channel* tmp_ch=join_chat(tmp_us);
        ret= sem_post(&channels_sem);
        ERROR_HELPER(ret,"error on sem_post to channels_sem");

        print_stats_channels();
        if(tmp_ch==NULL){
          ERROR_HELPER(ret,"error on sem_post to channels_sem");

          break;
        }
        snprintf(buffer,sizeof(buffer),"%s","You joined the chat. Type and press ENTER to send messages to the others!\n");
        send_message(descriptor,buffer,NULL);
        memset(buffer,0,sizeof(buffer));
        snprintf(buffer,BUFFER_SIZE,"%s joined the chat\n",tmp_us->username);
        send_all(tmp_ch,tmp_us,buffer);
        chat_handler(tmp_ch,tmp_us);
        break;

      case 1:

        memset(buffer,0,sizeof(buffer));
        snprintf(buffer,sizeof(buffer),"%s","\nType the name of your new chat.:\n");
        do{
          ret= send_message(descriptor,buffer,NULL);
          ret= receive_message(descriptor,buffer);
          if(buffer[0]=='$'){
            ret=cmd_check(buffer,tmp_us);
            if(ret==QUIT_RET) break;
          }
        }
        while(already_exists(buffer));
        if(ret==QUIT_RET) break;
        Channel* temp_ch= createChannel(buffer, tmp_us);
        printf("canale %s creato e l'admin è %d\n", temp_ch->channel_name, temp_ch->admin);
        memset(buffer,0,sizeof(buffer));
        snprintf(buffer,sizeof(buffer),"%s","\nYou are in your new chat. Type and press ENTER to send messages to the others!\n\n");
        ret= send_message(descriptor,buffer,NULL);
        memset(buffer,0,sizeof(buffer));

        Channel* last_channel= add_lastChannel(temp_ch,tmp_us);
        if(last_channel==NULL){
          snprintf(buffer,sizeof(buffer),"%s","Chat are full right now. Do you want to continue using the chat? (y/n) ");
          send_message(descriptor,buffer,strlen(buffer));
          break;
        }

        chat_handler(last_channel,tmp_us);
        break;
      case 2:
        memset(buffer,0,sizeof(buffer));
        snprintf(buffer,sizeof(buffer),"%s",QUIT_INIT);
        send_message(tmp_us->socket,buffer,strlen(buffer));
        delete_user_from_users(tmp_us->socket);
        pthread_exit(NULL);
        break;
    }
    do{
      ret= receive_message(descriptor,buffer);
      if(strlen(buffer)==1){
        if(buffer[0]=='n'){
          send_message(descriptor,QUIT_INIT,strlen(QUIT_INIT));
          delete_user_from_users(descriptor);
          pthread_exit(NULL);
        }
        if(buffer[0]=='y') break;
      }
      snprintf(buffer,sizeof(buffer),"%s","Invalid input: choose between y or n!\n");
      send_message(descriptor,buffer,strlen(buffer));
    }while(1);
  }
  send_message(descriptor,QUIT_INIT,strlen(QUIT_INIT));
  delete_user_from_users(descriptor);
  pthread_exit(NULL);
}
Exemple #14
0
int main(int argc, char* argv[]) {
    int ret;

    void* res1;

    // variables for handling a socket
    int socket_desc;
    struct sockaddr_in server_addr = {0}; // some fields are required to be filled with 0

    // create a socket
    socket_desc = socket(AF_INET, SOCK_STREAM, 0);
    ERROR_HELPER(socket_desc, "Could not create socket");

    // set up parameters for the connection
    server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT); // don't forget about network byte order!

    // initiate a connection on the socket
    ret = connect(socket_desc, (struct sockaddr*) &server_addr, sizeof (struct sockaddr_in));
    ERROR_HELPER(ret, "Could not create connection");
    if (DEBUG) fprintf(stderr, "Connection established!\n");
    printf("/create or /join <name_channel>\n");


    //thread dedicato per la rcv
    pthread_t thread_rcv;

    // put arguments for the new thread into a buffer
    struct_arg_client* thread_rcv_args = (struct_arg_client*) malloc(sizeof (struct_arg_client));
    thread_rcv_args -> desc = socket_desc;

    if (pthread_create(&thread_rcv, NULL, ricevi, (void*) thread_rcv_args) != 0) {
        fprintf(stderr, "Can't create a new thread, error %d\n", errno);
        exit(EXIT_FAILURE);
    }

    //thread dedicato per la send
    pthread_t thread_send;

    // put arguments for the new thread into a buffer
    struct_arg_client* thread_send_args = (struct_arg_client*) malloc(sizeof (struct_arg_client));
    thread_send_args -> desc = socket_desc;

    if (pthread_create(&thread_send, NULL, invia, (void*) thread_send_args) != 0) {
        fprintf(stderr, "Can't create a new thread, error %d\n", errno);
        exit(EXIT_FAILURE);
    }


    pthread_join(thread_rcv, &res1);

    //printf("Joined thread1 computing send work and thread2 computing rcv work.\nTotal bytes sent: %d bytes\nTotal bytes received: %d bytes\n", (unsigned int) res1, (unsigned int) res2);

    printf("Finished my job, received %d bytes\n", (unsigned int) res1);
    // close the socket
    ret = close(socket_desc);
    ERROR_HELPER(ret, "Cannot close socket");

    if (DEBUG) fprintf(stderr, "Exiting...\n");

    exit(EXIT_SUCCESS);

}