owlps/owlps-positioning/server.cc

281 lines
8.1 KiB
C++

#include "server.hh"
template <class T>
inline T from_string(const string &s)
{
T t;
istringstream iss(s);
iss >> t;
return t;
}
int Server::init(const boost::program_options::variables_map vm)
{
ostringstream oss;
string buf;
oss << "hostaddr = '";
if (vm.count("BDD.hostaddr"))
oss << vm["BDD.hostaddr"].as<string>();
else
oss << DEFAULT_BDD_HOST;
oss << "' dbname = '";
if (vm.count("BDD.name"))
oss << vm["BDD.name"].as<string>();
else
oss << DEFAULT_BDD_NAME;
oss << "' user = '";
if (vm.count("BDD.user"))
oss << vm["BDD.user"].as<string>();
else
oss << DEFAULT_BDD_USER;
oss << "' password = '";
if (vm.count("BDD.passwd"))
oss << vm["BDD.passwd"].as<string>() << "'";
else
oss << DEFAULT_BDD_PASS << "'";
buf = oss.str();
const char *conninfo = buf.c_str();
conn = PQconnectdb(conninfo);
if (PQstatus(conn) != CONNECTION_OK)
{
cout << "Connection à la base de donnée échouée: " << PQerrorMessage(conn) << endl;
return 1;
}
if (vm.count("input-topo")) pos.makeTopologyFromFile(vm["input-topo"].as<string>());
else pos.makeTopologyFromDb(conn);
if (vm.count("input-waypoint")) pos.makeWaypointListFromFile(vm["input-waypoint"].as<string>());
else pos.makeWaypointListFromDb(conn);
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 topology" << endl;
return 1;
}
pos.makeReferencePointDistances();
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)
{
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;
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();
}
}
void Server::treatment()
{
Point solution;
int id_request;
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 << "';";
res = PQexec(conn, oss.str().c_str());
id_request = (PQntuples(res) != 0)? from_string<int>(PQgetvalue(res, PQntuples(res) - 1, 0)): 0;
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);
}
void Server::createResult(Point solution, int id_request, string use_algo)
{
int id_result;
string buf;
ostringstream oss;
struct timeval current;
PGresult *res;
gettimeofday(&current, NULL);
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 != 0) oss << ", id_request";
oss << ") VALUES('";
oss << id_result << "','" << solution.getX() << "','" << solution.getY() << "','" << solution.getZ();
oss << "','" << timeval_to_ms(current) << "','" << use_algo;
if (id_request != 0) 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 << "';";
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();
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);
}