(self)
| 470 | self.handle_close() |
| 471 | |
| 472 | def handle_read(self): |
| 473 | global connections |
| 474 | global dns_cache |
| 475 | try: |
| 476 | while True: |
| 477 | # Consume in up-to packet-sized chunks (TCP packet payload as 1460 bytes from 1500 byte ethernet frames) |
| 478 | data = self.recv(1460) |
| 479 | if data: |
| 480 | data_len = len(data) |
| 481 | if self.state == self.STATE_CONNECTED: |
| 482 | logging.debug('[{0:d}] SOCKS => {1:d} byte(s)'.format(self.client_id, data_len)) |
| 483 | self.SendMessage('data', {'data': data}) |
| 484 | elif self.state == self.STATE_WAITING_FOR_HANDSHAKE: |
| 485 | self.state = self.STATE_ERROR #default to an error state, set correctly if things work out |
| 486 | if data_len >= 2 and ord(data[0]) == 0x05: |
| 487 | supports_no_auth = False |
| 488 | auth_count = ord(data[1]) |
| 489 | if data_len == auth_count + 2: |
| 490 | for i in range(auth_count): |
| 491 | offset = i + 2 |
| 492 | if ord(data[offset]) == 0: |
| 493 | supports_no_auth = True |
| 494 | if supports_no_auth: |
| 495 | # Respond with a message that "No Authentication" was agreed to |
| 496 | logging.info('[{0:d}] New Socks5 client'.format(self.client_id)) |
| 497 | response = chr(0x05) + chr(0x00) |
| 498 | self.state = self.STATE_WAITING_FOR_CONNECT_REQUEST |
| 499 | self.buffer += response |
| 500 | self.handle_write() |
| 501 | elif self.state == self.STATE_WAITING_FOR_CONNECT_REQUEST: |
| 502 | self.state = self.STATE_ERROR #default to an error state, set correctly if things work out |
| 503 | if data_len >= 10 and ord(data[0]) == 0x05 and ord(data[2]) == 0x00: |
| 504 | if ord(data[1]) == 0x01: #TCP connection (only supported method for now) |
| 505 | connections[self.client_id]['server'] = TCPConnection(self.client_id) |
| 506 | self.requested_address = data[3:] |
| 507 | port_offset = 0 |
| 508 | if ord(data[3]) == 0x01: |
| 509 | port_offset = 8 |
| 510 | self.ip = '{0:d}.{1:d}.{2:d}.{3:d}'.format(ord(data[4]), ord(data[5]), ord(data[6]), ord(data[7])) |
| 511 | elif ord(data[3]) == 0x03: |
| 512 | name_len = ord(data[4]) |
| 513 | if data_len >= 6 + name_len: |
| 514 | port_offset = 5 + name_len |
| 515 | self.hostname = data[5:5 + name_len] |
| 516 | elif ord(data[3]) == 0x04 and data_len >= 22: |
| 517 | port_offset = 20 |
| 518 | self.ip = '' |
| 519 | for i in range(16): |
| 520 | self.ip += '{0:02x}'.format(ord(data[4 + i])) |
| 521 | if i % 2 and i < 15: |
| 522 | self.ip += ':' |
| 523 | if port_offset and connections[self.client_id]['server'] is not None: |
| 524 | self.port = 256 * ord(data[port_offset]) + ord(data[port_offset + 1]) |
| 525 | if self.port: |
| 526 | if self.ip is None and self.hostname is not None: |
| 527 | if dns_cache is not None and self.hostname in dns_cache: |
| 528 | self.state = self.STATE_CONNECTING |
| 529 | cache_entry = dns_cache[self.hostname] |
nothing calls this directly
no test coverage detected