Commit 4a3ed08a authored by Alexandre's avatar Alexandre
Browse files

Use a specific class to hold a curl handle

parent 4d0876a9
......@@ -277,6 +277,8 @@ class Connection:
self.dot = dot
self.verbose = verbose
self.insecure = insecure
self.forceIPv4 = forceIPv4
self.forceIPv6 = forceIPv6
def __str__(self):
return self.server
......@@ -383,6 +385,37 @@ class ConnectionDoT(Connection):
request.check_response()
return request
class CurlHandle():
def __init__(self, connect=None, forceIPv4=False, forceIPv6=False,
verbose=verbose, insecure=insecure):
self.handle = pycurl.Curl()
# Does not work if pycurl was not compiled with nghttp2 (recent Debian
# packages are OK) https://github.com/pycurl/pycurl/issues/477
self.handle.setopt(pycurl.HTTP_VERSION, pycurl.CURL_HTTP_VERSION_2)
if verbose:
self.handle.setopt(pycurl.VERBOSE, True)
if insecure:
self.handle.setopt(pycurl.SSL_VERIFYPEER, False)
self.handle.setopt(pycurl.SSL_VERIFYHOST, False)
if forceIPv4:
self.handle.setopt(pycurl.IPRESOLVE, pycurl.IPRESOLVE_V4)
if forceIPv6:
self.handle.setopt(pycurl.IPRESOLVE, pycurl.IPRESOLVE_V6)
if connect is not None:
family, repraddress = check_ip_address(connect, dot=False)
self.handle.setopt(pycurl.CONNECT_TO, [f'::{repraddress}:443',])
self.handle.setopt(pycurl.HTTPHEADER, ["Content-type: application/dns-message"])
def reset_opt_default(self):
opts = {
pycurl.NOBODY: False,
pycurl.POST: False,
pycurl.POSTFIELDS: '',
pycurl.URL: ''
}
for opt, value in opts.items():
self.handle.setopt(opt, value)
class ConnectionDoH(Connection):
def __init__(self, server, servername=None, connect=None, forceIPv4=False, forceIPv6=False,
......@@ -396,8 +429,10 @@ class ConnectionDoH(Connection):
def create_handle(self):
if not self.multistreams:
self.curl = pycurl.Curl()
self.curl = CurlHandle(self.connect, self.forceIPv4, self.forceIPv6, self.verbose, self.insecure)
else:
self.curl = CurlHandle(self.connect, self.forceIPv4, self.forceIPv6, self.verbose, self.insecure)
return
self.curl = pycurl.Curl() # TODO: use CurlMulti()
# http://pycurl.io/docs/latest/curlmultiobject.html
# but first we have to
......@@ -405,42 +440,16 @@ class ConnectionDoH(Connection):
# most options are not for
# the multi handle but for
# each stream handle.
# Does not work if pycurl was not compiled with nghttp2 (recent Debian
# packages are OK) https://github.com/pycurl/pycurl/issues/477
self.curl.setopt(pycurl.HTTP_VERSION, pycurl.CURL_HTTP_VERSION_2)
if self.verbose:
self.curl.setopt(pycurl.VERBOSE, True)
if self.insecure:
self.curl.setopt(pycurl.SSL_VERIFYPEER, False)
self.curl.setopt(pycurl.SSL_VERIFYHOST, False)
if forceIPv4:
self.curl.setopt(pycurl.IPRESOLVE, pycurl.IPRESOLVE_V4)
if forceIPv6:
self.curl.setopt(pycurl.IPRESOLVE, pycurl.IPRESOLVE_V6)
if self.connect is not None:
self.family, self.repraddress = check_ip_address(self.connect, dot=False)
self.curl.setopt(pycurl.CONNECT_TO, [f'::{self.repraddress}:443',])
self.curl.setopt(pycurl.HTTPHEADER, ["Content-type: application/dns-message"])
def end(self):
self.curl.close()
def set_opt(self, opt, value):
self.curl.setopt(opt, value)
self.curl.handle.close()
def reset_opt_default(self):
opts = {
pycurl.NOBODY: False,
pycurl.POST: False,
pycurl.POSTFIELDS: '',
pycurl.URL: ''
}
for opt, value in opts.items():
self.set_opt(opt, value)
self.curl.reset_opt_default()
def prepare(self, request):
try:
self.reset_opt_default()
self.curl.reset_opt_default()
except AttributeError:
self.create_handle()
if request.post:
......@@ -451,25 +460,25 @@ class ConnectionDoH(Connection):
self.prepare_get(request)
def prepare_get(self, request):
self.set_opt(pycurl.HTTPGET, True)
self.curl.handle.setopt(pycurl.HTTPGET, True)
dns_req = base64.urlsafe_b64encode(request.data).decode('UTF8').rstrip('=')
self.set_opt(pycurl.URL, self.server + ("?dns=%s" % dns_req))
self.curl.handle.setopt(pycurl.URL, self.server + ("?dns=%s" % dns_req))
def prepare_post(self, request):
request.post = True
self.set_opt(pycurl.POST, True)
self.set_opt(pycurl.POSTFIELDS, request.data)
self.set_opt(pycurl.URL, self.server)
self.curl.handle.setopt(pycurl.POST, True)
self.curl.handle.setopt(pycurl.POSTFIELDS, request.data)
self.curl.handle.setopt(pycurl.URL, self.server)
def prepare_head(self, request):
request.head = True
self.prepare_get(request)
self.set_opt(pycurl.NOBODY, True)
self.curl.handle.setopt(pycurl.NOBODY, True)
def perform(self):
self.buffer = io.BytesIO()
self.set_opt(pycurl.WRITEDATA, self.buffer)
self.curl.perform()
self.curl.handle.setopt(pycurl.WRITEDATA, self.buffer)
self.curl.handle.perform()
def send(self, request):
request.to_wire()
......@@ -479,8 +488,8 @@ class ConnectionDoH(Connection):
def receive(self, request):
body = self.buffer.getvalue()
body_size = len(body)
http_code = self.curl.getinfo(pycurl.RESPONSE_CODE)
content_type = self.curl.getinfo(pycurl.CONTENT_TYPE)
http_code = self.curl.handle.getinfo(pycurl.RESPONSE_CODE)
content_type = self.curl.handle.getinfo(pycurl.CONTENT_TYPE)
request.response = body
request.response_size = body_size
request.rcode = http_code
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment