#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) ; // Mobile MAC string mac_mobile( owl_mac_bytes_to_string(request.mobile_mac_addr_bytes)) ; PosUtil::to_upper(mac_mobile) ; if (! Configuration::bool_value("positioning.accept-new-mobiles") && ! Stock::mobile_exists(mac_mobile)) 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(owl_ntohf(request.x_position), owl_ntohf(request.y_position), owl_ntohf(request.z_position)) ; // Read {MAC_AP;SS} mcouples (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) ; if (! Configuration::bool_value("positioning.accept-new-aps") && ! Stock::ap_exists(mac_ap)) continue ; const AccessPoint &ap = Stock::find_create_ap(mac_ap) ; measurements[mac_ap].set_ap(&ap) ; measurements[mac_ap].add_ss(static_cast (request_info.antenna_signal_dbm)) ; } 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 ; }