Support HTTPS

This commit is contained in:
Lonami Exo 2018-07-08 17:39:06 +02:00
parent e2c1efd0f1
commit 22a7b64e4e
2 changed files with 46 additions and 7 deletions

View File

@ -11,6 +11,7 @@ import asyncio
import errno
import logging
import socket
import ssl
from io import BytesIO
CONN_RESET_ERRNOS = {
@ -28,6 +29,7 @@ try:
except ImportError:
socks = None
SSL_PORT = 443
__log__ = logging.getLogger(__name__)
@ -37,15 +39,18 @@ class TcpClient:
class SocketClosed(ConnectionError):
pass
def __init__(self, *, loop, timeout, proxy=None):
def __init__(self, *, loop, timeout, ssl=None, proxy=None):
"""
Initializes the TCP client.
:param proxy: the proxy to be used, if any.
:param timeout: the timeout for connect, read and write operations.
:param ssl: ssl.wrap_socket keyword arguments to use when connecting
if port == SSL_PORT, or do nothing if not present.
"""
self._loop = loop
self.proxy = proxy
self.ssl = ssl
self._socket = None
self._closed = asyncio.Event(loop=self._loop)
self._closed.set()
@ -87,6 +92,8 @@ class TcpClient:
try:
if self._socket is None:
self._socket = self._create_socket(mode, self.proxy)
if self.ssl and port == SSL_PORT:
self._socket = ssl.wrap_socket(self._socket, **self.ssl)
await asyncio.wait_for(
self._loop.sock_connect(self._socket, address),

View File

@ -1,17 +1,49 @@
from .tcpfull import ConnectionTcpFull
import errno
import ssl
try:
import aiohttp
except ImportError:
aiohttp = None
class ConnectionHttp(ConnectionTcpFull):
from .common import Connection
from ...extensions import TcpClient
class ConnectionHttp(Connection):
def __init__(self, *, loop, timeout, proxy=None):
if aiohttp is None:
raise RuntimeError('HTTP(S) mode requires the aiohttp '
'package, which is not installed')
super().__init__(loop=loop, timeout=timeout, proxy=proxy)
self.conn = TcpClient(
timeout=self._timeout, loop=self._loop, proxy=self._proxy,
ssl=dict(ssl_version=ssl.PROTOCOL_SSLv23, ciphers='ADH-AES256-SHA')
)
self.read = self.conn.read
self.write = self.conn.write
self._host = None
async def connect(self, ip, port):
if port != 80:
port = 80 # HTTP without TLS needs port 80
self._host = '{}:{}'.format(ip, port)
return await super().connect(ip, port)
try:
await self.conn.connect(ip, port)
except OSError as e:
if e.errno == errno.EISCONN:
return # Already connected, no need to re-set everything up
else:
raise
def get_timeout(self):
return self.conn.timeout
def is_connected(self):
return self.conn.is_connected
async def close(self):
self.conn.close()
async def recv(self):
while True: