Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "mocap_optitrack/socket.h"
00011 #include <cstring>
00012 #include <cerrno>
00013 #include <fcntl.h>
00014 #include <iostream>
00015 #include <stdio.h>
00016 #include <sstream>
00017
00018 #include <ros/ros.h>
00019
00020 UdpMulticastSocket::UdpMulticastSocket( const int local_port, const std::string multicast_ip )
00021 {
00022
00023 ROS_INFO( "Creating socket..." );
00024 m_socket = socket( AF_INET, SOCK_DGRAM, 0 );
00025 if( m_socket < 0 )
00026 throw SocketException( strerror( errno ) );
00027
00028
00029 ROS_INFO( "Setting socket options..." );
00030 int option_value = 1;
00031 int result = setsockopt( m_socket, SOL_SOCKET, SO_REUSEADDR, (void*)&option_value, sizeof( int ) );
00032 if( result == -1 )
00033 {
00034 std::stringstream error;
00035 error << "Failed to set socket option: ";
00036 switch( errno )
00037 {
00038 case EBADF:
00039 error << "EBADF";
00040 break;
00041 case EFAULT:
00042 error << "EFAULT";
00043 break;
00044 case EINVAL:
00045 error << "EINVAL";
00046 break;
00047 case ENOPROTOOPT:
00048 error << "ENOPROTOOPT";
00049 break;
00050 case ENOTSOCK:
00051 error << "ENOTSOCK";
00052 break;
00053 default:
00054 error << "unknown error";
00055 break;
00056 }
00057 throw SocketException( error.str().c_str() );
00058 }
00059
00060
00061 memset ( &m_local_addr, 0, sizeof ( m_local_addr ) );
00062 m_local_addr.sin_family = AF_INET;
00063 m_local_addr.sin_addr.s_addr = htonl( INADDR_ANY );
00064 m_local_addr.sin_port = htons( local_port );
00065 ROS_INFO( "Local address: %s:%i", inet_ntoa( m_local_addr.sin_addr ), ntohs( m_local_addr.sin_port ) );
00066
00067
00068 ROS_INFO( "Binding socket to local address..." );
00069 result = bind( m_socket, (sockaddr*)&m_local_addr, sizeof( m_local_addr ) );
00070 if( result == -1 )
00071 {
00072 std::stringstream error;
00073 error << "Failed to bind socket to local address:" << strerror( errno );
00074 throw SocketException( error.str().c_str() );
00075 }
00076
00077
00078 struct ip_mreq mreq;
00079 mreq.imr_multiaddr.s_addr = inet_addr( multicast_ip.c_str() );
00080 mreq.imr_interface = m_local_addr.sin_addr;
00081 ROS_INFO( "Joining multicast group %s...", inet_ntoa( mreq.imr_multiaddr ) );
00082
00083 result = setsockopt(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
00084 if( result == -1 )
00085 {
00086 std::stringstream error;
00087 error << "Failed to set socket option: ";
00088 switch( errno )
00089 {
00090 case EBADF:
00091 error << "EBADF";
00092 break;
00093 case EFAULT:
00094 error << "EFAULT";
00095 break;
00096 case EINVAL:
00097 error << "EINVAL";
00098 break;
00099 case ENOPROTOOPT:
00100 error << "ENOPROTOOPT";
00101 break;
00102 case ENOTSOCK:
00103 error << "ENOTSOCK";
00104 break;
00105 default:
00106 error << "unknown error";
00107 break;
00108 }
00109 throw SocketException( error.str().c_str() );
00110 }
00111
00112
00113 ROS_INFO( "Enabling non-blocking I/O" );
00114 int flags = fcntl( m_socket, F_GETFL , 0 );
00115 result = fcntl(m_socket, F_SETFL, flags | O_NONBLOCK);
00116 if( result == -1 )
00117 {
00118 std::stringstream error;
00119 error << "Failed to enable non-blocking I/O: " << strerror( errno );
00120 throw SocketException( error.str().c_str() );
00121 }
00122 }
00123
00124 UdpMulticastSocket::~UdpMulticastSocket()
00125 {
00126 close( m_socket );
00127 }
00128
00129 int UdpMulticastSocket::recv()
00130 {
00131 memset ( buf, 0, MAXRECV + 1 );
00132
00133 sockaddr_in remote_addr;
00134 int addr_len = sizeof(struct sockaddr);
00135 int status = recvfrom(
00136 m_socket,
00137 buf,
00138 MAXRECV,
00139 0,
00140 (sockaddr *)&remote_addr,
00141 (socklen_t*)&addr_len);
00142
00143 if( status > 0 )
00144 ROS_INFO( "%4i bytes received from %s:%i", status, inet_ntoa( remote_addr.sin_addr ), ntohs( remote_addr.sin_port ) );
00145 else if( status == 0 )
00146 ROS_INFO( "Connection closed by peer" );
00147
00148 return status;
00149 }