Skip to content

Commit 57a3392

Browse files
mbeijendrshvik
andauthored
Propagate timeout through SOCKS5 handshake (#1009)
Co-authored-by: drshvik <ai23btech11004@iith.ac.in>
1 parent 82b9e2d commit 57a3392

2 files changed

Lines changed: 22 additions & 12 deletions

File tree

src/httpcore2/httpcore2/_async/socks_proxy.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ async def _init_socks5_connection(
4545
host: bytes,
4646
port: int,
4747
auth: tuple[bytes, bytes] | None = None,
48+
timeouts: dict[str, float | None] | None = None,
4849
) -> None:
50+
timeouts = timeouts or {}
51+
write_timeout = timeouts.get("write", None)
52+
read_timeout = timeouts.get("read", None)
4953
conn = socksio.socks5.SOCKS5Connection()
5054

5155
# Auth method request
@@ -56,10 +60,10 @@ async def _init_socks5_connection(
5660
)
5761
conn.send(socksio.socks5.SOCKS5AuthMethodsRequest([auth_method]))
5862
outgoing_bytes = conn.data_to_send()
59-
await stream.write(outgoing_bytes)
63+
await stream.write(outgoing_bytes, timeout=write_timeout)
6064

6165
# Auth method response
62-
incoming_bytes = await stream.read(max_bytes=4096)
66+
incoming_bytes = await stream.read(max_bytes=4096, timeout=read_timeout)
6367
response = conn.receive_data(incoming_bytes)
6468
assert isinstance(response, socksio.socks5.SOCKS5AuthReply)
6569
if response.method != auth_method:
@@ -73,10 +77,10 @@ async def _init_socks5_connection(
7377
username, password = auth
7478
conn.send(socksio.socks5.SOCKS5UsernamePasswordRequest(username, password))
7579
outgoing_bytes = conn.data_to_send()
76-
await stream.write(outgoing_bytes)
80+
await stream.write(outgoing_bytes, timeout=write_timeout)
7781

7882
# Username/password response
79-
incoming_bytes = await stream.read(max_bytes=4096)
83+
incoming_bytes = await stream.read(max_bytes=4096, timeout=read_timeout)
8084
response = conn.receive_data(incoming_bytes)
8185
assert isinstance(response, socksio.socks5.SOCKS5UsernamePasswordReply)
8286
if not response.success:
@@ -85,10 +89,10 @@ async def _init_socks5_connection(
8589
# Connect request
8690
conn.send(socksio.socks5.SOCKS5CommandRequest.from_address(socksio.socks5.SOCKS5Command.CONNECT, (host, port)))
8791
outgoing_bytes = conn.data_to_send()
88-
await stream.write(outgoing_bytes)
92+
await stream.write(outgoing_bytes, timeout=write_timeout)
8993

9094
# Connect response
91-
incoming_bytes = await stream.read(max_bytes=4096)
95+
incoming_bytes = await stream.read(max_bytes=4096, timeout=read_timeout)
9296
response = conn.receive_data(incoming_bytes)
9397
assert isinstance(response, socksio.socks5.SOCKS5Reply)
9498
if response.reply_code != socksio.socks5.SOCKS5ReplyCode.SUCCEEDED:
@@ -229,6 +233,7 @@ async def handle_async_request(self, request: Request) -> Response:
229233
"host": self._remote_origin.host.decode("ascii"),
230234
"port": self._remote_origin.port,
231235
"auth": self._proxy_auth,
236+
"timeouts": timeouts,
232237
}
233238
async with Trace("setup_socks5_connection", logger, request, kwargs) as trace:
234239
await _init_socks5_connection(**kwargs)

src/httpcore2/httpcore2/_sync/socks_proxy.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ def _init_socks5_connection(
4545
host: bytes,
4646
port: int,
4747
auth: tuple[bytes, bytes] | None = None,
48+
timeouts: dict[str, float | None] | None = None,
4849
) -> None:
50+
timeouts = timeouts or {}
51+
write_timeout = timeouts.get("write", None)
52+
read_timeout = timeouts.get("read", None)
4953
conn = socksio.socks5.SOCKS5Connection()
5054

5155
# Auth method request
@@ -56,10 +60,10 @@ def _init_socks5_connection(
5660
)
5761
conn.send(socksio.socks5.SOCKS5AuthMethodsRequest([auth_method]))
5862
outgoing_bytes = conn.data_to_send()
59-
stream.write(outgoing_bytes)
63+
stream.write(outgoing_bytes, timeout=write_timeout)
6064

6165
# Auth method response
62-
incoming_bytes = stream.read(max_bytes=4096)
66+
incoming_bytes = stream.read(max_bytes=4096, timeout=read_timeout)
6367
response = conn.receive_data(incoming_bytes)
6468
assert isinstance(response, socksio.socks5.SOCKS5AuthReply)
6569
if response.method != auth_method:
@@ -73,10 +77,10 @@ def _init_socks5_connection(
7377
username, password = auth
7478
conn.send(socksio.socks5.SOCKS5UsernamePasswordRequest(username, password))
7579
outgoing_bytes = conn.data_to_send()
76-
stream.write(outgoing_bytes)
80+
stream.write(outgoing_bytes, timeout=write_timeout)
7781

7882
# Username/password response
79-
incoming_bytes = stream.read(max_bytes=4096)
83+
incoming_bytes = stream.read(max_bytes=4096, timeout=read_timeout)
8084
response = conn.receive_data(incoming_bytes)
8185
assert isinstance(response, socksio.socks5.SOCKS5UsernamePasswordReply)
8286
if not response.success:
@@ -85,10 +89,10 @@ def _init_socks5_connection(
8589
# Connect request
8690
conn.send(socksio.socks5.SOCKS5CommandRequest.from_address(socksio.socks5.SOCKS5Command.CONNECT, (host, port)))
8791
outgoing_bytes = conn.data_to_send()
88-
stream.write(outgoing_bytes)
92+
stream.write(outgoing_bytes, timeout=write_timeout)
8993

9094
# Connect response
91-
incoming_bytes = stream.read(max_bytes=4096)
95+
incoming_bytes = stream.read(max_bytes=4096, timeout=read_timeout)
9296
response = conn.receive_data(incoming_bytes)
9397
assert isinstance(response, socksio.socks5.SOCKS5Reply)
9498
if response.reply_code != socksio.socks5.SOCKS5ReplyCode.SUCCEEDED:
@@ -229,6 +233,7 @@ def handle_request(self, request: Request) -> Response:
229233
"host": self._remote_origin.host.decode("ascii"),
230234
"port": self._remote_origin.port,
231235
"auth": self._proxy_auth,
236+
"timeouts": timeouts,
232237
}
233238
with Trace("setup_socks5_connection", logger, request, kwargs) as trace:
234239
_init_socks5_connection(**kwargs)

0 commit comments

Comments
 (0)