Package lacewing :: Module packet
[frames] | no frames]

Source Code for Module lacewing.packet

  1  """ 
  2  The container for packetloaders, which represents 
  3  a whole packet 
  4  """ 
  5   
  6  from struct import Struct 
  7  import struct 
  8   
  9  from lacewing.packetloaders import client, server 
 10  from lacewing.baseloader import _BaseLoader 
 11  from lacewing.exceptions import OutOfData 
 12   
 13  SC_PACKET_TABLE = [ 
 14      # server to client types 
 15      server.Response, 
 16      server.BinaryServerMessage, 
 17      server.BinaryChannelMessage, 
 18      server.BinaryPeerMessage, 
 19      server.ObjectServerMessage, 
 20      server.ObjectChannelMessage, 
 21      server.ObjectPeerMessage, 
 22      server.Peer, 
 23      server.UDPWelcome, 
 24      server.Ping 
 25  ] 
 26   
 27  CS_PACKET_TABLE = [ 
 28      # client to server types 
 29      client.Request, 
 30      client.BinaryServerMessage, 
 31      client.BinaryChannelMessage, 
 32      client.BinaryPeerMessage, 
 33      client.ObjectServerMessage, 
 34      client.ObjectChannelMessage, 
 35      client.ObjectPeerMessage, 
 36      client.UDPHello, 
 37      client.ChannelMaster, 
 38      client.Pong 
 39  ] 
 40   
 41  for items in (CS_PACKET_TABLE, SC_PACKET_TABLE): 
 42      for index, item in enumerate(items): 
 43          item.id = index 
 44   
 45  HEADER_DATA = Struct('<BB') 
 46  FROM_ID = Struct('<H') 
 47  HEADER_DATA_UDP = Struct('<B') 
 48  SHORT_SIZE = Struct('<H') 
 49  INT_SIZE = Struct('<I') 
 50   
51 -class _Packet(_BaseLoader):
52 """ 53 The base packet. 54 55 @ivar loader: The loader that this packet contains 56 @ivar maxSize: The max size of a packet. 57 @ivar settings: Settings for this packet. 58 """ 59 loader = None 60 fromId = None 61
62 - def read(self, data):
63 """ 64 Load the specified data with the given settings. 65 @type data: buffer or str 66 """ 67 datagram = self.settings.get('datagram', False) 68 packetSize = 0 69 if datagram: 70 headerByte, = HEADER_DATA_UDP.unpack_from(data) 71 if self.isClient: 72 self.fromId, = FROM_ID.unpack_from(data, 1) 73 packetData = buffer(data, 3) 74 else: 75 packetData = buffer(data, 1) 76 else: 77 if len(data) < 2: 78 raise OutOfData 79 headerByte, size = HEADER_DATA.unpack_from(data) 80 packetSize += HEADER_DATA.size 81 82 messageType = (headerByte & 0b11110000) >> 4 83 variant = headerByte & 0b00001111 84 85 if not datagram: 86 if size == 254: 87 size, = SHORT_SIZE.unpack_from(data, 2) 88 packetData = buffer(data, 4, size) 89 packetSize += 2 + size 90 elif size == 255: 91 size, = INT_SIZE.unpack_from(data, 2) 92 packetData = buffer(data, 6, size) 93 packetSize += 4 + size 94 else: 95 packetData = buffer(data, 2, size) 96 packetSize += size 97 if len(packetData) < size: 98 raise OutOfData 99 loaderClass = self.packetTable[messageType] 100 self.loader = self.new(loaderClass, packetData, variant = variant) 101 return packetSize
102
103 - def generate(self):
104 """ 105 Generates the binary representation of the packet. 106 """ 107 datagram = self.settings.get('datagram', False) 108 typeData = self.loader.generate() 109 variant = self.loader.settings.get('variant', 0) 110 headerByte = variant | (self.loader.id << 4) 111 if datagram: 112 if self.isClient: 113 fromData = FROM_ID.pack(self.fromId) 114 else: 115 fromData = '' 116 return HEADER_DATA_UDP.pack(headerByte) + fromData + typeData 117 else: 118 size = len(typeData) 119 sizeData = '' 120 if 65535 > size >= 254: 121 sizeData = SHORT_SIZE.pack(size) 122 size = 254 123 elif 4294967295 > size >= 65535: 124 sizeData = INT_SIZE.pack(size) 125 size = 255 126 return HEADER_DATA.pack(headerByte, size) + sizeData + typeData
127
128 -class ClientPacket(_Packet):
129 packetTable = CS_PACKET_TABLE 130 isClient = True
131
132 -class ServerPacket(_Packet):
133 packetTable = SC_PACKET_TABLE 134 isClient = False
135