#include "inputudpsocket.hh" #include "posexcept.hh" #include "stock.hh" #include #include #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 true if the socket were successfully opened, 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 reads the next Request in the UDP input socket. * It cannot read calibration requests. * * #sockfd should be opened before processing requests; otherwise, * #current_request is \link Request::clear() cleared\endlink and a * blank Request is returned. * * @return The read Request, or a blank Request in case of error (socket * not opened, bad packet format). */ const Request& InputUDPSocket::get_next_request() { clear_current_request() ; if (eof()) return *current_request ; 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 << "No request received!" << endl ; return *current_request ; } // Endianess conversions request.request_time = owl_ntoh_timestamp(request.request_time) ; request.nb_info = ntohs(request.nb_info) ; // Mobile MAC const char *const mac_mobile = owl_mac_bytes_to_string(request.mobile_mac_addr_bytes) ; 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)) ; // 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 ; current_request->clear() ; return *current_request ; } const char *const mac_ap = owl_mac_bytes_to_string(request_info.ap_mac_addr_bytes) ; 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)) ; } current_request->set_measurements(measurements) ; return *current_request ; }