diff --git a/bin/copyparty-fuse.py b/bin/copyparty-fuse.py index 2640047d..2d81f295 100755 --- a/bin/copyparty-fuse.py +++ b/bin/copyparty-fuse.py @@ -54,7 +54,7 @@ def boring_log(msg): def rice_tid(): tid = threading.current_thread().ident - c = struct.unpack("B" * 5, struct.pack(">Q", tid)[-5:]) + c = struct.unpack(b"B" * 5, struct.pack(b">Q", tid)[-5:]) return "".join("\033[1;37;48;5;{}m{:02x}".format(x, x) for x in c) diff --git a/copyparty/httpconn.py b/copyparty/httpconn.py index 03c9745a..5e969037 100644 --- a/copyparty/httpconn.py +++ b/copyparty/httpconn.py @@ -44,8 +44,21 @@ class HttpConn(object): def run(self): method = None + self.sr = None if self.cert_path: - method = self.s.recv(4, socket.MSG_PEEK) + try: + method = self.s.recv(4, socket.MSG_PEEK) + except AttributeError: + # jython does not support msg_peek; forget about https + method = self.s.recv(4) + self.sr = Unrecv(self.s) + self.sr.buf = method + + # jython used to do this, they stopped since it's broken + # but reimplementing sendall is out of scope for now + if not getattr(self.s, "sendall", None): + self.s.sendall = self.s.send + if len(method) != 4: err = "need at least 4 bytes in the first packet; got {}".format( len(method) @@ -55,6 +68,10 @@ class HttpConn(object): return if method not in [None, b"GET ", b"HEAD", b"POST"]: + if self.sr: + self.log("\033[1;31mTODO: cannot do https in jython\033[0m") + return + self.log_src = self.log_src.replace("[36m", "[35m") try: self.s = ssl.wrap_socket( @@ -76,7 +93,8 @@ class HttpConn(object): return - self.sr = Unrecv(self.s) + if not self.sr: + self.sr = Unrecv(self.s) while True: cli = HttpCli(self) diff --git a/copyparty/httpsrv.py b/copyparty/httpsrv.py index 6947b78d..11ad9406 100644 --- a/copyparty/httpsrv.py +++ b/copyparty/httpsrv.py @@ -75,8 +75,9 @@ class HttpSrv(object): sck.shutdown(socket.SHUT_RDWR) sck.close() except (OSError, socket.error) as ex: - if ex.errno not in [107, 9]: + if ex.errno not in [107, 57, 9]: # 107 Transport endpoint not connected + # 57 Socket is not connected # 9 Bad file descriptor raise finally: diff --git a/copyparty/tcpsrv.py b/copyparty/tcpsrv.py index 3a23ff48..57ba7e64 100644 --- a/copyparty/tcpsrv.py +++ b/copyparty/tcpsrv.py @@ -22,10 +22,9 @@ class TcpSrv(object): self.num_clients = Counter() ip = "127.0.0.1" - if self.args.i == ip: - eps = {ip: "local only"} - else: - eps = self.detect_interfaces(self.args.i) + eps = {ip: "local only"} + if self.args.i != ip: + eps = self.detect_interfaces(self.args.i) or eps for ip, desc in sorted(eps.items(), key=lambda x: x[1]): self.log( @@ -97,9 +96,11 @@ class TcpSrv(object): s.connect(("10.255.255.255", 1)) ip = s.getsockname()[0] except (OSError, socket.error) as ex: - if ex.errno != 101: + if ex.errno not in [101, 10065]: raise + return None + s.close() if ext_ip in ["0.0.0.0", ip]: diff --git a/copyparty/util.py b/copyparty/util.py index 48984406..0029ca5b 100644 --- a/copyparty/util.py +++ b/copyparty/util.py @@ -15,11 +15,14 @@ from .stolen import surrogateescape FAKE_MP = False -if FAKE_MP: - import multiprocessing.dummy as mp # noqa: F401 -else: - import multiprocessing as mp # noqa: F401 - +try: + if FAKE_MP: + import multiprocessing.dummy as mp # noqa: F401 + else: + import multiprocessing as mp # noqa: F401 +except ImportError: + # support jython + mp = None if not PY2: from urllib.parse import unquote_to_bytes as unquote @@ -473,7 +476,7 @@ def chkcmd(*argv): def gzip_orig_sz(fn): with open(fsenc(fn), "rb") as f: f.seek(-4, 2) - return struct.unpack("I", f.read(4))[0] + return struct.unpack(b"I", f.read(4))[0] def py_desc(): @@ -482,7 +485,7 @@ def py_desc(): if ofs > 0: py_ver = py_ver[:ofs] - bitness = struct.calcsize("P") * 8 + bitness = struct.calcsize(b"P") * 8 host_os = platform.system() return "{0} on {1}{2}".format(py_ver, host_os, bitness) diff --git a/docs/mistakes.py b/docs/mistakes.py new file mode 100644 index 00000000..f7de5cce --- /dev/null +++ b/docs/mistakes.py @@ -0,0 +1,26 @@ + + method = self.s.recv(4) + self.s.unrecv(method) + print("xxx unrecv'd [{}]".format(method)) + + # jython used to do this, they stopped since it's broken + # but reimplementing sendall is out of scope for now + if not getattr(self.s.s, "sendall", None): + self.s.s.sendall = self.s.s.send + + # TODO this is also pretty bad + have = dir(self.s) + for k in self.s.s.__dict__: + if k not in have and not k.startswith("__"): + if k == "recv": + raise Exception("wait what") + + self.s.__dict__[k] = self.s.s.__dict__[k] + + have = dir(self.s) + for k in dir(self.s.s): + if k not in have and not k.startswith("__"): + if k == "recv": + raise Exception("wait what") + + setattr(self.s, k, getattr(self.s.s, k)) diff --git a/docs/notes.sh b/docs/notes.sh index afc8d236..d756a760 100644 --- a/docs/notes.sh +++ b/docs/notes.sh @@ -76,3 +76,7 @@ cat copyparty/httpcli.py | awk '/^[^a-zA-Z0-9]+def / {printf "%s\n%s\n\n", f, pl # create a folder with symlinks to big files for d in /usr /var; do find $d -type f -size +30M 2>/dev/null; done | while IFS= read -r x; do ln -s "$x" big/; done + +# py2 on osx +brew install python@2 +pip install virtualenv