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 
19 namespace 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  boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(),
49  host, s_port,
50  boost::asio::ip::resolver_query_base::passive);
51  io_service.run();
52  endpoint = *resolver.resolve(query);
53  if (errno > 0)
54  {
55  printf("cannot resolve host IP %s error: %s\n", host.c_str(),
56  strerror(errno));
57  }
58  else
59  {
60  socket = new boost::asio::ip::udp::socket(io_service);
61  socket->open(endpoint.protocol());
62  boost::asio::socket_base::linger loption(true, 0);
63  socket->set_option(loption);
64  boost::asio::socket_base::reuse_address roption(true);
65  socket->set_option(roption);
66  boost::asio::socket_base::receive_buffer_size boption(33554432);
67  socket->set_option(boption);
68  boost::asio::socket_base::receive_buffer_size boption2;
69  socket->get_option(boption2);
70  if (boption2.value()!=33554432) {
71  printf("\nCould not set UDP buffer size!\n");
72  printf("Please run 'sudo sysctl net.core.rmem_max=50000000'.\n\n");
73  }
74  socket->bind(endpoint);
75  connected = true;
76  }
77  }
78  }
79 
80  VitaIqUdpPort::~VitaIqUdpPort()
81  {
82  connected = false;
83  io_service.reset();
84  io_service.stop();
85  if (socket != NULL)
86  {
87  socket->close();
88  delete socket;
89  }
90  // Deallocate the receive buffer
91  if (recv_buffer != NULL)
92  delete [] recv_buffer;
93  }
94 
95  void VitaIqUdpPort::read_data()
96  {
97  int socket_fd, result, num_received;
98  fd_set readset;
99  struct timeval timeout;
100  timeout.tv_sec = 0;
101  timeout.tv_usec = 100;
102 
103  socket_fd = socket->native_handle();
104  /* Socket has been created and connected to the other party */
105  do
106  {
107  FD_ZERO(&readset);
108  FD_SET(socket_fd, &readset);
109  result = select(socket_fd + 1, &readset, NULL, NULL, &timeout);
110  } while (result == -1 && errno == EINTR);
111 
112  if (result > 0)
113  {
114  if (FD_ISSET(socket_fd, &readset))
115  {
116  /* The socket_fd has data available to be read */
117  do
118  {
119  num_received = socket->receive(
120  boost::asio::buffer(
121  (void*)(recv_buffer + bytes_recvd),
122  packet_size - bytes_recvd
123  )
124  );
125  bytes_recvd += num_received;
126  }
127  while ( (num_received != 0) && (bytes_recvd < packet_size));
128  }
129  }
130  else if (result < 0)
131  {
132  /* An error ocurred, just print it to stdout */
133  }
134 
135  }
136 
137  void VitaIqUdpPort::clear_buffer()
138  {
139  memset(recv_buffer, 0, packet_size);
140  bytes_recvd = 0;
141  }
142 
143  bool VitaIqUdpPort::is_packet_ready() const
144  {
145  return (bytes_recvd == packet_size);
146  }
147 
148 } /* namespace LibCyberRadio */
149 
Defines functionality for LibCyberRadio applications.
Definition: App.h:23