simple-socket library 1.1.5

UDPSocket.cpp

Go to the documentation of this file.
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 }