• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

romis2012 / python-socks / 89

pending completion
89

push

travis-ci-com

romis2012
Optimize socks5 bound address reading

6 of 6 new or added lines in 3 files covered. (100.0%)

1586 of 1597 relevant lines covered (99.31%)

3.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.12
/python_socks/_proto/socks5_sync.py
1
import socket
4✔
2

3
from .socks5 import (
4✔
4
    AuthMethod,
5
    AddressType,
6
    AuthMethodsRequest,
7
    AuthMethodsResponse,
8
    AuthRequest,
9
    AuthResponse,
10
    ConnectRequest,
11
    ConnectResponse,
12
)
13
from .. import _abc as abc
4✔
14
from .._errors import ProxyError
4✔
15

16

17
class Socks5Proto:
4✔
18
    def __init__(
4✔
19
        self,
20
        stream: abc.SyncSocketStream,
21
        resolver: abc.SyncResolver,
22
        dest_host,
23
        dest_port,
24
        username=None,
25
        password=None,
26
        rdns=None,
27
    ):
28
        if rdns is None:
4✔
29
            rdns = True
4✔
30

31
        self._dest_port = dest_port
4✔
32
        self._dest_host = dest_host
4✔
33
        self._username = username
4✔
34
        self._password = password
4✔
35
        self._rdns = rdns
4✔
36

37
        self._stream = stream
4✔
38
        self._resolver = resolver
4✔
39

40
    def negotiate(self):
4✔
41
        self._socks_auth()
4✔
42
        self._socks_connect()
4✔
43

44
    def _socks_auth(self):
4✔
45
        auth_method = self._choose_auth_method()
4✔
46

47
        # authenticate
48
        if auth_method == AuthMethod.USERNAME_PASSWORD:
4✔
49
            req = AuthRequest(username=self._username, password=self._password)
4✔
50

51
            self._stream.write_all(bytes(req))
4✔
52

53
            res = AuthResponse(self._stream.read_exact(2))
4✔
54
            res.validate()
4✔
55

56
    def _choose_auth_method(self) -> AuthMethod:
4✔
57
        req = AuthMethodsRequest(username=self._username, password=self._password)
4✔
58

59
        self._stream.write_all(bytes(req))
4✔
60

61
        res = AuthMethodsResponse(self._stream.read_exact(2))
4✔
62
        res.validate(request=req)
4✔
63
        return res.auth_method
4✔
64

65
    def _socks_connect(self):
4✔
66
        req = ConnectRequest(host=self._dest_host, port=self._dest_port, rdns=self._rdns)
4✔
67

68
        if req.need_resolve:
4✔
69
            _, addr = self._resolver.resolve(req.host, family=socket.AF_UNSPEC)
4✔
70
            req.set_resolved_host(addr)
4✔
71

72
        self._stream.write_all(bytes(req))
4✔
73

74
        res = ConnectResponse(self._stream.read_exact(3))
4✔
75
        res.validate()
4✔
76

77
        # read remaining data (server bound address)
78
        # self._stream.read()
79
        self._read_bound_address()
4✔
80

81
    def _read_bound_address(self):
4✔
82
        addr_type, *_ = self._stream.read_exact(1)
4✔
83
        if addr_type == AddressType.IPV4:
4✔
84
            host = self._stream.read_exact(4)
4✔
85
            host = socket.inet_ntop(socket.AF_INET, host)
4✔
86
        elif addr_type == AddressType.IPV6:
×
87
            host = self._stream.read_exact(16)
×
88
            host = socket.inet_ntop(socket.AF_INET6, host)
×
89
        elif addr_type == AddressType.DOMAIN:  # pragma: no cover
90
            host_len, *_ = self._stream.read_exact(1)
91
            host = self._stream.read_exact(host_len)
92
            host = host.decode()
93
        else:  # pragma: no cover
94
            raise ProxyError('Invalid address type: {:#02X}'.format(addr_type))
95

96
        port = self._stream.read_exact(2)
4✔
97
        port = int.from_bytes(port, 'big')
4✔
98

99
        return host, port
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc