#include "inputudpsocket.hh" #include "posexcept.hh" #include "stock.hh" #include "configuration.hh" #include #include #include // For perror() #include using namespace std ; using std::tr1::unordered_map ; /* *** Constructors *** */ InputUDPSocket::InputUDPSocket(const uint_fast16_t _port): listening_port(_port) { if (! init_socket()) throw error_opening_input_file("UDP socket") ; } InputUDPSocket::~InputUDPSocket() { close_socket() ; } /* *** Operations *** */ /** * @return \em true if the socket were successfully opened. * @return \em false in case of error. */ bool InputUDPSocket::init_socket() { sockfd = owl_create_udp_listening_socket(listening_port) ; return sockfd >= 0 ; } /** * Normally, the socket is closed automatically by the destructor. Use * this if you want to close the socket prematurely. * #sockfd is set to -1, even in case of error. * @return \em true if the socket were successfully closed or were not * opened. * @return \em false in case of error. */ bool InputUDPSocket::close_socket() { if (sockfd >= 0) { if (close(sockfd)) { perror("Cannot close UDP socket") ; return false ; } sockfd = -1 ; } return true ; } /** * This function fills the current Request from the UDP input socket. * * @returns \em true if #current_request was correctly filled. * @returns \em false in case of error (socket not opened, bad packet * format). */ bool InputUDPSocket::fill_current_request() { if (eof()) return false ; struct sockaddr_in client; // UDP client structure socklen_t client_len = sizeof(client) ; // Size of clients // Read the main request data owl_request request ; ssize_t nread = recvfrom(sockfd, &request, sizeof(request), 0, (struct sockaddr *) &client, &client_len) ; if (nread <= 0) { cerr << "InputUDPSocket: No request received!" << endl ; return false ; } // Endianess conversions request.request_time = owl_ntoh_timestamp(request.request_time) ; request.nb_info = ntohs(request.nb_info) ; request.x_position = owl_ntohf(request.x_position) ; request.y_position = owl_ntohf(request.y_position) ; request.z_position = owl_ntohf(request.z_position) ; // Mobile MAC string mac_mobile( owl_mac_bytes_to_string(request.mobile_mac_addr_bytes)) ; PosUtil::to_upper(mac_mobile) ; // Display request's info if (Configuration::is_configured("verbose")) cout << "*** Request received from the aggregator ***" << "\n\tType: " << static_cast(request.type) << "\n\tMobile MAC: " << mac_mobile << "\n\tRequest timestamp: " << Timestamp(request.request_time) << "\n\tPosition X: " << request.x_position << "\n\tPosition Y: " << request.y_position << "\n\tPosition Z: " << request.z_position << "\n\tDirection: " << static_cast(request.direction) << "\n\tNumber of SS: " << request.nb_info << '\n' ; // Mobile MAC (continued) if (! Configuration::bool_value("positioning.accept-new-mobiles") && ! Stock::mobile_exists(mac_mobile)) { if (Configuration::is_configured("verbose")) cout << "Dropping request from unknown mobile " << mac_mobile << ".\n" ; return false ; } const Mobile &mobile = Stock::find_create_mobile(mac_mobile) ; current_request->set_mobile(&mobile) ; // Request type current_request->set_type(request.type) ; // Timestamp current_request->set_time_sent(Timestamp(request.request_time)) ; // Position Point3D position(request.x_position, request.y_position, request.z_position) ; // Read the {MAC_AP;SS} couples (request_info) unordered_map measurements ; owl_request_info request_info ; for (int i = 0 ; i < request.nb_info ; ++i) { nread = recvfrom(sockfd, &request_info, sizeof(request_info), 0, (struct sockaddr *) &client, &client_len) ; if (nread <= 0) { cerr << "No request info received!" << endl ; return false ; } string mac_ap( owl_mac_bytes_to_string(request_info.ap_mac_addr_bytes)) ; PosUtil::to_upper(mac_ap) ; // Substracting 256 is not mandatory here since it is done // automatically when casting from unsigned to signed, but // I write it anyway for the sake of clarity. int_fast8_t ss = request_info.ss_dbm - 0x100 ; if (Configuration::is_configured("verbose")) cout << "\t* Packet received from the aggregator:" << "\n\t\tAP MAC: " << mac_ap << "\n\t\tSignal: " << static_cast(ss) << " dBm" << '\n' ; if (! Configuration::bool_value("positioning.accept-new-aps") && ! Stock::ap_exists(mac_ap)) { if (Configuration::is_configured("verbose")) cout << "Dropping packet from unknown AP " << mac_ap << ".\n" ; continue ; } const AccessPoint &ap = Stock::find_create_ap(mac_ap) ; measurements[mac_ap].set_ap(&ap) ; measurements[mac_ap].add_ss(ss) ; } if (measurements.empty()) return false ; current_request->set_measurements(measurements) ; // Calibration request? fill_calibration_request_data( mac_mobile, position, request.direction, request.type) ; return true ; }