312 lines
9.7 KiB
C++
312 lines
9.7 KiB
C++
#include "server.hh"
|
|
|
|
|
|
|
|
/* Transforme un string en un type différent */
|
|
template <class T>
|
|
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<string>();
|
|
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<string>();
|
|
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<string>();
|
|
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<string>() << "'";
|
|
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<string>());
|
|
else pos.makeTopologyFromDb(conn);
|
|
|
|
/* Création de la liste des points de passage */
|
|
if (vm.count("input-waypoint")) pos.makeWaypointListFromFile(vm["input-waypoint"].as<string>());
|
|
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<string>(), 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<string>()) ;
|
|
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<int>(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<int>(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);
|
|
}
|