ip.cc
Go to the documentation of this file.
1 
37 #include <utility/Exception.hh>
38 
39 #include "details/legacy/ip.hh"
40 
41 namespace multisense{
42 namespace legacy{
43 
44 std::unique_ptr<sockaddr_in> get_sockaddr(const std::string &ip_address, uint16_t command_port)
45 {
46  struct addrinfo hints, *res;
47  memset(&hints, 0, sizeof(hints));
48  hints.ai_family = AF_INET;
49  hints.ai_socktype = 0;
50 
51  const int addrstatus = getaddrinfo(ip_address.c_str(), NULL, &hints, &res);
52  if (addrstatus != 0 || res == NULL)
53  {
54  CRL_EXCEPTION("unable to resolve \"%s\": %s", ip_address.c_str(), strerror(errno));
55  }
56 
57  in_addr addr;
58  memcpy(&addr, &(((struct sockaddr_in *)(res->ai_addr))->sin_addr), sizeof(in_addr));
59 
60  auto socaddr = std::unique_ptr<sockaddr_in>(new sockaddr_in);
61  socaddr->sin_family = AF_INET;
62  socaddr->sin_port = htons(command_port);
63  socaddr->sin_addr = addr;
64 
65  freeaddrinfo(res);
66 
67  return socaddr;
68 }
69 
70 std::unique_ptr<sockaddr_in> get_broadcast_sockaddr(uint16_t command_port)
71 {
72  auto socaddr = std::unique_ptr<sockaddr_in>(new sockaddr_in);
73  socaddr->sin_family = AF_INET;
74  socaddr->sin_port = htons(command_port);
75  socaddr->sin_addr.s_addr = htonl(INADDR_BROADCAST);
76 
77  return socaddr;
78 }
79 
80 std::tuple<socket_t, uint16_t> bind(const std::optional<std::string>& interface_name, bool broadcast)
81 {
82  //
83  // Create the socket.
84 
85  auto server_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
86 #if defined(__MINGW64__)
87  if (server_socket == INVALID_SOCKET)
88 #else
89  if (server_socket < 0)
90 #endif
91  CRL_EXCEPTION("failed to create the UDP socket: %s",
92  strerror(errno));
93 
94  //
95  // Bind to specific interface if specified
96  if (interface_name && !interface_name->empty())
97  {
98  #if __linux__
99  if (0 != setsockopt(server_socket,
100  SOL_SOCKET,
101  SO_BINDTODEVICE,
102  interface_name->c_str(),
103  interface_name->size()))
104  {
105  CRL_EXCEPTION("Failed to bind to device %s. Error: %s", interface_name->c_str(),
106  strerror(errno));
107  }
108  #elif __APPLE__
109  if (0 != setsockopt(server_socket,
110  SOL_SOCKET,
111  IP_RECVIF,
112  interface_name->c_str(),
113  interface_name->size() + 1))
114  {
115  CRL_EXCEPTION("Failed to bind to device %s. Error: %s", interface_name->c_str(),
116  strerror(errno));
117  }
118  #else
119  if (interface_name && !interface_name->empty())
120  {
121  CRL_DEBUG("User specified binding to adapter %s, but this feature is only supported under linux."
122  "Ignoring bind to specific adapter", interface_name->c_str());
123  }
124  #endif
125  }
126 
127  if (broadcast)
128  {
129  #ifdef WIN32
130  CRL_DEBUG("User specified configuring the socket to broadcast. This feature is only supported under linux."
131  "Ignoring the broadcast request");
132  #else
133  const int b = 1;
134  if (0 != setsockopt(server_socket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char const*>(&b), sizeof(b)))
135  {
136  CRL_EXCEPTION("Failed to configure broadcasting on a the socket. Error: %s", strerror(errno));
137  }
138  #endif
139  }
140 
141  //
142  // Turn non-blocking on.
143 #if WIN32
144  u_long ioctl_arg = 1;
145  if (0 != ioctlsocket(server_socket, FIONBIO, &ioctl_arg))
146  CRL_EXCEPTION("failed to make a socket non-blocking: %d",WSAGetLastError ());
147 #else
148  const int flags = fcntl(server_socket, F_GETFL, 0);
149 
150  if (0 != fcntl(server_socket, F_SETFL, flags | O_NONBLOCK))
151  CRL_EXCEPTION("failed to make a socket non-blocking: %s",
152  strerror(errno));
153 #endif
154 
155  //
156  // Allow reusing sockets.
157 
158  int reuseSocket = 1;
159 
160  if (0 != setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char*) &reuseSocket,
161  sizeof(reuseSocket)))
162  CRL_EXCEPTION("failed to turn on socket reuse flag: %s",
163  strerror(errno));
164 
165  //
166  // We want very large buffers to store several images
167 
168 #if __APPLE__
169  // MacOS cannot reliably allocate a buffer larger than this
170  int bufferSize = 4 * 1024 * 1024;
171 #else
172  int bufferSize = 48 * 1024 * 1024;
173 #endif
174 
175  if (0 != setsockopt(server_socket, SOL_SOCKET, SO_RCVBUF, (char*) &bufferSize,
176  sizeof(bufferSize)) ||
177  0 != setsockopt(server_socket, SOL_SOCKET, SO_SNDBUF, (char*) &bufferSize,
178  sizeof(bufferSize)))
179  {
180  CRL_EXCEPTION("failed to adjust socket buffer sizes (%d bytes): %s",
181  bufferSize, strerror(errno));
182  }
183 
184  //
185  // Bind the connection to the port.
186 
187  struct sockaddr_in address;
188 
189  address.sin_family = AF_INET;
190  address.sin_port = htons(0); // system assigned
191  address.sin_addr.s_addr = htonl(INADDR_ANY);
192 
193  if (0 != ::bind(server_socket, (struct sockaddr*) &address, sizeof(address)))
194  CRL_EXCEPTION("failed to bind the server socket to system-assigned port: %s",
195  strerror(errno));
196 
197  //
198  // Retrieve the system assigned local UDP port
199 #if WIN32
200  int len = sizeof(address);
201 #else
202  socklen_t len = sizeof(address);
203 #endif
204  if (0 != getsockname(server_socket, (struct sockaddr*) &address, &len))
205  {
206  CRL_EXCEPTION("getsockname() failed: %s", strerror(errno));
207  }
208 
209  auto server_socket_port = htons(address.sin_port);
210 
211  return std::make_tuple(server_socket, server_socket_port);
212 }
213 
214 }
215 }
CRL_DEBUG
#define CRL_DEBUG(fmt,...)
Definition: Exception.hh:71
Exception.hh
multisense::legacy::get_broadcast_sockaddr
std::unique_ptr< sockaddr_in > get_broadcast_sockaddr(uint16_t command_port)
Create a socketaddr_in object to boradcast to a given port.
Definition: ip.cc:70
CRL_EXCEPTION
#define CRL_EXCEPTION(fmt,...)
Definition: Exception.hh:85
multisense::legacy::bind
std::tuple< socket_t, uint16_t > bind(const std::optional< std::string > &interface_name, bool broadcast)
Create a UDP socket to communicate with the MultiSense. Optionally bind to a specific interface.
Definition: ip.cc:80
multisense
Definition: factory.cc:39
ip.hh
INVALID_SOCKET
#define INVALID_SOCKET
Definition: Legacy/include/MultiSense/details/channel.hh:69
multisense::legacy::get_sockaddr
std::unique_ptr< sockaddr_in > get_sockaddr(const std::string &ip_address, uint16_t command_port)
Create a socketaddr_in object for a given IP address and port.
Definition: ip.cc:44


multisense_lib
Author(s):
autogenerated on Thu Apr 17 2025 02:49:09