Advanced Packet Concepts

Creating simple packets with the basic Fields one thing but typically packets are more complex. For example, one might want to create a packet with an array of fields, or even encapsulating a packet within another as a field. This is easy to do within calpack through the use of the ArrayField or PacketField Fields.

Creating an Array of IntField’s

When deal with a lot of fields that are the same it can become a bear to create each field

>>> class my_long_packet(models.Packet):
...     data1 = models.IntField()
...     data2 = models.IntField()
...     data3 = models.IntField()
...     data4 = models.IntField()
...     data5 = models.IntField()
...     data6 = models.IntField()
...     data7 = models.IntField()
...     data8 = models.IntField()

This can be simplified by using the models.ArrayField

>>> class ArrayPacket(models.Packet):
...     data = models.ArrayField(models.IntField(), 8)

Writing to the array requires writing the entire list to the array

>>> my_array_pkt = ArrayPacket()
>>> my_array_pkt.data = list(range(8))
>>> my_array_pkt.data
(0, 1, 2, 3, 4, 5, 6, 7)

Access to individual member is currently readonly

>>> my_array_pkt.data[1] = 12
Traceback (most recent call last):
  File "<doctest adv_pkt[0]>", line 1, in <module>
    my_array_pkt.data[1] = 12
TypeError: 'tuple' object does not support item assignment

>>> print(my_array_pkt.data[1])
1

Iterating over the field using the for loop is also readonly as well.

>>> for val in my_array_pkt.data:
...     val = 100
>>> print(my_array_pkt.data)
(0, 1, 2, 3, 4, 5, 6, 7)

>>> for i, val in my_array_pkt.data:
...     my_array_pkt.data[i] = val * 2
Traceback (most recent call last):
  File "<doctest adv_pkt[0]>", line 1, in <module>
    my_array_pkt.data[1] = val * 2
TypeError: 'tuple' object does not support item assignment

Encapsulating another Packet within a Packet

Sometimes you might want to encapsulate another packet within a packet as a field. This can be done by using the models.PacketField

>>> class Header(models.Packet):
...     source = models.IntField()
...     destination = models.IntField()

>>> class CustomPacket(models.Packet):
...     header = models.PacketField(Header)
...     spare = models.IntField()
...     body = models.ArrayField(models.IntField(), 28)

Access to the fields within the encapsulated packet is as simple as calling that packets members

>>> pkt = CustomPacket()
>>> pkt.header.source = 1
>>> pkt.header.source == 1
True
>>> pkt.header.destination = 2
>>> print(pkt.header.destination)
2