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

Source Code for Module lacewing.packet

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