class UDPDispatcher(object): #implements(IUDPDispatcher) def __init__(self, udp_client = None, settings = None, message_handler = None, message_template = None, message_xml = None): #holds the details of the message, or how the messages should be sent, #built, and read self.packets_in = 0 self.packets_out = 0 self.circuit_manager = CircuitManager() self.data_unpacker = DataUnpacker() #the ID of the packet we most recently received self.receive_packet_id = -1 if udp_client == None: self.udp_client = NetUDPClient() else: self.udp_client = udp_client self.udp_client.start_udp_connection() # allow the settings to be passed in # otherwise, grab the defaults if settings != None: self.settings = settings else: self.settings = Settings() # allow the passing in of message_template.xml as a file handle if not message_template: self.message_template = None else: if isinstance(message_template, file): self.message_template = message_template else: log.warning("%s parameter is expected to be a filehandle, it is a %s. \ Using the embedded message_template.msg" % (message_template, type(message_template))) self.message_template = None if not message_xml: self.message_xml = MessageDotXML() else: self.message_xml = message_xml self.helpers = Helpers() # allow the packet_handler to be passed in # otherwise, grab the defaults if message_handler != None: self.message_handler = message_handler elif self.settings.HANDLE_PACKETS: from pyogp.lib.base.message.message_handler import MessageHandler self.message_handler = MessageHandler() # set up our parsers self.udp_deserializer = UDPMessageDeserializer(self.message_handler, self.settings, message_template = self.message_template) self.udp_serializer = UDPMessageSerializer(message_template = self.message_template) def find_circuit(self, host): circuit = self.circuit_manager.get_circuit(host) if circuit == None: #there is a case where we want to return None, #when the last packet was protected circuit = self.circuit_manager.add_circuit(host, self.receive_packet_id) return circuit def receive_check(self, host, msg_buf, msg_size): #determine if we have any messages that can be received through UDP #also, check and decode the message we have received recv_packet = None #msg_buf, msg_size = self.udp_client.receive_packet(self.socket) #we have a message if msg_size > 0: #determine sender #host = self.udp_client.get_sender() circuit = self.find_circuit(host) if circuit == None: raise exc.CircuitNotFound(host, 'preparing to check for packets') self.packets_in += 1 recv_packet = self.udp_deserializer.deserialize(msg_buf) #couldn't deserialize if recv_packet == None: # if its sent as reliable, we should ack it even if we aren't going to parse it # since we can skip parsing the packet in self.udp_deserializer # this indicate reliable send_flags = ord(msg_buf[0]) packet_id = self.data_unpacker.unpack_data(msg_buf, MsgType.MVT_U32, 1, endian_type=EndianType.BIG) # queue the ack up circuit.collect_ack(packet_id) return None #Case - trusted packets can only come in over trusted circuits if circuit.is_trusted and \ recv_packet.trusted == False: return None circuit.handle_packet(recv_packet) if self.settings.ENABLE_UDP_LOGGING: if self.settings.ENABLE_BYTES_TO_HEX_LOGGING: hex_string = '<=>' + self.helpers.bytes_to_hex(msg_buf) else: hex_string = '' if self.settings.ENABLE_HOST_LOGGING: host_string = ' (%s)' % (host) else: host_string = '' if not self.settings.PROXY_LOGGING: logger.debug('Received packet%s : %s (%s)%s' % (host_string, recv_packet.name, recv_packet.packet_id, hex_string)) if self.settings.HANDLE_PACKETS: self.message_handler.handle(recv_packet) return recv_packet def send_reliable(self, message, host, retries): """ Wants to be acked """ #sets up the message so send_message will add the RELIABLE flag to #the message return self.__send_message(message, host, reliable=True, retries=retries) def send_retry(self, message, host): """ This is a retry because we didn't get acked """ #sets up the message so send_message will add the RETRY flag to it return self.__send_message(host, message, retrying=True) def send_message(self, message, host): return self.__send_message(message, host) def __send_message(self, message, host, reliable=False, retries=0, retrying=False): """ Sends the message that is currently built to the desired host """ #make sure host is OK (ip and address aren't null) if host.is_ok() == False: return if isinstance(message,Message): packet = message else: packet = message() # enable monitoring of outgoing packets if self.settings.HANDLE_OUTGOING_PACKETS: self.message_handler.handle(packet) #use circuit manager to get the circuit to send on circuit = self.find_circuit(host) if reliable == True: circuit.prepare_packet(packet, PackFlags.LL_RELIABLE_FLAG, retries) if circuit.unack_packet_count <= 0: self.circuit_manager.unacked_circuits[host] = circuit elif retrying == True: circuit.prepare_packet(packet, PackFlags.LL_RESENT_FLAG) else: circuit.prepare_packet(packet) try: send_buffer = self.udp_serializer.serialize(packet) if self.settings.ENABLE_UDP_LOGGING: if packet.name in self.settings.UDP_SPAMMERS and self.settings.DISABLE_SPAMMERS: pass else: if self.settings.ENABLE_BYTES_TO_HEX_LOGGING: hex_string = '<=>' + self.helpers.bytes_to_hex(send_buffer) else: hex_string = '' if self.settings.ENABLE_HOST_LOGGING: host_string = ' (%s)' % (host) else: host_string = '' logger.debug('Sent packet %s : %s (%s)%s' % (host_string, packet.name, packet.packet_id, hex_string)) #TODO: remove this when testing a network self.udp_client.send_packet(send_buffer, host) self.packets_out += 1 return send_buffer except AssertionError: pass except Exception, error: logger.warning("Error trying to serialize the following packet: %s" % (packet)) traceback.print_exc() return