00001 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 #ifdef _WIN32
00033 #ifdef _MSC_VER
00034 #pragma warning(disable:4786)
00035 #endif
00036 #include <stdlib.h>
00037 #else
00038 #include <errno.h>
00039 #endif
00040 
00041 #include "ISocketHandler.h"
00042 #include "UdpSocket.h"
00043 #include "Utility.h"
00044 #include "Ipv4Address.h"
00045 #include "Ipv6Address.h"
00046 #ifdef ENABLE_EXCEPTIONS
00047 #include "Exception.h"
00048 #endif
00049 
00050 
00051 
00052 
00053 #ifdef SOCKETS_NAMESPACE
00054 namespace SOCKETS_NAMESPACE {
00055 #endif
00056 
00057 
00058 UdpSocket::UdpSocket(ISocketHandler& h, int ibufsz, bool ipv6, int retries) : Socket(h)
00059 , m_ibuf(new char[ibufsz])
00060 , m_ibufsz(ibufsz)
00061 , m_bind_ok(false)
00062 , m_port(0)
00063 , m_last_size_written(-1)
00064 , m_retries(retries)
00065 , m_b_read_ts(false)
00066 {
00067 #ifdef ENABLE_IPV6
00068 #ifdef IPPROTO_IPV6
00069         SetIpv6(ipv6);
00070 #endif
00071 #endif
00072 }
00073 
00074 
00075 UdpSocket::~UdpSocket()
00076 {
00077         Close();
00078         delete[] m_ibuf;
00079 }
00080 
00081 
00082 int UdpSocket::Bind(port_t &port, int range)
00083 {
00084 #ifdef ENABLE_IPV6
00085 #ifdef IPPROTO_IPV6
00086         if (IsIpv6())
00087         {
00088                 Ipv6Address ad(port);
00089                 int n = Bind(ad, range);
00090                 if (m_bind_ok)
00091                         port = m_port;
00092                 return n;
00093         }
00094 #endif
00095 #endif
00096         Ipv4Address ad(port);
00097         int n = Bind(ad, range);
00098         if (m_bind_ok)
00099                 port = m_port;
00100         return n;
00101 }
00102 
00103 
00104 int UdpSocket::Bind(const std::string& intf, port_t &port, int range)
00105 {
00106 #ifdef ENABLE_IPV6
00107 #ifdef IPPROTO_IPV6
00108         if (IsIpv6())
00109         {
00110                 Ipv6Address ad(intf, port);
00111                 if (ad.IsValid())
00112                 {
00113                         int n = Bind(ad, range);
00114                         if (m_bind_ok)
00115                                 port = m_port;
00116                         return n;
00117                 }
00118                 SetCloseAndDelete();
00119                 return -1;
00120         }
00121 #endif
00122 #endif
00123         Ipv4Address ad(intf, port);
00124         if (ad.IsValid())
00125         {
00126                 int n = Bind(ad, range);
00127                 if (m_bind_ok)
00128                         port = m_port;
00129                 return n;
00130         }
00131         SetCloseAndDelete();
00132         return -1;
00133 }
00134 
00135 
00136 int UdpSocket::Bind(ipaddr_t a, port_t &port, int range)
00137 {
00138         Ipv4Address ad(a, port);
00139         int n = Bind(ad, range);
00140         if (m_bind_ok)
00141                 port = m_port;
00142         return n;
00143 }
00144 
00145 
00146 #ifdef ENABLE_IPV6
00147 #ifdef IPPROTO_IPV6
00148 int UdpSocket::Bind(in6_addr a, port_t &port, int range)
00149 {
00150         Ipv6Address ad(a, port);
00151         int n = Bind(ad, range);
00152         if (m_bind_ok)
00153                 port = m_port;
00154         return n;
00155 }
00156 #endif
00157 #endif
00158 
00159 
00160 int UdpSocket::Bind(SocketAddress& ad, int range)
00161 {
00162         if (GetSocket() == INVALID_SOCKET)
00163         {
00164                 Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp"));
00165         }
00166         if (GetSocket() != INVALID_SOCKET)
00167         {
00168                 SetNonblocking(true);
00169                 int n = bind(GetSocket(), ad, ad);
00170                 int tries = range;
00171                 while (n == -1 && tries--)
00172                 {
00173                         ad.SetPort(ad.GetPort() + 1);
00174                         n = bind(GetSocket(), ad, ad);
00175                 }
00176                 if (n == -1)
00177                 {
00178                         Handler().LogError(this, "bind", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00179                         SetCloseAndDelete();
00180 #ifdef ENABLE_EXCEPTIONS
00181                         throw Exception("bind() failed for UdpSocket, port:range: " + Utility::l2string(ad.GetPort()) + ":" + Utility::l2string(range));
00182 #endif
00183                         return -1;
00184                 }
00185                 m_bind_ok = true;
00186                 m_port = ad.GetPort();
00187                 return 0;
00188         }
00189         return -1;
00190 }
00191 
00192 
00194 bool UdpSocket::Open(ipaddr_t l, port_t port)
00195 {
00196         Ipv4Address ad(l, port);
00197         return Open(ad);
00198 }
00199 
00200 
00201 bool UdpSocket::Open(const std::string& host, port_t port)
00202 {
00203 #ifdef ENABLE_IPV6
00204 #ifdef IPPROTO_IPV6
00205         if (IsIpv6())
00206         {
00207                 Ipv6Address ad(host, port);
00208                 if (ad.IsValid())
00209                 {
00210                         return Open(ad);
00211                 }
00212                 return false;
00213         }
00214 #endif
00215 #endif
00216         Ipv4Address ad(host, port);
00217         if (ad.IsValid())
00218         {
00219                 return Open(ad);
00220         }
00221         return false;
00222 }
00223 
00224 
00225 #ifdef ENABLE_IPV6
00226 #ifdef IPPROTO_IPV6
00227 bool UdpSocket::Open(struct in6_addr& a, port_t port)
00228 {
00229         Ipv6Address ad(a, port);
00230         return Open(ad);
00231 }
00232 #endif
00233 #endif
00234 
00235 
00236 bool UdpSocket::Open(SocketAddress& ad)
00237 {
00238         if (GetSocket() == INVALID_SOCKET)
00239         {
00240                 Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp"));
00241         }
00242         if (GetSocket() != INVALID_SOCKET)
00243         {
00244                 SetNonblocking(true);
00245                 if (connect(GetSocket(), ad, ad) == -1)
00246                 {
00247                         Handler().LogError(this, "connect", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00248                         SetCloseAndDelete();
00249                         return false;
00250                 }
00251                 SetConnected();
00252                 return true;
00253         }
00254         return false;
00255 }
00256 
00257 
00258 void UdpSocket::CreateConnection()
00259 {
00260 #ifdef ENABLE_IPV6
00261 #ifdef IPPROTO_IPV6
00262         if (IsIpv6())
00263         {
00264                 if (GetSocket() == INVALID_SOCKET)
00265                 {
00266                         SOCKET s = CreateSocket(AF_INET6, SOCK_DGRAM, "udp");
00267                         if (s == INVALID_SOCKET)
00268                         {
00269                                 return;
00270                         }
00271                         SetNonblocking(true, s);
00272                         Attach(s);
00273                 }
00274                 return;
00275         }
00276 #endif
00277 #endif
00278         if (GetSocket() == INVALID_SOCKET)
00279         {
00280                 SOCKET s = CreateSocket(AF_INET, SOCK_DGRAM, "udp");
00281                 if (s == INVALID_SOCKET)
00282                 {
00283                         return;
00284                 }
00285                 SetNonblocking(true, s);
00286                 Attach(s);
00287         }
00288 }
00289 
00290 
00292 void UdpSocket::SendToBuf(const std::string& h, port_t p, const char *data, int len, int flags)
00293 {
00294 #ifdef ENABLE_IPV6
00295 #ifdef IPPROTO_IPV6
00296         if (IsIpv6())
00297         {
00298                 Ipv6Address ad(h, p);
00299                 if (ad.IsValid())
00300                 {
00301                         SendToBuf(ad, data, len, flags);
00302                 }
00303                 return;
00304         }
00305 #endif
00306 #endif
00307         Ipv4Address ad(h, p);
00308         if (ad.IsValid())
00309         {
00310                 SendToBuf(ad, data, len, flags);
00311         }
00312 }
00313 
00314 
00316 void UdpSocket::SendToBuf(ipaddr_t a, port_t p, const char *data, int len, int flags)
00317 {
00318         Ipv4Address ad(a, p);
00319         SendToBuf(ad, data, len, flags);
00320 }
00321 
00322 
00323 #ifdef ENABLE_IPV6
00324 #ifdef IPPROTO_IPV6
00325 void UdpSocket::SendToBuf(in6_addr a, port_t p, const char *data, int len, int flags)
00326 {
00327         Ipv6Address ad(a, p);
00328         SendToBuf(ad, data, len, flags);
00329 }
00330 #endif
00331 #endif
00332 
00333 
00334 void UdpSocket::SendToBuf(SocketAddress& ad, const char *data, int len, int flags)
00335 {
00336         if (GetSocket() == INVALID_SOCKET)
00337         {
00338                 Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp"));
00339         }
00340         if (GetSocket() != INVALID_SOCKET)
00341         {
00342                 SetNonblocking(true);
00343                 if ((m_last_size_written = sendto(GetSocket(), data, len, flags, ad, ad)) == -1)
00344                 {
00345                         Handler().LogError(this, "sendto", Errno, StrError(Errno), LOG_LEVEL_ERROR);
00346                 }
00347         }
00348 }
00349 
00350 
00351 void UdpSocket::SendTo(const std::string& a, port_t p, const std::string& str, int flags)
00352 {
00353         SendToBuf(a, p, str.c_str(), (int)str.size(), flags);
00354 }
00355 
00356 
00357 void UdpSocket::SendTo(ipaddr_t a, port_t p, const std::string& str, int flags)
00358 {
00359         SendToBuf(a, p, str.c_str(), (int)str.size(), flags);
00360 }
00361 
00362 
00363 #ifdef ENABLE_IPV6
00364 #ifdef IPPROTO_IPV6
00365 void UdpSocket::SendTo(in6_addr a, port_t p, const std::string& str, int flags)
00366 {
00367         SendToBuf(a, p, str.c_str(), (int)str.size(), flags);
00368 }
00369 #endif
00370 #endif
00371 
00372 
00373 void UdpSocket::SendTo(SocketAddress& ad, const std::string& str, int flags)
00374 {
00375         SendToBuf(ad, str.c_str(), (int)str.size(), flags);
00376 }
00377 
00378 
00380 void UdpSocket::SendBuf(const char *data, size_t len, int flags)
00381 {
00382         if (!IsConnected())
00383         {
00384                 Handler().LogError(this, "SendBuf", 0, "not connected", LOG_LEVEL_ERROR);
00385                 return;
00386         }
00387         if ((m_last_size_written = send(GetSocket(), data, (int)len, flags)) == -1)
00388         {
00389                 Handler().LogError(this, "send", Errno, StrError(Errno), LOG_LEVEL_ERROR);
00390         }
00391 }
00392 
00393 
00394 void UdpSocket::Send(const std::string& str, int flags)
00395 {
00396         SendBuf(str.c_str(), (int)str.size(), flags);
00397 }
00398 
00399 
00400 #if defined(LINUX) || defined(MACOSX)
00401 int UdpSocket::ReadTS(char *ioBuf, int inBufSize, struct sockaddr *from, socklen_t fromlen, struct timeval *ts)
00402 {
00403         struct msghdr msg;
00404         struct iovec vec[1];
00405         union {
00406                 struct cmsghdr cm;
00407 #ifdef MACOSX
00408 #ifdef __DARWIN_UNIX03
00409 #define ALIGNBYTES __DARWIN_ALIGNBYTES
00410 #endif
00411 #define myALIGN(p) (((unsigned int)(p) + ALIGNBYTES) &~ ALIGNBYTES)
00412 #define myCMSG_SPACE(l) (myALIGN(sizeof(struct cmsghdr)) + myALIGN(l))
00413                 char data[ myCMSG_SPACE(sizeof(struct timeval)) ];
00414 #else
00415                 char data[ CMSG_SPACE(sizeof(struct timeval)) ];
00416 #endif
00417         } cmsg_un;
00418         struct cmsghdr *cmsg;
00419         struct timeval *tv;
00420 
00421         vec[0].iov_base = ioBuf;
00422         vec[0].iov_len = inBufSize;
00423 
00424         memset(&msg, 0, sizeof(msg));
00425         memset(from, 0, fromlen);
00426         memset(ioBuf, 0, inBufSize);
00427         memset(&cmsg_un, 0, sizeof(cmsg_un));
00428 
00429         msg.msg_name = (caddr_t)from;
00430         msg.msg_namelen = fromlen;
00431         msg.msg_iov = vec;
00432         msg.msg_iovlen = 1;
00433         msg.msg_control = cmsg_un.data;
00434         msg.msg_controllen = sizeof(cmsg_un.data);
00435         msg.msg_flags = 0;
00436 
00437         
00438         
00439 
00440         int n = recvmsg(GetSocket(), &msg, MSG_DONTWAIT);
00441 
00442         
00443 
00444         
00445         if(n != -1 && msg.msg_controllen >= sizeof(struct cmsghdr) && !(msg.msg_flags & MSG_CTRUNC))
00446         {
00447                 tv = 0;
00448                 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
00449                 {
00450                         if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP)
00451                         {
00452                                 tv = (struct timeval *)CMSG_DATA(cmsg);
00453                         }
00454                 }
00455                 if (tv)
00456                 {
00457                         memcpy(ts, tv, sizeof(struct timeval));
00458                 }
00459         }
00460         
00461         return n;
00462 }
00463 #endif
00464 
00465 
00466 void UdpSocket::OnRead()
00467 {
00468 #ifdef ENABLE_IPV6
00469 #ifdef IPPROTO_IPV6
00470         if (IsIpv6())
00471         {
00472                 struct sockaddr_in6 sa;
00473                 socklen_t sa_len = sizeof(sa);
00474                 if (m_b_read_ts)
00475                 {
00476                         struct timeval ts;
00477                         Utility::GetTime(&ts);
00478 #if !defined(LINUX) && !defined(MACOSX)
00479                         int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
00480 #else
00481                         int n = ReadTS(m_ibuf, m_ibufsz, (struct sockaddr *)&sa, sa_len, &ts);
00482 #endif
00483                         if (n > 0)
00484                         {
00485                                 this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len, &ts);
00486                         }
00487                         else
00488                         if (n == -1)
00489                         {
00490 #ifdef _WIN32
00491                                 if (Errno != WSAEWOULDBLOCK)
00492 #else
00493                                 if (Errno != EWOULDBLOCK)
00494 #endif
00495                                         Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
00496                         }
00497                         return;
00498                 }
00499                 int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
00500                 int q = m_retries; 
00501                 while (n > 0)
00502                 {
00503                         if (sa_len != sizeof(sa))
00504                         {
00505                                 Handler().LogError(this, "recvfrom", 0, "unexpected address struct size", LOG_LEVEL_WARNING);
00506                         }
00507                         this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len);
00508                         if (!q--)
00509                                 break;
00510                         
00511                         n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
00512                 }
00513                 if (n == -1)
00514                 {
00515 #ifdef _WIN32
00516                         if (Errno != WSAEWOULDBLOCK)
00517 #else
00518                         if (Errno != EWOULDBLOCK)
00519 #endif
00520                                 Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
00521                 }
00522                 return;
00523         }
00524 #endif
00525 #endif
00526         struct sockaddr_in sa;
00527         socklen_t sa_len = sizeof(sa);
00528         if (m_b_read_ts)
00529         {
00530                 struct timeval ts;
00531                 Utility::GetTime(&ts);
00532 #if !defined(LINUX) && !defined(MACOSX)
00533                 int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
00534 #else
00535                 int n = ReadTS(m_ibuf, m_ibufsz, (struct sockaddr *)&sa, sa_len, &ts);
00536 #endif
00537                 if (n > 0)
00538                 {
00539                         this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len, &ts);
00540                 }
00541                 else
00542                 if (n == -1)
00543                 {
00544 #ifdef _WIN32
00545                         if (Errno != WSAEWOULDBLOCK)
00546 #else
00547                         if (Errno != EWOULDBLOCK)
00548 #endif
00549                                 Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
00550                 }
00551                 return;
00552         }
00553         int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
00554         int q = m_retries;
00555         while (n > 0)
00556         {
00557                 if (sa_len != sizeof(sa))
00558                 {
00559                         Handler().LogError(this, "recvfrom", 0, "unexpected address struct size", LOG_LEVEL_WARNING);
00560                 }
00561                 this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len);
00562                 if (!q--)
00563                         break;
00564                 
00565                 n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
00566         }
00567         if (n == -1)
00568         {
00569 #ifdef _WIN32
00570                 if (Errno != WSAEWOULDBLOCK)
00571 #else
00572                 if (Errno != EWOULDBLOCK)
00573 #endif
00574                         Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
00575         }
00576 }
00577 
00578 
00579 void UdpSocket::SetBroadcast(bool b)
00580 {
00581         int one = 1;
00582         int zero = 0;
00583 
00584         if (GetSocket() == INVALID_SOCKET)
00585         {
00586                 CreateConnection();
00587         }
00588         if (b)
00589         {
00590                 if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof(one)) == -1)
00591                 {
00592                         Handler().LogError(this, "SetBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00593                 }
00594         }
00595         else
00596         {
00597                 if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *) &zero, sizeof(zero)) == -1)
00598                 {
00599                         Handler().LogError(this, "SetBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00600                 }
00601         }
00602 }
00603 
00604 
00605 bool UdpSocket::IsBroadcast()
00606 {
00607         int is_broadcast = 0;
00608         socklen_t size = sizeof(int);
00609 
00610         if (GetSocket() == INVALID_SOCKET)
00611         {
00612                 CreateConnection();
00613         }
00614         if (getsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *)&is_broadcast, &size) == -1)
00615         {
00616                 Handler().LogError(this, "IsBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00617         }
00618         return is_broadcast != 0;
00619 }
00620 
00621 
00622 void UdpSocket::SetMulticastTTL(int ttl)
00623 {
00624         if (GetSocket() == INVALID_SOCKET)
00625         {
00626                 CreateConnection();
00627         }
00628         if (setsockopt(GetSocket(), SOL_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(int)) == -1)
00629         {
00630                 Handler().LogError(this, "SetMulticastTTL", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00631         }
00632 }
00633 
00634 
00635 int UdpSocket::GetMulticastTTL()
00636 {
00637         int ttl = 0;
00638         socklen_t size = sizeof(int);
00639 
00640         if (GetSocket() == INVALID_SOCKET)
00641         {
00642                 CreateConnection();
00643         }
00644         if (getsockopt(GetSocket(), SOL_IP, IP_MULTICAST_TTL, (char *)&ttl, &size) == -1)
00645         {
00646                 Handler().LogError(this, "GetMulticastTTL", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00647         }
00648         return ttl;
00649 }
00650 
00651 
00652 void UdpSocket::SetMulticastLoop(bool x)
00653 {
00654         if (GetSocket() == INVALID_SOCKET)
00655         {
00656                 CreateConnection();
00657         }
00658 #ifdef ENABLE_IPV6
00659 #ifdef IPPROTO_IPV6
00660         if (IsIpv6())
00661         {
00662                 int val = x ? 1 : 0;
00663                 if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&val, sizeof(int)) == -1)
00664                 {
00665                         Handler().LogError(this, "SetMulticastLoop(ipv6)", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00666                 }
00667                 return;
00668         }
00669 #endif
00670 #endif
00671         int val = x ? 1 : 0;
00672         if (setsockopt(GetSocket(), SOL_IP, IP_MULTICAST_LOOP, (char *)&val, sizeof(int)) == -1)
00673         {
00674                 Handler().LogError(this, "SetMulticastLoop(ipv4)", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00675         }
00676 }
00677 
00678 
00679 bool UdpSocket::IsMulticastLoop()
00680 {
00681         if (GetSocket() == INVALID_SOCKET)
00682         {
00683                 CreateConnection();
00684         }
00685 #ifdef ENABLE_IPV6
00686 #ifdef IPPROTO_IPV6
00687         if (IsIpv6())
00688         {
00689                 int is_loop = 0;
00690                 socklen_t size = sizeof(int);
00691                 if (getsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&is_loop, &size) == -1)
00692                 {
00693                         Handler().LogError(this, "IsMulticastLoop(ipv6)", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00694                 }
00695                 return is_loop ? true : false;
00696         }
00697 #endif
00698 #endif
00699         int is_loop = 0;
00700         socklen_t size = sizeof(int);
00701         if (getsockopt(GetSocket(), SOL_IP, IP_MULTICAST_LOOP, (char *)&is_loop, &size) == -1)
00702         {
00703                 Handler().LogError(this, "IsMulticastLoop(ipv4)", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00704         }
00705         return is_loop ? true : false;
00706 }
00707 
00708 
00709 void UdpSocket::AddMulticastMembership(const std::string& group, const std::string& local_if, int if_index)
00710 {
00711         if (GetSocket() == INVALID_SOCKET)
00712         {
00713                 CreateConnection();
00714         }
00715 #ifdef ENABLE_IPV6
00716 #ifdef IPPROTO_IPV6
00717         if (IsIpv6())
00718         {
00719                 struct ipv6_mreq x;
00720                 struct in6_addr addr;
00721                 if (Utility::u2ip( group, addr ))
00722                 {
00723                         x.ipv6mr_multiaddr = addr;
00724                         x.ipv6mr_interface = if_index;
00725                         if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&x, sizeof(struct ipv6_mreq)) == -1)
00726                         {
00727                                 Handler().LogError(this, "AddMulticastMembership(ipv6)", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00728                         }
00729                 }
00730                 return;
00731         }
00732 #endif
00733 #endif
00734         struct ip_mreq x; 
00735         ipaddr_t addr;
00736         if (Utility::u2ip( group, addr ))
00737         {
00738                 memcpy(&x.imr_multiaddr.s_addr, &addr, sizeof(addr));
00739                 Utility::u2ip( local_if, addr);
00740                 memcpy(&x.imr_interface.s_addr, &addr, sizeof(x.imr_interface.s_addr));
00741 
00742                 if (setsockopt(GetSocket(), SOL_IP, IP_ADD_MEMBERSHIP, (char *)&x, sizeof(struct ip_mreq)) == -1)
00743                 {
00744                         Handler().LogError(this, "AddMulticastMembership(ipv4)", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00745                 }
00746         }
00747 }
00748 
00749 
00750 void UdpSocket::DropMulticastMembership(const std::string& group, const std::string& local_if, int if_index)
00751 {
00752         if (GetSocket() == INVALID_SOCKET)
00753         {
00754                 CreateConnection();
00755         }
00756 #ifdef ENABLE_IPV6
00757 #ifdef IPPROTO_IPV6
00758         if (IsIpv6())
00759         {
00760                 struct ipv6_mreq x;
00761                 struct in6_addr addr;
00762                 if (Utility::u2ip( group, addr ))
00763                 {
00764                         x.ipv6mr_multiaddr = addr;
00765                         x.ipv6mr_interface = if_index;
00766                         if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *)&x, sizeof(struct ipv6_mreq)) == -1)
00767                         {
00768                                 Handler().LogError(this, "DropMulticastMembership(ipv6)", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00769                         }
00770                 }
00771                 return;
00772         }
00773 #endif
00774 #endif
00775         struct ip_mreq x; 
00776         ipaddr_t addr;
00777         if (Utility::u2ip( group, addr ))
00778         {
00779                 memcpy(&x.imr_multiaddr.s_addr, &addr, sizeof(addr));
00780                 Utility::u2ip( local_if, addr);
00781                 memcpy(&x.imr_interface.s_addr, &addr, sizeof(x.imr_interface.s_addr));
00782 
00783                 if (setsockopt(GetSocket(), SOL_IP, IP_DROP_MEMBERSHIP, (char *)&x, sizeof(struct ip_mreq)) == -1)
00784                 {
00785                         Handler().LogError(this, "DropMulticastMembership(ipv4)", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00786                 }
00787         }
00788 }
00789 
00790 
00791 #ifdef ENABLE_IPV6
00792 #ifdef IPPROTO_IPV6
00793 void UdpSocket::SetMulticastHops(int hops)
00794 {
00795         if (GetSocket() == INVALID_SOCKET)
00796         {
00797                 CreateConnection();
00798         }
00799         if (!IsIpv6())
00800         {
00801                 Handler().LogError(this, "SetMulticastHops", 0, "Ipv6 only", LOG_LEVEL_ERROR);
00802                 return;
00803         }
00804         if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, sizeof(int)) == -1)
00805         {
00806                 Handler().LogError(this, "SetMulticastHops", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00807         }
00808 }
00809 
00810 
00811 int UdpSocket::GetMulticastHops()
00812 {
00813         if (GetSocket() == INVALID_SOCKET)
00814         {
00815                 CreateConnection();
00816         }
00817         if (!IsIpv6())
00818         {
00819                 Handler().LogError(this, "SetMulticastHops", 0, "Ipv6 only", LOG_LEVEL_ERROR);
00820                 return -1;
00821         }
00822         int hops = 0;
00823         socklen_t size = sizeof(int);
00824         if (getsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, &size) == -1)
00825         {
00826                 Handler().LogError(this, "GetMulticastHops", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00827         }
00828         return hops;
00829 }
00830 #endif // IPPROTO_IPV6
00831 #endif
00832 
00833 
00834 bool UdpSocket::IsBound()
00835 {
00836         return m_bind_ok;
00837 }
00838 
00839 
00840 void UdpSocket::OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len)
00841 {
00842 }
00843 
00844 
00845 void UdpSocket::OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len, struct timeval *ts)
00846 {
00847 }
00848 
00849 
00850 port_t UdpSocket::GetPort()
00851 {
00852         return m_port;
00853 }
00854 
00855 
00856 int UdpSocket::GetLastSizeWritten()
00857 {
00858         return m_last_size_written;
00859 }
00860 
00861 
00862 void UdpSocket::SetTimestamp(bool x)
00863 {
00864         m_b_read_ts = x;
00865 }
00866 
00867 
00868 void UdpSocket::SetMulticastDefaultInterface(ipaddr_t a, int if_index)
00869 {
00870         struct in_addr x;
00871         memcpy(&x.s_addr, &a, sizeof(x.s_addr));
00872         if (setsockopt(GetSocket(), IPPROTO_IP, IP_MULTICAST_IF, (char *)&x, sizeof(x)) == -1)
00873         {
00874                 Handler().LogError(this, "SetMulticastDefaultInterface(ipv4)", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00875         }
00876 }
00877 
00878 
00879 #ifdef ENABLE_IPV6
00880 #ifdef IPPROTO_IPV6
00881 void UdpSocket::SetMulticastDefaultInterface(in6_addr a, int if_index)
00882 {
00883         if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_index, sizeof(if_index)) == -1)
00884         {
00885                 Handler().LogError(this, "SetMulticastDefaultInterface(ipv6)", Errno, StrError(Errno), LOG_LEVEL_WARNING);
00886         }
00887 }
00888 #endif
00889 #endif
00890 
00891 
00892 void UdpSocket::SetMulticastDefaultInterface(const std::string& intf, int if_index)
00893 {
00894         if (GetSocket() == INVALID_SOCKET)
00895         {
00896                 CreateConnection();
00897         }
00898 #ifdef ENABLE_IPV6
00899 #ifdef IPPROTO_IPV6
00900         if (IsIpv6())
00901         {
00902                 struct in6_addr a;
00903                 if (Utility::u2ip( intf, a ))
00904                 {
00905                         SetMulticastDefaultInterface( a, if_index );
00906                 }
00907                 return;
00908         }
00909 #endif
00910 #endif
00911         ipaddr_t a;
00912         if (Utility::u2ip( intf, a ))
00913         {
00914                 SetMulticastDefaultInterface( a, if_index );
00915         }
00916 }
00917 
00918 
00919 #ifdef SOCKETS_NAMESPACE
00920 }
00921 #endif
00922 
00923