/* * This file is part of the Owl Positioning System (OwlPS) project. * It is subject to the copyright notice and license terms in the * COPYRIGHT.t2t file found in the top-level directory of this * distribution and at * https://code.lm7.fr/mcy/owlps/src/master/COPYRIGHT.t2t * No part of the OwlPS Project, including this file, may be copied, * modified, propagated, or distributed except according to the terms * contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be * distributed along with this file, either separately or by replacing * this notice by the COPYRIGHT.t2t file's contents. * *********************************************************************** * * This is the main source file of libowlps-client. */ #include "owlps-client.h" #include #include #include #include #include /** * Opens a transmission UDP socket to a server in a simplified way. * This function uses owl_create_udp_trx_socket() (from libowlps) * as a backend, and allows to select a particular network interface. * * @param[in] dest_host host name or IP address of the remote server. * @param[in] dest_port Port on which the remote server listens. * @param[out] server Structure in which the server information will * be saved. * @param[in] iface The name of the network interface to send through. * If this parameter is `NULL` or an empty string, the interface will * be selected automatically. */ int owl_create_trx_socket(const char *const dest_host, const uint_fast16_t dest_port, struct sockaddr *const server, const char *const iface) { int sockfd = owl_create_udp_trx_socket(dest_host, dest_port, server) ; if (sockfd < 0) { perror("Error! Cannot create UDP sending socket to the aggregation" " server") ; exit(OWL_ERR_SOCKET_CREATE) ; } // If we specified an interface name if (iface != NULL && iface[0] != '\0') owl_use_iface(sockfd, iface) ; return sockfd ; } /** * Selects the interface named `iface` as a transmission interface for * the socket `sockfd`. */ void owl_use_iface(const int sockfd, const char *const iface) { #if defined(linux) && defined(__GLIBC__) if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface) + 1) == -1) { fprintf(stderr, "Error! Cannot select interface %s to send the" " packet: ", iface) ; perror("") ; fprintf(stderr, "Sending through the default interface.\n") ; } #else // linux && __GLIBC__ fprintf(stderr, "Cannot select interface %s to send the packet:" " this option is currently Linux and GNU libc-specific.\n" "Sending through the default interface.\n", iface) ; #endif // linux && __GLIBC__ } /** * Transmits a request. * No packet will be transmitted if the global variable `owl_run` is * `false`, and the transmission will stop as soon as possible if it * becomes `false`. * * @param[in] sockfd The file descriptor of the socket to use for the * transmission. * @param[in] server The server's information (as generated by * owl_create_trx_socket(), for example). * @param[in] packet The buffer to send through the socket. * @param[in] packet_size The buffer's size. * @param[in] nb_pkt Number of packets to transmit. * @param[in] delay Delay between two transmissions, in milliseconds. * @param[in] verbose If `true`, a "progress bar" will be printed on the * standard output. */ void owl_send_request(const int sockfd, const struct sockaddr *const server, const void *const packet, const uint_fast16_t packet_size, const uint_fast16_t nb_pkt, const uint_fast32_t delay, const bool verbose) { uint_fast16_t i ; if (nb_pkt == 0 || !owl_run) return ; if (verbose) printf("Sent packets: ") ; // Transmit first packet: owl_send_packet(sockfd, server, packet, packet_size, verbose) ; // Transmit remaining packets (if any): for (i = 1 ; i < nb_pkt ; ++i) { uint16_t current_pkt = htons(i + 1) ; owl_msleep(delay) ; // Wait during the wanted delay if (! owl_run) break ; // Update the packet number: memcpy(&((char*) packet)[1], ¤t_pkt, sizeof(uint16_t)) ; owl_send_packet(sockfd, server, packet, packet_size, verbose) ; } if (verbose) putchar('\n') ; } /** * Transmits a single packet of a request. * See the documentation of the owl_send_request() function for an * explanation on the parameters. * When `verbose` if `true`, a dot will be printed on the standard output * and the standard output will be flushed. */ void owl_send_packet(const int sockfd, const struct sockaddr *const server, const void *const packet, const uint_fast16_t packet_size, const bool verbose) { ssize_t nsent = sendto(sockfd, packet, packet_size, 0, server, (socklen_t) sizeof(*server)) ; if (nsent != (ssize_t) packet_size) { perror("Error sending data to the network") ; exit(OWL_ERR_SOCKET_SEND) ; } if (verbose) { putchar('.') ; fflush(stdout) ; } }