def _on_client_close(self, client): # log.debug('tcp_server_client_close|id=%s,remote=%s', client.id.encode('hex'), client.remote_address) log.debug('tcp_server_client_close|id=%s,remote=%s', byteshex(client.id), client.remote_address) if client.id not in self._clients: # log.error('tcp_server_close_conn_not_found|id=%s,remote=%s', client.id.encode('hex'), client.remote_address) log.error('tcp_server_close_conn_not_found|id=%s,remote=%s', byteshex(client.id), client.remote_address) return self._handle_task(client, GTCP_CMD_DISCONNECT, b'') del self._clients[client.id]
def run(self): random.seed() self.on_init() from sakura.gtcpclient import GTcpClient log.debug('tcp_worker_start|id=%d', self._id) self._client = GTcpClient(self._config.WORK_ENDPOINT['address'], self._config.WORK_ENDPOINT['port'], 0) while True: try: request = self._client.receive() if request is None: log.warn( 'tcp worker lost_connection|client_id=%s,client=%s', byteshex(self._id), self._client._address) self._client.close() elif len(request) < GTCP_HEADER_SIZE: log.error( 'tcp_worker_request_packet_error|client_id=%s,client=%s,request=%s', byteshex(self._id), self._client._address, byteshex(request)) self._client.close() else: request_cmd = request[:GTCP_CMD_SIZE] request_client = TcpEndpoint( request[GTCP_CMD_SIZE:GTCP_HEADER_SIZE]) reply_body = None if request_cmd == GTCP_CMD_RELAY: request_body = request[GTCP_HEADER_SIZE:] reply_body = self.on_packet(request_client, request_body) elif request_cmd == GTCP_CMD_CONNECT: reply_body = self.on_client_connect(request_client) elif request_cmd == GTCP_CMD_DISCONNECT: self.on_client_disconnect(request_client) if reply_body is None: self._client.send(GTCP_CMD_NONE + request_client.client_id) else: self._client.send(GTCP_CMD_RELAY + request_client.client_id + reply_body) except Exception as ex: log.exception('tcp_worker_exception|id=%u,exception=%s', self._id, ex, exc_info=True) self._client.close()
def _on_recv_body(self, data): if self._on_receive_packet_callback is not None: try: self._on_receive_packet_callback(self, data) except: # log.exception('tcp_asnyc_client_on_receive_exception|id=%s,packet=%s', self._id, data.encode('hex')) log.exception( 'tcp_asnyc_client_on_receive_exception|id=%s,packet=%s', self._id, byteshex(data)) self._recv_header()
def _on_worker_packet(self, worker, data): client = worker.running_task.client packet_size = len(data) if packet_size < GTCP_HEADER_SIZE: # log.error('tcp_worker_reply_error|client_id=%s,client=%s,reply=%s', client.id.encode('hex'), client.remote_address, data.encode('hex')) log.error('tcp_worker_reply_error|client_id=%s,client=%s,reply=%s', byteshex(client.id), client.remote_address, byteshex(data)) worker.running_task.client.close() return reply_cmd = data[:1] if reply_cmd == GTCP_CMD_RELAY or reply_cmd == GTCP_CMD_NOTIFY: reply_client = data[GTCP_CMD_SIZE:GTCP_HEADER_SIZE] reply_data = data[GTCP_HEADER_SIZE:] if reply_client in self._clients: self._clients[reply_client].send_packet(reply_data) else: # log.error('tcp_reply_client_not_found|client_id=%s,reply=%s', reply_client.encode('hex'), reply_data.encode('hex')) log.error('tcp_reply_client_not_found|client_id=%s,reply=%s', byteshex(reply_client), byteshex(reply_data)) worker.running_task.client.close() if reply_cmd != GTCP_CMD_NOTIFY: self._on_worker_idle(worker)
def _on_recv_header(self, data): if len(data) != self.HEADER_SIZE: # log.error('tcp_conn_header_size_error|remote=%s,header=%s', self._remote_address, data.encode('hex')) log.error('tcp_conn_header_size_error|remote=%s,header=%s', self._remote_address, byteshex(data)) self._stream.close() return (body_size, ) = struct.unpack('%sI' % self._endian, data) if body_size >= self._config.TCP_MAX_PACKET_SIZE: log.error('tcp_conn_body_size_overflow|remote=%s,size=%u', self._remote_address, body_size) self._stream.close() return self._stream.read_bytes(body_size, self._on_recv_body)
def send(self, request): if self._socket is None: if not self._connect(): return False packet = struct.pack('<I%ds' % len(request), len(request), request) try: self._socket.sendall(packet) return True except Exception as ex: self.close() if not self._retry: # log.exception('tcp_send_fail|error=send_fail,address=%s,port=%u,request=%s', self._address, self._port, request.encode('hex')) log.exception( 'tcp_send_fail|error=send_fail,address=%s,port=%u,request=%s', self._address, self._port, byteshex(request)) return False # log.warn('tcp_send_fail|error=send_fail_will_retry,address=%s,port=%u,retry=0,request=%s,ex=%s', self._address, self._port, request.encode('hex'), ex) log.warn( 'tcp_send_fail|error=send_fail_will_retry,address=%s,port=%u,retry=0,request=%s,ex=%s', self._address, self._port, byteshex(request), ex) if not self._connect(): # log.exception('tcp_send_fail|error=retry_reconnect,address=%s,port=%u,retry=0,request=%s', self._address, self._port, request.encode('hex')) log.exception( 'tcp_send_fail|error=retry_reconnect,address=%s,port=%u,retry=0,request=%s', self._address, self._port, byteshex(request)) return False try: self._socket.sendall(packet) return True except Exception as ex: # log.exception('tcp_send_fail|error=retry_send_fail,address=%s,port=%u,retry=1,request=%s', self._address, self._port, request.encode('hex')) log.exception( 'tcp_send_fail|error=retry_send_fail,address=%s,port=%u,retry=1,request=%s', self._address, self._port, byteshex(request)) self.close() return False
def request(self, request): if self._socket is None: if not self._connect(): return None packet = struct.pack('<I%ds' % len(request), len(request), request) try: self._socket.sendall(packet) length_data = self._recv(4) except Exception as ex: self.close() if not self._retry: # log.exception('tcp_request_fail|error=recv_length_fail,address=%s,port=%u,request=%s', self._address, self._port, request.encode('hex')) log.exception( 'tcp_request_fail|error=recv_length_fail,address=%s,port=%u,request=%s', self._address, self._port, byteshex(request)) return None if isinstance(ex, socket.timeout): # log.exception('tcp_request_fail|error=recv_length_timeout,address=%s,port=%u,retry=0,request=%s', self._address, self._port, request.encode('hex')) log.exception( 'tcp_request_fail|error=recv_length_timeout,address=%s,port=%u,retry=0,request=%s', self._address, self._port, byteshex(request)) return None # log.warn('tcp_request_fail|error=recv_length_fail_will_retry,address=%s,port=%u,retry=0,request=%s,ex=%s', self._address, self._port, request.encode('hex'), ex) log.warn( 'tcp_request_fail|error=recv_length_fail_will_retry,address=%s,port=%u,retry=0,request=%s,ex=%s', self._address, self._port, byteshex(request), ex) if not self._connect(): # log.exception('tcp_request_fail|error=retry_reconnect,address=%s,port=%u,retry=0,request=%s', self._address, self._port, request.encode('hex')) log.exception( 'tcp_request_fail|error=retry_reconnect,address=%s,port=%u,retry=0,request=%s', self._address, self._port, byteshex(request)) return None try: self._socket.sendall(packet) length_data = self._recv(4) except Exception as ex: # log.exception('tcp_request_fail|error=retry_recv_length_fail,address=%s,port=%u,retry=1,request=%s', self._address, self._port, request.encode('hex')) log.exception( 'tcp_request_fail|error=retry_recv_length_fail,address=%s,port=%u,retry=1,request=%s', self._address, self._port, byteshex(request)) self.close() return None try: length = struct.unpack('<I', length_data)[0] return self._recv(length) except Exception as ex: # log.exception('tcp_request_fail|error=recv_data_fail,address=%s,port=%u,request=%s', self._address, self._port, request.encode('hex')) log.exception( 'tcp_request_fail|error=recv_data_fail,address=%s,port=%u,request=%s', self._address, self._port, byteshex(request)) self.close() return None