diff --git a/pep-3156.txt b/pep-3156.txt index e75672cda..254d84ee3 100644 --- a/pep-3156.txt +++ b/pep-3156.txt @@ -198,7 +198,8 @@ It is expected that ``get_event_loop()`` returns a different event loop object depending on the context (in fact, this is the definition of context). It may create a new event loop object if none is set and creation is allowed by the policy. The default policy will create a -new event loop only in the main thread, and only if +new event loop only in the main thread (as defined by threading.py, +which uses a special subclass for the main thread), and only if ``get_event_loop()`` is called before ``set_event_loop()`` is ever called. (To reset this state, reset the policy.) In other threads an event loop must be explicitly set. Other policies may behave @@ -233,11 +234,10 @@ implementations, and serves primarily as documentation. The following concrete classes are defined: - ``SelectorEventLoop`` is a concrete implementation of the full API - based on the ``selectors`` module. (This module is part of Tulip, - but not specified by this PEP. It is separately proposed for - inclusion in the standard library.) The constructor takes one - optional argument, a ``selectors.Selector`` object. By default an - instance of ``selectors.DefaultSelector`` is created and used. + based on the ``selectors`` module (new in Python 3.4). The + constructor takes one optional argument, a ``selectors.Selector`` + object. By default an instance of ``selectors.DefaultSelector`` is + created and used. - ``ProactorEventLoop`` is a concrete implementation of the API except for the I/O event handling and signal handling methods. It is only @@ -485,7 +485,7 @@ Note that the client and server side of stream connections use the same transport and protocol interface. However, datagram endpoints use a different transport and protocol interface. -- ``create_connection(protocol_factory, host, port, **kwargs)``. +- ``create_connection(protocol_factory, host, port, )``. Creates a stream connection to a given internet host and port. This is a task that is typically called from the client side of the connection. It creates an implementation-dependent (bidirectional @@ -507,11 +507,23 @@ use a different transport and protocol interface. You can also pass a trivial ``lambda`` that returns a previously constructed Protocol instance. - Optional keyword arguments: + The are all specified using optional keyword arguments: - ``ssl``: Pass ``True`` to create an SSL transport (by default a plain TCP transport is created). Or pass an ``ssl.SSLContext`` - object to override the default SSL context object to be used. + object to override the default SSL context object to be used. If + a default context is created it is up to the implementation to + configure reasonable defaults. The reference implementation + currently uses ``PROTOCOL_SSLv23`` and sets the ``OP_NO_SSLv2`` + option, calls ``set_default_verify_paths()`` and sets verify_mode + to ``CERT_REQUIRED``. In addition, whenever the context (default + or otherwise) specifies a verify_mode of ``CERT_REQUIRED``, if a + hostname is given, immediately after a successful handshake + ``ss.ssl.match_hostname(peercert, hostname)`` is called, and if + this raises an exception the conection is closed. (To avoid this + behavior, pass in an context that doesn't have verify_mode set to + ``CERT_REQUIRED``. But this means you are not secure, and + vulnerable to for example man-in-the-middle attacks.) - ``family``, ``proto``, ``flags``: Address family, protocol and flags to be passed through to ``getaddrinfo()``. These all @@ -532,13 +544,15 @@ use a different transport and protocol interface. specific address. This is how you would do that. The host and port are looked up using ``getaddrinfo()``. -- ``start_serving(protocol_factory, host, port, **kwds)``. Enters a - serving loop that accepts connections. This is a coroutine that - completes once the serving loop is set up to serve. The return - value is a list of one or more sockets in listening mode. (Multiple - sockets may be returned if the specified address allows both IPv4 - and IPv6 connections.) You can use ``stop_serving()`` to stop the - serving loop. Each time a connection is accepted, +- ``create_server_serving(protocol_factory, host, port, + )``. Enters a serving loop that accepts connections. + This is a coroutine that completes once the serving loop is set up + to serve. The return value is a ``Server`` object which can be used + to stop the serving loop in a controlled fashion by calling its + ``close()`` method. + + Multiple sockets may be bound if the specified address allows + both IPv4 and IPv6 connections. Each time a connection is accepted, ``protocol_factory`` is called without arguments(*) to create a Protocol, a (bidirectional stream) Transport is created to represent the network side of the connection, and the two are tied together by @@ -549,7 +563,7 @@ use a different transport and protocol interface. connection, it should return a new Protocol object each time it is called. - Optional keyword arguments: + The are all specified using optional keyword arguments: - ``ssl``: Pass an ``ssl.SSLContext`` object to override the default SSL context object to be used. (Unlike ``create_connection()``, @@ -583,8 +597,8 @@ use a different transport and protocol interface. return a list of opaque objects that can be passed to ``stop_serving()``.) -- ``create_datagram_endpoint(protocol_factory, local_addr, - remote_addr, **kwds)``. Creates an endpoint for sending and +- ``create_datagram_endpoint(protocol_factory, local_addr=None, + remote_addr=None, **kwds)``. Creates an endpoint for sending and receiving datagrams (typically UDP packets). Because of the nature of datagram traffic, there are no separate calls to set up client and server side, since usually a single endpoint acts as both client @@ -1027,12 +1041,12 @@ Bidirectional stream transports have the following public methods: is known ahead of time, the best approach in both cases is to use the Content-Length header.) -- ``pause()``. Suspend delivery of data to the protocol until a - subsequent ``resume()`` call. Between ``pause()`` and ``resume()``, - the protocol's ``data_received()`` method will not be called. This - has no effect on ``write()``. +- ``pause_reading()``. Suspend delivery of data to the protocol until + a subsequent ``resume_reading()`` call. Between ``pause_reading()`` + and ``resume_reading()``, the protocol's ``data_received()`` method + will not be called. This has no effect on ``write()``. -- ``resume()``. Restart delivery of data to the protocol via +- ``resume_reading()``. Restart delivery of data to the protocol via ``data_received()``. - ``close()``. Sever the connection with the entity at the other end. @@ -1053,8 +1067,8 @@ Bidirectional stream transports have the following public methods: TBD: Provide flow control the other way -- the transport may need to suspend the protocol if the amount of data buffered becomes a burden. -Proposal: let the transport call ``protocol.pause()`` and -``protocol.resume()`` if they exist; if they don't exist, the +Proposal: let the transport call ``protocol.pause_writing()`` and +``protocol.resume_writing()`` if they exist; if they don't exist, the protocol doesn't support flow control. (Perhaps different names to avoid confusion between protocols and transports?) @@ -1065,8 +1079,9 @@ A writing stream transport supports the ``write()``, ``writelines()``, ``write_eof()``, ``can_write_eof()``, close() and ``abort()`` methods described for bidrectional stream transports. -A reading stream transport supports the ``pause()``, ``resume()`` and -``close()`` methods described for bidrectional stream transports. +A reading stream transport supports the ``pause_reading()``, +``resume_reading()`` and ``close()`` methods described for +bidrectional stream transports. A writing stream transport calls only ``connection_made()`` and ``connection_lost()`` on its associated protocol. @@ -1146,9 +1161,11 @@ context. (See the "Context" section way above.) p.data_received(b'def') - ``eof_received()``. This is called when the other end called - ``write_eof()`` (or something equivalent). The default - implementation calls ``close()`` on the transport, which causes - ``connection_lost()`` to be called (eventually) on the protocol. + ``write_eof()`` (or something equivalent). If this returns a false + value (including None), the transport will close itself. If it + returns a true value, closing the transport is up to the protocol. + + The default implementation returns None. - ``connection_lost(exc)``. The transport has been closed or aborted, has detected that the other end has closed the connection cleanly, @@ -1412,6 +1429,9 @@ off the coroutine when ``connection_made()`` is called. Open Issues =========== +- Make ``loop.stop()`` optional (and hence + ``loop.run_until_complete()`` too). + - A fuller public API for Handle? What's the use case? - Should we require all event loops to implement ``sock_recv()`` and @@ -1434,8 +1454,8 @@ Open Issues - Locks and queues? The Tulip implementation contains implementations of most types of locks and queues modeled after the standard library - ``threading`` and ``queue`` modules. Should we incorporate these in - the PEP? + ``threading`` and ``queue`` modules. These should be incorporated + into the PEP. - Probably need more socket I/O methods, e.g. ``sock_sendto()`` and ``sock_recvfrom()``, and perhaps others like ``pipe_read()``. Or