5 // Created by Terrin Eager on 10/24/12.
8 #define __APPLE_USE_RFC_2292
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
22 ////////////////////////////
24 ///////////////////////////
25 const BJ_UINT16 BonjourPort
= 5353;
44 buffer
= (BJ_UINT8
*)malloc(MAX_FRAME_SIZE
);
50 memset(&socketMsghdr
, '\0', sizeof(socketMsghdr
));
51 socketMsghdr
.msg_name
= &peerAddr
;
52 socketMsghdr
.msg_namelen
= sizeof(peerAddr
);
53 socketMsghdr
.msg_iov
= socketIovec
;
54 socketMsghdr
.msg_iovlen
= 1;
55 socketIovec
[0].iov_base
= (char *) buffer
;
56 socketIovec
[0].iov_len
= MAX_FRAME_SIZE
;
59 socketMsghdr
.msg_control
= socketCmsghdr
;
60 socketMsghdr
.msg_controllen
= sizeof(socketCmsghdr
);
66 bool BJSocket::CreateListenerIPv4(BJString interfaceName
)
69 const int onoptval
= 1;
77 if (interfaceName
.GetLength() > 0)
78 interfaceID
= if_nametoindex(interfaceName
.GetBuffer());
81 socketHandle
= socket(PF_INET
,SOCK_DGRAM
,IPPROTO_UDP
);
82 // socketHandle = socket(PF_INET,SOCK_DGRAM,IPPROTO_RAW);
84 if (-1 == setsockopt(socketHandle
,SOL_SOCKET
,SO_REUSEPORT
,&onoptval
,sizeof(onoptval
)))
86 printf("setsockopt for SO_REUSEPORT failed");
91 JoinMulticastv4(interfaceName
);
93 // set PktInfo to get dest address
95 if (-1 == setsockopt(socketHandle
, IPPROTO_IP
, IP_PKTINFO
, &onoptval
, sizeof(onoptval
)))
97 printf("setsockopt for IP_PKTINFO failed");
104 struct sockaddr_in sa
;
105 memset(&sa
,0,sizeof(sockaddr_in
));
106 sa
.sin_len
= sizeof(sockaddr_in
);
107 sa
.sin_family
= AF_INET
;
108 sa
.sin_addr
.s_addr
= INADDR_ANY
;
109 sa
.sin_port
= htons(BonjourPort
);
111 if (-1 == bind(socketHandle
,(struct sockaddr
*)&sa
,sizeof(sa
)))
113 printf("error in bind: %s\n",strerror(errno
));
122 bool BJSocket::CreateListenerIPv6(BJString interfaceName
)
125 const int onoptval
=1;
132 if (interfaceName
.GetLength() > 0)
133 interfaceID
= if_nametoindex(interfaceName
.GetBuffer());
135 socketHandle
= socket(PF_INET6
,SOCK_DGRAM
,IPPROTO_UDP
);
137 if (-1 == setsockopt(socketHandle
,SOL_SOCKET
,SO_REUSEPORT
,&onoptval
,sizeof(onoptval
)))
139 printf("setsockopt for SO_REUSEPORT failed");
144 JoinMulticastv6(interfaceName
);
146 // set PktInfo to get dest address
147 if (-1 == setsockopt(socketHandle
, IPPROTO_IPV6
, IPV6_PKTINFO
, &onoptval
, sizeof(onoptval
)))
149 printf("setsockopt for IP_PKTINFO failed");
155 struct sockaddr_in6 sa6
;
156 memset(&sa6
,0,sizeof(sockaddr_in6
));
157 sa6
.sin6_len
= sizeof(sockaddr_in6
);
158 sa6
.sin6_family
= AF_INET6
;
159 sa6
.sin6_addr
= in6addr_any
;
160 sa6
.sin6_port
= htons(BonjourPort
);
162 if (-1 == bind(socketHandle
,(struct sockaddr
*)&sa6
,sizeof(sa6
)))
164 printf("error in bind: %s\n",strerror(errno
));
173 bool BJSocket::Close()
187 int nLength
= (int) recvmsg(socketHandle
, &socketMsghdr
,0);
188 if (!CheckInterface())
191 gettimeofday(&tv
, NULL
);
192 m_CurrentFrame
.Set(buffer
-14-40-8,nLength
,tv
.tv_sec
*1000000ll + tv
.tv_usec
);
196 BJIPAddr
* BJSocket::GetSrcAddr()
198 sourceAddr
.Set(&peerAddr
);
202 BJIPAddr
* BJSocket::GetDestAddr()
205 struct cmsghdr
*cmsg
;
207 for(cmsg
= CMSG_FIRSTHDR(&socketMsghdr
); cmsg
!= NULL
; cmsg
= CMSG_NXTHDR(&socketMsghdr
, cmsg
))
210 if (cmsg
->cmsg_level
== IPPROTO_IP
&& cmsg
->cmsg_type
== IP_PKTINFO
)
212 struct in_pktinfo
* pPktInfo
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
214 destAddr
.Set(&pPktInfo
->ipi_addr
);
216 if (cmsg
->cmsg_level
== IPPROTO_IPV6
&& cmsg
->cmsg_type
== IPV6_PKTINFO
)
218 struct in6_pktinfo
* pPktInfo
= (struct in6_pktinfo
*)CMSG_DATA(cmsg
);
219 destAddr
.Set(&pPktInfo
->ipi6_addr
);
225 bool BJSocket::CheckInterface()
229 struct cmsghdr
*cmsg
;
233 for(cmsg
= CMSG_FIRSTHDR(&socketMsghdr
); cmsg
!= NULL
; cmsg
= CMSG_NXTHDR(&socketMsghdr
, cmsg
))
236 if ((cmsg
->cmsg_level
== IPPROTO_IP
) && cmsg
->cmsg_type
== IP_PKTINFO
)
239 struct in_pktinfo
* pPktInfo
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
240 if (pPktInfo
->ipi_ifindex
== interfaceID
)
244 if (pPktInfo
->ipi_ifindex
!= 4)
246 sourceAddr
.Set(&peerAddr
);
247 printf("address:%d %s \n",pPktInfo
->ipi_ifindex
,sourceAddr
.GetString());
251 if (cmsg
->cmsg_level
== IPPROTO_IPV6
&& cmsg
->cmsg_type
== IPV6_PKTINFO
)
254 struct in6_pktinfo
* pPktInfo
= (struct in6_pktinfo
*)CMSG_DATA(cmsg
);
255 if (pPktInfo
->ipi6_ifindex
== interfaceID
)
260 printf("PKTINFO not found \n");
264 bool BJSocket::IsMulticastPacket()
266 return GetDestAddr()->IsBonjourMulticast();
270 int BJSocket::GetSockectHandle()
275 BJ_UINT8
* BJSocket::GetBuffer()
280 void BJSocket::JoinMulticastv4(BJString interfaceName
)
282 if (interfaceName
.GetLength() == 0)
284 // join Multicast group
286 imr
.imr_multiaddr
.s_addr
= inet_addr( "224.0.0.251");
287 imr
.imr_interface
.s_addr
= INADDR_ANY
;
288 if (-1 == setsockopt(socketHandle
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &imr
, sizeof(imr
)))
290 printf("setsockopt for IP_ADD_MEMBERSHIP failed");
295 struct ifaddrs
*ifa
, *orig
;
301 for ( ; ifa
; ifa
= ifa
->ifa_next
)
303 if (interfaceName
== ifa
->ifa_name
&& ifa
->ifa_addr
->sa_family
== AF_INET
)
305 struct sockaddr_in
*ifa_addr
= (struct sockaddr_in
*)ifa
->ifa_addr
;
307 imr
.imr_multiaddr
.s_addr
= inet_addr( "224.0.0.251");
308 imr
.imr_interface
.s_addr
= ifa_addr
->sin_addr
.s_addr
;
309 if (-1 == setsockopt(socketHandle
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &imr
, sizeof(imr
)))
311 printf("setsockopt for IP_ADD_MEMBERSHIP failed");
320 void BJSocket::JoinMulticastv6(BJString interfaceName
)
323 if (interfaceName
.GetLength() == 0)
326 // join Multicast group
327 struct in6_addr BonjourMultiaddr
= {{{ 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB }}};
328 struct ipv6_mreq i6mr
;
329 memset(&i6mr
,0,sizeof(i6mr
));
330 memcpy(&i6mr
.ipv6mr_multiaddr
, &BonjourMultiaddr
, sizeof(BonjourMultiaddr
));
331 if (interfaceName
.GetLength() > 0)
332 i6mr
.ipv6mr_interface
= interfaceID
;
334 i6mr
.ipv6mr_interface
= __IPV6_ADDR_SCOPE_SITELOCAL
;
335 int err
= setsockopt(socketHandle
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, &i6mr
, sizeof(i6mr
));
336 if (err
< 0 && (errno
!= EADDRINUSE
))
338 printf("setsockopt for IPV6_JOIN_GROUP failed %d",errno
);
342 ////////////////////////////////////////
344 ///////////////////////////////////////
354 bool BJSelect::Add(BJSocket
& s
)
356 int sock
= s
.GetSockectHandle();
357 FD_SET(sock
, &socketSet
);
358 if (sock
> maxSocket
)
365 int BJSelect::Wait(int sec
)
368 memset(&tv
, 0, sizeof(tv
));
371 int result
= select(maxSocket
+1, &socketSet
, NULL
, NULL
, &tv
);
376 bool BJSelect::IsReady(BJSocket
& Socket
)
378 int bIsSet
= FD_ISSET(Socket
.GetSockectHandle(), &socketSet
);
379 return (bIsSet
!= 0);