def getRecvFrom(addressType):
def recvfrom(s, sz):
_to = None
data, ancdata, msg_flags, _from = s.recvmsg(sz, socket.CMSG_LEN(sz))
for anc in ancdata:
if anc[0] == socket.SOL_IP and anc[1] == socket.IP_PKTINFO:
addr = in_pktinfo.from_buffer_copy(anc[2])
addr = ipaddress.IPv4Address(memoryview(addr.ipi_addr).tobytes())
_to = (str(addr), s.getsockname()[1])
elif anc[0] == socket.SOL_IPV6 and anc[1] == socket.IPV6_PKTINFO:
addr = in6_pktinfo.from_buffer_copy(anc[2])
addr = ipaddress.ip_address(memoryview(addr.ipi6_addr).tobytes())
_to = (str(addr), s.getsockname()[1])
return data, addressType(_from).setLocalAddress(_to)
return recvfrom
python类SOL_IP的实例源码
def close(self):
"""Ends the background threads, and prevent this instance from
servicing further queries."""
if globals()['_GLOBAL_DONE'] == 0:
globals()['_GLOBAL_DONE'] = 1
self.notifyAll()
self.engine.notify()
self.unregisterAllServices()
self.socket.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP, socket.inet_aton(_MDNS_ADDR) + socket.inet_aton('0.0.0.0'))
self.socket.close()
# Test a few module features, including service registration, service
# query (for Zoe), and service unregistration.
def setUdpSocketForMulticastReceive(sock, multicastGroupTuple, ipAddressStrOfMulticastInterface):
sock.bind(("", multicastGroupTuple[1]))
sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(multicastGroupTuple[0]) + socket.inet_aton(ipAddressStrOfMulticastInterface))
#
# gets the IP address (as string) of local hostname
#
def __init__(self, type = ETH_P_IP, filter=None, iface=None, promisc=None, nofilter=0):
self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
if iface is not None:
self.ins.bind((iface, type))
def correct_header(self, header, auth, sock, **kw):
try:
buf = sock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
assert len(buf) == 16
remote = (socket.inet_ntoa(buf[4:8]), int.from_bytes(buf[2:4], 'big'))
assert sock.getsockname() != remote
except Exception:
return False
return auth and header == auth[:1] or not auth
def parse(self, reader, auth, authtable, sock, **kw):
if auth:
if (yield from reader.read_n(len(auth)-1)) != auth[1:]:
raise Exception('Unauthorized Redir')
authtable.set_authed()
buf = sock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
return socket.inet_ntoa(buf[4:8]), int.from_bytes(buf[2:4], 'big'), b''
def getRecvFrom(addressType):
def recvfrom(s, sz):
_to = None
data, ancdata, msg_flags, _from = s.recvmsg(sz, socket.CMSG_LEN(sz))
for anc in ancdata:
if anc[0] == socket.SOL_IP and anc[1] == socket.IP_PKTINFO:
addr = in_pktinfo.from_buffer_copy(anc[2])
addr = ipaddress.IPv4Address(memoryview(addr.ipi_addr).tobytes())
_to = (str(addr), s.getsockname()[1])
elif anc[0] == socket.SOL_IPV6 and anc[1] == socket.IPV6_PKTINFO:
addr = in6_pktinfo.from_buffer_copy(anc[2])
addr = ipaddress.ip_address(memoryview(addr.ipi6_addr).tobytes())
_to = (str(addr), s.getsockname()[1])
return data, addressType(_from).setLocalAddress(_to)
return recvfrom
def __init__(self, type = ETH_P_IP, filter=None, iface=None, promisc=None, nofilter=0):
self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
if iface is not None:
self.ins.bind((iface, type))
def join(self, multicast_addr):
with self.lock:
if multicast_addr not in self.multicastSet:
self.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(multicast_addr) + socket.inet_aton(self.bind_addr))
self.multicastSet.add(multicast_addr)
if self.callback_obj is not None:
self.callback_obj.on_join(self, multicast_addr)
# for RECEIVER to stop receiving datagram from the multicast group
def leave(self, multicast_addr):
with self.lock:
try:
if multicast_addr in self.multicastSet:
self.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP,
socket.inet_aton(multicast_addr) + socket.inet_aton('0.0.0.0'))
self.multicastSet.discard(multicast_addr)
if self.callback_obj is not None:
self.callback_obj.on_leave(self, multicast_addr)
except Exception as e:
print e
def one_ping(self, ip, port, identifier, sequence, ttl, timeout):
#prepare result dict
result = {'error': None}
#create sockets
ins = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
#bind and set timeout for IN socket
ins.bind(("", port))
ins.settimeout(timeout)
#set TTL for OUT socket
outs.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
#create packet and send it
#print('sending to', ip, 'packet with', identifier, sequence)
packet = messages.EchoRequest(identifier = identifier, sequence = sequence)
outs.sendto(packet.pack(), (ip, port))
#get answer and time it
start = datetime.datetime.now()
try:
s = time.time()
while time.time() - s < timeout:
a = ins.recvfrom(1024)[0]
ip_header = ip_m.Header(a[:20])
outp = messages.types[a[20]]()
outp.unpack(a[20:])
if (
(
#handle errors
type(outp) in messages.error_messages and
#cover not specification complient routers
outp.original_message is not None and
identifier == outp.original_message.identifier and
sequence == outp.original_message.sequence
)
or
(
#handle normal responses
type(outp) in messages.reply_messages and
identifier == outp.identifier and
sequence == outp.sequence
)
):
if type(outp) == messages.EchoReply:
self.result['on'] = True
delta = datetime.datetime.now() - start
self.result['times'].append(delta.seconds * 1000000 + delta.microseconds)
self.result['responses'].append((ip_header, outp))
break
except socket.timeout as e:
self.result['packet_loss'] += 1
def get_multicast_socket(sock=None):
if not sock:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(0.001)
# set multicast interface to any local interface
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton('0.0.0.0'))
# Enable multicast, TTL should be <32 (local network)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 5)
# Allow reuse of addresses
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Allow receiving multicast broadcasts (subscribe to multicast group)
try:
mreq = struct.pack('4sL', socket.inet_aton(multicast_ip), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
# Do not loop back own messages
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 0)
except OSError as e:
logger.error('Unable to obtain socket with multicast enabled.')
raise e
port = None
for i in range(30100, 30105):
try:
# Binding to 0.0.0.0 results in multiple messages if there is multiple interfaces available
# Kept as-is to avoid losing messages
sock.bind(('0.0.0.0', i))
port = i
break
except OSError as e:
# Socket already in use without SO_REUSEADDR enabled
continue
if not port:
raise RuntimeError('No IMC multicast ports free on local interface.')
return sock
def __init__(self, bindaddress=None):
"""Creates an instance of the Zeroconf class, establishing
multicast communications, listening and reaping threads."""
globals()['_GLOBAL_DONE'] = 0
self.intf = bindaddress
self.group = ('', _MDNS_PORT)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
except Exception:
# SO_REUSEADDR should be equivalent to SO_REUSEPORT for
# multicast UDP sockets (p 731, "TCP/IP Illustrated,
# Volume 2"), but some BSD-derived systems require
# SO_REUSEPORT to be specified explicity. Also, not all
# versions of Python have SO_REUSEPORT available. So
# if you're on a BSD-based system, and haven't upgraded
# to Python 2.3 yet, you may find this library doesn't
# work as expected.
#
pass
self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 255)
self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
try:
self.socket.bind(self.group)
except Exception:
# Some versions of linux raise an exception even though
# the SO_REUSE* options have been set, so ignore it
#
pass
if self.intf is not None:
self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(self.intf) + socket.inet_aton('0.0.0.0'))
self.socket.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(_MDNS_ADDR) + socket.inet_aton('0.0.0.0'))
self.listeners = []
self.browsers = []
self.services = {}
self.cache = DNSCache()
self.condition = threading.Condition()
self.engine = Engine(self)
self.listener = Listener(self)
self.reaper = Reaper(self)
def __init__(self, port, callback_obj, ttl=1, enable_loopback=False, bind_addr=''):
asyncore.dispatcher.__init__(self)
# self.lock = threading.RLock()
self.MAX_MTU = 1500
self.callback_obj = None
self.port = port
self.multicastSet = Set([])
self.lock = threading.RLock()
self.ttl = ttl
self.enable_loopback = enable_loopback
if callback_obj is not None and isinstance(callback_obj, IUdpCallback):
self.callback_obj = callback_obj
else:
raise Exception('callback_obj is None or not an instance of IUdpCallback class')
try:
self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
self.set_reuse_addr()
try:
socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
except AttributeError:
pass # Some systems don't support SO_REUSEPORT
# for both SENDER and RECEIVER to restrict the region
self.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, self.ttl)
# for SENDER to choose whether to use loop back
if self.enable_loopback:
self.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
else:
self.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)
self.bind_addr = bind_addr
if self.bind_addr is None or self.bind_addr == '':
self.bind_addr = socket.gethostbyname(socket.gethostname())
# for both SENDER and RECEIVER to bind to specific network adapter
self.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(self.bind_addr))
# for RECEIVE to receive from multiple multicast groups
self.bind(('', port))
except Exception as e:
print e
traceback.print_exc()
self.sendQueue = Queue.Queue() # thread-safe queue
AsyncController.instance().add(self)
if self.callback_obj is not None:
self.callback_obj.on_started(self)
# Even though UDP is connectionless this is called when it binds to a port
def run(self):
"""Run the server."""
# Listen for UDP port 1900 packets sent to SSDP multicast address
ssdp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ssdp_socket.setblocking(False)
# Required for receiving multicast
ssdp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ssdp_socket.setsockopt(
socket.SOL_IP,
socket.IP_MULTICAST_IF,
socket.inet_aton(self.host_ip_addr))
ssdp_socket.setsockopt(
socket.SOL_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton("239.255.255.250") +
socket.inet_aton(self.host_ip_addr))
ssdp_socket.bind(("239.255.255.250", 1900))
while True:
if self._interrupted:
clean_socket_close(ssdp_socket)
return
try:
read, _, _ = select.select(
[self._interrupted_read_pipe, ssdp_socket], [],
[ssdp_socket])
if self._interrupted_read_pipe in read:
# Implies self._interrupted is True
clean_socket_close(ssdp_socket)
return
elif ssdp_socket in read:
data, addr = ssdp_socket.recvfrom(1024)
else:
continue
except socket.error as ex:
if self._interrupted:
clean_socket_close(ssdp_socket)
return
_LOGGER.error("UPNP Responder socket exception occured: %s",
ex.__str__)
if "M-SEARCH" in data.decode('utf-8'):
# SSDP M-SEARCH method received, respond to it with our info
resp_socket = socket.socket(
socket.AF_INET, socket.SOCK_DGRAM)
resp_socket.sendto(self.upnp_response, addr)
resp_socket.close()