/* * File: bomberstudent_server.c * Author: Arthur Brandao * * Created on 14 novembre 2018 */ #include #include #include #include #include "arraylist.h" #include "bomberstudent_server.h" #include "error.h" /* --- Globale --- */ arraylist get; arraylist post; /* --- Fonctions privées --- */ /** * Thread de gestion d'un client * @param data * @return */ void* client_thread(void* data) { int* tmp, cliId, nbError = 0; Client* cli; //Recup la valeur de data tmp = (int*) data; cliId = *tmp; //Recup le client cli = get_client(cliId); if (cli == NULL) { adderror("Le client n'existe pas"); return NULL; } //Attente requete du client while (true) { if (!receive_client(cli)) { adderror("Erreur lors de la reception d'une requete du client"); nbError++; } else { nbError = 0; } //Si trop d'erreur d'affilé if (nbError == NBERRORRESET) { //Fermeture du client et fin du thread remove_client(cliId); break; } } return NULL; } void* udp_thread(void* data) { Server s; char buffer[BUFFER_SIZE]; //Cast data en serveur s = (Server) data; //Detache le thread if (pthread_detach(pthread_self()) != 0) { return NULL; } //Boucle attente while (true) { //Attente connexion if (s->server_receive(s, buffer, BUFFER_SIZE) == ERR) { addserror("Impossible de recevoir le demande de recherche"); continue; } //Si la phrase est correcte if (strncmp(buffer, SEARCH_SERV, strlen(buffer)) == 0) { if (!s->server_send(s, "i'm a bomberstudent server")) { addserror("Impossible de repondre à la recherche"); } } } return NULL; } void* tcp_thread(void* data) { Server* s; boolean res; int cliId; pthread_t client; //Cast data en serveur s = (Server*) data; //Detache le thread if (pthread_detach(pthread_self()) != 0) { return NULL; } //Boucle attente while (true) { res = s[0]->server_accept(s[0]); res = res && s[1]->server_accept(s[1]); if (!res) { addserror("Impossible d'etablir la connexion TCP"); continue; } //Creation d'un client et de son thread cliId = add_client(s[0], s[1]); if (pthread_create(&client, NULL, client_thread, &cliId) != 0) { adderror("Impossible de créer le thread CLient"); /*ToDo Avertir Client du probleme*/ } } return NULL; } /* --- Fonctions publiques --- */ void ini_server() { arraylist_ini(&get); arraylist_ini(&post); } void add_handler(char* method, char* ressource, int(*handler)(int, JsonParser*)) { if (strncmp(method, "POST", 5) == 0) { arraylist_add(&post, ressource, handler); } else if (strncmp(method, "POST", 5) == 0) { arraylist_add(&get, ressource, handler); } } boolean launch_udp_server(int port) { Server s; pthread_t udp; //Creation serveur s = server_create_udp(); if (s == NULL) { addserror("Impossible de créer le serveur UDP"); return false; } if (!s->server_bind(s, port)) { addserror("Impossible de bind le serveur UDP"); return false; } //Lancement thread serveur udp if (pthread_create(&udp, NULL, udp_thread, s) != 0) { adderror("Impossible de créer le thread UDP"); server_close(s); return false; } return true; } boolean launch_tcp_server(int port) { Server* s; pthread_t tcp; //Creation serveur s = malloc(sizeof (Server) * 2); s[0] = server_create_tcp(); s[1] = server_create_tcp(); if (s[0] == NULL || s[1] == NULL) { addserror("Impossible de créer les serveurs TCP"); return false; } if (!(s[0]->server_bind(s[0], port) && s[1]->server_bind(s[1], port + 1))) { addserror("Impossible de bind les serveurs TCP"); return false; } //Lancement Thread attente connexion TCP if (pthread_create(&tcp, NULL, tcp_thread, s) != 0) { adderror("Impossible de créer le thread TCP"); server_close(s[0]); server_close(s[1]); return false; } return true; } boolean receive_client(Client* cli) { char buffer[BUFFER_SIZE]; char* reader, * ressource, * json = NULL; int method, pos, compteur = 0; JsonParser* jp = NULL; arraylist* al = &get; //Attente reception printf("Ici\n"); if (cli->main->server_receive(cli->main, buffer, BUFFER_SIZE) == ERR) { addserror("Impossible de recevoire les données du client"); return false; } //Recup la methode if (buffer[0] == 'P') { pos = 5; reader = buffer + pos; method = POST; } else if (buffer[0] == 'G') { pos = 4; reader = buffer + pos; method = GET; } else { //Methode incorrect return false; } //Recup la ressource while (buffer[pos] != '\n' && buffer[pos] != '\0') { compteur++; pos++; } if (compteur == 0) { return false; } ressource = malloc(sizeof (char) * compteur); strncpy(ressource, reader, compteur); //Recup param JSON if (method == POST) { if (buffer[pos] == '\0') { //Pas de parametre avec le post return false; } json = reader + compteur + 1; jp = malloc(sizeof (JsonParser)); if (json_parse(jp, json) != JSON_OK) { return false; } //Change la liste à utiliser al = &post; } //Appel le callback if (arraylist_call(al, ressource, cli->id, jp) == ERR) { return false; } return true; } boolean send_client(Client* cli, JsonEncoder* answer); boolean notify_client(Client* cli, char* method, char* ressource, JsonEncoder* param);