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