Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.001 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'that?': 0.05; '(all': 0.07; 'duplicate': 0.07; 'only,': 0.07; 'socket': 0.07; 'arguments': 0.09; 'below).': 0.09; 'newly': 0.09; 'pyopenssl': 0.09; '\xe2\x80\xa6)': 0.09; 'python': 0.11; 'itself.': 0.14; '(it': 0.16; 'factory,': 0.16; 'feasible': 0.16; 'hack,': 0.16; 'ideally,': 0.16; 'i\xe2\x80\x99m': 0.16; 'minus': 0.16; 'parts.': 0.16; 'port),': 0.16; 'process?': 0.16; 'tcp': 0.16; 'unneeded': 0.16; 'discussion': 0.18; 'library': 0.18; 'all,': 0.19; 'implementing': 0.19; 'seems': 0.21; 'code,': 0.22; 'input': 0.22; 'preferred': 0.22; 'creating': 0.23; 'header:User-Agent:1': 0.23; 'ssl': 0.24; 'question': 0.24; 'options': 0.25; '(for': 0.26; 'supported': 0.26; 'code': 0.31; '(possibly': 0.31; 'context,': 0.31; 'layer': 0.31; 'object.': 0.31; 'though.': 0.31; 'anyone': 0.31; 'quite': 0.32; 'entirely': 0.33; 'trouble': 0.34; 'could': 0.34; 'created': 0.35; 'but': 0.35; 'there': 0.35; 'version': 0.36; 'should': 0.36; 'so,': 0.37; 'implement': 0.38; 'subject:new': 0.38; '(3)': 0.38; 'depends': 0.38; 'to:addr :python-list': 0.38; 'rather': 0.38; 'expect': 0.39; 'does': 0.39; 'sure': 0.39; 'to:addr:python.org': 0.39; 'how': 0.40; 'most': 0.60; 'details.': 0.61; 'simple': 0.61; 'first': 0.61; 'making': 0.63; 'subject:The': 0.64; 'provide': 0.64; 'more': 0.64; 'direct': 0.67; 'background:': 0.68; '3.4': 0.84; 'client-side': 0.84; 'mind:': 0.84; 'transport,': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=wielicki.name; s=k001.sol; t=1417949953; bh=xRwfAcx5vlfLhoMuZ4uyr5b52QLtL746NgD2z2e+uzQ=; h=Date:From:To:Subject; b=mKXaLcXPb5m914TY0pTD6x3aOTRUa9GfGu8seBZBVnpD2GnIujl1rfG5eXib7NRw2 263PbHT+/DhareWJeKk45mCyM9VhmWdkuydfk6DW3eMXKU/sCDIR2WUeutt0z97x/x tFpQnrE+nDd4BmzWK7kgwaSnayXG+eczTMAPPC3oFOgFHyixWtSdQs7ptuJDuyzKBh SbRf9V2grpeL371xemzXVc/rtrTDLwWu4x77cD4N14MKiIJqhOn9CTLDgghLCNdvN5 YF0BJmnM8tbI2gYydSQ47Xlx0yZxSsnj8Em4MtFRQvXviA3DhZTnjBN83OPoEZD9uc 2j4GuXK4ldK7A== Date: Sun, 07 Dec 2014 11:59:11 +0100 From: Jonas Wielicki User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: python-list@python.org Subject: The preferred way to implement a new transport in asyncio Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Mailman-Approved-At: Sun, 07 Dec 2014 14:06:14 +0100 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 51 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1417957575 news.xs4all.nl 2849 [2001:888:2000:d::a6]:33899 X-Complaints-To: abuse@xs4all.nl Path: csiph.com!usenet.pasdenom.info!bete-des-vosges.org!feed.ac-versailles.fr!nerim.net!novso.com!newsfeed.xs4all.nl!newsfeed4a.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Xref: csiph.com comp.lang.python:82054 Hello fellow pythoneers, First some background: I am implementing an XMPP client library in asyncio. XMPP uses (START-)TLS. However, the native SSL support of Python is rather restricted: We cannot hook into the certificate validation process (it is PKI-all-or-nothing) at all, in addition many of the goodies arrive with Python 3.4 only, while asyncio is available in 3.3 already (with tulip). STARTTLS is also not quite supported with asyncio (for which I found a hack, but it is about as unpleasant as number (3) below). So I wondered how feasible a PyOpenSSL based transport would be. From looking into the asyncio selector_events.py code, it should be managealbe to implement a client-side PyOpenSSL based transport (possibly with STARTTLS support). The main question I have is how to interweave this transport with asyncio itself. Is there a preferred process? My approach would have been to provide a coroutine to the user which takes a loop and the arguments neccessary to create a transport (socket/(hostname, port), ssl context, protocol factory, …) and returns the newly created transport. I’m not entirely sure yet how to create the socket though. I have three (all more or less unpleasant) options in mind: 1. Instead of making a simple transport, I make a Protocol/Transport hybrid one would layer on top of the TCP transport provided by asyncio. This is unpleasant because OpenSSL wants direct access to the socket and I expect trouble with that (have not dug into that yet though). 2. Create a Transport using the original create_connection and hard-unwire it from the loop using remove_reader/writer and hostily take over the socket object. This is unpleasant because it depends on things which I would consider internal details. 3. Duplicate the whole code from the original create_connection implementation, minus the unneeded parts. This is unpleasant because of code duplication. (3) seems like the safest approach to me, as it does not rely on any internalities of asyncio, but it is also the most cumbersome. Ideally, there would be a public version of create_connection which returns the socket instead of creating a transport from it. (If there is general agreement on this, we could take this discussion to python-ideas. ) So, does anyone have input on that? best regards, jwi