def serialize(self): """ Serialize the RangeList. This is meant to be compatible with RakNet's serialization. (This currently serializes items as uints, since currently the only occurence where I need to serialize a rangelist is with an uint) """ out = BitStream() out.write(c_ushort(len(self)), compressed=True) for range in self: out.write(c_bit(range[0] == range[1])) out.write(c_uint(range[0])) if range[0] != range[1]: out.write(c_uint(range[1])) return out
def __init__(self, input_stream: BitStream=None): """Init the rangelist, optionally by deserializing from a bitstream.""" self._ranges: List[_Range] = [] if input_stream is not None: count = input_stream.read(c_ushort, compressed=True) for _ in range(count): max_equal_to_min = input_stream.read(c_bit) min = input_stream.read(c_uint) if max_equal_to_min: max = min else: max = input_stream.read(c_uint) self._ranges.append(_Range(min, max))
def _send_loop(self): for packet in self._sends: data, reliability, ordering_index, split_packet_id, split_packet_index, split_packet_count = packet message_number = self._send_message_number_index self._send_message_number_index += 1 self._send_packet(data, message_number, reliability, ordering_index, split_packet_id, split_packet_index, split_packet_count) if reliability == PacketReliability.Reliable or reliability == PacketReliability.ReliableOrdered: self._resends[message_number] = time.time()+1, packet self._sends.clear() for message_number, resend_data in self._resends.items(): resend_time, packet = resend_data if resend_time > time.time(): continue log.info("actually resending %i", message_number) data, reliability, ordering_index, split_packet_id, split_packet_index, split_packet_count = packet self._send_packet(data, message_number, reliability, ordering_index, split_packet_id, split_packet_index, split_packet_count) if reliability == PacketReliability.Reliable or reliability == PacketReliability.ReliableOrdered: self._resends[message_number] = time.time()+1, packet if self._acks: out = BitStream() out.write(c_bit(True)) out.write(c_uint(self._remote_system_time)) out.write(self._acks.serialize()) self._acks.clear() self._transport.sendto(out, self._address) if not self.stop: asyncio.get_event_loop().call_later(0.03, self._send_loop)
def on_internal_ping(self, data, address): ping_send_time = data[:4] pong = BitStream() pong.write(c_ubyte(Message.ConnectedPong)) pong.write(ping_send_time) pong.write(c_uint(int(time.perf_counter() * 1000))) self.send(pong, address, PacketReliability.Unreliable)
def serialize(self, obj): out = BitStream() out.write(c_ubyte(Message.ReplicaManagerSerialize)) out.write(c_ushort(self._network_ids[obj])) out.write(obj.serialize()) for participant in self._participants: self.send(out, participant)
def construct(self, obj, recipients=None, new=True): # recipients is needed to send replicas to new participants if recipients is None: recipients = self._participants if new: self._network_ids[obj] = self._current_network_id self._current_network_id += 1 out = BitStream() out.write(c_ubyte(Message.ReplicaManagerConstruction)) out.write(c_bit(True)) out.write(c_ushort(self._network_ids[obj])) out.write(obj.send_construction()) for recipient in recipients: self.send(out, recipient)
def on_packet(self, data, address): self.log_packet(data, address, received=True) handlers = self.handlers.get(self.packet_id(data), ()) if not handlers: log.warning("No handlers for the previously received message") data = self.handler_data(data) for handler in handlers: stream = BitStream(data) if asyncio.iscoroutinefunction(handler): asyncio.ensure_future(handler(stream, address)) else: handler(stream, address)
def destruct(self, obj): log.debug("destructing %s", obj) obj.on_destruction() out = BitStream() out.write(c_ubyte(Message.ReplicaManagerDestruction)) out.write(c_ushort(self._network_ids[obj])) for participant in self._participants: self.send(out, participant) del self._network_ids[obj]
def on_packet(self, data, address): self.log_packet(data, address, received=True) handlers = self.handlers.get(self.packet_id(data), ()) origin_handlers = [ i for i in handlers if i[1] is None or i[1] == address ] if not origin_handlers: log.warning("No handlers for the previously received message") data = self.handler_data(data) for handler_tuple in origin_handlers: handler, origin_filter = handler_tuple stream = BitStream(data) if asyncio.iscoroutinefunction(handler): asyncio.ensure_future(handler(stream, address)) else: handler(stream, address)
def on_connection_request(self, data, address): packet_password = data if self.incoming_password == packet_password: response = BitStream() response.write(c_ubyte(Message.ConnectionRequestAccepted)) response.write(socket.inet_aton(address[0])) response.write(c_ushort(address[1])) response.write( bytes(2) ) # Connection index, seems like this was right out ignored in RakNet response.write(socket.inet_aton(self._address[0])) response.write(c_ushort(self._address[1])) self.send(response, address, reliability=PacketReliability.Reliable) else: raise NotImplementedError
def handle_datagram(self, datagram): stream = BitStream(datagram) if self.handle_datagram_header(stream): return # Acks only packet # There can be multiple packets in one datagram yield from self.parse_packets(stream)
def _send_packet(self, data, message_number, reliability, ordering_index, split_packet_id, split_packet_index, split_packet_count): out = BitStream() out.write(c_bit(len(self._acks) != 0)) if self._acks: out.write(c_uint(self._remote_system_time)) out.write(self._acks.serialize()) self._acks.clear() assert len(out) + ReliabilityLayer.packet_header_length(reliability, split_packet_id is not None) + len(data) < 1492 has_remote_system_time = False # time is only used for us to get back to calculate ping, and we don't do that out.write(c_bit(has_remote_system_time)) #out.write(c_uint(remote_system_time)) out.write(c_uint(message_number)) out.write_bits(reliability, 3) if reliability in (PacketReliability.UnreliableSequenced, PacketReliability.ReliableOrdered): out.write_bits(0, 5) # ordering_channel, no one ever uses anything else than 0 out.write(c_uint(ordering_index)) is_split_packet = split_packet_id is not None out.write(c_bit(is_split_packet)) if is_split_packet: out.write(c_ushort(split_packet_id)) out.write(c_uint(split_packet_index), compressed=True) out.write(c_uint(split_packet_count), compressed=True) out.write(c_ushort(len(data) * 8), compressed=True) out.align_write() out.write(data) assert len(out) < 1492 # maximum packet size handled by raknet self._transport.sendto(out, self._address)
def setUp(self): self.stream = BitStream()