openc3-cosmos-cfdp 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +18 -0
- data/README.md +181 -0
- data/Rakefile +40 -0
- data/lib/cfdp.rb +283 -0
- data/lib/cfdp_api.rb +204 -0
- data/microservices/CFDP/Gemfile +37 -0
- data/microservices/CFDP/Rakefile +6 -0
- data/microservices/CFDP/app/controllers/application_controller.rb +46 -0
- data/microservices/CFDP/app/controllers/cfdp_controller.rb +222 -0
- data/microservices/CFDP/app/models/cfdp_checksum.rb +52 -0
- data/microservices/CFDP/app/models/cfdp_crc_checksum.rb +41 -0
- data/microservices/CFDP/app/models/cfdp_mib.rb +613 -0
- data/microservices/CFDP/app/models/cfdp_model.rb +25 -0
- data/microservices/CFDP/app/models/cfdp_null_checksum.rb +29 -0
- data/microservices/CFDP/app/models/cfdp_pdu.rb +202 -0
- data/microservices/CFDP/app/models/cfdp_receive_transaction.rb +590 -0
- data/microservices/CFDP/app/models/cfdp_source_transaction.rb +449 -0
- data/microservices/CFDP/app/models/cfdp_topic.rb +58 -0
- data/microservices/CFDP/app/models/cfdp_transaction.rb +188 -0
- data/microservices/CFDP/app/models/cfdp_user.rb +601 -0
- data/microservices/CFDP/bin/rails +4 -0
- data/microservices/CFDP/bin/rake +4 -0
- data/microservices/CFDP/bin/setup +25 -0
- data/microservices/CFDP/config/application.rb +55 -0
- data/microservices/CFDP/config/boot.rb +4 -0
- data/microservices/CFDP/config/credentials.yml.enc +1 -0
- data/microservices/CFDP/config/environment.rb +5 -0
- data/microservices/CFDP/config/environments/development.rb +53 -0
- data/microservices/CFDP/config/environments/production.rb +75 -0
- data/microservices/CFDP/config/environments/test.rb +50 -0
- data/microservices/CFDP/config/initializers/application_controller_renderer.rb +8 -0
- data/microservices/CFDP/config/initializers/backtrace_silencers.rb +7 -0
- data/microservices/CFDP/config/initializers/cfdp_initializer.rb +26 -0
- data/microservices/CFDP/config/initializers/cors.rb +16 -0
- data/microservices/CFDP/config/initializers/filter_parameter_logging.rb +8 -0
- data/microservices/CFDP/config/initializers/inflections.rb +16 -0
- data/microservices/CFDP/config/initializers/mime_types.rb +4 -0
- data/microservices/CFDP/config/initializers/wrap_parameters.rb +9 -0
- data/microservices/CFDP/config/locales/en.yml +29 -0
- data/microservices/CFDP/config/puma.rb +38 -0
- data/microservices/CFDP/config/routes.rb +16 -0
- data/microservices/CFDP/config.ru +5 -0
- data/microservices/CFDP/init.sh +9 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_ack.rb +82 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_enum.rb +237 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_eof.rb +87 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_file_data.rb +98 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_finished.rb +114 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_keep_alive.rb +65 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_metadata.rb +116 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_nak.rb +91 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_prompt.rb +60 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_tlv.rb +291 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_user_ops.rb +749 -0
- data/microservices/CFDP/public/robots.txt +1 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_ack_spec.rb +114 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_eof_spec.rb +159 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_file_data_spec.rb +76 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_finished_spec.rb +192 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_keep_alive_spec.rb +69 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_metadata_spec.rb +346 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_nak_spec.rb +126 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_prompt_spec.rb +94 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_spec.rb +111 -0
- data/microservices/CFDP/spec/rails_helper.rb +71 -0
- data/microservices/CFDP/spec/requests/cfdp_spec.rb +1965 -0
- data/microservices/CFDP/spec/spec_helper.rb +200 -0
- data/plugin.txt +67 -0
- data/targets/CFDPTEST/cmd_tlm/cmd.txt +5 -0
- data/targets/CFDPTEST/cmd_tlm/tlm.txt +4 -0
- data/targets/CFDPTEST/procedures/cfdp_test_suite.rb +130 -0
- data/targets/CFDPTEST/target.txt +4 -0
- metadata +118 -0
@@ -0,0 +1,202 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2023 OpenC3, Inc.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# Licensed for Evaluation and Educational Use
|
7
|
+
#
|
8
|
+
# This file may only be used commercially under the terms of a commercial license
|
9
|
+
# purchased from OpenC3, Inc.
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
14
|
+
#
|
15
|
+
# The development of this software was funded in-whole or in-part by MethaneSAT LLC.
|
16
|
+
|
17
|
+
require 'openc3/packets/packet'
|
18
|
+
require 'openc3/utilities/crc'
|
19
|
+
|
20
|
+
require 'cfdp_pdu/cfdp_pdu_enum'
|
21
|
+
require 'cfdp_pdu/cfdp_pdu_tlv'
|
22
|
+
require 'cfdp_pdu/cfdp_pdu_eof'
|
23
|
+
require 'cfdp_pdu/cfdp_pdu_finished'
|
24
|
+
require 'cfdp_pdu/cfdp_pdu_ack'
|
25
|
+
require 'cfdp_pdu/cfdp_pdu_metadata'
|
26
|
+
require 'cfdp_pdu/cfdp_pdu_nak'
|
27
|
+
require 'cfdp_pdu/cfdp_pdu_prompt'
|
28
|
+
require 'cfdp_pdu/cfdp_pdu_keep_alive'
|
29
|
+
require 'cfdp_pdu/cfdp_pdu_file_data'
|
30
|
+
require 'cfdp_pdu/cfdp_pdu_user_ops'
|
31
|
+
|
32
|
+
class CfdpPdu < OpenC3::Packet
|
33
|
+
def initialize(crcs_required:)
|
34
|
+
super()
|
35
|
+
append_item("VERSION", 3, :UINT)
|
36
|
+
item = append_item("TYPE", 1, :UINT)
|
37
|
+
item.states = {"FILE_DIRECTIVE" => 0, "FILE_DATA" => 1}
|
38
|
+
item = append_item("DIRECTION", 1, :UINT)
|
39
|
+
item.states = {"TOWARD_FILE_RECEIVER" => 0, "TOWARD_FILE_SENDER" => 1}
|
40
|
+
item = append_item("TRANSMISSION_MODE", 1, :UINT)
|
41
|
+
item.states = TRANSMISSION_MODES
|
42
|
+
item = append_item("CRC_FLAG", 1, :UINT)
|
43
|
+
item.states = {"CRC_NOT_PRESENT" => 0, "CRC_PRESENT" => 1}
|
44
|
+
item = append_item("LARGE_FILE_FLAG", 1, :UINT)
|
45
|
+
item.states = {"SMALL_FILE" => 0, "LARGE_FILE" => 1}
|
46
|
+
item = append_item("PDU_DATA_LENGTH", 16, :UINT)
|
47
|
+
item = append_item("SEGMENTATION_CONTROL", 1, :UINT)
|
48
|
+
item.states = SEGMENTATION_MODES
|
49
|
+
item = append_item("ENTITY_ID_LENGTH", 3, :UINT)
|
50
|
+
item = append_item("SEGMENT_METADATA_FLAG", 1, :UINT)
|
51
|
+
item.states = {"NOT_PRESENT" => 0, "PRESENT" => 1}
|
52
|
+
item = append_item("SEQUENCE_NUMBER_LENGTH", 3, :UINT)
|
53
|
+
if crcs_required
|
54
|
+
item = append_item("VARIABLE_DATA", -16, :BLOCK)
|
55
|
+
item = define_item("CRC", -16, 16, :UINT)
|
56
|
+
else
|
57
|
+
item = append_item("VARIABLE_DATA", 0, :BLOCK)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.decom(pdu_data)
|
62
|
+
pdu_hash = {}
|
63
|
+
source_entity = CfdpMib.source_entity
|
64
|
+
crcs_required = source_entity['crcs_required']
|
65
|
+
pdu = new(crcs_required: crcs_required)
|
66
|
+
pdu.buffer = pdu_data
|
67
|
+
|
68
|
+
# Handle CRC
|
69
|
+
pdu_hash["CRC_FLAG"] = pdu.read("CRC_FLAG")
|
70
|
+
if pdu_hash["CRC_FLAG"] == "CRC_PRESENT"
|
71
|
+
unless crcs_required
|
72
|
+
# Recreate with CRC
|
73
|
+
pdu = new(crcs_required: true)
|
74
|
+
pdu.buffer = pdu_data
|
75
|
+
end
|
76
|
+
pdu_hash["CRC"] = pdu.read("CRC")
|
77
|
+
crc16 = OpenC3::Crc16.new
|
78
|
+
calculated = crc16.calc(pdu.buffer(false)[0..-3])
|
79
|
+
if pdu_hash["CRC"] != calculated
|
80
|
+
raise "PDU with invalid CRC received: Received: #{sprintf("0x%04X", pdu_hash["CRC"])}, Calculated: #{sprintf("0x%04X", calculated)}"
|
81
|
+
end
|
82
|
+
elsif crcs_required
|
83
|
+
raise "PDU without required CRC received"
|
84
|
+
end
|
85
|
+
|
86
|
+
# Static header
|
87
|
+
keys = [
|
88
|
+
"VERSION",
|
89
|
+
"TYPE",
|
90
|
+
"DIRECTION",
|
91
|
+
"TRANSMISSION_MODE",
|
92
|
+
"LARGE_FILE_FLAG",
|
93
|
+
"PDU_DATA_LENGTH",
|
94
|
+
"SEGMENTATION_CONTROL",
|
95
|
+
"ENTITY_ID_LENGTH",
|
96
|
+
"SEGMENT_METADATA_FLAG",
|
97
|
+
"SEQUENCE_NUMBER_LENGTH",
|
98
|
+
"VARIABLE_DATA"
|
99
|
+
]
|
100
|
+
keys.each do |key|
|
101
|
+
pdu_hash[key] = pdu.read(key)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Variable Header
|
105
|
+
s = pdu.define_variable_header
|
106
|
+
variable_header = pdu_hash['VARIABLE_DATA'][0..(s.defined_length - 1)]
|
107
|
+
s.buffer = variable_header
|
108
|
+
variable_header_keys = [
|
109
|
+
"SOURCE_ENTITY_ID",
|
110
|
+
"SEQUENCE_NUMBER",
|
111
|
+
"DESTINATION_ENTITY_ID"
|
112
|
+
]
|
113
|
+
variable_header_keys << "DIRECTIVE_CODE" if pdu_hash['TYPE'] == "FILE_DIRECTIVE"
|
114
|
+
variable_header_keys.each do |key|
|
115
|
+
pdu_hash[key] = s.read(key)
|
116
|
+
end
|
117
|
+
|
118
|
+
variable_data = pdu_hash['VARIABLE_DATA'][(s.defined_length)..-1]
|
119
|
+
|
120
|
+
# PDU Specific Data
|
121
|
+
case pdu_hash["DIRECTIVE_CODE"]
|
122
|
+
when "EOF"
|
123
|
+
decom_eof_pdu_contents(pdu, pdu_hash, variable_data)
|
124
|
+
when "FINISHED"
|
125
|
+
decom_finished_pdu_contents(pdu, pdu_hash, variable_data)
|
126
|
+
when "ACK"
|
127
|
+
decom_ack_pdu_contents(pdu, pdu_hash, variable_data)
|
128
|
+
when "METADATA"
|
129
|
+
decom_metadata_pdu_contents(pdu, pdu_hash, variable_data)
|
130
|
+
when "NAK"
|
131
|
+
decom_nak_pdu_contents(pdu, pdu_hash, variable_data)
|
132
|
+
when "PROMPT"
|
133
|
+
decom_prompt_pdu_contents(pdu, pdu_hash, variable_data)
|
134
|
+
when "KEEP_ALIVE"
|
135
|
+
decom_keep_alive_pdu_contents(pdu, pdu_hash, variable_data)
|
136
|
+
else # File Data
|
137
|
+
decom_file_data_pdu_contents(pdu, pdu_hash, variable_data)
|
138
|
+
end
|
139
|
+
|
140
|
+
return pdu_hash
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.build_initial_pdu(type:, destination_entity:, file_size:, segmentation_control: "NOT_PRESERVED", transmission_mode: nil)
|
144
|
+
pdu = self.new(crcs_required: destination_entity['crcs_required'])
|
145
|
+
pdu.write("VERSION", destination_entity['protocol_version_number'])
|
146
|
+
pdu.write("TYPE", type)
|
147
|
+
pdu.write("DIRECTION", "TOWARD_FILE_RECEIVER")
|
148
|
+
if transmission_mode
|
149
|
+
transmission_mode = transmission_mode.upcase
|
150
|
+
pdu.write("TRANSMISSION_MODE", transmission_mode)
|
151
|
+
else
|
152
|
+
pdu.write("TRANSMISSION_MODE", destination_entity['default_transmission_mode'].upcase)
|
153
|
+
end
|
154
|
+
if destination_entity['crcs_required']
|
155
|
+
pdu.write("CRC_FLAG", "CRC_PRESENT")
|
156
|
+
else
|
157
|
+
pdu.write("CRC_FLAG", "CRC_NOT_PRESENT")
|
158
|
+
end
|
159
|
+
if file_size >= 4_294_967_296
|
160
|
+
pdu.write("LARGE_FILE_FLAG", "LARGE_FILE")
|
161
|
+
else
|
162
|
+
pdu.write("LARGE_FILE_FLAG", "SMALL_FILE")
|
163
|
+
end
|
164
|
+
pdu.write("SEGMENTATION_CONTROL", segmentation_control)
|
165
|
+
pdu.write("ENTITY_ID_LENGTH", destination_entity['entity_id_length'])
|
166
|
+
pdu.write("SEGMENT_METADATA_FLAG", "NOT_PRESENT") # Not implemented
|
167
|
+
pdu.write("SEQUENCE_NUMBER_LENGTH", destination_entity['sequence_number_length'])
|
168
|
+
return pdu
|
169
|
+
end
|
170
|
+
|
171
|
+
def define_variable_header
|
172
|
+
id_length = read("ENTITY_ID_LENGTH") + 1
|
173
|
+
seq_num_length = read("SEQUENCE_NUMBER_LENGTH") + 1
|
174
|
+
type = read("TYPE")
|
175
|
+
s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
176
|
+
s.append_item("SOURCE_ENTITY_ID", id_length * 8, :UINT)
|
177
|
+
s.append_item("SEQUENCE_NUMBER", seq_num_length * 8, :UINT, nil, :BIG_ENDIAN, :TRUNCATE)
|
178
|
+
s.append_item("DESTINATION_ENTITY_ID", id_length * 8, :UINT)
|
179
|
+
if type == "FILE_DIRECTIVE"
|
180
|
+
item = s.append_item("DIRECTIVE_CODE", 8, :UINT)
|
181
|
+
item.states = DIRECTIVE_CODES
|
182
|
+
end
|
183
|
+
return s
|
184
|
+
end
|
185
|
+
|
186
|
+
def build_variable_header(source_entity_id:, transaction_seq_num:, destination_entity_id:, directive_code: nil)
|
187
|
+
s = define_variable_header()
|
188
|
+
s.write("SOURCE_ENTITY_ID", source_entity_id)
|
189
|
+
s.write("SEQUENCE_NUMBER", transaction_seq_num)
|
190
|
+
s.write("DESTINATION_ENTITY_ID", destination_entity_id)
|
191
|
+
s.write("DIRECTIVE_CODE", directive_code) if directive_code
|
192
|
+
return s.buffer(false)
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.checksum_type_implemented(checksum_type)
|
196
|
+
if [0,1,2,3,15].include?(checksum_type)
|
197
|
+
return true
|
198
|
+
else
|
199
|
+
return false
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|