19
19
from .stream import Stream
20
20
from .response import HTTP20Response , HTTP20Push
21
21
from .window import FlowControlManager
22
- from .exceptions import ConnectionError , ProtocolError
22
+ from .exceptions import ConnectionError
23
23
from . import errors
24
24
25
25
import errno
26
26
import logging
27
27
import socket
28
+ import time
28
29
29
30
log = logging .getLogger (__name__ )
30
31
31
32
DEFAULT_WINDOW_SIZE = 65535
32
33
34
+ TRANSIENT_SSL_ERRORS = (ssl .SSL_ERROR_WANT_READ , ssl .SSL_ERROR_WANT_WRITE )
35
+
33
36
34
37
class HTTP20Connection (object ):
35
38
"""
@@ -44,30 +47,31 @@ class HTTP20Connection(object):
44
47
:param host: The host to connect to. This may be an IP address or a
45
48
hostname, and optionally may include a port: for example,
46
49
``'http2bin.org'``, ``'http2bin.org:443'`` or ``'127.0.0.1'``.
47
- :param port: (optional) The port to connect to. If not provided and one also
48
- isn't provided in the ``host`` parameter, defaults to 443.
50
+ :param port: (optional) The port to connect to. If not provided and one
51
+ also isn't provided in the ``host`` parameter, defaults to 443.
49
52
:param secure: (optional) Whether the request should use TLS. Defaults to
50
53
``False`` for most requests, but to ``True`` for any request issued to
51
54
port 443.
52
55
:param window_manager: (optional) The class to use to manage flow control
53
56
windows. This needs to be a subclass of the
54
- :class:`BaseFlowControlManager <hyper.http20.window.BaseFlowControlManager>`.
55
- If not provided,
57
+ :class:`BaseFlowControlManager
58
+ <hyper.http20.window.BaseFlowControlManager>`. If not provided,
56
59
:class:`FlowControlManager <hyper.http20.window.FlowControlManager>`
57
60
will be used.
58
61
:param enable_push: (optional) Whether the server is allowed to push
59
62
resources to the client (see
60
63
:meth:`get_pushes() <hyper.HTTP20Connection.get_pushes>`).
61
64
:param ssl_context: (optional) A class with custom certificate settings.
62
65
If not provided then hyper's default ``SSLContext`` is used instead.
63
- :param proxy_host: (optional) The proxy to connect to. This can be an IP address
64
- or a host name and may include a port.
66
+ :param proxy_host: (optional) The proxy to connect to. This can be an IP
67
+ address or a host name and may include a port.
65
68
:param proxy_port: (optional) The proxy port to connect to. If not provided
66
- and one also isn't provided in the ``proxy`` parameter, defaults to 8080.
69
+ and one also isn't provided in the ``proxy`` parameter, defaults to
70
+ 8080.
67
71
"""
68
- def __init__ (self , host , port = None , secure = None , window_manager = None , enable_push = False ,
69
- ssl_context = None , proxy_host = None , proxy_port = None ,
70
- force_proto = None , ** kwargs ):
72
+ def __init__ (self , host , port = None , secure = None , window_manager = None ,
73
+ enable_push = False , ssl_context = None , proxy_host = None ,
74
+ proxy_port = None , force_proto = None , ** kwargs ):
71
75
"""
72
76
Creates an HTTP/2 connection to a specific server.
73
77
"""
@@ -89,7 +93,9 @@ def __init__(self, host, port=None, secure=None, window_manager=None, enable_pus
89
93
# Setup proxy details if applicable.
90
94
if proxy_host :
91
95
if proxy_port is None :
92
- self .proxy_host , self .proxy_port = to_host_port_tuple (proxy_host , default_port = 8080 )
96
+ self .proxy_host , self .proxy_port = to_host_port_tuple (
97
+ proxy_host , default_port = 8080
98
+ )
93
99
else :
94
100
self .proxy_host , self .proxy_port = proxy_host , proxy_port
95
101
else :
@@ -241,7 +247,7 @@ def connect(self):
241
247
sock = socket .create_connection ((host , port ))
242
248
243
249
if self .secure :
244
- assert not self .proxy_host , "Using a proxy with HTTPS not yet supported."
250
+ assert not self .proxy_host , "Proxy with HTTPS not supported."
245
251
sock , proto = wrap_socket (sock , host , self .ssl_context ,
246
252
force_proto = self .force_proto )
247
253
else :
@@ -426,7 +432,7 @@ def _send_cb(self, data, tolerate_peer_gone=False):
426
432
self ._sock .sendall (data )
427
433
except socket .error as e :
428
434
if (not tolerate_peer_gone or
429
- e .errno not in (errno .EPIPE , errno .ECONNRESET )):
435
+ e .errno not in (errno .EPIPE , errno .ECONNRESET )):
430
436
raise
431
437
432
438
def _adjust_receive_window (self , frame_len ):
@@ -535,14 +541,14 @@ def _recv_cb(self):
535
541
except ssl .SSLError as e : # pragma: no cover
536
542
# these are transient errors that can occur while reading from
537
543
# ssl connections.
538
- if e .args [0 ] in ( ssl . SSL_ERROR_WANT_READ , SSL_ERROR_WANT_WRITE ) :
544
+ if e .args [0 ] in TRANSIENT_SSL_ERRORS :
539
545
continue
540
546
else :
541
547
raise
542
548
except socket .error as e : # pragma: no cover
543
549
if e .errno in (errno .EINTR , errno .EAGAIN ):
544
550
# if 'interrupted' or 'try again', continue
545
- sleep (retry_wait )
551
+ time . sleep (retry_wait )
546
552
continue
547
553
elif e .errno == errno .ECONNRESET :
548
554
break
0 commit comments