root/trunk/dep/src/sockets/UdpSocket.cpp @ 2

Revision 2, 18.0 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/** \file UdpSocket.cpp
2 **     \date  2004-02-13
3 **     \author grymse@alhem.net
4**/
5/*
6Copyright (C) 2004-2007  Anders Hedstrom
7
8This library is made available under the terms of the GNU GPL.
9
10If you would like to use this library in a closed-source application,
11a separate license agreement is available. For information about
12the closed-source license agreement for the C++ sockets library,
13please visit http://www.alhem.net/Sockets/license.html and/or
14email license@alhem.net.
15
16This program is free software; you can redistribute it and/or
17modify it under the terms of the GNU General Public License
18as published by the Free Software Foundation; either version 2
19of the License, or (at your option) any later version.
20
21This program is distributed in the hope that it will be useful,
22but WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24GNU General Public License for more details.
25
26You should have received a copy of the GNU General Public License
27along with this program; if not, write to the Free Software
28Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
29*/
30#ifdef _WIN32
31#ifdef _MSC_VER
32#pragma warning(disable:4786)
33#endif
34#include <stdlib.h>
35#else
36#include <errno.h>
37#endif
38
39#include "ISocketHandler.h"
40#include "UdpSocket.h"
41#include "Utility.h"
42#include "Ipv4Address.h"
43#include "Ipv6Address.h"
44#ifdef ENABLE_EXCEPTIONS
45#include "Exception.h"
46#endif
47// include this to see strange sights
48//#include <linux/in6.h>
49
50
51#ifdef SOCKETS_NAMESPACE
52namespace SOCKETS_NAMESPACE {
53#endif
54
55
56UdpSocket::UdpSocket(ISocketHandler& h, int ibufsz, bool ipv6, int retries) : Socket(h)
57, m_ibuf(new char[ibufsz])
58, m_ibufsz(ibufsz)
59, m_bind_ok(false)
60, m_port(0)
61, m_last_size_written(-1)
62, m_retries(retries)
63, m_b_read_ts(false)
64{
65#ifdef ENABLE_IPV6
66#ifdef IPPROTO_IPV6
67        SetIpv6(ipv6);
68#endif
69#endif
70}
71
72
73UdpSocket::~UdpSocket()
74{
75        Close();
76        delete[] m_ibuf;
77}
78
79
80int UdpSocket::Bind(port_t &port, int range)
81{
82#ifdef ENABLE_IPV6
83#ifdef IPPROTO_IPV6
84        if (IsIpv6())
85        {
86                Ipv6Address ad(port);
87                return Bind(ad, range);
88        }
89#endif
90#endif
91        Ipv4Address ad(port);
92        return Bind(ad, range);
93}
94
95
96int UdpSocket::Bind(const std::string& intf, port_t &port, int range)
97{
98#ifdef ENABLE_IPV6
99#ifdef IPPROTO_IPV6
100        if (IsIpv6())
101        {
102                Ipv6Address ad(intf, port);
103                if (ad.IsValid())
104                {
105                        return Bind(ad, range);
106                }
107                SetCloseAndDelete();
108                return -1;
109        }
110#endif
111#endif
112        Ipv4Address ad(intf, port);
113        if (ad.IsValid())
114        {
115                return Bind(ad, range);
116        }
117        SetCloseAndDelete();
118        return -1;
119}
120
121
122int UdpSocket::Bind(ipaddr_t a, port_t &port, int range)
123{
124        Ipv4Address ad(a, port);
125        return Bind(ad, range);
126}
127
128
129#ifdef ENABLE_IPV6
130#ifdef IPPROTO_IPV6
131int UdpSocket::Bind(in6_addr a, port_t &port, int range)
132{
133        Ipv6Address ad(a, port);
134        return Bind(ad, range);
135}
136#endif
137#endif
138
139
140int UdpSocket::Bind(SocketAddress& ad, int range)
141{
142        if (GetSocket() == INVALID_SOCKET)
143        {
144                Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp"));
145        }
146        if (GetSocket() != INVALID_SOCKET)
147        {
148                SetNonblocking(true);
149                int n = bind(GetSocket(), ad, ad);
150                int tries = range;
151                while (n == -1 && tries--)
152                {
153                        ad.SetPort(ad.GetPort() + 1);
154                        n = bind(GetSocket(), ad, ad);
155                }
156                if (n == -1)
157                {
158                        Handler().LogError(this, "bind", Errno, StrError(Errno), LOG_LEVEL_FATAL);
159                        SetCloseAndDelete();
160#ifdef ENABLE_EXCEPTIONS
161                        throw Exception("bind() failed for UdpSocket, port:range: " + Utility::l2string(ad.GetPort()) + ":" + Utility::l2string(range));
162#endif
163                        return -1;
164                }
165                m_bind_ok = true;
166                m_port = ad.GetPort();
167                return 0;
168        }
169        return -1;
170}
171
172
173/** if you wish to use Send, first Open a connection */
174bool UdpSocket::Open(ipaddr_t l, port_t port)
175{
176        Ipv4Address ad(l, port);
177        return Open(ad);
178}
179
180
181bool UdpSocket::Open(const std::string& host, port_t port)
182{
183#ifdef ENABLE_IPV6
184#ifdef IPPROTO_IPV6
185        if (IsIpv6())
186        {
187                Ipv6Address ad(host, port);
188                if (ad.IsValid())
189                {
190                        return Open(ad);
191                }
192                return false;
193        }
194#endif
195#endif
196        Ipv4Address ad(host, port);
197        if (ad.IsValid())
198        {
199                return Open(ad);
200        }
201        return false;
202}
203
204
205#ifdef ENABLE_IPV6
206#ifdef IPPROTO_IPV6
207bool UdpSocket::Open(struct in6_addr& a, port_t port)
208{
209        Ipv6Address ad(a, port);
210        return Open(ad);
211}
212#endif
213#endif
214
215
216bool UdpSocket::Open(SocketAddress& ad)
217{
218        if (GetSocket() == INVALID_SOCKET)
219        {
220                Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp"));
221        }
222        if (GetSocket() != INVALID_SOCKET)
223        {
224                SetNonblocking(true);
225                if (connect(GetSocket(), ad, ad) == -1)
226                {
227                        Handler().LogError(this, "connect", Errno, StrError(Errno), LOG_LEVEL_FATAL);
228                        SetCloseAndDelete();
229                        return false;
230                }
231                SetConnected();
232                return true;
233        }
234        return false;
235}
236
237
238void UdpSocket::CreateConnection()
239{
240#ifdef ENABLE_IPV6
241#ifdef IPPROTO_IPV6
242        if (IsIpv6())
243        {
244                if (GetSocket() == INVALID_SOCKET)
245                {
246                        SOCKET s = CreateSocket(AF_INET6, SOCK_DGRAM, "udp");
247                        if (s == INVALID_SOCKET)
248                        {
249                                return;
250                        }
251                        SetNonblocking(true, s);
252                        Attach(s);
253                }
254                return;
255        }
256#endif
257#endif
258        if (GetSocket() == INVALID_SOCKET)
259        {
260                SOCKET s = CreateSocket(AF_INET, SOCK_DGRAM, "udp");
261                if (s == INVALID_SOCKET)
262                {
263                        return;
264                }
265                SetNonblocking(true, s);
266                Attach(s);
267        }
268}
269
270
271/** send to specified address */
272void UdpSocket::SendToBuf(const std::string& h, port_t p, const char *data, int len, int flags)
273{
274#ifdef ENABLE_IPV6
275#ifdef IPPROTO_IPV6
276        if (IsIpv6())
277        {
278                Ipv6Address ad(h, p);
279                if (ad.IsValid())
280                {
281                        SendToBuf(ad, data, len, flags);
282                }
283                return;
284        }
285#endif
286#endif
287        Ipv4Address ad(h, p);
288        if (ad.IsValid())
289        {
290                SendToBuf(ad, data, len, flags);
291        }
292}
293
294
295/** send to specified address */
296void UdpSocket::SendToBuf(ipaddr_t a, port_t p, const char *data, int len, int flags)
297{
298        Ipv4Address ad(a, p);
299        SendToBuf(ad, data, len, flags);
300}
301
302
303#ifdef ENABLE_IPV6
304#ifdef IPPROTO_IPV6
305void UdpSocket::SendToBuf(in6_addr a, port_t p, const char *data, int len, int flags)
306{
307        Ipv6Address ad(a, p);
308        SendToBuf(ad, data, len, flags);
309}
310#endif
311#endif
312
313
314void UdpSocket::SendToBuf(SocketAddress& ad, const char *data, int len, int flags)
315{
316        if (GetSocket() == INVALID_SOCKET)
317        {
318                Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp"));
319        }
320        if (GetSocket() != INVALID_SOCKET)
321        {
322                SetNonblocking(true);
323                if ((m_last_size_written = sendto(GetSocket(), data, len, flags, ad, ad)) == -1)
324                {
325                        Handler().LogError(this, "sendto", Errno, StrError(Errno), LOG_LEVEL_ERROR);
326                }
327        }
328}
329
330
331void UdpSocket::SendTo(const std::string& a, port_t p, const std::string& str, int flags)
332{
333        SendToBuf(a, p, str.c_str(), (int)str.size(), flags);
334}
335
336
337void UdpSocket::SendTo(ipaddr_t a, port_t p, const std::string& str, int flags)
338{
339        SendToBuf(a, p, str.c_str(), (int)str.size(), flags);
340}
341
342
343#ifdef ENABLE_IPV6
344#ifdef IPPROTO_IPV6
345void UdpSocket::SendTo(in6_addr a, port_t p, const std::string& str, int flags)
346{
347        SendToBuf(a, p, str.c_str(), (int)str.size(), flags);
348}
349#endif
350#endif
351
352
353void UdpSocket::SendTo(SocketAddress& ad, const std::string& str, int flags)
354{
355        SendToBuf(ad, str.c_str(), (int)str.size(), flags);
356}
357
358
359/** send to connected address */
360void UdpSocket::SendBuf(const char *data, size_t len, int flags)
361{
362        if (!IsConnected())
363        {
364                Handler().LogError(this, "SendBuf", 0, "not connected", LOG_LEVEL_ERROR);
365                return;
366        }
367        if ((m_last_size_written = send(GetSocket(), data, (int)len, flags)) == -1)
368        {
369                Handler().LogError(this, "send", Errno, StrError(Errno), LOG_LEVEL_ERROR);
370        }
371}
372
373
374void UdpSocket::Send(const std::string& str, int flags)
375{
376        SendBuf(str.c_str(), (int)str.size(), flags);
377}
378
379
380#if defined(LINUX) || defined(MACOSX)
381int UdpSocket::ReadTS(char *ioBuf, int inBufSize, struct sockaddr *from, socklen_t fromlen, struct timeval *ts)
382{
383        struct msghdr msg;
384        struct iovec vec[1];
385        union {
386                struct cmsghdr cm;
387#ifdef MACOSX
388#ifdef __DARWIN_UNIX03
389#define ALIGNBYTES __DARWIN_ALIGNBYTES
390#endif
391#define myALIGN(p) (((unsigned int)(p) + ALIGNBYTES) &~ ALIGNBYTES)
392#define myCMSG_SPACE(l) (myALIGN(sizeof(struct cmsghdr)) + myALIGN(l))
393                char data[ myCMSG_SPACE(sizeof(struct timeval)) ];
394#else
395                char data[ CMSG_SPACE(sizeof(struct timeval)) ];
396#endif
397        } cmsg_un;
398        struct cmsghdr *cmsg;
399        struct timeval *tv;
400
401        vec[0].iov_base = ioBuf;
402        vec[0].iov_len = inBufSize;
403
404        memset(&msg, 0, sizeof(msg));
405        memset(from, 0, fromlen);
406        memset(ioBuf, 0, inBufSize);
407        memset(&cmsg_un, 0, sizeof(cmsg_un));
408
409        msg.msg_name = (caddr_t)from;
410        msg.msg_namelen = fromlen;
411        msg.msg_iov = vec;
412        msg.msg_iovlen = 1;
413        msg.msg_control = cmsg_un.data;
414        msg.msg_controllen = sizeof(cmsg_un.data);
415        msg.msg_flags = 0;
416
417        // Original version - for reference only
418        //int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
419
420        int n = recvmsg(GetSocket(), &msg, MSG_DONTWAIT);
421
422        // now ioBuf will contain the data, as if we used recvfrom
423
424        // Now get the time
425        if(n != -1 && msg.msg_controllen >= sizeof(struct cmsghdr) && !(msg.msg_flags & MSG_CTRUNC))
426        {
427                tv = 0;
428                for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
429                {
430                        if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP)
431                        {
432                                tv = (struct timeval *)CMSG_DATA(cmsg);
433                        }
434                }
435                if (tv)
436                {
437                        memcpy(ts, tv, sizeof(struct timeval));
438                }
439        }
440        // The address is in network order, but that's OK right now
441        return n;
442}
443#endif
444
445
446void UdpSocket::OnRead()
447{
448#ifdef ENABLE_IPV6
449#ifdef IPPROTO_IPV6
450        if (IsIpv6())
451        {
452                struct sockaddr_in6 sa;
453                socklen_t sa_len = sizeof(sa);
454                if (m_b_read_ts)
455                {
456                        struct timeval ts;
457                        Utility::GetTime(&ts);
458#if !defined(LINUX) && !defined(MACOSX)
459                        int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
460#else
461                        int n = ReadTS(m_ibuf, m_ibufsz, (struct sockaddr *)&sa, sa_len, &ts);
462#endif
463                        if (n > 0)
464                        {
465                                this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len, &ts);
466                        }
467                        else
468                        if (n == -1)
469                        {
470#ifdef _WIN32
471                                if (Errno != WSAEWOULDBLOCK)
472#else
473                                if (Errno != EWOULDBLOCK)
474#endif
475                                        Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
476                        }
477                        return;
478                }
479                int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
480                int q = m_retries; // receive max 10 at one cycle
481                while (n > 0)
482                {
483                        if (sa_len != sizeof(sa))
484                        {
485                                Handler().LogError(this, "recvfrom", 0, "unexpected address struct size", LOG_LEVEL_WARNING);
486                        }
487                        this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len);
488                        if (!q--)
489                                break;
490                        //
491                        n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
492                }
493                if (n == -1)
494                {
495#ifdef _WIN32
496                        if (Errno != WSAEWOULDBLOCK)
497#else
498                        if (Errno != EWOULDBLOCK)
499#endif
500                                Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
501                }
502                return;
503        }
504#endif
505#endif
506        struct sockaddr_in sa;
507        socklen_t sa_len = sizeof(sa);
508        if (m_b_read_ts)
509        {
510                struct timeval ts;
511                Utility::GetTime(&ts);
512#if !defined(LINUX) && !defined(MACOSX)
513                int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
514#else
515                int n = ReadTS(m_ibuf, m_ibufsz, (struct sockaddr *)&sa, sa_len, &ts);
516#endif
517                if (n > 0)
518                {
519                        this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len, &ts);
520                }
521                else
522                if (n == -1)
523                {
524#ifdef _WIN32
525                        if (Errno != WSAEWOULDBLOCK)
526#else
527                        if (Errno != EWOULDBLOCK)
528#endif
529                                Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
530                }
531                return;
532        }
533        int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
534        int q = m_retries;
535        while (n > 0)
536        {
537                if (sa_len != sizeof(sa))
538                {
539                        Handler().LogError(this, "recvfrom", 0, "unexpected address struct size", LOG_LEVEL_WARNING);
540                }
541                this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len);
542                if (!q--)
543                        break;
544                //
545                n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
546        }
547        if (n == -1)
548        {
549#ifdef _WIN32
550                if (Errno != WSAEWOULDBLOCK)
551#else
552                if (Errno != EWOULDBLOCK)
553#endif
554                        Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
555        }
556}
557
558
559void UdpSocket::SetBroadcast(bool b)
560{
561        int one = 1;
562        int zero = 0;
563
564        if (GetSocket() == INVALID_SOCKET)
565        {
566                CreateConnection();
567        }
568        if (b)
569        {
570                if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof(one)) == -1)
571                {
572                        Handler().LogError(this, "SetBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
573                }
574        }
575        else
576        {
577                if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *) &zero, sizeof(zero)) == -1)
578                {
579                        Handler().LogError(this, "SetBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
580                }
581        }
582}
583
584
585bool UdpSocket::IsBroadcast()
586{
587        int is_broadcast = 0;
588        socklen_t size;
589
590        if (GetSocket() == INVALID_SOCKET)
591        {
592                CreateConnection();
593        }
594        if (getsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *)&is_broadcast, &size) == -1)
595        {
596                Handler().LogError(this, "IsBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
597        }
598        return is_broadcast != 0;
599}
600
601
602void UdpSocket::SetMulticastTTL(int ttl)
603{
604        if (GetSocket() == INVALID_SOCKET)
605        {
606                CreateConnection();
607        }
608        if (setsockopt(GetSocket(), SOL_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(int)) == -1)
609        {
610                Handler().LogError(this, "SetMulticastTTL", Errno, StrError(Errno), LOG_LEVEL_WARNING);
611        }
612}
613
614
615int UdpSocket::GetMulticastTTL()
616{
617        int ttl = 0;
618        socklen_t size = sizeof(int);
619
620        if (GetSocket() == INVALID_SOCKET)
621        {
622                CreateConnection();
623        }
624        if (getsockopt(GetSocket(), SOL_IP, IP_MULTICAST_TTL, (char *)&ttl, &size) == -1)
625        {
626                Handler().LogError(this, "GetMulticastTTL", Errno, StrError(Errno), LOG_LEVEL_WARNING);
627        }
628        return ttl;
629}
630
631
632void UdpSocket::SetMulticastLoop(bool x)
633{
634        if (GetSocket() == INVALID_SOCKET)
635        {
636                CreateConnection();
637        }
638#ifdef ENABLE_IPV6
639#ifdef IPPROTO_IPV6
640        if (IsIpv6())
641        {
642                int val = x ? 1 : 0;
643                if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&val, sizeof(int)) == -1)
644                {
645                        Handler().LogError(this, "SetMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
646                }
647                return;
648        }
649#endif
650#endif
651        int val = x ? 1 : 0;
652        if (setsockopt(GetSocket(), SOL_IP, IP_MULTICAST_LOOP, (char *)&val, sizeof(int)) == -1)
653        {
654                Handler().LogError(this, "SetMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
655        }
656}
657
658
659bool UdpSocket::IsMulticastLoop()
660{
661        if (GetSocket() == INVALID_SOCKET)
662        {
663                CreateConnection();
664        }
665#ifdef ENABLE_IPV6
666#ifdef IPPROTO_IPV6
667        if (IsIpv6())
668        {
669                int is_loop = 0;
670                socklen_t size = sizeof(int);
671                if (getsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&is_loop, &size) == -1)
672                {
673                        Handler().LogError(this, "IsMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
674                }
675                return is_loop ? true : false;
676        }
677#endif
678#endif
679        int is_loop = 0;
680        socklen_t size = sizeof(int);
681        if (getsockopt(GetSocket(), SOL_IP, IP_MULTICAST_LOOP, (char *)&is_loop, &size) == -1)
682        {
683                Handler().LogError(this, "IsMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
684        }
685        return is_loop ? true : false;
686}
687
688
689void UdpSocket::AddMulticastMembership(const std::string& group, const std::string& local_if, int if_index)
690{
691        if (GetSocket() == INVALID_SOCKET)
692        {
693                CreateConnection();
694        }
695#ifdef ENABLE_IPV6
696#ifdef IPPROTO_IPV6
697        if (IsIpv6())
698        {
699                struct ipv6_mreq x;
700                struct in6_addr addr;
701                if (Utility::u2ip( group, addr ))
702                {
703                        x.ipv6mr_multiaddr = addr;
704                        x.ipv6mr_interface = if_index;
705                        if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&x, sizeof(struct ipv6_mreq)) == -1)
706                        {
707                                Handler().LogError(this, "AddMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
708                        }
709                }
710                return;
711        }
712#endif
713#endif
714        struct ip_mreq x; // ip_mreqn
715        ipaddr_t addr;
716        if (Utility::u2ip( group, addr ))
717        {
718                memcpy(&x.imr_multiaddr.s_addr, &addr, sizeof(addr));
719                Utility::u2ip( local_if, addr);
720                memcpy(&x.imr_interface.s_addr, &addr, sizeof(addr));
721//              x.imr_ifindex = if_index;
722                if (setsockopt(GetSocket(), SOL_IP, IP_ADD_MEMBERSHIP, (char *)&x, sizeof(struct ip_mreq)) == -1)
723                {
724                        Handler().LogError(this, "AddMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
725                }
726        }
727}
728
729
730void UdpSocket::DropMulticastMembership(const std::string& group, const std::string& local_if, int if_index)
731{
732        if (GetSocket() == INVALID_SOCKET)
733        {
734                CreateConnection();
735        }
736#ifdef ENABLE_IPV6
737#ifdef IPPROTO_IPV6
738        if (IsIpv6())
739        {
740                struct ipv6_mreq x;
741                struct in6_addr addr;
742                if (Utility::u2ip( group, addr ))
743                {
744                        x.ipv6mr_multiaddr = addr;
745                        x.ipv6mr_interface = if_index;
746                        if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *)&x, sizeof(struct ipv6_mreq)) == -1)
747                        {
748                                Handler().LogError(this, "DropMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
749                        }
750                }
751                return;
752        }
753#endif
754#endif
755        struct ip_mreq x; // ip_mreqn
756        ipaddr_t addr;
757        if (Utility::u2ip( group, addr ))
758        {
759                memcpy(&x.imr_multiaddr.s_addr, &addr, sizeof(addr));
760                Utility::u2ip( local_if, addr);
761                memcpy(&x.imr_interface.s_addr, &addr, sizeof(addr));
762//              x.imr_ifindex = if_index;
763                if (setsockopt(GetSocket(), SOL_IP, IP_DROP_MEMBERSHIP, (char *)&x, sizeof(struct ip_mreq)) == -1)
764                {
765                        Handler().LogError(this, "DropMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
766                }
767        }
768}
769
770
771#ifdef ENABLE_IPV6
772#ifdef IPPROTO_IPV6
773void UdpSocket::SetMulticastHops(int hops)
774{
775        if (GetSocket() == INVALID_SOCKET)
776        {
777                CreateConnection();
778        }
779        if (!IsIpv6())
780        {
781                Handler().LogError(this, "SetMulticastHops", 0, "Ipv6 only", LOG_LEVEL_ERROR);
782                return;
783        }
784        if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, sizeof(int)) == -1)
785        {
786                Handler().LogError(this, "SetMulticastHops", Errno, StrError(Errno), LOG_LEVEL_WARNING);
787        }
788}
789
790
791int UdpSocket::GetMulticastHops()
792{
793        if (GetSocket() == INVALID_SOCKET)
794        {
795                CreateConnection();
796        }
797        if (!IsIpv6())
798        {
799                Handler().LogError(this, "SetMulticastHops", 0, "Ipv6 only", LOG_LEVEL_ERROR);
800                return -1;
801        }
802        int hops = 0;
803        socklen_t size = sizeof(int);
804        if (getsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, &size) == -1)
805        {
806                Handler().LogError(this, "GetMulticastHops", Errno, StrError(Errno), LOG_LEVEL_WARNING);
807        }
808        return hops;
809}
810#endif // IPPROTO_IPV6
811#endif
812
813
814bool UdpSocket::IsBound()
815{
816        return m_bind_ok;
817}
818
819
820void UdpSocket::OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len)
821{
822}
823
824
825void UdpSocket::OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len, struct timeval *ts)
826{
827}
828
829
830port_t UdpSocket::GetPort()
831{
832        return m_port;
833}
834
835
836int UdpSocket::GetLastSizeWritten()
837{
838        return m_last_size_written;
839}
840
841
842void UdpSocket::SetTimestamp(bool x)
843{
844        m_b_read_ts = x;
845}
846
847
848#ifdef SOCKETS_NAMESPACE
849}
850#endif
851
852
Note: See TracBrowser for help on using the browser.