forked from ffnord/mesh-announce
-
Notifications
You must be signed in to change notification settings - Fork 0
/
metasocketserver.py
47 lines (39 loc) · 1.54 KB
/
metasocketserver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import ctypes
import socket
from socketserver import ThreadingUDPServer
class in6_addr_U(ctypes.Union):
_fields_ = [
('__u6_addr8', ctypes.c_uint8 * 16),
('__u6_addr16', ctypes.c_uint16 * 8),
('__u6_addr32', ctypes.c_uint32 * 4),
]
class in6_addr(ctypes.Structure):
_fields_ = [
('__in6_u', in6_addr_U),
]
class in6_pktinfo(ctypes.Structure):
_fields_ = [
('ipi6_addr', in6_addr),
('ipi6_ifindex', ctypes.c_uint),
]
class MetadataUDPServer(ThreadingUDPServer):
"""Extension of ThreadingUDPServer.
Provides the ifindex of the interface on which
a message was received in addition to message data
and source address. IPv6 only
"""
def __init__(self, *args, **kwargs):
super(MetadataUDPServer, self).__init__(*args, **kwargs)
# Enable IPV6_PKTINFO ancilliary data
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_RECVPKTINFO, 1)
def get_request(self):
data, anc_data, _, client_addr = self.socket.recvmsg(self.max_packet_size, socket.CMSG_SPACE(65535))
ifindex = None
for anc_record in anc_data:
(anc_level, anc_type, anc_datum) = anc_record
# Check for IPV6_PKTINFO ancilliary data
if anc_level == socket.IPPROTO_IPV6 and anc_type == socket.IPV6_PKTINFO:
# Parse binary ancilliary data
pktinfo = in6_pktinfo.from_buffer_copy(anc_datum)
ifindex = pktinfo.ipi6_ifindex
return (data, self.socket, ifindex), client_addr