#include "server.hh" /* Transforme un string en un type différent */ template inline T from_string(const string &s) { T t; istringstream iss(s); iss >> t; return t; } /* Initialisation du serveur */ int Server::init(const boost::program_options::variables_map vm) { ostringstream oss; string buf; /* Connexion à la BdD */ oss << "hostaddr = '"; if (vm.count("db.host")) // Recherche du nom de l'hôte de la BdD oss << vm["db.host"].as(); else { cerr << "Attention ! Hôte de la BDD non spécifié, utilisation de la valeur par défaut..." << endl ; oss << DEFAULT_BDD_HOST; } oss << "' dbname = '"; if (vm.count("db.name")) // Recherche du nom de la BdD oss << vm["db.name"].as(); else { cerr << "Attention ! Nom de la BDD non spécifié, utilisation de la valeur par défaut..." << endl ; oss << DEFAULT_BDD_NAME; } oss << "' user = '"; if (vm.count("db.user")) // Recherche du nom d'utilisateur de la BdD oss << vm["db.user"].as(); else { cerr << "Attention ! Utilisateur non spécifié pour la connexion à la BDD, utilisation de la valeur par défaut..." << endl ; oss << DEFAULT_BDD_USER; } oss << "' password = '"; if (vm.count("db.passwd")) // Recherche du mot de passe oss << vm["db.passwd"].as() << "'"; else { cerr << "Attention ! Mot de passe non spécifié pour la connexion à la BDD, utilisation de la valeur par défaut..." << endl ; oss << DEFAULT_BDD_PASS << "'"; } buf = oss.str(); const char *conninfo = buf.c_str(); conn = PQconnectdb(conninfo); if (PQstatus(conn) != CONNECTION_OK) { cout << "Erreur ! Connexion à la base de donnée échouée : " << PQerrorMessage(conn) << endl; return 1; } /* Création de la topology */ if (vm.count("input-topo")) pos.makeTopologyFromFile(vm["input-topo"].as()); else pos.makeTopologyFromDb(conn); /* Création de la liste des points de passage */ if (vm.count("input-waypoint")) pos.makeWaypointListFromFile(vm["input-waypoint"].as()); else pos.makeWaypointListFromDb(conn); /* Création de la liste des points de référence */ if (vm.count("input-refpoint")) pos.makeReferencePointListFromFile(vm["input-refpoint"].as(), true); else pos.makeReferencePointListFromDb(conn, true); if (!pos.checkTopology()) { cerr << "Erreur lors de la création de la topologie !" << endl; return 1; } pos.makeReferencePointDistances(); /* Création de la liste des Access Point */ if (vm.count("input-ap")) pos.makeApListFromFile(vm["input-ap"].as()) ; else pos.makeApListFromDb(conn) ; return 0; } int Server::start() { struct sockaddr_in serv_addr; struct sockaddr_in client; socklen_t client_len = sizeof(client); Point solution; char *mac = (char *) malloc(18 * sizeof(char)); /* Création d'une socket UDP */ listen_socket = socket(AF_INET, SOCK_DGRAM, 0) ; if (listen_socket < 0) { cerr << "Échec de la création de la socket " << endl; exit(1); } /* Remise à zéro et initialisation de la structure du serveur */ bzero((char *) &serv_addr, sizeof(serv_addr)) ; // RÀZ serv_addr.sin_family = AF_INET ; // Socket INET serv_addr.sin_addr.s_addr = htonl(INADDR_ANY) ; // Toutes les connexions sont acceptées serv_addr.sin_port = htons(listen_port) ; // Port d'écoute /* Réservation du port */ if (bind(listen_socket, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { cerr << "Impossible de créer la socket (bind) " << endl; close(listen_socket) ; exit(1); } cout << "Serveur prêt" << endl; /* Récupération des données envoyées par le client */ while (true) { /* Attente d'une demande d'un serveur d'aggrégation */ if (recvfrom(listen_socket, &att_request, sizeof(att_request), 0, (struct sockaddr *) &client, &client_len) < 0) { cerr << "Aucun message reçu du client" << endl; close(listen_socket); return 1; } recv_info.resize(att_request.nb_couples); sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", att_request.mobile_mac_addr_bytes[0],att_request.mobile_mac_addr_bytes[1], att_request.mobile_mac_addr_bytes[2],att_request.mobile_mac_addr_bytes[3], att_request.mobile_mac_addr_bytes[4],att_request.mobile_mac_addr_bytes[5]); cout << "\n*** Message reçu de l'aggregator ***" << endl; cout << "\tMAC Mobile\t: " << mac << endl; cout << "\tHeure de la demande\t: " << timeval_to_ms(att_request.request_time) << endl; cout << "\tNombre de couples\t: " << att_request.nb_couples << endl; /* Récupération des couples (AP;Puissance) */ for (int i = 0; i < att_request.nb_couples; i++) recvfrom(listen_socket, &recv_info.at(i), sizeof(couple_info), 0, (struct sockaddr *) &client, &client_len); treatment(); recv_info.clear(); } } /* Calcul de la position avec les différents algo */ void Server::treatment() { Point solution; int id_request; // Permet de récupérer l'id de la requête pour lui assigner les résultats char *mac = (char *) malloc(18 * sizeof(char)); ostringstream oss; PGresult *res; /* */ Treatment treat(pos.getAccessPointList(), pos.getReferencePointList()); treat.makeMeasurementList(recv_info); sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", att_request.mobile_mac_addr_bytes[0],att_request.mobile_mac_addr_bytes[1], att_request.mobile_mac_addr_bytes[2],att_request.mobile_mac_addr_bytes[3], att_request.mobile_mac_addr_bytes[4],att_request.mobile_mac_addr_bytes[5]); oss << "SELECT r.id_request FROM request r, mobile m "; oss << "WHERE r.mobile_time = " << timeval_to_ms(att_request.request_time); oss << " AND m.id_mobile = r.id_mobile"; oss << " AND m.mobile_addr = '" << mac << "';"; // On recherche dans la BdD la requête consernée res = PQexec(conn, oss.str().c_str()); id_request = (PQntuples(res) != 0)? from_string(PQgetvalue(res, PQntuples(res) - 1, 0)): -1; // On conserve l'id de la requête PQclear(res); /* Interlink Networks */ solution = treat.interlink(0) ; createResult(solution, id_request, "Interlink Network"); /* RADAR */ solution = treat.getkClosestInSs(1, NULL)[0] ; createResult(solution, id_request, "Radar"); /* FBCM */ solution = treat.fbcm(0) ; createResult(solution, id_request, "FCBM"); /* 1-NSS + FBCM */ solution = treat.getkClosestInSs(1, NULL)[0] ; solution = treat.fbcm_friis(treat.computeFriisFromRefList(solution), solution.getZ()) ; createResult(solution, id_request, "1-NSS + FBCM"); /* 2-NSS */ solution = treat.getkWeightedInSs(2, NULL); createResult(solution, id_request, "2-NSS"); /* 3-NSS */ solution = treat.getkWeightedInSs(3, NULL); createResult(solution, id_request, "3-NSS"); /* 5-NSS */ solution = treat.getkWeightedInSs(5, NULL); createResult(solution, id_request, "5-NSS"); sendToClient(solution, mac); free(mac); } /* Enregistrement du résultat dans la BdD */ void Server::createResult(Point solution, int id_request, string use_algo) { int id_result; string buf; ostringstream oss; struct timeval current; PGresult *res; gettimeofday(¤t, NULL); // On récupère l'heure du calcul buf = "SELECT * FROM result;"; res = PQexec(conn, buf.c_str()); id_result = (PQntuples(res) != 0)? from_string(PQgetvalue(res, PQntuples(res) - 1, 0)) + 1: 1; oss << "INSERT INTO result(id_result, x, y, z, calcul_date, using_algo"; if (id_request != -1) oss << ", id_request"; // Si la requête n'a pas été trouvé, on enregistre le résultat mais sans associé de requête oss << ") VALUES('"; oss << id_result << "','" << solution.getX() << "','" << solution.getY() << "','" << solution.getZ(); oss << "','" << timeval_to_ms(current) << "','" << use_algo; if (id_request != -1) oss << "','" << id_request; oss << "');"; PQexec(conn, oss.str().c_str()); PQclear(res); } void Server::sendToClient(Point solution, char *mac) { int sockfd ; // Descripteur de la socket struct sockaddr_in serv; struct sockaddr_in mobile; socklen_t mobile_len = sizeof(mobile); ostringstream oss; float x,y,z; PGresult *res; oss << "SELECT ip_mobile FROM mobile "; oss << "WHERE mobile_addr = '" << mac << "';"; // On récupére l'adresse IP du mobile res = PQexec(conn, oss.str().c_str()); if (PQntuples(res) != 0) { /* Ceation de la socket UDP */ sockfd = socket(AF_INET, SOCK_DGRAM, 0) ; if (sockfd < 0) { cerr << "Échec de la création de la socket " << endl; exit(1); } /* Remise à zéro et initialisation de la structure du server */ bzero((char *) &serv, sizeof(serv)) ; serv.sin_family = AF_INET ; // Socket INET serv.sin_addr.s_addr = htonl(INADDR_ANY) ; // Toutes les connexions /* Remise à zéro et initialisation de la structure du mobile */ bzero((char *) &mobile, sizeof(mobile)) ; // RÀZ mobile.sin_family = AF_INET ; // Socket INET mobile.sin_addr.s_addr = inet_addr(PQgetvalue(res, 0, 0)) ; mobile.sin_port = htons(mobile_port) ; x = solution.getX(); y = solution.getY(); z = solution.getZ(); /* On envoie les coordonnées de la position */ sendto(sockfd, (void *)&x, sizeof(float), 0, (struct sockaddr *)&mobile, mobile_len); sendto(sockfd, (void *)&y, sizeof(float), 0, (struct sockaddr *)&mobile, mobile_len); sendto(sockfd, (void *)&z, sizeof(float), 0, (struct sockaddr *)&mobile, mobile_len); close(sockfd); cout << "Envoi de la position au client " << mac << " à l'adresse IP " << PQgetvalue(res, 0, 0) << endl; } PQclear(res); }