socket.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 University of Bonn, Computer Science Institute,
3  * Kathrin Gräve
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 #include "mocap_optitrack/socket.h"
31 #include <cstring>
32 #include <cerrno>
33 #include <fcntl.h>
34 #include <iostream>
35 #include <stdio.h>
36 #include <sstream>
37 #include <string>
38 #include <ros/ros.h>
39 
40 UdpMulticastSocket::UdpMulticastSocket(const int local_port, const std::string multicast_ip)
41 {
42  remote_ip_exist = false;
43 
44  // Create a UDP socket
45  ROS_INFO("Creating socket...");
46  m_socket = socket(AF_INET, SOCK_DGRAM, 0);
47  if (m_socket < 0)
48  throw SocketException(strerror(errno));
49 
50  // Allow reuse of local addresses
51  ROS_INFO("Setting socket options...");
52  int option_value = 1;
53  int result = setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (void*)&option_value, sizeof(int));
54  if (result == -1)
55  {
56  std::stringstream error;
57  error << "Failed to set socket option: ";
58  switch (errno)
59  {
60  case EBADF:
61  error << "EBADF";
62  break;
63  case EFAULT:
64  error << "EFAULT";
65  break;
66  case EINVAL:
67  error << "EINVAL";
68  break;
69  case ENOPROTOOPT:
70  error << "ENOPROTOOPT";
71  break;
72  case ENOTSOCK:
73  error << "ENOTSOCK";
74  break;
75  default:
76  error << "unknown error";
77  break;
78  }
79  throw SocketException(error.str().c_str());
80  }
81 
82  // Fill struct for local address
83  memset(&m_local_addr, 0, sizeof(m_local_addr));
84  m_local_addr.sin_family = AF_INET;
85  m_local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
86  m_local_addr.sin_port = htons(local_port);
87  ROS_INFO("Local address: %s:%i", inet_ntoa(m_local_addr.sin_addr), ntohs(m_local_addr.sin_port));
88 
89  // Bind the socket
90  ROS_INFO("Binding socket to local address...");
91  result = bind(m_socket, (sockaddr*)&m_local_addr, sizeof(m_local_addr));
92  if (result == -1)
93  {
94  std::stringstream error;
95  error << "Failed to bind socket to local address:" << strerror(errno);
96  throw SocketException(error.str().c_str());
97  }
98 
99  // Join multicast group
100  struct ip_mreq mreq;
101  mreq.imr_multiaddr.s_addr = inet_addr(multicast_ip.c_str());
102  mreq.imr_interface = m_local_addr.sin_addr;
103  ROS_INFO("Joining multicast group %s...", inet_ntoa(mreq.imr_multiaddr));
104 
105  result = setsockopt(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
106  if (result == -1)
107  {
108  std::stringstream error;
109  error << "Failed to set socket option: ";
110  switch (errno)
111  {
112  case EBADF:
113  error << "EBADF";
114  break;
115  case EFAULT:
116  error << "EFAULT";
117  break;
118  case EINVAL:
119  error << "EINVAL";
120  break;
121  case ENOPROTOOPT:
122  error << "ENOPROTOOPT";
123  break;
124  case ENOTSOCK:
125  error << "ENOTSOCK";
126  break;
127  default:
128  error << "unknown error";
129  break;
130  }
131  throw SocketException(error.str().c_str());
132  }
133 
134  // Make socket non-blocking
135  ROS_INFO("Enabling non-blocking I/O");
136  int flags = fcntl(m_socket, F_GETFL, 0);
137  result = fcntl(m_socket, F_SETFL, flags | O_NONBLOCK);
138  if (result == -1)
139  {
140  std::stringstream error;
141  error << "Failed to enable non-blocking I/O: " << strerror(errno);
142  throw SocketException(error.str().c_str());
143  }
144 }
145 
147 {
148  close(m_socket);
149 }
150 
152 {
153  memset(buf, 0, MAXRECV + 1);
154 
155  sockaddr_in remote_addr;
156  int addr_len = sizeof(struct sockaddr);
157  int status = recvfrom(
158  m_socket,
159  buf,
160  MAXRECV,
161  0,
162  (sockaddr *)&remote_addr,
163  (socklen_t*)&addr_len);
164 
165  if (status > 0)
166  ROS_DEBUG("%4i bytes received from %s:%i", status, inet_ntoa(remote_addr.sin_addr), ntohs(remote_addr.sin_port));
167  else if (status == 0)
168  ROS_DEBUG("Connection closed by peer");
169 
170  HostAddr.sin_addr = remote_addr.sin_addr;
171  remote_ip_exist = true;
172 
173  return status;
174 }
175 
176 int UdpMulticastSocket::send(const char* buf, unsigned int sz, int port)
177 {
178  HostAddr.sin_family = AF_INET;
179  HostAddr.sin_port = htons(port);
180  return sendto(m_socket, buf, sz, 0, (sockaddr*)&HostAddr, sizeof(HostAddr));
181 }
Exception class thrown by socket classes in this file.
Definition: socket.h:43
UdpMulticastSocket(const int local_port, const std::string multicast_ip="224.0.0.1")
Creates a socket and joins the multicast group with the given address.
Definition: socket.cpp:40
int recv()
Retrieve data from multicast group.
Definition: socket.cpp:151
sockaddr_in HostAddr
Definition: socket.h:88
#define ROS_INFO(...)
static const int MAXRECV
Maximum number of bytse that can be read at a time.
Definition: socket.h:60
sockaddr_in m_local_addr
Definition: socket.h:87
int send(const char *buf, unsigned int sz, int port)
Definition: socket.cpp:176
bool remote_ip_exist
Definition: socket.h:89
char buf[MAXRECV+1]
Definition: socket.h:90
#define ROS_DEBUG(...)


mocap_optitrack
Author(s): Kathrin Gräve , Alex Bencz/ , Tony Baltovski , JD Yamokoski
autogenerated on Fri Mar 26 2021 02:05:51