Commit 359069f9 authored by Alexandre's avatar Alexandre
Browse files

[DoH] Delete CurlHandle class and use curl object instead

Do not use the CurlHandle class to store the curl handle.
Instead, use the `pycurl.Curl` class and add attributes to it.
parent 17890fbd
......@@ -432,37 +432,8 @@ class ConnectionDoT(Connection):
request.check_response()
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, ["Accept: application/dns-message", "Content-type: application/dns-message"])
def close(self):
self.handle.close()
def setopt(self, key, value):
self.handle.setopt(key, value)
def perform(self):
self.handle.perform()
def reset_opt_default(self):
def create_handle(connection):
def reset_opt_default(handle):
opts = {
pycurl.NOBODY: False,
pycurl.POST: False,
......@@ -470,35 +441,45 @@ class CurlHandle():
pycurl.URL: ''
}
for opt, value in opts.items():
self.handle.setopt(opt, value)
handle.setopt(opt, value)
def prepare(self, connection, request):
def prepare(handle, connection, request):
if not connection.multistreams:
self.reset_opt_default()
handle.reset_opt_default(handle)
if request.post:
self.prepare_post(connection, request)
elif request.head:
self.prepare_head(connection, request)
handle.setopt(pycurl.POST, True)
handle.setopt(pycurl.POSTFIELDS, request.data)
handle.setopt(pycurl.URL, connection.server)
else:
self.prepare_get(connection, request)
handle.setopt(pycurl.HTTPGET, True) # automatically sets CURLOPT_NOBODY to 0
if request.head:
handle.setopt(pycurl.NOBODY, True)
dns_req = base64.urlsafe_b64encode(request.data).decode('UTF8').rstrip('=')
handle.setopt(pycurl.URL, connection.server + ("?dns=%s" % dns_req))
request.buffer = io.BytesIO()
self.handle.setopt(pycurl.WRITEDATA, request.buffer)
def prepare_get(self, connection, request):
self.handle.setopt(pycurl.HTTPGET, True)
dns_req = base64.urlsafe_b64encode(request.data).decode('UTF8').rstrip('=')
self.handle.setopt(pycurl.URL, connection.server + ("?dns=%s" % dns_req))
def prepare_post(self, connection, request):
request.post = True
self.handle.setopt(pycurl.POST, True)
self.handle.setopt(pycurl.POSTFIELDS, request.data)
self.handle.setopt(pycurl.URL, connection.server)
def prepare_head(self, connection, request):
request.head = True
self.prepare_get(connection, request)
self.handle.setopt(pycurl.NOBODY, True)
handle.setopt(pycurl.WRITEDATA, request.buffer)
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
handle.setopt(pycurl.HTTP_VERSION, pycurl.CURL_HTTP_VERSION_2)
if connection.verbose:
handle.setopt(pycurl.VERBOSE, True)
if connection.insecure:
handle.setopt(pycurl.SSL_VERIFYPEER, False)
handle.setopt(pycurl.SSL_VERIFYHOST, False)
if connection.forceIPv4:
handle.setopt(pycurl.IPRESOLVE, pycurl.IPRESOLVE_V4)
if connection.forceIPv6:
handle.setopt(pycurl.IPRESOLVE, pycurl.IPRESOLVE_V6)
if connection.connect is not None:
family, repraddress = check_ip_address(connection.connect, dot=False)
handle.setopt(pycurl.CONNECT_TO, [f'::{repraddress}:443',])
handle.setopt(pycurl.HTTPHEADER,
["Accept: application/dns-message", "Content-type: application/dns-message"])
handle.reset_opt_default = reset_opt_default
handle.prepare = prepare
return handle
class ConnectionDoH(Connection):
......@@ -513,10 +494,7 @@ class ConnectionDoH(Connection):
if self.multistreams:
self.multi = self.create_multi()
else:
self.curl_handle = self.create_handle()
def create_handle(self):
return CurlHandle(self.connect, self.forceIPv4, self.forceIPv6, self.verbose, self.insecure)
self.curl_handle = create_handle(self)
def create_multi(self):
multi = pycurl.CurlMulti()
......@@ -563,7 +541,7 @@ class ConnectionDoH(Connection):
self.perform(request)
def receive(self, request):
handle = request.handle.handle
handle = request.handle
body = request.buffer.getvalue()
body_size = len(body)
http_code = handle.getinfo(pycurl.RESPONSE_CODE)
......@@ -585,13 +563,13 @@ class ConnectionDoH(Connection):
if synchronous:
request.handle = self.curl_handle
else:
request.handle = self.create_handle()
request.handle.prepare(self, request)
request.handle = create_handle(self)
request.handle.prepare(request.handle, self, request)
if synchronous:
self.send_and_receive(request)
request.check_response()
else:
self.multi.add_handle(request.handle.handle)
self.multi.add_handle(request.handle)
def get_next_domain(input_file):
......@@ -705,7 +683,7 @@ def run_check_default(connection):
elif method == DOH_HEAD:
request.head = True
request.handle = connection.curl_handle
request.handle.prepare(connection, request)
request.handle.prepare(request.handle, connection, request)
try:
connection.send_and_receive(request)
except CustomException as e:
......@@ -729,7 +707,7 @@ def run_check_mime(connection, accept="application/dns-message", content_type="a
request = create_request(**req_args)
connection.curl_handle.setopt(pycurl.HTTPHEADER, header)
request.handle = connection.curl_handle
request.handle.prepare(connection, request)
request.handle.prepare(request.handle, connection, request)
try:
connection.send_and_receive(request)
except CustomException as e:
......@@ -755,7 +733,7 @@ def run_check_trunc(connection):
request = create_request(trunc=True, **req_args)
request.post = True
request.handle = connection.curl_handle
request.handle.prepare(connection, request)
request.handle.prepare(request.handle, connection, request)
try:
# 8.8.8.8 replies FORMERR but most DoT servers violently shut down the connection (which is legal)
connection.send_and_receive(request)
......
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