python: wrap socket in overridden process_request.
This commit is contained in:
parent
e208305505
commit
9d66fc4b88
|
@ -1235,7 +1235,7 @@ try:
|
||||||
|
|
||||||
|
|
||||||
def send_cb(self, session, data):
|
def send_cb(self, session, data):
|
||||||
return self.sslsock.send(data)
|
return self.request.send(data)
|
||||||
|
|
||||||
def read_cb(self, session, stream_id, length, read_ctrl, source):
|
def read_cb(self, session, stream_id, length, read_ctrl, source):
|
||||||
data = source.read(length)
|
data = source.read(length)
|
||||||
|
@ -1277,65 +1277,54 @@ try:
|
||||||
def handle(self):
|
def handle(self):
|
||||||
self.request.setsockopt(socket.IPPROTO_TCP,
|
self.request.setsockopt(socket.IPPROTO_TCP,
|
||||||
socket.TCP_NODELAY, True)
|
socket.TCP_NODELAY, True)
|
||||||
# TODO We need to call handshake manually because 3.3.0b2
|
try:
|
||||||
# crashes if do_handshake_on_connect=True
|
self.request.do_handshake()
|
||||||
self.sslsock = self.server.ctx.wrap_socket(\
|
self.request.setblocking(False)
|
||||||
self.request,
|
|
||||||
server_side=True,
|
|
||||||
do_handshake_on_connect=False)
|
|
||||||
|
|
||||||
self.sslsock.setblocking(False)
|
version = npn_get_version(self.request.selected_npn_protocol())
|
||||||
|
if version == 0:
|
||||||
|
return
|
||||||
|
|
||||||
while True:
|
self.ssctrl = SessionCtrl()
|
||||||
try:
|
self.session = Session(\
|
||||||
self.sslsock.do_handshake()
|
SERVER, version,
|
||||||
break
|
send_cb=self.send_cb,
|
||||||
except ssl.SSLWantReadError as e:
|
on_ctrl_recv_cb=self.on_ctrl_recv_cb,
|
||||||
select.select([self.sslsock], [], [])
|
on_data_chunk_recv_cb=self.on_data_chunk_recv_cb,
|
||||||
except ssl.SSLWantWriteError as e:
|
on_stream_close_cb=self.on_stream_close_cb,
|
||||||
select.select([], [self.sslsock], [])
|
on_request_recv_cb=self.on_request_recv_cb)
|
||||||
|
|
||||||
version = npn_get_version(self.sslsock.selected_npn_protocol())
|
self.session.submit_settings(\
|
||||||
if version == 0:
|
FLAG_SETTINGS_NONE,
|
||||||
return
|
[(SETTINGS_MAX_CONCURRENT_STREAMS, ID_FLAG_SETTINGS_NONE,
|
||||||
|
100)]
|
||||||
|
)
|
||||||
|
|
||||||
self.ssctrl = SessionCtrl()
|
while self.session.want_read() or self.session.want_write():
|
||||||
self.session = Session(\
|
want_read = want_write = False
|
||||||
SERVER, version,
|
try:
|
||||||
send_cb=self.send_cb,
|
data = self.request.recv(4096)
|
||||||
on_ctrl_recv_cb=self.on_ctrl_recv_cb,
|
if data:
|
||||||
on_data_chunk_recv_cb=self.on_data_chunk_recv_cb,
|
self.session.recv(data)
|
||||||
on_stream_close_cb=self.on_stream_close_cb,
|
else:
|
||||||
on_request_recv_cb=self.on_request_recv_cb)
|
break
|
||||||
|
except ssl.SSLWantReadError:
|
||||||
|
want_read = True
|
||||||
|
except ssl.SSLWantWriteError:
|
||||||
|
want_write = True
|
||||||
|
try:
|
||||||
|
self.session.send()
|
||||||
|
except ssl.SSLWantReadError:
|
||||||
|
want_read = True
|
||||||
|
except ssl.SSLWantWriteError:
|
||||||
|
want_write = True
|
||||||
|
|
||||||
self.session.submit_settings(\
|
if want_read or want_write:
|
||||||
FLAG_SETTINGS_NONE,
|
select.select([self.request] if want_read else [],
|
||||||
[(SETTINGS_MAX_CONCURRENT_STREAMS, ID_FLAG_SETTINGS_NONE, 100)]
|
[self.request] if want_write else [],
|
||||||
)
|
[])
|
||||||
|
finally:
|
||||||
while self.session.want_read() or self.session.want_write():
|
self.request.setblocking(True)
|
||||||
want_read = want_write = False
|
|
||||||
try:
|
|
||||||
data = self.sslsock.recv(4096)
|
|
||||||
if data:
|
|
||||||
self.session.recv(data)
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
except ssl.SSLWantReadError:
|
|
||||||
want_read = True
|
|
||||||
except ssl.SSLWantWriteError:
|
|
||||||
want_write = True
|
|
||||||
try:
|
|
||||||
self.session.send()
|
|
||||||
except ssl.SSLWantReadError:
|
|
||||||
want_read = True
|
|
||||||
except ssl.SSLWantWriteError:
|
|
||||||
want_write = True
|
|
||||||
|
|
||||||
if want_read or want_write:
|
|
||||||
select.select([self.sslsock] if want_read else [],
|
|
||||||
[self.sslsock] if want_write else [],
|
|
||||||
[])
|
|
||||||
|
|
||||||
# The following methods and attributes are copied from
|
# The following methods and attributes are copied from
|
||||||
# Lib/http/server.py of cpython source code
|
# Lib/http/server.py of cpython source code
|
||||||
|
@ -1463,6 +1452,18 @@ try:
|
||||||
server_thread.daemon = daemon
|
server_thread.daemon = daemon
|
||||||
server_thread.start()
|
server_thread.start()
|
||||||
|
|
||||||
|
def process_request(self, request, client_address):
|
||||||
|
# ThreadingMixIn.process_request() dispatches request and
|
||||||
|
# client_address to separate thread. To cleanly shutdown
|
||||||
|
# SSL/TLS wrapped socket, we wrap socket here.
|
||||||
|
|
||||||
|
# SSL/TLS handshake is postponed to each thread.
|
||||||
|
request = self.ctx.wrap_socket(\
|
||||||
|
request, server_side=True, do_handshake_on_connect=False)
|
||||||
|
|
||||||
|
socketserver.ThreadingMixIn.process_request(self,
|
||||||
|
request, client_address)
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# No server for 2.x because they lack TLS NPN.
|
# No server for 2.x because they lack TLS NPN.
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Reference in New Issue