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);