diff --git a/appPublic/across_nat.py b/appPublic/across_nat.py index 33beec7..434bac3 100644 --- a/appPublic/across_nat.py +++ b/appPublic/across_nat.py @@ -22,20 +22,14 @@ class AcrossNat(object): except pmp.NATPMPUnsupportedError: self.pmp_supported = False - def init_upnp(self): - try: - self.upnp = UPnP() - devices = self.upnp.discover() - if len(devices) == 0: - self.upnp_supported = False - except: - self.upnp_supported = False - async def get_external_ip(self): if self.pmp_supported: - return self._pmp_get_external_ip() + self.external_ip = pmp.get_public_address() + return self.external_ip if self.upnp_supported: + if self.upnp is None: + await self.init_upnp() return await self.upnp.get_external_ip() try: @@ -43,13 +37,10 @@ class AcrossNat(object): except: return get('https://ipapi.co/ip/').text - - def _pmp_get_external_ip(self): - return pmp.get_public_address() - - def _upnp_get_external_ip(self): - - await def upnp_map_port(inner_port, protocol='TCP', from_port=40003): + async def upnp_map_port(self, inner_port, + protocol='TCP', from_port=40003): + if self.upnp is None: + await self.init_upnp() protocol = protocol.upper() external_port = from_port while external_port < 52333: @@ -68,6 +59,8 @@ class AcrossNat(object): return None async def is_port_mapped(self, external_port, protocol='TCP'): + if self.upnp is None: + await self.init_upnp() protocol = protocol.upper() if self.upnp_supported: x = await self.upnp.get_specific_port_mapping(external_port, @@ -78,81 +71,25 @@ class AcrossNat(object): raise Exception('not implemented') async def port_unmap(self, external_port, protocol='TCP'): + if self.upnp is None: + await self.init_upnp() protocol = protocol.upper() if self.upnp_supported: await self.upnp.delete_port_mapping(external_port, protocol) raise Exception('not implemented') - def map_port(self, inner_port, protocol='tcp', from_port=40003): - if pmp_supported: - return _map_port(inner_port, protocol=protocol) - - return self.upnp.add_port_mapping( - - inner_port, protocol=protocol) - - - -pmp_supported = True - -""" -_natmap mapping a localhost port to network gateway outter ip's port -input: - port: integer, localhost host port - protocal: string, 'tcp', or 'udp', default is 'tcp' - from_port: integer, the return port will from this prot, - default is 49000, if mapping failed, increases by one, - and try it again. - -return: - gateway outter ip's port, if gateway not support natpmp, return None -""" - -def pmp_getExtenalIPAddress(): - return pmp.get_public_address() - - - -def get_external_ip(): - global pmp_supported - if pmp_supported: - try: - return pmp_get_public_address() - except pmp.NATPMPUnsupportedError: - pmp_supported = False - except Exception as e: - raise e - upnp = UPnP() - devices = upnp.discover() - if len(devices) < 1: - return None - d = devices[0] - services = d.get_services() - -def _pmp_natmap(innerport, - protocol='tcp', - from_port=49000, - timeout=3600): - gateway = pmp.get_gateway_addr() - ret_port = from_port - while 1: - try: - mode = pmp.NATPMP_PROTOCOL_TCP - if protocol != 'tcp': - mode = pmp.NATPMP_PROTOCOL_UDP - - x = pmp.map_port(mode, - ret_port, - innerport, - timeout, - gateway_ip=gateway) + def pmp_map_port(self, inner_port, protocol='TCP', from_port=40003): + if protocol.upper() == 'TCP': + x = pmp.map_tcp_port(from_port, inner_port, + lifetime=999999999) return x.public_port - except pmp.NATPMPUnsupportedError: - return None - except Exception, e: - time.sleep(0.01) - ret_port+=1 - if ret_port > 60000: - return None + x = pmp.map_udp_port(from_port, inner_port, + lifetime=999999999) + return x.public_port + + async def map_port(self, inner_port, protocol='tcp', from_port=40003): + if self.pmp_supported: + return self.pmp_map_port(inner_port, protocol=protocol) + + return await self.upnp_map_port( inner_port, protocol=protocol) -def natmap( diff --git a/appPublic/rc4.py b/appPublic/rc4.py index fcb75a2..e2ef31b 100644 --- a/appPublic/rc4.py +++ b/appPublic/rc4.py @@ -68,6 +68,8 @@ class KeyChain(object): self.keylen = keylen self.keypool = { } + delta = datetime.timedelta(0) + self.timezone = datetime.timezone(delta, name='gmt') def genKey(self, y, m, d): vv = y * 1000 + m * 100 + d @@ -95,7 +97,7 @@ class KeyChain(object): return self.encode_bytes(bdata) def encode_bytes(self, bdata): - dt = datetime.datetime.now() + dt = datetime.datetime.now(self.timezone) key = self.genKey(dt.year, dt.month, dt.day) data = key + bdata return self.crypter.encode_bytes(data, key) @@ -107,7 +109,7 @@ class KeyChain(object): return None def decode_bytes(self, data): - dt = datetime.datetime.now() + dt = datetime.datetime.now(self.timezone) key = self.genKey(dt.year, dt.month, dt.day) d = self._decode(data, key) if d is not None: diff --git a/requirements.txt b/requirements.txt index 9af24b6..534832f 100755 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,7 @@ cryptography brotli aiohttp aioupnp +natpmp asyncio requests jinja2 diff --git a/test/test_across_nat.py b/test/test_across_nat.py new file mode 100644 index 0000000..5d6bc62 --- /dev/null +++ b/test/test_across_nat.py @@ -0,0 +1,17 @@ +from appPublic.across_nat import * +import asyncio + +async def run(): + an = AcrossNat() + an.pmp_supported = False + x = await an.get_external_ip() + print('external ip=', x) + print('pmp_supported=', an.pmp_supported, + 'upnp_supported=', an.upnp_supported) + for p in [ 8080, 8081 ]: + x = await an.map_port(p, 'TCP') + print(p, '-->', x) + +loop = asyncio.get_event_loop() +loop.run_until_complete(run()) + diff --git a/test/test_aioupnp.py b/test/test_aioupnp.py new file mode 100644 index 0000000..a826084 --- /dev/null +++ b/test/test_aioupnp.py @@ -0,0 +1,26 @@ + +import asyncio +from aioupnp.upnp import UPnP + +async def main(): + upnp = await UPnP.discover() + print(dir(upnp)) + print('gateway=', upnp.gateway, upnp.gateway_address, upnp.lan_address) + print(await upnp.get_external_ip()) + print(await upnp.get_redirects()) + + x = await upnp.get_specific_port_mapping(40009, 'TCP') + if len(x) == 0: + print('port available') + + print("adding a port mapping") + + x = await upnp.add_port_mapping(40009, 'TCP', 8999, '192.168.1.8', 'test mapping') + print('x=', x, await upnp.get_redirects()) + + # print("deleting the port mapping") + # await upnp.delete_port_mapping(51234, 'TCP') + print(await upnp.get_redirects()) + + +asyncio.run(main()) diff --git a/test/zmqreply.py b/test/zmqreply.py new file mode 100644 index 0000000..0cf3643 --- /dev/null +++ b/test/zmqreply.py @@ -0,0 +1,18 @@ +from appPublic.zmq_reqrep import ZmqReplier +import time + +def handler(b): + print(b.decode('utf-8')) + return 'got it' + +x = ZmqReplier('tcp://127.0.0.1:9999', handler) +x.run() +f = 0 +while 1: + time.sleep(0.1) + if f==0: + print(dir(x.sock.get_peer())) + f += 1 + +x.stop() +