libcyberradio 22.01.24
VitaIqUdpPort.cpp
1/***************************************************************************
2 * \file VitaIqUdpPort.cpp
3 *
4 * \brief UDP port for handling incoming VITA 49 or I/Q data.
5 *
6 * \author DA
7 * \copyright 2016-2021 CyberRadio Solutions, Inc.
8 */
9
10#ifdef HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14#include <LibCyberRadio/Common/VitaIqUdpPort.h>
15#include <stdarg.h>
16#include <sstream>
17
18
19namespace LibCyberRadio
20{
21
22 VitaIqUdpPort::VitaIqUdpPort(const std::string& host,
23 int port,
24 int packet_size,
25 bool debug) :
26 Debuggable(debug, ""),
27 host(host),
28 port(port),
29 packet_size(packet_size),
30 connected(false),
31 socket(NULL),
32 recv_buffer(NULL),
33 bytes_recvd(0)
34 {
35 // Set the object debug name
36 std::ostringstream oss;
37 oss << "VitaIqUdpPort " << port;
38 _debugName = oss.str();
39 // Allocate the receive buffer
40 recv_buffer = new unsigned char[packet_size];
41 memset(recv_buffer, 0, packet_size);
42 // Connect to the UDP port
43 boost::system::error_code error = boost::asio::error::host_not_found;
44 std::string s_port = (boost::format("%d") % port).str();
45 if (host.size() > 0)
46 {
47 boost::asio::ip::udp::resolver resolver(io_service);
48 auto query = resolver.resolve(boost::asio::ip::udp::v4(),host, s_port, boost::asio::ip::resolver_base::passive);
49 // boost::asio::ip::udp::resolver::resolve_query query(boost::asio::ip::udp::v4(),
50 // host, s_port,
51 // boost::asio::ip::resolver_query_base::passive);
52 io_service.run();
53 endpoint = *query.begin();
54 if (errno > 0)
55 {
56 printf("cannot resolve host IP %s error: %s\n", host.c_str(),
57 strerror(errno));
58 }
59 else
60 {
61 socket = new boost::asio::ip::udp::socket(io_service);
62 socket->open(endpoint.protocol());
63 boost::asio::socket_base::linger loption(true, 0);
64 socket->set_option(loption);
65 boost::asio::socket_base::reuse_address roption(true);
66 socket->set_option(roption);
67 boost::asio::socket_base::receive_buffer_size boption(33554432);
68 socket->set_option(boption);
69 boost::asio::socket_base::receive_buffer_size boption2;
70 socket->get_option(boption2);
71 if (boption2.value()!=33554432) {
72 printf("\nCould not set UDP buffer size!\n");
73 printf("Please run 'sudo sysctl net.core.rmem_max=50000000'.\n\n");
74 }
75 socket->bind(endpoint);
76 connected = true;
77 }
78 }
79 }
80
81 VitaIqUdpPort::~VitaIqUdpPort()
82 {
83 connected = false;
84 io_service.restart();
85 io_service.stop();
86 if (socket != NULL)
87 {
88 socket->close();
89 delete socket;
90 }
91 // Deallocate the receive buffer
92 if (recv_buffer != NULL)
93 delete [] recv_buffer;
94 }
95
96 void VitaIqUdpPort::read_data()
97 {
98 int socket_fd, result, num_received;
99 fd_set readset;
100 struct timeval timeout;
101 timeout.tv_sec = 0;
102 timeout.tv_usec = 100;
103
104 socket_fd = socket->native_handle();
105 /* Socket has been created and connected to the other party */
106 do
107 {
108 FD_ZERO(&readset);
109 FD_SET(socket_fd, &readset);
110 result = select(socket_fd + 1, &readset, NULL, NULL, &timeout);
111 } while (result == -1 && errno == EINTR);
112
113 if (result > 0)
114 {
115 if (FD_ISSET(socket_fd, &readset))
116 {
117 /* The socket_fd has data available to be read */
118 do
119 {
120 num_received = socket->receive(
121 boost::asio::buffer(
122 (void*)(recv_buffer + bytes_recvd),
123 packet_size - bytes_recvd
124 )
125 );
126 bytes_recvd += num_received;
127 }
128 while ( (num_received != 0) && (bytes_recvd < packet_size));
129 }
130 }
131 else if (result < 0)
132 {
133 /* An error ocurred, just print it to stdout */
134 }
135
136 }
137
138 void VitaIqUdpPort::clear_buffer()
139 {
140 memset(recv_buffer, 0, packet_size);
141 bytes_recvd = 0;
142 }
143
144 bool VitaIqUdpPort::is_packet_ready() const
145 {
146 return (bytes_recvd == packet_size);
147 }
148
149} /* namespace LibCyberRadio */
150
Class that supports debug output.
Definition Debuggable.h:39
Defines functionality for LibCyberRadio applications.
Definition App.h:24