Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #368: Bad packet size handling in built-in server handlers #456

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ait/core/server/broker.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import zmq.green as zmq
import gevent
import gevent.monkey
from gevent import monkey
monkey.patch_all()

gevent.monkey.patch_all()
import zmq.green as zmq

from typing import List, Any

Expand Down
22 changes: 8 additions & 14 deletions ait/core/server/handlers/ccsds_packet_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ def __init__(self, input_type=None, output_type=None, **kwargs):
tlm_dict = tlm.getDefaultDict()
for packet_name in self.packet_types.values():
if packet_name not in tlm_dict.keys():
msg = "CCSDSPacketHandler: Packet name {} not present in telemetry dictionary.".format(
packet_name
)
msg += " Available packet types are {}".format(tlm_dict.keys())
msg = f"CCSDSPacketHandler: Packet name {packet_name} not present in telemetry dictionary."
msg += f" Available packet types are {tlm_dict.keys()}"
raise ValueError(msg)

def handle(self, input_data):
Expand All @@ -59,24 +57,20 @@ def handle(self, input_data):
# Check if packet length is at least 7 bytes
primary_header_length = 6
if len(input_data) < primary_header_length + 1:
ait.core.log.info(
ait.core.log.error(
"CCSDSPacketHandler: Received packet length is less than minimum of 7 bytes."
)
return

# Extract APID from packet
packet_apid = str(bin(int(binascii.hexlify(input_data[0:2]), 16) & 0x07FF))[
2:
].zfill(11)
packet_apid = str(bin(int(binascii.hexlify(input_data[0:2]), 16) & 0x07FF))[2:].zfill(11)

# Check if packet_apid matches with an APID in the config
config_apid = self.comp_apid(packet_apid)
if not config_apid:
msg = "CCSDSPacketHandler: Packet APID {} not present in config.".format(
packet_apid
)
msg += " Available packet APIDs are {}".format(self.packet_types.keys())
ait.core.log.info(msg)
msg = f"CCSDSPacketHandler: Packet APID {packet_apid} not present in config."
msg += f" Available packet APIDs are {self.packet_types.keys()}"
ait.core.log.error(msg)
return

# Map APID to packet name in config to get UID from telemetry dictionary
Expand All @@ -87,7 +81,7 @@ def handle(self, input_data):
# Extract user data field from packet
packet_data_length = int(binascii.hexlify(input_data[4:6]), 16) + 1
if len(input_data) < primary_header_length + packet_data_length:
ait.core.log.info(
ait.core.log.error(
"CCSDSPacketHandler: Packet data length is less than stated length in packet primary header."
)
return
Expand Down
48 changes: 33 additions & 15 deletions ait/core/server/handlers/packet_handler.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,63 @@
import pickle

from ait.core.server.handler import Handler
from ait.core import tlm
from ait.core import tlm, log


class PacketHandler(Handler):
def __init__(self, input_type=None, output_type=None, **kwargs):
"""
This handler provides a way to accept multiple packet types
(e.g. '1553_HS_Packet' and 'Ethernet_HS_Packet') single stream
and have them be processed. This handler takes a string of
raw binary data containing the packet data. It gets the UID from
the telemetry dictionary. A tuple of the UID and user data
field is returned.

Params:
input_type: (optional) Specifies expected input type, used to
validate handler workflow. Defaults to None.
output_type: (optional) Specifies expected output type, used to
validate handler workflow. Defaults to None
**kwargs:
packet: (required) Name of packet, present in default tlm dict.
packet: (required) Type of packet (e.g. '1553_HS_Packet', 'Ethernet_HS_Packet')
Present in default tlm dict.
Raises:
ValueError: If packet is not present in kwargs.
ValueError: If packet type is not present in kwargs.
If packet is specified but not present in default tlm dict.
"""
"""
super(PacketHandler, self).__init__(input_type, output_type)
self.packet = kwargs.get("packet", None)
self.packet_name = kwargs.get("packet", None)
self.tlm_dict = tlm.getDefaultDict()

if not self.packet:
msg = 'PacketHandler: No packet name provided in handler config as key "packet"'
if not self.packet_name:
msg = f'PacketHandler: No packet type provided in handler config as key {self.packet_name}'
raise ValueError(msg)

tlm_dict = tlm.getDefaultDict()
if self.packet not in tlm_dict:
msg = "PacketHandler: Packet name {} not present in telemetry dictionary".format(
self.packet
)
msg += " Available packet types are {}".format(tlm_dict.keys())
if self.packet_name not in self.tlm_dict:
msg = f"PacketHandler: Packet name '{self.packet_name}' not present in telemetry dictionary."
msg += f" Available packet types are {self.tlm_dict.keys()}"
raise ValueError(msg)

self._pkt_defn = tlm_dict[self.packet]
self._pkt_defn = self.tlm_dict[self.packet_name]

def handle(self, input_data):
"""
Test the input_data length against the length in the telemetry

Params:
input_data: message received by stream
input_data : byteArray
message received by stream (raw data)
Returns:
tuple of packet UID and message received by stream
"""

if self._pkt_defn.nbytes != len(input_data):
log.error(
f"PacketHandler: Packet data length does not match packet definition."
)
return 0
else:
return pickle.dumps((self._pkt_defn.uid, input_data), 2)

return pickle.dumps((self._pkt_defn.uid, input_data), 2)
6 changes: 3 additions & 3 deletions ait/core/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ def __init__(self):

def wait(self):
"""
Starts all greenlets and plugin-pocesses for concurrent processing.
Starts all greenlets and plugin-processes for concurrent processing.
Joins over all greenlets that are not servers.
"""
# Start all of the greenlets managed by this process
# Start all greenlets managed by this process
for greenlet in self.greenlets + self.servers:
log.info(f"Starting {greenlet} greenlet...")
greenlet.start()

# Start all of the separate plugin processes
# Start all separate plugin processes
for plugin_process in self.plugin_processes:
log.info(f"Spawning {plugin_process} process...")
plugin_process.spawn_process()
Expand Down
3 changes: 2 additions & 1 deletion ait/core/tlm.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ def __getitem__(self, key):
"""Returns the words in this wordarray at the given Python slice
or word at the given integer index."""
length = len(self)

if isinstance(key, slice):
return [self[n] for n in range(*key.indices(length))]

Expand Down Expand Up @@ -371,6 +370,7 @@ def validate(self, value, messages=None):
Validation error messages are appended to an optional messages
array.
"""

valid = True
primitive = value

Expand Down Expand Up @@ -520,6 +520,7 @@ def validate(self, messages=None):
Validation error messages are appended to an optional messages
array.
"""

return self._defn.validate(self, messages)


Expand Down
Binary file modified config/leapseconds.dat
Binary file not shown.
Loading