python: Support ALPN, require Python 3.5
This commit also fixes the bug that SETTINGS timer continues after connection was closed.
This commit is contained in:
parent
0ea44072a3
commit
cd471a989a
|
@ -1370,7 +1370,7 @@ The extension module is called ``nghttp2``.
|
|||
determined by the ``configure`` script. If the detected Python version is not
|
||||
what you expect, specify a path to Python executable in a ``PYTHON``
|
||||
variable as an argument to configure script (e.g., ``./configure
|
||||
PYTHON=/usr/bin/python3.4``).
|
||||
PYTHON=/usr/bin/python3.5``).
|
||||
|
||||
The following example code illustrates basic usage of the HPACK compressor
|
||||
and decompressor in Python:
|
||||
|
|
|
@ -13,7 +13,7 @@ The extension module is called ``nghttp2``.
|
|||
determined by configure script. If the detected Python version is not
|
||||
what you expect, specify a path to Python executable in ``PYTHON``
|
||||
variable as an argument to configure script (e.g., ``./configure
|
||||
PYTHON=/usr/bin/python3.4``).
|
||||
PYTHON=/usr/bin/python3.5``).
|
||||
|
||||
HPACK API
|
||||
---------
|
||||
|
@ -136,15 +136,15 @@ HTTP/2 servers
|
|||
|
||||
.. note::
|
||||
|
||||
We use :py:mod:`asyncio` for HTTP/2 server classes. Therefore,
|
||||
Python 3.4 or later is required to use these objects. To
|
||||
explicitly configure nghttp2 build to use Python 3.4, specify the
|
||||
``PYTHON`` variable to the path to Python 3.4 executable when
|
||||
We use :py:mod:`asyncio` for HTTP/2 server classes, and ALPN.
|
||||
Therefore, Python 3.5 or later is required to use these objects.
|
||||
To explicitly configure nghttp2 build to use Python 3.5, specify
|
||||
the ``PYTHON`` variable to the path to Python 3.5 executable when
|
||||
invoking configure script like this:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ ./configure PYTHON=/usr/bin/python3.4
|
||||
$ ./configure PYTHON=/usr/bin/python3.5
|
||||
|
||||
.. py:class:: HTTP2Server(address, RequestHandlerClass, ssl=None)
|
||||
|
||||
|
|
|
@ -260,6 +260,7 @@ try:
|
|||
import email.utils
|
||||
import datetime
|
||||
import time
|
||||
import ssl as tls
|
||||
from urllib.parse import urlparse
|
||||
except ImportError:
|
||||
asyncio = None
|
||||
|
@ -294,6 +295,25 @@ def wrap_body(body):
|
|||
# string and flag.
|
||||
return body
|
||||
|
||||
def negotiated_protocol(ssl_obj):
|
||||
protocol = ssl_obj.selected_alpn_protocol()
|
||||
if protocol:
|
||||
logging.info('alpn, protocol:%s', protocol)
|
||||
return protocol
|
||||
|
||||
protocol = ssl_obj.selected_npn_protocol()
|
||||
if protocol:
|
||||
logging.info('npn, protocol:%s', protocol)
|
||||
return protocol
|
||||
|
||||
return None
|
||||
|
||||
def set_application_protocol(ssl_ctx):
|
||||
app_protos = [cnghttp2.NGHTTP2_PROTO_VERSION_ID.decode('utf-8')]
|
||||
ssl_ctx.set_npn_protocols(app_protos)
|
||||
if tls.HAS_ALPN:
|
||||
ssl_ctx.set_alpn_protocols(app_protos)
|
||||
|
||||
cdef _get_stream_user_data(cnghttp2.nghttp2_session *session,
|
||||
int32_t stream_id):
|
||||
cdef void *stream_user_data
|
||||
|
@ -902,6 +922,8 @@ cdef class _HTTP2SessionCore(_HTTP2SessionCoreBase):
|
|||
return promised_handler
|
||||
|
||||
def connection_lost(self):
|
||||
self._stop_settings_timer()
|
||||
|
||||
for handler in self.handlers:
|
||||
handler.on_close(cnghttp2.NGHTTP2_INTERNAL_ERROR)
|
||||
self.handlers = set()
|
||||
|
@ -1284,8 +1306,8 @@ if asyncio:
|
|||
logging.info('failed to set tcp-nodelay: %s', str(e))
|
||||
ssl_ctx = self.transport.get_extra_info('sslcontext')
|
||||
if ssl_ctx:
|
||||
protocol = sock.selected_npn_protocol()
|
||||
logging.info('npn, protocol:%s', protocol)
|
||||
ssl_obj = self.transport.get_extra_info('ssl_object')
|
||||
protocol = negotiated_protocol(ssl_obj)
|
||||
if protocol is None or protocol.encode('utf-8') != \
|
||||
cnghttp2.NGHTTP2_PROTO_VERSION_ID:
|
||||
self.transport.abort()
|
||||
|
@ -1346,8 +1368,7 @@ if asyncio:
|
|||
self.loop = asyncio.get_event_loop()
|
||||
|
||||
if ssl:
|
||||
ssl.set_npn_protocols([cnghttp2.NGHTTP2_PROTO_VERSION_ID\
|
||||
.decode('utf-8')])
|
||||
set_application_protocol(ssl)
|
||||
|
||||
coro = self.loop.create_server(session_factory,
|
||||
host=address[0], port=address[1],
|
||||
|
@ -1516,8 +1537,8 @@ if asyncio:
|
|||
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
ssl_ctx = self.transport.get_extra_info('sslcontext')
|
||||
if ssl_ctx:
|
||||
protocol = sock.selected_npn_protocol()
|
||||
logging.info('npn, protocol:%s', protocol)
|
||||
ssl_obj = self.transport.get_extra_info('ssl_object')
|
||||
protocol = negotiated_protocol(ssl_obj)
|
||||
if protocol is None or protocol.encode('utf-8') != \
|
||||
cnghttp2.NGHTTP2_PROTO_VERSION_ID:
|
||||
self.transport.abort()
|
||||
|
@ -1594,8 +1615,7 @@ if asyncio:
|
|||
return self.session
|
||||
|
||||
if ssl:
|
||||
ssl.set_npn_protocols([cnghttp2.NGHTTP2_PROTO_VERSION_ID\
|
||||
.decode('utf-8')])
|
||||
set_application_protocol(ssl)
|
||||
|
||||
self.loop = loop
|
||||
if not self.loop:
|
||||
|
|
Loading…
Reference in New Issue