(self)
| 236 | yield from self.state() |
| 237 | |
| 238 | def state_connect(self) -> layer.CommandGenerator[None]: |
| 239 | # Parse Connect Request |
| 240 | if len(self.buf) < 5: |
| 241 | return |
| 242 | |
| 243 | if self.buf[:3] != b"\x05\x01\x00": |
| 244 | yield from self.socks_err( |
| 245 | f"Unsupported SOCKS5 request: {self.buf!r}", |
| 246 | SOCKS5_REP_COMMAND_NOT_SUPPORTED, |
| 247 | ) |
| 248 | return |
| 249 | |
| 250 | # Determine message length |
| 251 | atyp = self.buf[3] |
| 252 | message_len: int |
| 253 | if atyp == SOCKS5_ATYP_IPV4_ADDRESS: |
| 254 | message_len = 4 + 4 + 2 |
| 255 | elif atyp == SOCKS5_ATYP_IPV6_ADDRESS: |
| 256 | message_len = 4 + 16 + 2 |
| 257 | elif atyp == SOCKS5_ATYP_DOMAINNAME: |
| 258 | message_len = 4 + 1 + self.buf[4] + 2 |
| 259 | else: |
| 260 | yield from self.socks_err( |
| 261 | f"Unknown address type: {atyp}", SOCKS5_REP_ADDRESS_TYPE_NOT_SUPPORTED |
| 262 | ) |
| 263 | return |
| 264 | |
| 265 | # Do we have enough bytes yet? |
| 266 | if len(self.buf) < message_len: |
| 267 | return |
| 268 | |
| 269 | # Parse host and port |
| 270 | msg, self.buf = self.buf[:message_len], self.buf[message_len:] |
| 271 | |
| 272 | host: str |
| 273 | if atyp == SOCKS5_ATYP_IPV4_ADDRESS: |
| 274 | host = socket.inet_ntop(socket.AF_INET, msg[4:-2]) |
| 275 | elif atyp == SOCKS5_ATYP_IPV6_ADDRESS: |
| 276 | host = socket.inet_ntop(socket.AF_INET6, msg[4:-2]) |
| 277 | else: |
| 278 | host_bytes = msg[5:-2] |
| 279 | host = host_bytes.decode("ascii", "replace") |
| 280 | |
| 281 | (port,) = struct.unpack("!H", msg[-2:]) |
| 282 | |
| 283 | # We now have all we need, let's get going. |
| 284 | self.context.server.address = (host, port) |
| 285 | self.child_layer = layer.NextLayer(self.context) |
| 286 | |
| 287 | # this already triggers the child layer's Start event, |
| 288 | # but that's not a problem in practice... |
| 289 | err = yield from self.finish_start() |
| 290 | if err: |
| 291 | yield commands.SendData( |
| 292 | self.context.client, b"\x05\x04\x00\x01\x00\x00\x00\x00\x00\x00" |
| 293 | ) |
| 294 | yield commands.CloseConnection(self.context.client) |
| 295 | else: |
nothing calls this directly
no test coverage detected