Async port opening using different nic ips

This commit is contained in:
shortcutme 2017-11-09 13:33:02 +01:00
parent 5026f1b0a8
commit b01e381087
No known key found for this signature in database
GPG key ID: 5B63BAE6CB9613AE

View file

@ -7,6 +7,7 @@ from xml.dom.minidom import parseString
from xml.parsers.expat import ExpatError from xml.parsers.expat import ExpatError
from gevent import socket from gevent import socket
import gevent
# Relevant UPnP spec: # Relevant UPnP spec:
# http://www.upnp.org/specs/gw/UPnP-gw-WANIPConnection-v1-Service.pdf # http://www.upnp.org/specs/gw/UPnP-gw-WANIPConnection-v1-Service.pdf
@ -46,7 +47,7 @@ def perform_m_search(local_ip):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((local_ip, 10000)) sock.bind((local_ip, 0))
sock.sendto(ssdp_request, ('239.255.255.250', 1900)) sock.sendto(ssdp_request, ('239.255.255.250', 1900))
if local_ip == "127.0.0.1": if local_ip == "127.0.0.1":
@ -295,20 +296,40 @@ def _communicate_with_igd(port=15441,
Manage sending a message generated by 'fn'. Manage sending a message generated by 'fn'.
""" """
# Retry every ip 'retries' times local_ips = _get_local_ips()
local_ips = _get_local_ips() * retries
success = False success = False
for local_ip in local_ips: def job(local_ip):
for retry in range(retries):
try: try:
_orchestrate_soap_request(local_ip, port, fn, desc, protos) _orchestrate_soap_request(local_ip, port, fn, desc, protos)
success = True return True
break
except (UpnpError, IGDError) as e: except (UpnpError, IGDError) as e:
logging.debug('Upnp request using "{0}" failed: {1}'.format( logging.debug('Upnp request using "{0}" failed: {1}'.format(
local_ip, e)) local_ip, e))
success = False gevent.sleep(1)
continue return False
threads = []
for local_ip in local_ips:
thread = gevent.spawn(job, local_ip)
threads.append(thread)
gevent.sleep(0.1)
if any([thread.value for thread in threads]):
success = True
break
# Wait another 10sec for competition or any positibe result
for _ in range(10):
all_done = all([thread.value != None for thread in threads])
any_succeed = any([thread.value for thread in threads])
if all_done or any_succeed:
break
gevent.sleep(1)
if any([thread.value for thread in threads]):
success = True
if not success: if not success:
raise UpnpError( raise UpnpError(
@ -330,7 +351,7 @@ def ask_to_close_port(port=15441, desc="UpnpPunch", retries=3, protos=("TCP", "U
# retries=1 because multiple successes cause 500 response and failure # retries=1 because multiple successes cause 500 response and failure
_communicate_with_igd(port=port, _communicate_with_igd(port=port,
desc=desc, desc=desc,
retries=1, retries=retries,
fn=_create_close_message, fn=_create_close_message,
protos=protos) protos=protos)
@ -338,15 +359,15 @@ def ask_to_close_port(port=15441, desc="UpnpPunch", retries=3, protos=("TCP", "U
if __name__ == "__main__": if __name__ == "__main__":
from gevent import monkey from gevent import monkey
monkey.patch_socket() monkey.patch_all()
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
import time import time
s = time.time() s = time.time()
print "Opening port..." print "Opening port..."
print ask_to_open_port(15443, "ZeroNet", retries=3, protos=["TCP"]) print ask_to_open_port(15443, "ZeroNet",protos=["TCP"])
print "Done in", time.time()-s print "Done in", time.time()-s
print "Closing port..." print "Closing port..."
print ask_to_close_port(15443, "ZeroNet", retries=3, protos=["TCP"]) print ask_to_close_port(15443, "ZeroNet", protos=["TCP"])
print "Done in", time.time()-s print "Done in", time.time()-s