From a95b627a7e586c70be5d95984a96f10231a02fc7 Mon Sep 17 00:00:00 2001 From: ed Date: Wed, 12 Jun 2019 23:55:13 +0000 Subject: [PATCH] list all external IPs --- copyparty/tcpsrv.py | 63 +++++++++++++++++++++++++++++++++++++-------- copyparty/util.py | 21 +++++++++++++-- 2 files changed, 71 insertions(+), 13 deletions(-) diff --git a/copyparty/tcpsrv.py b/copyparty/tcpsrv.py index 5de0e88a..229898e2 100644 --- a/copyparty/tcpsrv.py +++ b/copyparty/tcpsrv.py @@ -2,6 +2,7 @@ # coding: utf-8 from __future__ import print_function, unicode_literals +import re import sys import time import socket @@ -10,6 +11,7 @@ from datetime import datetime, timedelta import calendar from .__init__ import PY2, WINDOWS +from .util import chkcmd class TcpSrv(object): @@ -26,18 +28,18 @@ class TcpSrv(object): self.next_day = 0 ip = "127.0.0.1" - if self.args.i != ip: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - s.connect(("10.255.255.255", 1)) - ip = s.getsockname()[0] - except (OSError, socket.error) as ex: - if ex.errno != 101: - raise + if self.args.i == ip: + eps = {ip: "local only"} + else: + eps = self.detect_interfaces(self.args.i) - s.close() - - self.log("root", "available @ http://{0}:{1}/".format(ip, self.args.p)) + for ip, desc in sorted(eps.items(), key=lambda x: x[1]): + self.log( + "root", + "available @ http://{}:{}/ (\033[33m{}\033[0m)".format( + ip, self.args.p, desc + ), + ) self.srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -127,3 +129,42 @@ class TcpSrv(object): with self.log_mutex: ts = datetime.utcfromtimestamp(now).strftime("%H:%M:%S") print("\033[36m{} \033[33m{:21} \033[0m{}".format(ts, src, msg)) + + def detect_interfaces(self, ext_ip): + eps = {} + + # get all ips and their interfaces + try: + ip_addr, _ = chkcmd("ip", "addr") + except: + ip_addr = None + + if ip_addr: + r = re.compile("^\s+inet ([^ ]+)/.* (.*)") + for ln in ip_addr.split("\n"): + try: + ip, dev = r.match(ln.rstrip()).groups() + if ext_ip in ["0.0.0.0", ip]: + eps[ip] = dev + except: + pass + + # get ip with default route + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect(("10.255.255.255", 1)) + ip = s.getsockname()[0] + except (OSError, socket.error) as ex: + if ex.errno != 101: + raise + + s.close() + + if ext_ip in ["0.0.0.0", ip]: + desc = "\033[32mexternal" + try: + eps[ip] += ", " + desc + except: + eps[ip] = desc + + return eps diff --git a/copyparty/util.py b/copyparty/util.py index 8be58230..0b8f44c5 100644 --- a/copyparty/util.py +++ b/copyparty/util.py @@ -5,6 +5,7 @@ from __future__ import print_function, unicode_literals import re import sys import hashlib +import subprocess as sp # nosec from .__init__ import PY2 @@ -304,8 +305,8 @@ def quotep(txt): btxt = fsenc(txt) quot1 = quote(btxt, safe=b"/") if not PY2: - quot1 = quot1.encode('ascii') - + quot1 = quot1.encode("ascii") + quot2 = quot1.replace(b" ", b"+") return fsdec(quot2) @@ -378,5 +379,21 @@ def unescape_cookie(orig): return ret +def runcmd(*argv): + p = sp.Popen(argv, stdout=sp.PIPE, stderr=sp.PIPE) + stdout, stderr = p.communicate() + stdout = stdout.decode("utf-8") + stderr = stderr.decode("utf-8") + return [p.returncode, stdout, stderr] + + +def chkcmd(*argv): + ok, sout, serr = runcmd(*argv) + if ok != 0: + raise Exception(serr) + + return sout, serr + + class Pebkac(Exception): pass