python-socks 2.8.2__py3-none-any.whl → 3.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python_socks/__init__.py +11 -13
- python_socks/_abc.py +35 -22
- python_socks/_connectors/abc.py +5 -3
- python_socks/_connectors/factory_async.py +8 -8
- python_socks/_connectors/factory_sync.py +8 -8
- python_socks/_connectors/http_async.py +7 -7
- python_socks/_connectors/http_sync.py +7 -7
- python_socks/_connectors/socks4_async.py +10 -10
- python_socks/_connectors/socks4_sync.py +10 -10
- python_socks/_connectors/socks5_async.py +29 -26
- python_socks/_connectors/socks5_sync.py +36 -28
- python_socks/_errors.py +15 -2
- python_socks/_helpers.py +35 -32
- python_socks/_protocols/errors.py +10 -1
- python_socks/_protocols/http.py +55 -60
- python_socks/_protocols/socks4.py +22 -26
- python_socks/_protocols/socks5.py +77 -70
- python_socks/_types.py +4 -0
- python_socks/_version.py +2 -2
- python_socks/async_/__init__.py +0 -3
- python_socks/async_/anyio/__init__.py +1 -2
- python_socks/async_/anyio/_connect.py +6 -4
- python_socks/async_/anyio/_proxy.py +85 -92
- python_socks/async_/anyio/_resolver.py +10 -3
- python_socks/async_/anyio/_stream.py +11 -26
- python_socks/async_/anyio/v2/__init__.py +1 -5
- python_socks/async_/anyio/v2/_connect.py +7 -4
- python_socks/async_/anyio/v2/_proxy.py +36 -26
- python_socks/async_/anyio/v2/_stream.py +11 -11
- python_socks/async_/asyncio/__init__.py +1 -2
- python_socks/async_/asyncio/_connect.py +12 -7
- python_socks/async_/asyncio/_proxy.py +48 -49
- python_socks/async_/asyncio/_resolver.py +11 -4
- python_socks/async_/asyncio/_stream.py +9 -13
- python_socks/async_/asyncio/v2/__init__.py +1 -2
- python_socks/async_/asyncio/v2/_connect.py +8 -5
- python_socks/async_/asyncio/v2/_proxy.py +38 -28
- python_socks/async_/asyncio/v2/_stream.py +20 -18
- python_socks/async_/trio/__init__.py +1 -1
- python_socks/async_/trio/_connect.py +5 -4
- python_socks/async_/trio/_proxy.py +46 -48
- python_socks/async_/trio/_resolver.py +11 -3
- python_socks/async_/trio/_stream.py +9 -9
- python_socks/async_/trio/v2/__init__.py +1 -5
- python_socks/async_/trio/v2/_connect.py +3 -2
- python_socks/async_/trio/v2/_proxy.py +34 -24
- python_socks/async_/trio/v2/_stream.py +13 -13
- python_socks/sync/__init__.py +1 -3
- python_socks/sync/_connect.py +4 -3
- python_socks/sync/_proxy.py +42 -43
- python_socks/sync/_resolver.py +17 -5
- python_socks/sync/_stream.py +9 -9
- python_socks/sync/v2/__init__.py +1 -5
- python_socks/sync/v2/_connect.py +5 -3
- python_socks/sync/v2/_proxy.py +35 -26
- python_socks/sync/v2/_ssl_transport.py +3 -0
- python_socks/sync/v2/_stream.py +19 -14
- python_socks-3.1.0.dist-info/METADATA +346 -0
- python_socks-3.1.0.dist-info/RECORD +65 -0
- {python_socks-2.8.2.dist-info → python_socks-3.1.0.dist-info}/WHEEL +1 -1
- python_socks/async_/_proxy_chain.py +0 -34
- python_socks/async_/anyio/_chain.py +0 -42
- python_socks/async_/anyio/v2/_chain.py +0 -32
- python_socks/async_/asyncio/v2/_chain.py +0 -32
- python_socks/async_/curio/__init__.py +0 -4
- python_socks/async_/curio/_connect.py +0 -17
- python_socks/async_/curio/_proxy.py +0 -132
- python_socks/async_/curio/_resolver.py +0 -25
- python_socks/async_/curio/_stream.py +0 -32
- python_socks/async_/trio/v2/_chain.py +0 -32
- python_socks/sync/_chain.py +0 -32
- python_socks/sync/v2/_chain.py +0 -26
- python_socks-2.8.2.dist-info/METADATA +0 -295
- python_socks-2.8.2.dist-info/RECORD +0 -77
- {python_socks-2.8.2.dist-info → python_socks-3.1.0.dist-info}/licenses/LICENSE.txt +0 -0
- {python_socks-2.8.2.dist-info → python_socks-3.1.0.dist-info}/top_level.txt +0 -0
python_socks/__init__.py
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
from ._version import __version__, __title__
|
|
2
|
-
|
|
3
|
-
from ._types import ProxyType
|
|
4
|
-
from ._helpers import parse_proxy_url
|
|
5
|
-
|
|
6
1
|
from ._errors import (
|
|
2
|
+
ProxyConnectionError,
|
|
7
3
|
ProxyError,
|
|
8
4
|
ProxyTimeoutError,
|
|
9
|
-
ProxyConnectionError,
|
|
10
5
|
)
|
|
6
|
+
from ._helpers import parse_proxy_url
|
|
7
|
+
from ._types import ProxyType
|
|
8
|
+
from ._version import __title__, __version__
|
|
11
9
|
|
|
12
10
|
__all__ = (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
"ProxyConnectionError",
|
|
12
|
+
"ProxyError",
|
|
13
|
+
"ProxyTimeoutError",
|
|
14
|
+
"ProxyType",
|
|
15
|
+
"__title__",
|
|
16
|
+
"__version__",
|
|
17
|
+
"parse_proxy_url",
|
|
20
18
|
)
|
python_socks/_abc.py
CHANGED
|
@@ -1,40 +1,53 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import socket
|
|
4
|
+
|
|
5
|
+
from ._types import ResolvedAddress
|
|
2
6
|
|
|
3
7
|
|
|
4
8
|
class SyncResolver:
|
|
5
|
-
def resolve(
|
|
6
|
-
|
|
9
|
+
def resolve(
|
|
10
|
+
self,
|
|
11
|
+
host: str,
|
|
12
|
+
port: int = 0,
|
|
13
|
+
family: socket.AddressFamily = socket.AF_UNSPEC,
|
|
14
|
+
) -> ResolvedAddress:
|
|
15
|
+
raise NotImplementedError
|
|
7
16
|
|
|
8
17
|
|
|
9
18
|
class AsyncResolver:
|
|
10
|
-
async def resolve(
|
|
11
|
-
|
|
19
|
+
async def resolve(
|
|
20
|
+
self,
|
|
21
|
+
host: str,
|
|
22
|
+
port: int = 0,
|
|
23
|
+
family: socket.AddressFamily = socket.AF_UNSPEC,
|
|
24
|
+
) -> ResolvedAddress:
|
|
25
|
+
raise NotImplementedError
|
|
12
26
|
|
|
13
27
|
|
|
14
28
|
class SyncSocketStream:
|
|
29
|
+
def write(self, data: bytes) -> None:
|
|
30
|
+
raise NotImplementedError
|
|
15
31
|
|
|
16
|
-
def
|
|
17
|
-
raise NotImplementedError
|
|
18
|
-
|
|
19
|
-
def read(self, max_bytes: Optional[int] = None):
|
|
20
|
-
raise NotImplementedError()
|
|
32
|
+
def read(self, max_bytes: int = ...) -> bytes:
|
|
33
|
+
raise NotImplementedError
|
|
21
34
|
|
|
22
|
-
def
|
|
23
|
-
raise NotImplementedError
|
|
35
|
+
def read_exactly(self, n: int) -> bytes:
|
|
36
|
+
raise NotImplementedError
|
|
24
37
|
|
|
25
|
-
def close(self):
|
|
26
|
-
raise NotImplementedError
|
|
38
|
+
def close(self) -> None:
|
|
39
|
+
raise NotImplementedError
|
|
27
40
|
|
|
28
41
|
|
|
29
42
|
class AsyncSocketStream:
|
|
30
|
-
async def
|
|
31
|
-
raise NotImplementedError
|
|
43
|
+
async def write(self, data: bytes) -> None:
|
|
44
|
+
raise NotImplementedError
|
|
32
45
|
|
|
33
|
-
async def read(self, max_bytes:
|
|
34
|
-
raise NotImplementedError
|
|
46
|
+
async def read(self, max_bytes: int = ...) -> bytes:
|
|
47
|
+
raise NotImplementedError
|
|
35
48
|
|
|
36
|
-
async def
|
|
37
|
-
raise NotImplementedError
|
|
49
|
+
async def read_exactly(self, n: int) -> bytes:
|
|
50
|
+
raise NotImplementedError
|
|
38
51
|
|
|
39
|
-
async def close(self):
|
|
40
|
-
raise NotImplementedError
|
|
52
|
+
async def close(self) -> None:
|
|
53
|
+
raise NotImplementedError
|
python_socks/_connectors/abc.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from .._abc import AsyncSocketStream, SyncSocketStream
|
|
2
4
|
|
|
3
5
|
|
|
4
6
|
class SyncConnector:
|
|
@@ -7,7 +9,7 @@ class SyncConnector:
|
|
|
7
9
|
stream: SyncSocketStream,
|
|
8
10
|
host: str,
|
|
9
11
|
port: int,
|
|
10
|
-
):
|
|
12
|
+
) -> Any:
|
|
11
13
|
raise NotImplementedError
|
|
12
14
|
|
|
13
15
|
|
|
@@ -17,5 +19,5 @@ class AsyncConnector:
|
|
|
17
19
|
stream: AsyncSocketStream,
|
|
18
20
|
host: str,
|
|
19
21
|
port: int,
|
|
20
|
-
):
|
|
22
|
+
) -> Any:
|
|
21
23
|
raise NotImplementedError
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
2
3
|
from .._abc import AsyncResolver
|
|
3
4
|
from .._types import ProxyType
|
|
4
|
-
|
|
5
5
|
from .abc import AsyncConnector
|
|
6
|
-
from .socks5_async import Socks5AsyncConnector
|
|
7
|
-
from .socks4_async import Socks4AsyncConnector
|
|
8
6
|
from .http_async import HttpAsyncConnector
|
|
7
|
+
from .socks4_async import Socks4AsyncConnector
|
|
8
|
+
from .socks5_async import Socks5AsyncConnector
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def create_connector(
|
|
12
12
|
proxy_type: ProxyType,
|
|
13
|
-
username:
|
|
14
|
-
password:
|
|
15
|
-
rdns:
|
|
13
|
+
username: str | None,
|
|
14
|
+
password: str | None,
|
|
15
|
+
rdns: bool | None, # noqa: FBT001
|
|
16
16
|
resolver: AsyncResolver,
|
|
17
17
|
) -> AsyncConnector:
|
|
18
18
|
if proxy_type == ProxyType.SOCKS4:
|
|
@@ -37,4 +37,4 @@ def create_connector(
|
|
|
37
37
|
resolver=resolver,
|
|
38
38
|
)
|
|
39
39
|
|
|
40
|
-
raise ValueError(f
|
|
40
|
+
raise ValueError(f"Invalid proxy type: {proxy_type}")
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
2
3
|
from .._abc import SyncResolver
|
|
3
4
|
from .._types import ProxyType
|
|
4
|
-
|
|
5
5
|
from .abc import SyncConnector
|
|
6
|
-
from .socks5_sync import Socks5SyncConnector
|
|
7
|
-
from .socks4_sync import Socks4SyncConnector
|
|
8
6
|
from .http_sync import HttpSyncConnector
|
|
7
|
+
from .socks4_sync import Socks4SyncConnector
|
|
8
|
+
from .socks5_sync import Socks5SyncConnector
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def create_connector(
|
|
12
12
|
proxy_type: ProxyType,
|
|
13
|
-
username:
|
|
14
|
-
password:
|
|
15
|
-
rdns:
|
|
13
|
+
username: str | None,
|
|
14
|
+
password: str | None,
|
|
15
|
+
rdns: bool | None, # noqa: FBT001
|
|
16
16
|
resolver: SyncResolver,
|
|
17
17
|
) -> SyncConnector:
|
|
18
18
|
if proxy_type == ProxyType.SOCKS4:
|
|
@@ -37,4 +37,4 @@ def create_connector(
|
|
|
37
37
|
resolver=resolver,
|
|
38
38
|
)
|
|
39
39
|
|
|
40
|
-
raise ValueError(f
|
|
40
|
+
raise ValueError(f"Invalid proxy type: {proxy_type}")
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
from
|
|
2
|
-
from .._abc import AsyncSocketStream, AsyncResolver
|
|
3
|
-
from .abc import AsyncConnector
|
|
1
|
+
from __future__ import annotations
|
|
4
2
|
|
|
3
|
+
from .._abc import AsyncResolver, AsyncSocketStream
|
|
5
4
|
from .._protocols import http
|
|
5
|
+
from .abc import AsyncConnector
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class HttpAsyncConnector(AsyncConnector):
|
|
9
9
|
def __init__(
|
|
10
10
|
self,
|
|
11
|
-
username:
|
|
12
|
-
password:
|
|
11
|
+
username: str | None,
|
|
12
|
+
password: str | None,
|
|
13
13
|
resolver: AsyncResolver,
|
|
14
|
-
):
|
|
14
|
+
) -> None:
|
|
15
15
|
self._username = username
|
|
16
16
|
self._password = password
|
|
17
17
|
self._resolver = resolver
|
|
@@ -31,7 +31,7 @@ class HttpAsyncConnector(AsyncConnector):
|
|
|
31
31
|
password=self._password,
|
|
32
32
|
)
|
|
33
33
|
data = conn.send(request)
|
|
34
|
-
await stream.
|
|
34
|
+
await stream.write(data)
|
|
35
35
|
|
|
36
36
|
data = await stream.read()
|
|
37
37
|
reply: http.ConnectReply = conn.receive(data)
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
from
|
|
2
|
-
from .._abc import SyncSocketStream, SyncResolver
|
|
3
|
-
from .abc import SyncConnector
|
|
1
|
+
from __future__ import annotations
|
|
4
2
|
|
|
3
|
+
from .._abc import SyncResolver, SyncSocketStream
|
|
5
4
|
from .._protocols import http
|
|
5
|
+
from .abc import SyncConnector
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class HttpSyncConnector(SyncConnector):
|
|
9
9
|
def __init__(
|
|
10
10
|
self,
|
|
11
|
-
username:
|
|
12
|
-
password:
|
|
11
|
+
username: str | None,
|
|
12
|
+
password: str | None,
|
|
13
13
|
resolver: SyncResolver,
|
|
14
|
-
):
|
|
14
|
+
) -> None:
|
|
15
15
|
self._username = username
|
|
16
16
|
self._password = password
|
|
17
17
|
self._resolver = resolver
|
|
@@ -31,7 +31,7 @@ class HttpSyncConnector(SyncConnector):
|
|
|
31
31
|
password=self._password,
|
|
32
32
|
)
|
|
33
33
|
data = conn.send(request)
|
|
34
|
-
stream.
|
|
34
|
+
stream.write(data)
|
|
35
35
|
|
|
36
36
|
data = stream.read()
|
|
37
37
|
reply: http.ConnectReply = conn.receive(data)
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Optional
|
|
1
|
+
from __future__ import annotations
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
from .abc import AsyncConnector
|
|
3
|
+
import socket
|
|
6
4
|
|
|
7
|
-
from ..
|
|
5
|
+
from .._abc import AsyncResolver, AsyncSocketStream
|
|
8
6
|
from .._helpers import is_ip_address
|
|
7
|
+
from .._protocols import socks4
|
|
8
|
+
from .abc import AsyncConnector
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Socks4AsyncConnector(AsyncConnector):
|
|
12
12
|
def __init__(
|
|
13
13
|
self,
|
|
14
|
-
user_id:
|
|
15
|
-
rdns:
|
|
14
|
+
user_id: str | None,
|
|
15
|
+
rdns: bool | None, # noqa: FBT001
|
|
16
16
|
resolver: AsyncResolver,
|
|
17
|
-
):
|
|
17
|
+
) -> None:
|
|
18
18
|
if rdns is None:
|
|
19
19
|
rdns = False
|
|
20
20
|
|
|
@@ -38,8 +38,8 @@ class Socks4AsyncConnector(AsyncConnector):
|
|
|
38
38
|
|
|
39
39
|
request = socks4.ConnectRequest(host=host, port=port, user_id=self._user_id)
|
|
40
40
|
data = conn.send(request)
|
|
41
|
-
await stream.
|
|
41
|
+
await stream.write(data)
|
|
42
42
|
|
|
43
|
-
data = await stream.
|
|
43
|
+
data = await stream.read_exactly(socks4.ConnectReply.SIZE)
|
|
44
44
|
reply: socks4.ConnectReply = conn.receive(data)
|
|
45
45
|
return reply
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Optional
|
|
1
|
+
from __future__ import annotations
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
from .abc import SyncConnector
|
|
3
|
+
import socket
|
|
6
4
|
|
|
7
|
-
from ..
|
|
5
|
+
from .._abc import SyncResolver, SyncSocketStream
|
|
8
6
|
from .._helpers import is_ip_address
|
|
7
|
+
from .._protocols import socks4
|
|
8
|
+
from .abc import SyncConnector
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Socks4SyncConnector(SyncConnector):
|
|
12
12
|
def __init__(
|
|
13
13
|
self,
|
|
14
|
-
user_id:
|
|
15
|
-
rdns:
|
|
14
|
+
user_id: str | None,
|
|
15
|
+
rdns: bool | None, # noqa: FBT001
|
|
16
16
|
resolver: SyncResolver,
|
|
17
|
-
):
|
|
17
|
+
) -> None:
|
|
18
18
|
if rdns is None:
|
|
19
19
|
rdns = False
|
|
20
20
|
|
|
@@ -38,8 +38,8 @@ class Socks4SyncConnector(SyncConnector):
|
|
|
38
38
|
|
|
39
39
|
request = socks4.ConnectRequest(host=host, port=port, user_id=self._user_id)
|
|
40
40
|
data = conn.send(request)
|
|
41
|
-
stream.
|
|
41
|
+
stream.write(data)
|
|
42
42
|
|
|
43
|
-
data = stream.
|
|
43
|
+
data = stream.read_exactly(socks4.ConnectReply.SIZE)
|
|
44
44
|
reply: socks4.ConnectReply = conn.receive(data)
|
|
45
45
|
return reply
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Optional
|
|
1
|
+
from __future__ import annotations
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
from .abc import AsyncConnector
|
|
3
|
+
import socket
|
|
6
4
|
|
|
7
|
-
from ..
|
|
5
|
+
from .._abc import AsyncResolver, AsyncSocketStream
|
|
8
6
|
from .._helpers import is_ip_address
|
|
7
|
+
from .._protocols import socks5
|
|
8
|
+
from .abc import AsyncConnector
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Socks5AsyncConnector(AsyncConnector):
|
|
12
12
|
def __init__(
|
|
13
13
|
self,
|
|
14
|
-
username:
|
|
15
|
-
password:
|
|
16
|
-
rdns:
|
|
14
|
+
username: str | None,
|
|
15
|
+
password: str | None,
|
|
16
|
+
rdns: bool | None, # noqa: FBT001
|
|
17
17
|
resolver: AsyncResolver,
|
|
18
|
-
):
|
|
18
|
+
) -> None:
|
|
19
19
|
if rdns is None:
|
|
20
20
|
rdns = True
|
|
21
21
|
|
|
@@ -38,41 +38,44 @@ class Socks5AsyncConnector(AsyncConnector):
|
|
|
38
38
|
password=self._password,
|
|
39
39
|
)
|
|
40
40
|
data = conn.send(request)
|
|
41
|
-
await stream.
|
|
41
|
+
await stream.write(data)
|
|
42
42
|
|
|
43
|
-
data = await stream.
|
|
44
|
-
reply: socks5.AuthMethodReply = conn.receive(data)
|
|
43
|
+
data = await stream.read_exactly(socks5.AuthMethodReply.SIZE)
|
|
44
|
+
reply: socks5.AuthMethodReply = conn.receive(data) # type:ignore[assignment]
|
|
45
45
|
|
|
46
46
|
# Authenticate
|
|
47
47
|
if reply.method == socks5.AuthMethod.USERNAME_PASSWORD:
|
|
48
|
-
|
|
48
|
+
assert self._username is not None
|
|
49
|
+
assert self._password is not None
|
|
50
|
+
|
|
51
|
+
request = socks5.AuthRequest( # type:ignore[assignment]
|
|
49
52
|
username=self._username,
|
|
50
53
|
password=self._password,
|
|
51
54
|
)
|
|
52
55
|
data = conn.send(request)
|
|
53
|
-
await stream.
|
|
56
|
+
await stream.write(data)
|
|
54
57
|
|
|
55
|
-
data = await stream.
|
|
56
|
-
_: socks5.AuthReply = conn.receive(data)
|
|
58
|
+
data = await stream.read_exactly(socks5.AuthReply.SIZE)
|
|
59
|
+
_: socks5.AuthReply = conn.receive(data) # type:ignore[assignment]
|
|
57
60
|
|
|
58
61
|
# Connect
|
|
59
62
|
if not is_ip_address(host) and not self._rdns:
|
|
60
|
-
|
|
63
|
+
_family, host = await self._resolver.resolve(
|
|
61
64
|
host,
|
|
62
65
|
family=socket.AF_UNSPEC,
|
|
63
66
|
)
|
|
64
67
|
|
|
65
68
|
request = socks5.ConnectRequest(host=host, port=port)
|
|
66
69
|
data = conn.send(request)
|
|
67
|
-
await stream.
|
|
70
|
+
await stream.write(data)
|
|
68
71
|
|
|
69
72
|
data = await self._read_reply(stream)
|
|
70
|
-
reply: socks5.ConnectReply = conn.receive(data)
|
|
71
|
-
return reply
|
|
73
|
+
reply: socks5.ConnectReply = conn.receive(data) # type:ignore[assignment]
|
|
74
|
+
return reply # type:ignore[return-value]
|
|
72
75
|
|
|
73
76
|
# noinspection PyMethodMayBeStatic
|
|
74
77
|
async def _read_reply(self, stream: AsyncSocketStream) -> bytes:
|
|
75
|
-
data = await stream.
|
|
78
|
+
data = await stream.read_exactly(3)
|
|
76
79
|
if data[0] != socks5.SOCKS_VER:
|
|
77
80
|
return data
|
|
78
81
|
if data[1] != socks5.ReplyCode.SUCCEEDED:
|
|
@@ -80,16 +83,16 @@ class Socks5AsyncConnector(AsyncConnector):
|
|
|
80
83
|
if data[2] != socks5.RSV:
|
|
81
84
|
return data
|
|
82
85
|
|
|
83
|
-
data += await stream.
|
|
86
|
+
data += await stream.read_exactly(1)
|
|
84
87
|
addr_type = data[3]
|
|
85
88
|
|
|
86
89
|
if addr_type == socks5.AddressType.IPV4:
|
|
87
|
-
data += await stream.
|
|
90
|
+
data += await stream.read_exactly(6)
|
|
88
91
|
elif addr_type == socks5.AddressType.IPV6:
|
|
89
|
-
data += await stream.
|
|
92
|
+
data += await stream.read_exactly(18)
|
|
90
93
|
elif addr_type == socks5.AddressType.DOMAIN:
|
|
91
|
-
data += await stream.
|
|
94
|
+
data += await stream.read_exactly(1)
|
|
92
95
|
host_len = data[-1]
|
|
93
|
-
data += await stream.
|
|
96
|
+
data += await stream.read_exactly(host_len + 2)
|
|
94
97
|
|
|
95
98
|
return data
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Optional
|
|
1
|
+
from __future__ import annotations
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
from .abc import SyncConnector
|
|
3
|
+
import socket
|
|
6
4
|
|
|
7
|
-
from ..
|
|
5
|
+
from .._abc import SyncResolver, SyncSocketStream
|
|
8
6
|
from .._helpers import is_ip_address
|
|
7
|
+
from .._protocols import socks5
|
|
8
|
+
from .abc import SyncConnector
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Socks5SyncConnector(SyncConnector):
|
|
12
12
|
def __init__(
|
|
13
13
|
self,
|
|
14
|
-
username:
|
|
15
|
-
password:
|
|
16
|
-
rdns:
|
|
14
|
+
username: str | None,
|
|
15
|
+
password: str | None,
|
|
16
|
+
rdns: bool | None, # noqa: FBT001
|
|
17
17
|
resolver: SyncResolver,
|
|
18
|
-
):
|
|
18
|
+
) -> None:
|
|
19
19
|
if rdns is None:
|
|
20
20
|
rdns = True
|
|
21
21
|
|
|
@@ -33,37 +33,45 @@ class Socks5SyncConnector(SyncConnector):
|
|
|
33
33
|
conn = socks5.Connection()
|
|
34
34
|
|
|
35
35
|
# Auth methods
|
|
36
|
-
request = socks5.AuthMethodsRequest(
|
|
36
|
+
request = socks5.AuthMethodsRequest(
|
|
37
|
+
username=self._username,
|
|
38
|
+
password=self._password,
|
|
39
|
+
)
|
|
37
40
|
data = conn.send(request)
|
|
38
|
-
stream.
|
|
41
|
+
stream.write(data)
|
|
39
42
|
|
|
40
|
-
data = stream.
|
|
41
|
-
reply: socks5.AuthMethodReply = conn.receive(data)
|
|
43
|
+
data = stream.read_exactly(socks5.AuthMethodReply.SIZE)
|
|
44
|
+
reply: socks5.AuthMethodReply = conn.receive(data) # type:ignore[assignment]
|
|
42
45
|
|
|
43
46
|
# Authenticate
|
|
44
47
|
if reply.method == socks5.AuthMethod.USERNAME_PASSWORD:
|
|
45
|
-
|
|
48
|
+
assert self._username is not None
|
|
49
|
+
assert self._password is not None
|
|
50
|
+
|
|
51
|
+
request = socks5.AuthRequest( # type:ignore[assignment]
|
|
52
|
+
username=self._username,
|
|
53
|
+
password=self._password,
|
|
54
|
+
)
|
|
46
55
|
data = conn.send(request)
|
|
47
|
-
stream.
|
|
56
|
+
stream.write(data)
|
|
48
57
|
|
|
49
|
-
data = stream.
|
|
50
|
-
_: socks5.AuthReply = conn.receive(data)
|
|
58
|
+
data = stream.read_exactly(socks5.AuthReply.SIZE)
|
|
59
|
+
_: socks5.AuthReply = conn.receive(data) # type:ignore[assignment]
|
|
51
60
|
|
|
52
61
|
# Connect
|
|
53
62
|
if not is_ip_address(host) and not self._rdns:
|
|
54
|
-
|
|
63
|
+
_family, host = self._resolver.resolve(host, family=socket.AF_UNSPEC)
|
|
55
64
|
|
|
56
65
|
request = socks5.ConnectRequest(host=host, port=port)
|
|
57
66
|
data = conn.send(request)
|
|
58
|
-
stream.
|
|
67
|
+
stream.write(data)
|
|
59
68
|
|
|
60
69
|
data = self._read_reply(stream)
|
|
61
|
-
reply: socks5.ConnectReply = conn.receive(data)
|
|
62
|
-
return reply
|
|
70
|
+
reply: socks5.ConnectReply = conn.receive(data) # type:ignore[assignment]
|
|
71
|
+
return reply # type:ignore[return-value]
|
|
63
72
|
|
|
64
|
-
# noinspection PyMethodMayBeStatic
|
|
65
73
|
def _read_reply(self, stream: SyncSocketStream) -> bytes:
|
|
66
|
-
data = stream.
|
|
74
|
+
data = stream.read_exactly(3)
|
|
67
75
|
if data[0] != socks5.SOCKS_VER:
|
|
68
76
|
return data
|
|
69
77
|
if data[1] != socks5.ReplyCode.SUCCEEDED:
|
|
@@ -71,16 +79,16 @@ class Socks5SyncConnector(SyncConnector):
|
|
|
71
79
|
if data[2] != socks5.RSV:
|
|
72
80
|
return data
|
|
73
81
|
|
|
74
|
-
data += stream.
|
|
82
|
+
data += stream.read_exactly(1)
|
|
75
83
|
addr_type = data[3]
|
|
76
84
|
|
|
77
85
|
if addr_type == socks5.AddressType.IPV4:
|
|
78
|
-
data += stream.
|
|
86
|
+
data += stream.read_exactly(6)
|
|
79
87
|
elif addr_type == socks5.AddressType.IPV6:
|
|
80
|
-
data += stream.
|
|
88
|
+
data += stream.read_exactly(18)
|
|
81
89
|
elif addr_type == socks5.AddressType.DOMAIN:
|
|
82
|
-
data += stream.
|
|
90
|
+
data += stream.read_exactly(1)
|
|
83
91
|
host_len = data[-1]
|
|
84
|
-
data += stream.
|
|
92
|
+
data += stream.read_exactly(host_len + 2)
|
|
85
93
|
|
|
86
94
|
return data
|
python_socks/_errors.py
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class IncompleteReadError(Exception):
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ProxyException(Exception): # noqa: N818
|
|
2
11
|
pass
|
|
3
12
|
|
|
4
13
|
|
|
@@ -11,6 +20,10 @@ class ProxyConnectionError(ProxyException, OSError):
|
|
|
11
20
|
|
|
12
21
|
|
|
13
22
|
class ProxyError(ProxyException):
|
|
14
|
-
def __init__(
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
message: Any,
|
|
26
|
+
error_code: int | None = None,
|
|
27
|
+
) -> None:
|
|
15
28
|
super().__init__(message)
|
|
16
29
|
self.error_code = error_code
|