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