170 lines
5.3 KiB
C
170 lines
5.3 KiB
C
/*
|
|
* 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
|
|
* http://code.lm7.fr/p/owlps/source/tree/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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
|
|
|
|
/**
|
|
* 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) ;
|
|
}
|
|
}
|