/* * This file is part of the Owl Positioning System (OwlPS). * OwlPS is a project of the University of Franche-Comté * (Université de Franche-Comté), France. */ #include "inputudpsocket.hh" #include "posexcept.hh" #include "stock.hh" #include "configuration.hh" #include #include #include // For perror() #include // For inet_ntop() #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.nb_packets = ntohs(request.nb_packets) ; 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) ; // Mobile IP char ip_mobile_str[INET_ADDRSTRLEN] ; inet_ntop(AF_INET, &request.mobile_ip_addr_bytes, ip_mobile_str, INET_ADDRSTRLEN) ; string ip_mobile(ip_mobile_str) ; PosUtil::to_upper(ip_mobile) ; // Display request's info if (Configuration::is_configured("verbose")) cout << "*** Request received from the aggregator ***" << "\n\tType: " << static_cast(request.type) << "\n\tNumber of packets: " << request.nb_packets << "\n\tMobile MAC: " << mac_mobile << "\n\tMobile IP: " << ip_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) ; // Update the mobile's IP address: const_cast(mobile).set_ip_addr(ip_mobile) ; current_request->set_mobile(&mobile) ; // Request type current_request->set_type(request.type) ; // Number of packets current_request->set_nb_packets(request.nb_packets) ; // 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 ; } pkt_id_t packet_id = ntohs(request_info.packet_id) ; string mac_ap( owl_mac_bytes_to_string(request_info.ap_mac_addr_bytes)) ; PosUtil::to_upper(mac_ap) ; owl_ntoh_timestamp(&request_info.capture_time) ; Timestamp capture_time(request_info.capture_time) ; // 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. ss_t ss = request_info.ss_dbm - 256 ; if (Configuration::is_configured("verbose")) cout << "\t* Packet received from the aggregator:" << "\n\t\tPacket number: " << packet_id << "\n\t\tAP MAC: " << mac_ap << "\n\t\tCapture timestamp: " << capture_time << "\n\t\tSignal: " << 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(packet_id, 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 ; }