class ExtendedBroadcastData(Packet): fields_desc = [ XByteField('extended', 0x80), XShortField('device_number', 0), ByteEnumField('device_type', 0, ENUM_DEVICE_TYPE), # ByteField('transmission_type', 0), BitEnumField( 'channel_type', 0, 2, { 0: 'RESERVED', 1: 'INDEPENDENT', 2: 'SHARED 1-BYTE ADDR', 3: 'SHARED 2-BYTE ADDR', }, ), BitEnumField('global_data', 0, 1, { 0: 'NOT USED', 1: 'USED' }), BitField('undefined', 0, 1), BitField('ext_serial_number', 0, 4), ]
class TWAMPTestQuery(Packet): """A packet representing a TWAMP query""" name = "TWAMPQuery" fields_desc = [ IntField("SequenceNumber", 0), LongField("TransmitCounter", 0), BitEnumField("X", 1, 1, { 0: "32bit Counter", 1: "64bit Counter" }), BitEnumField("B", 0, 1, { 0: "Packet Counter", 1: "Octet Counter" }), BitField("MBZ", 0, 6), ByteField("BlockNumber", 0), ShortField("MBZ", 0), ThreeBytesField("MBZ", 0), ByteEnumField("SenderControlCode", 0, { 0: "Out-of-band Response Requested", 1: "In-band Response Requested" }) ] # manca il padding
class No_hop(Packet): name = "No_hop" fields_desc = [ BitEnumField(name="message_type", default=2, size=2, enum={ 0: "FIRST_CONTACT", 1: "LOOK_UP", 2: "FAILURE", 3: "JOIN" }), BitField(name="ID", default=0, size=6), BitField(name="gid", default=1, size=6), BitField(name="counter", default=0, size=10) ]
class P4dht(Packet): name = "P4dht" fields_desc = [ BitEnumField(name="message_type", default=2, size=2, enum={ 0: "FIRST_CONTACT", 1: "SEND_TO_CONTROLLER", 2: "LOOKUP_IN", 3: "LOOKUP_OUT" }), BitField(name="ID", default=0, size=6), BitField(name="gid", default=1, size=6), BitField(name="counter", default=0, size=10) ]
class InitPacket(Packet): """ The game initialization packet. Sent to initialize a game of Battleship. fields: first_player: 0 - SENDER : The sender will play first. 1 - RECIPIENT : The recipient will play first. * The default is 0, meaning by default the initiator of the game begins. """ name = 'INIT' fields_desc = [ BitEnumField('FIRST_PLAYER', default=0, size=PacketConsts.BYTE, enum=PacketConsts.PLAYERS), ]
class ErrorPacket(Packet): """ The error packet. Sent if the contents of a packet are invalid, or the order of the packets received is so. fields: error: 0 - 'INVALID TYPE' 1 - 'INVALID OFFER' 2 - 'INVALID COORDINATES' 3 - 'INVALID ANSWER' """ name = 'ERROR' fields_desc = [ BitEnumField('ERROR', default=0, size=PacketConsts.BYTE, enum=PacketConsts.ERROR_TYPES), ]
class ResponsePacket(Packet): """ The response packet. Sent by the recipient of a guess packet, after receiving it. fields: answer: 0 - 'MISS' 1 - 'HIT' 2 - 'SINK' 3 - 'WIN' """ name = 'RESPONSE' fields_desc = [ BitEnumField('ANSWER', default=0, size=PacketConsts.BYTE, enum=PacketConsts.RESPONSES), ]
class BP(Packet): """ The Battleship Protocol packet. Specifies the type of packet over this one. fields: :type: a type of BP message. 100 - INIT : InitPacket 101 - ACCEPT : 102 - DENY : 103 - READY : 110 - GUESS : GuessPacket 111 - RESPONSE : ResponsePacket 50 - TERMINATE : 99 - ERROR : ErrorPacket * if a class is specified after the colon (:), then the field also represents the type of packet over the BP packet. """ name = 'BP' fields_desc = [ BitEnumField('TYPE', default=0, size=PacketConsts.BYTE, enum=PacketConsts.MESSAGE_TYPES) ]
class FitnessPayload(OptionalExtended): fields_desc = ([ByteField('data_page_number', None)] + [ ConditionalField(f, lambda p: p.data_page_number == 16) for f in [ ByteEnumField('equip_type', 0, {}), ByteField('elapsed_time', 0), ByteField('distance_traveled', 0), LEShortField('speed', 0), ByteField('heart_rate', 0), BitField('capabilities', 0, 4), BitField('fe_status', 0, 4), ] ] + [ ConditionalField(f, lambda p: p.data_page_number == 17) for f in [ ByteField('reserved_1', 0), ByteField('reserved_2', 0), ByteField('cycle_length', 0), LEShortField('incline', 0), ByteField('resistance_level', 0), BitField('capabilities', 0, 4), BitField('fe_status', 0, 4), ] ] + [ ConditionalField(f, lambda p: p.data_page_number == 25) for f in [ ByteField('update_event_count', 0), ByteField('instant_cadence', 0), LEShortField('accum_power', 0), InstantPowerField('instant_power', 0), TSBField('trainer_status', 0), BitEnumField( 'target_power', 0, 2, { 0x0: 'at_target_power', 0x1: 'speed_too_low', 0x2: 'speed_too_high', 0x3: 'undetermined', }, ), BitField('reserved', 0, 2), BitEnumField( 'hr_data_source', 0, 2, { 0x0: 'invalid', 0x1: 'ANT+', 0x2: 'HRM', 0x3: 'Contact Sensor' }, ), BitEnumField('distance_traveled_enabled', 0, 1, { 0x0: 'no', 0x1: 'yes' }), BitEnumField('speed_flag', 0, 1, { 0x0: 'real_speed', 0x1: 'virtual_speed' }), ] ] + [ ConditionalField(f, lambda p: p.data_page_number == 26) for f in [ ByteField('update_event_count', 0), ByteField('wheel_ticks', 0), LEShortField('wheel_period', 0), LEShortField('accum_torque', 0), BitField('capabilities', 0, 4), BitField('fe_status', 0, 4), ] ] + [ ConditionalField(f, lambda p: p.data_page_number == 80) for f in [ ByteField('reserved1', 0xFF), ByteField('reserved2', 0xFF), ByteField('hw_revision', 0), LEShortField('manufacturer_id', 0), LEShortField('model_number', 0), ] ] + [ ConditionalField(f, lambda p: p.data_page_number == 81) for f in [ ByteField('reserved', 0xFF), ByteField('sw_revision_supplemental', 0), ByteField('sw_revision', 0), LEIntField('serial_number', 0), ] ]) def post_dissection(self, pkt): if self.data_page_number not in [16, 17, 25, 26, 80, 81]: msg = f'Unknown fitness data page {self.data_page_number}' log.error(msg)