Merge 0cf2d9b9f9 into 99f83ca083
This commit is contained in:
commit
36091fa1dc
|
|
@ -185,6 +185,11 @@ Traffic Legend:
|
||||||
else:
|
else:
|
||||||
self.heartbeat = None
|
self.heartbeat = None
|
||||||
|
|
||||||
|
# see comment below - an assertion to deal with the
|
||||||
|
# intrinsics of non-blocking SSL sockets and select.
|
||||||
|
assert not isinstance(target, ssl.SSLSocket) \
|
||||||
|
or (self.buffer_size >= 16 * 1024 and not target.getblocking())
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
wlist = []
|
wlist = []
|
||||||
|
|
||||||
|
|
@ -242,11 +247,15 @@ Traffic Legend:
|
||||||
self.server.target_host, self.server.target_port)
|
self.server.target_host, self.server.target_port)
|
||||||
raise self.CClose(closed['code'], closed['reason'])
|
raise self.CClose(closed['code'], closed['reason'])
|
||||||
|
|
||||||
|
|
||||||
if target in outs:
|
if target in outs:
|
||||||
# Send queued client data to the target
|
# Send queued client data to the target
|
||||||
dat = tqueue.pop(0)
|
dat = tqueue.pop(0)
|
||||||
sent = target.send(dat)
|
try:
|
||||||
|
sent = target.send(dat)
|
||||||
|
except ssl.SSLWantWriteError:
|
||||||
|
# nothing was sent - sending needs to be retried later
|
||||||
|
sent = 0
|
||||||
|
|
||||||
if sent == len(dat):
|
if sent == len(dat):
|
||||||
self.print_traffic(">")
|
self.print_traffic(">")
|
||||||
else:
|
else:
|
||||||
|
|
@ -254,10 +263,27 @@ Traffic Legend:
|
||||||
tqueue.insert(0, dat[sent:])
|
tqueue.insert(0, dat[sent:])
|
||||||
self.print_traffic(".>")
|
self.print_traffic(".>")
|
||||||
|
|
||||||
|
|
||||||
if target in ins:
|
if target in ins:
|
||||||
# Receive target data, encode it and queue for client
|
# Receive target data, encode it and queue for client
|
||||||
buf = target.recv(self.buffer_size)
|
try:
|
||||||
|
# It is strictly required that buffer size is more than 16kb, so that
|
||||||
|
# all possible data can be received from a SSL socket in a single call.
|
||||||
|
# Otherwise, there could be still data available for reading, but select
|
||||||
|
# wouldn't report the socket as readable again, since all data has already
|
||||||
|
# been read by the SSL socket from the OS.
|
||||||
|
# see also: https://docs.python.org/3/library/ssl.html#notes-on-non-blocking-sockets
|
||||||
|
|
||||||
|
# The maximum size of a single SSL record is 16kb. And OpenSSL's SSL_read()
|
||||||
|
# will only return data from the current record - until it has been fully read.
|
||||||
|
# see also: https://www.openssl.org/docs/man1.1.1/man3/SSL_read.html
|
||||||
|
buf = target.recv(self.buffer_size)
|
||||||
|
except ssl.SSLWantReadError:
|
||||||
|
# The underlying OS socket had data, but there isn't any data to
|
||||||
|
# receive from the SSL socket yet (SSL record not yet fully received,
|
||||||
|
# only SSL control data received, e.g. re-handshake, session tickets, ...)
|
||||||
|
# Let's retry later.
|
||||||
|
continue
|
||||||
|
|
||||||
if len(buf) == 0:
|
if len(buf) == 0:
|
||||||
|
|
||||||
# Target socket closed, flushing queues and closing client-side websocket
|
# Target socket closed, flushing queues and closing client-side websocket
|
||||||
|
|
|
||||||
|
|
@ -471,6 +471,10 @@ class WebSockifyServer():
|
||||||
sock.connect(addrs[0][4])
|
sock.connect(addrs[0][4])
|
||||||
if use_ssl:
|
if use_ssl:
|
||||||
sock = ssl.wrap_socket(sock)
|
sock = ssl.wrap_socket(sock)
|
||||||
|
# SSL socket must be non-blocking in order to properly
|
||||||
|
# handle receiving and sending data using select.
|
||||||
|
# See also the comment(s) in ProxyRequestHandler.do_proxy()
|
||||||
|
sock.setblocking(0)
|
||||||
else:
|
else:
|
||||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
sock.bind(addrs[0][4])
|
sock.bind(addrs[0][4])
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue