simple-socket library 1.1.5
|
00001 #include "UDPSocket.h" 00002 #include "TempFailure.h" 00003 00004 #include <sys/socket.h> 00005 #include <arpa/inet.h> 00006 #include <poll.h> 00007 00008 using namespace NET; 00009 00010 namespace { 00011 00012 void setBroadcast( int socket) 00013 { 00014 // If this fails, we'll hear about it when we try to send. This will allow 00015 // systems that cannot broadcast to continue if they don't plan to broadcast 00016 int broadcastPermission = 1; 00017 setsockopt( socket, 00018 SOL_SOCKET, 00019 SO_BROADCAST, 00020 (raw_type*)&broadcastPermission, 00021 sizeof(broadcastPermission)); 00022 } 00023 00024 int groupAction( int socket, const std::string& multicastGroup, int action) 00025 { 00026 struct ip_mreq multicastRequest; 00027 multicastRequest.imr_multiaddr.s_addr = inet_addr( multicastGroup.c_str()); 00028 multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); 00029 00030 return( setsockopt( socket, 00031 IPPROTO_IP, 00032 action, 00033 (raw_type*)&multicastRequest, 00034 sizeof(multicastRequest))); 00035 } 00036 00037 } // namespace 00038 00039 UDPSocket::UDPSocket() 00040 : InternetSocket( DATAGRAM, IPPROTO_UDP) 00041 { 00042 setBroadcast(m_socket); 00043 } 00044 00045 void UDPSocket::sendTo( const void* buffer, size_t len, const std::string& foreignAddress, unsigned short foreignPort) 00046 { 00047 sockaddr_in destAddr; 00048 fillAddress( foreignAddress, foreignPort, destAddr); 00049 00050 int sent = TEMP_FAILURE_RETRY (::sendto( m_socket, (const raw_type*)buffer, len, 0, (sockaddr*)&destAddr, sizeof(destAddr))); 00051 00052 // Write out the whole buffer as a single message 00053 if( sent != (int)len) 00054 throw SocketException("Send failed (sendto)"); 00055 } 00056 00057 int UDPSocket::receiveFrom( void* buffer, size_t len, std::string& sourceAddress, unsigned short& sourcePort) 00058 { 00059 sockaddr_in clientAddr; 00060 socklen_t addrLen = sizeof(clientAddr); 00061 00062 int ret = TEMP_FAILURE_RETRY (::recvfrom( m_socket, (raw_type*)buffer, len, 0, (sockaddr*)&clientAddr, &addrLen)); 00063 if( ret < 0) 00064 throw SocketException("Receive failed (recvfrom)"); 00065 00066 sourceAddress = inet_ntoa( clientAddr.sin_addr); 00067 sourcePort = ntohs( clientAddr.sin_port); 00068 00069 return ret; 00070 } 00071 00072 int UDPSocket::timedReceiveFrom( void* buffer, size_t len, std::string& sourceAddress, unsigned short& sourcePort, int timeout) 00073 { 00074 struct pollfd poll; 00075 poll.fd = m_socket; 00076 poll.events = POLLIN | POLLPRI | POLLRDHUP; 00077 00078 int ret = TEMP_FAILURE_RETRY (::poll( &poll, 1, timeout)); 00079 00080 if( ret == 0) return 0; 00081 if( ret < 0) throw SocketException("Receive failed (poll)"); 00082 00083 if( poll.revents & POLLRDHUP) 00084 m_peerDisconnected = true; 00085 00086 if( poll.revents & POLLIN || poll.revents & POLLPRI) 00087 return receiveFrom( buffer, len, sourceAddress, sourcePort); 00088 00089 return 0; 00090 } 00091 00092 void UDPSocket::setMulticastTTL( unsigned char multicastTTL) 00093 { 00094 if( setsockopt( m_socket, 00095 IPPROTO_IP, 00096 IP_MULTICAST_TTL, 00097 (raw_type*)&multicastTTL, 00098 sizeof(multicastTTL)) < 0) 00099 throw SocketException("Multicast set TTL failed (setsockopt)"); 00100 } 00101 00102 void UDPSocket::joinGroup( const std::string& multicastGroup) 00103 { 00104 if( groupAction( m_socket, multicastGroup, IP_ADD_MEMBERSHIP) < 0) 00105 throw SocketException("Multicast group join failed (setsockopt)"); 00106 } 00107 00108 void UDPSocket::leaveGroup( const std::string& multicastGroup) 00109 { 00110 if( groupAction( m_socket, multicastGroup, IP_DROP_MEMBERSHIP) < 0) 00111 throw SocketException("Multicast group leave failed (setsockopt)"); 00112 }