added cfdp module to common

This commit is contained in:
Robin Müller 2022-09-09 14:23:18 +02:00
parent 1c0905292e
commit b1b19f9cba
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
1 changed files with 135 additions and 4 deletions

139
common.py
View File

@ -1,11 +1,25 @@
import logging
import sys
from pathlib import Path
from typing import Optional, Sequence
from tmtccmd.com_if import ComInterface
from spacepackets import SpacePacket, SpacePacketHeader, PacketTypes
from spacepackets.cfdp import TransmissionModes, PduType, DirectiveType
from spacepackets.cfdp.pdu.helper import GenericPduPacket, PduHolder, PduFactory
from spacepackets.util import UnsignedByteField
from tmtccmd.cfdp import (
RemoteEntityCfgTable,
HostFilestore,
RemoteEntityCfg,
LocalEntityCfg,
CfdpUserBase,
)
from tmtccmd.cfdp.handler import SourceHandler, DestHandler
from tmtccmd.cfdp.request import PutRequest, PutRequestCfg
from tmtccmd.logging import get_current_time_string
from tmtccmd.pus.pus_11_tc_sched import Subservices as Pus11Subservices
from tmtccmd.tc.queue import DefaultPusQueueHelper
from tmtccmd.util import FileSeqCountProvider, PusFileSeqCountProvider
from tmtccmd.util import FileSeqCountProvider, PusFileSeqCountProvider, ProvidesSeqCount
from tmtccmd.util.tmtc_printer import FsfwTmTcPrinter
try:
@ -38,7 +52,6 @@ from tmtccmd.tc import (
ProcedureHelper,
FeedWrapper,
TcProcedureType,
QueueEntryHelper,
TcQueueEntryType,
SendCbParams,
)
@ -46,13 +59,131 @@ from tmtccmd.tc.pus_5_event import pack_generic_service_5_test_into
from tmtccmd.tm import SpecificApidHandlerBase, CcsdsTmHandler
from tmtccmd.logging.pus import RawTmtcTimedLogWrapper
from tmtccmd.config import CoreServiceList, SetupWrapper, SetupParams, ArgParserWrapper
from common_tmtc.config import __version__
from common_tmtc.pus_tm.factory_hook import pus_factory_hook
LOGGER = get_console_logger()
class CfdpCcsdsWrapper:
def __init__(
self,
cfg: LocalEntityCfg,
user: CfdpUserBase,
cfdp_seq_cnt_provider: ProvidesSeqCount,
remote_cfg: Sequence[RemoteEntityCfg],
ccsds_seq_cnt_provider: ProvidesSeqCount,
ccsds_apid: int,
):
self.handler = CfdpHandler(cfg, user, cfdp_seq_cnt_provider, remote_cfg)
self.ccsds_seq_cnt_provider = ccsds_seq_cnt_provider
self.ccsds_apid = ccsds_apid
def pull_next_dest_packet(self) -> Optional[SpacePacket]:
"""Retrieves the next PDU to send and wraps it into a space packet"""
next_packet = self.handler.pull_next_dest_packet()
if next_packet is None:
return next_packet
sp_header = SpacePacketHeader(
packet_type=PacketTypes.TC,
apid=self.ccsds_apid,
seq_count=self.ccsds_seq_cnt_provider.get_and_increment(),
data_len=next_packet.packet_len - 1,
)
return SpacePacket(sp_header, None, next_packet.pack())
def confirm_dest_packet_sent(self):
self.handler.confirm_dest_packet_sent()
def pass_packet(self, packet: SpacePacket):
# Unwrap the user data and pass it to the handler
pdu_raw = packet.user_data
pdu_base = PduFactory.from_raw(pdu_raw)
self.handler.pass_packet(pdu_base)
class CfdpHandler:
def __init__(
self,
cfg: LocalEntityCfg,
user: CfdpUserBase,
seq_cnt_provider: ProvidesSeqCount,
remote_cfg: Sequence[RemoteEntityCfg],
):
vfs = HostFilestore()
super().__init__(vfs)
self.dest_id = UnsignedByteField(EXAMPLE_APID, 2)
self.remote_cfg_table = RemoteEntityCfgTable()
self.remote_cfg_table.add_remote_entities(remote_cfg)
self.dest_handler = DestHandler(cfg, user, self.remote_cfg_table)
self.source_handler = SourceHandler(cfg, seq_cnt_provider, user)
def put_request_file(
self,
source_path: Path,
dest_path: Path,
trans_mode: TransmissionModes,
closure_requested: bool,
):
put_request_cfg = PutRequestCfg(
destination_id=self.dest_id,
source_file=source_path,
dest_file=dest_path.as_posix(),
trans_mode=trans_mode,
closure_requested=closure_requested,
)
put_request = PutRequest(put_request_cfg)
self.source_handler.put_request(
put_request, self.remote_cfg_table.get_remote_entity(self.dest_id)
)
def pull_next_dest_packet(self) -> Optional[PduHolder]:
res = self.dest_handler.state_machine()
if res.states.packet_ready:
return self.dest_handler.pdu_holder
return None
def confirm_dest_packet_sent(self):
self.dest_handler.confirm_packet_sent_advance_fsm()
def pass_packet(self, packet: GenericPduPacket):
"""This function routes the packets based on PDU type and directive type if applicable.
The routing is based on section 4.5 of the CFDP standard whcih specifies the PDU forwarding
procedure.
"""
if packet.pdu_type == PduType.FILE_DATA:
self.dest_handler.pass_packet(packet)
else:
if packet.directive_type in [
DirectiveType.METADATA_PDU,
DirectiveType.EOF_PDU,
DirectiveType.PROMPT_PDU,
]:
# Section b) of 4.5.3: These PDUs should always be targeted towards the file
# receiver a.k.a. the destination handler
self.dest_handler.pass_packet(packet)
elif packet.directive_type in [
DirectiveType.FINISHED_PDU,
DirectiveType.NAK_PDU,
DirectiveType.KEEP_ALIVE_PDU,
]:
# Section c) of 4.5.3: These PDUs should always be targeted towards the file sender
# a.k.a. the source handler
self.source_handler.pass_packet(packet)
elif packet.directive_type == DirectiveType.ACK_PDU:
# Section a): Recipient depends on the type of PDU that is being acknowledged.
# We can simply extract the PDU type from the raw stream. If it is an EOF PDU,
# this packet is passed to the source handler. For a finished PDU, it is
# passed to the destination handler
pdu_holder = PduHolder(packet)
ack_pdu = pdu_holder.to_ack_pdu()
if ack_pdu.directive_code_of_acked_pdu == DirectiveType.EOF_PDU:
self.source_handler.pass_packet(packet)
elif ack_pdu.directive_code_of_acked_pdu == DirectiveType.FINISHED_PDU:
self.dest_handler.pass_packet(packet)
class PusHandler(SpecificApidHandlerBase):
def __init__(
self,