(This is a cross-post to the mailing list; seemed like it should go here, too.)

It turns out that people largely dislike the deprecation of the Eventlet convenience functions (tcp_listener and friends). The elimination of redundant boilerplate code is a pretty important part of Eventlet. In the past few weeks since I’ve deprecated them and tried to force myself to use the standard socket interface in all my coding, I’ve come to agree.

So, convenience functions are back on the menu! This is an opportunity to do them up right, however. The old names were confusing, and the old functions could have been a bit more flexible. Sergey and I talked this over in #eventlet, and came up with the following four functions. These would be accessible as eventlet.connect, etc.

def connect(addr, family=socket.AF_INET, bind=None):
    """Convenience function for opening client sockets.
    :param addr: Address of the server to connect to.  For TCP sockets, 
    this is a (host, port) tuple.
    :param family: Socket family, optional.  See :mod:`socket` 
    documentation for available families.
    :param bind: Local address to bind to, optional.
    :return The connected green socket object.
def listen(addr, family=socket.AF_INET, backlog=50):
    """Convenience function for opening server sockets.  This
    socket can be used as the argument to :func:`serve`, or
    directly by setting up an ``accept()`` loop.

    Sets SO_REUSEADDR on the socket to save on annoyance.
    :param addr: Address to listen on.  For TCP sockets, this is a 
    (host, port)  tuple.
    :param family: Socket family, optional.  See :mod:`socket` 
    documentation for available families.
    :param backlog: The maximum number of queued connections. Should be 
    at least 1; the maximum value is system-dependent.
    :return The listening green socket object.

def wrap_ssl(sock, keyfile=None, certfile=None, server_side=False,
    cert_reqs=None, ssl_version=None, ca_certs=None, 
    do_handshake_on_connect=True, suppress_ragged_eofs=True):
    """Convenience function for converting a regular socket into an SSL 
    socket.  Has the same interface as :func:`ssl.wrap_socket`, but 
    works on 2.5 or earlier, using PyOpenSSL.

    The preferred idiom is to call wrap_ssl directly on the creation
    method, e.g., ``wrap_ssl(connect(addr))`` or 
    ``wrap_ssl(listen(addr), server_side=True)``. This way there is
    no "naked" socket sitting around to accidentally corrupt the SSL
    :return Green SSL object.

def serve(sock, handle, concurrency=1000):
    """Runs a server on the supplied socket.  Calls the function 
    *handle* in a separate greenthread for every incoming request. 
    This function blocks the calling greenthread; it won't return until 
    the server completes.  If you desire an immediate return,
    spawn a new greenthread for :func:`serve`.
    The *handle* function must raise an EndServerException to 
    gracefully terminate the server -- that's the only way to get the 
    server() function to return.  Any other uncaught exceptions raised
    in *handle* are raised as exceptions from :func:`serve`, so be 
    sure to do a good job catching exceptions that your application 
    raises.  The return value of *handle* is ignored.

    The value in *concurrency* controls the maximum number of 
    greenthreads that will be open at any time handling requests.  When 
    the server hits the concurrency limit, it stops accepting new 
    connections until the existing ones complete.

You read that last one correctly — the ghost of tcp_server rises! But I think that we’ve been able to deal with the issues faced by the original tcp_server and that serve is something that we can continue to support for the future.

Tell me what you think!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Get every new post delivered to your Inbox.