datagram_multicast.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <netcomm/socket/datagram_multicast.h>
00025
00026 #include <sys/socket.h>
00027 #include <netinet/in.h>
00028 #include <arpa/inet.h>
00029 #include <cstdlib>
00030 #include <cstring>
00031 #include <cerrno>
00032
00033 namespace fawkes {
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 MulticastDatagramSocket::MulticastDatagramSocket(const char *multicast_addr_s,
00051 unsigned short port,
00052 float timeout)
00053 : Socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP, timeout)
00054 {
00055 multicast_addr = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
00056
00057 struct in_addr a;
00058 if ( inet_aton(multicast_addr_s, &a) == -1 ) {
00059 throw SocketException("Invalid address given");
00060 }
00061 multicast_addr->sin_family = AF_INET;
00062 multicast_addr->sin_addr.s_addr = a.s_addr;
00063 multicast_addr->sin_port = htons(port);
00064
00065
00066 set_loop(false);
00067 }
00068
00069
00070
00071 MulticastDatagramSocket::~MulticastDatagramSocket()
00072 {
00073 free(multicast_addr);
00074 }
00075
00076
00077
00078
00079
00080 MulticastDatagramSocket::MulticastDatagramSocket(MulticastDatagramSocket &datagram_socket)
00081 : Socket(datagram_socket)
00082 {
00083 multicast_addr = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
00084 memcpy(multicast_addr, datagram_socket.multicast_addr, sizeof(struct ::sockaddr_in));
00085 }
00086
00087
00088
00089
00090
00091
00092 void
00093 MulticastDatagramSocket::bind()
00094 {
00095 int reuse = 1;
00096 if ( setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
00097 throw SocketException("Could not set SO_REUSEADDR", errno);
00098 }
00099
00100 struct ip_mreq imr;
00101 imr.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
00102 imr.imr_interface.s_addr = htonl( INADDR_ANY );
00103 if ( setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)) == -1 ) {
00104 throw SocketException("Could not add multicast group membership", errno);
00105 }
00106
00107 struct ::sockaddr_in local;
00108 local.sin_family = AF_INET;
00109 local.sin_addr.s_addr = INADDR_ANY;
00110 local.sin_port = multicast_addr->sin_port;
00111
00112 if (::bind(sock_fd, (struct ::sockaddr *) &local, sizeof(local)) < 0) {
00113 throw SocketException("Could not bind to port", errno);
00114 }
00115 }
00116
00117
00118
00119
00120
00121 Socket *
00122 MulticastDatagramSocket::clone()
00123 {
00124 return new MulticastDatagramSocket(*this);
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134 void
00135 MulticastDatagramSocket::send(void *buf, unsigned int buf_len)
00136 {
00137 try {
00138 Socket::send(buf, buf_len, (struct ::sockaddr *)multicast_addr, sizeof(struct ::sockaddr_in));
00139 } catch (SocketException &e) {
00140 e.append("MulticastDatagramSocket::send(void*, unsigned int) failed");
00141 throw;
00142 }
00143 }
00144
00145
00146
00147
00148
00149 void
00150 MulticastDatagramSocket::set_loop(bool loop)
00151 {
00152 int l = (loop ? 1 : 0);
00153 if (setsockopt(sock_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &l, sizeof(l)) == -1) {
00154 throw SocketException("MulticastDatagramSocket::set_loop: setsockopt failed", errno);
00155 }
00156 }
00157
00158
00159
00160
00161
00162 void
00163 MulticastDatagramSocket::set_ttl(int ttl)
00164 {
00165 if ( ttl < 0 ) ttl = -ttl;
00166 if ( setsockopt( sock_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl) ) == -1 ) {
00167 throw SocketException("MulticastDatagramSocket::set_ttl: setsockopt failed", errno);
00168 }
00169 }
00170
00171 }