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,116 @@
|
|
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
|
+
class CfdpPdu < OpenC3::Packet
|
18
|
+
def self.decom_metadata_pdu_contents(pdu, pdu_hash, variable_data)
|
19
|
+
s, s2 = pdu.define_metadata_pdu_contents
|
20
|
+
s.buffer = variable_data
|
21
|
+
pdu_hash["CLOSURE_REQUESTED"] = s.read("CLOSURE_REQUESTED")
|
22
|
+
pdu_hash["CHECKSUM_TYPE"] = s.read("CHECKSUM_TYPE")
|
23
|
+
pdu_hash["FILE_SIZE"] = s.read("FILE_SIZE")
|
24
|
+
source_file_name_length = s.read("SOURCE_FILE_NAME_LENGTH")
|
25
|
+
s.buffer = variable_data[0..(s.defined_length + source_file_name_length - 1)]
|
26
|
+
pdu_hash["SOURCE_FILE_NAME"] = s.read("SOURCE_FILE_NAME")
|
27
|
+
variable_data = variable_data[(s.defined_length + source_file_name_length)..-1]
|
28
|
+
if variable_data and variable_data.length > 0
|
29
|
+
s2.buffer = variable_data
|
30
|
+
destination_file_name_length = s2.read("DESTINATION_FILE_NAME_LENGTH")
|
31
|
+
s2.buffer = variable_data[0..(s2.defined_length + destination_file_name_length - 1)]
|
32
|
+
pdu_hash["DESTINATION_FILE_NAME"] = s2.read("DESTINATION_FILE_NAME")
|
33
|
+
variable_data = variable_data[(s2.defined_length + destination_file_name_length)..-1]
|
34
|
+
end
|
35
|
+
while variable_data and variable_data.length > 0
|
36
|
+
variable_data = decom_tlv(pdu, pdu_hash, variable_data)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.build_metadata_pdu(
|
41
|
+
source_entity:,
|
42
|
+
transaction_seq_num:,
|
43
|
+
destination_entity:,
|
44
|
+
file_size:,
|
45
|
+
segmentation_control: "NOT_PRESERVED",
|
46
|
+
transmission_mode: nil,
|
47
|
+
source_file_name: nil,
|
48
|
+
destination_file_name: nil,
|
49
|
+
closure_requested:,
|
50
|
+
options: [])
|
51
|
+
|
52
|
+
pdu = build_initial_pdu(type: "FILE_DIRECTIVE", destination_entity: destination_entity, transmission_mode: transmission_mode, file_size: file_size, segmentation_control: segmentation_control)
|
53
|
+
pdu_header_part_1_length = pdu.length # Measured here before writing variable data
|
54
|
+
pdu_header = pdu.build_variable_header(source_entity_id: source_entity['id'], transaction_seq_num: transaction_seq_num, destination_entity_id: destination_entity['id'], directive_code: "METADATA")
|
55
|
+
pdu_header_part_2_length = pdu_header.length
|
56
|
+
if checksum_type_implemented(destination_entity['default_checksum_type'])
|
57
|
+
checksum_type = destination_entity['default_checksum_type']
|
58
|
+
else
|
59
|
+
checksum_type = 0
|
60
|
+
end
|
61
|
+
pdu_contents = pdu.build_metadata_pdu_contents(source_entity: source_entity, closure_requested: closure_requested, checksum_type: checksum_type, file_size: file_size, source_file_name: source_file_name, destination_file_name: destination_file_name, options: options)
|
62
|
+
pdu.write("VARIABLE_DATA", pdu_header + pdu_contents)
|
63
|
+
pdu.write("PDU_DATA_LENGTH", pdu.length - pdu_header_part_1_length - pdu_header_part_2_length)
|
64
|
+
if destination_entity['crcs_required']
|
65
|
+
crc16 = OpenC3::Crc16.new
|
66
|
+
pdu.write("CRC", crc16.calc(pdu.buffer(false)[0..-3]))
|
67
|
+
end
|
68
|
+
return pdu.buffer(false)
|
69
|
+
end
|
70
|
+
|
71
|
+
def define_metadata_pdu_contents
|
72
|
+
s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
73
|
+
s.append_item("RESERVED", 1, :UINT)
|
74
|
+
item = s.append_item("CLOSURE_REQUESTED", 1, :UINT)
|
75
|
+
item.states = CLOSURE_MODES
|
76
|
+
s.append_item("RESERVED2", 2, :UINT)
|
77
|
+
s.append_item("CHECKSUM_TYPE", 4, :UINT)
|
78
|
+
large_file = read("LARGE_FILE_FLAG")
|
79
|
+
if large_file == "SMALL_FILE"
|
80
|
+
s.append_item("FILE_SIZE", 32, :UINT)
|
81
|
+
else
|
82
|
+
s.append_item("FILE_SIZE", 64, :UINT)
|
83
|
+
end
|
84
|
+
s.append_item("SOURCE_FILE_NAME_LENGTH", 8, :UINT)
|
85
|
+
s.append_item("SOURCE_FILE_NAME", 0, :BLOCK)
|
86
|
+
|
87
|
+
s2 = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
88
|
+
s2.append_item("DESTINATION_FILE_NAME_LENGTH", 8, :UINT)
|
89
|
+
s2.append_item("DESTINATION_FILE_NAME", 0, :BLOCK)
|
90
|
+
|
91
|
+
return s, s2
|
92
|
+
end
|
93
|
+
|
94
|
+
def build_metadata_pdu_contents(source_entity:, closure_requested:, checksum_type:, file_size:, source_file_name: nil, destination_file_name: nil, options: [])
|
95
|
+
s, s2 = define_metadata_pdu_contents()
|
96
|
+
s.write("RESERVED", 0)
|
97
|
+
if closure_requested
|
98
|
+
s.write("CLOSURE_REQUESTED", closure_requested)
|
99
|
+
else
|
100
|
+
s.write("CLOSURE_REQUESTED", source_entity['transaction_closure_requested'])
|
101
|
+
end
|
102
|
+
s.write("RESERVED2", 0)
|
103
|
+
s.write("CHECKSUM_TYPE", checksum_type)
|
104
|
+
s.write("FILE_SIZE", file_size)
|
105
|
+
s.write("SOURCE_FILE_NAME_LENGTH", source_file_name.to_s.length)
|
106
|
+
s.write("SOURCE_FILE_NAME", source_file_name.to_s) if source_file_name.to_s.length > 0
|
107
|
+
s2.write("DESTINATION_FILE_NAME_LENGTH", destination_file_name.to_s.length)
|
108
|
+
s2.write("DESTINATION_FILE_NAME", destination_file_name.to_s) if destination_file_name.to_s.length > 0
|
109
|
+
|
110
|
+
result = s.buffer(false) + s2.buffer(false)
|
111
|
+
options.each do |option|
|
112
|
+
result << self.class.build_tlv(option)
|
113
|
+
end
|
114
|
+
return result
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,91 @@
|
|
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
|
+
class CfdpPdu < OpenC3::Packet
|
18
|
+
def self.decom_nak_pdu_contents(pdu, pdu_hash, variable_data)
|
19
|
+
s, s2 = pdu.define_nak_pdu_contents()
|
20
|
+
s.buffer = variable_data[0..(s.defined_length - 1)]
|
21
|
+
pdu_hash["START_OF_SCOPE"] = s.read("START_OF_SCOPE")
|
22
|
+
pdu_hash["END_OF_SCOPE"] = s.read("END_OF_SCOPE")
|
23
|
+
pdu_hash["SEGMENT_REQUESTS"] = []
|
24
|
+
variable_data = variable_data[s.defined_length..-1]
|
25
|
+
while variable_data and variable_data.length > 0
|
26
|
+
s2.buffer = variable_data[0..(s2.defined_length - 1)]
|
27
|
+
pdu_hash["SEGMENT_REQUESTS"] << {}
|
28
|
+
pdu_hash["SEGMENT_REQUESTS"][-1]["START_OFFSET"] = s2.read("START_OFFSET")
|
29
|
+
pdu_hash["SEGMENT_REQUESTS"][-1]["END_OFFSET"] = s2.read("END_OFFSET")
|
30
|
+
variable_data = variable_data[s2.defined_length..-1]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.build_nak_pdu(
|
35
|
+
source_entity:,
|
36
|
+
transaction_seq_num:,
|
37
|
+
destination_entity:,
|
38
|
+
file_size:,
|
39
|
+
segmentation_control: "NOT_PRESERVED",
|
40
|
+
transmission_mode: nil,
|
41
|
+
start_of_scope:,
|
42
|
+
end_of_scope:,
|
43
|
+
segment_requests: [])
|
44
|
+
|
45
|
+
pdu = build_initial_pdu(type: "FILE_DIRECTIVE", destination_entity: destination_entity, transmission_mode: transmission_mode, file_size: file_size, segmentation_control: segmentation_control)
|
46
|
+
pdu.write("DIRECTION", "TOWARD_FILE_SENDER")
|
47
|
+
pdu_header_part_1_length = pdu.length # Measured here before writing variable data
|
48
|
+
pdu_header = pdu.build_variable_header(source_entity_id: source_entity['id'], transaction_seq_num: transaction_seq_num, destination_entity_id: destination_entity['id'], directive_code: "NAK")
|
49
|
+
pdu_header_part_2_length = pdu_header.length
|
50
|
+
pdu_contents = pdu.build_nak_pdu_contents(start_of_scope: start_of_scope, end_of_scope: end_of_scope, segment_requests: segment_requests)
|
51
|
+
pdu.write("VARIABLE_DATA", pdu_header + pdu_contents)
|
52
|
+
pdu.write("PDU_DATA_LENGTH", pdu.length - pdu_header_part_1_length - pdu_header_part_2_length)
|
53
|
+
if destination_entity['crcs_required']
|
54
|
+
crc16 = OpenC3::Crc16.new
|
55
|
+
pdu.write("CRC", crc16.calc(pdu.buffer(false)[0..-3]))
|
56
|
+
end
|
57
|
+
return pdu.buffer(false)
|
58
|
+
end
|
59
|
+
|
60
|
+
def define_nak_pdu_contents
|
61
|
+
s = OpenC3::Structure.new(:BIG_ENDIAN)
|
62
|
+
large_file = read("LARGE_FILE_FLAG")
|
63
|
+
if large_file == "SMALL_FILE"
|
64
|
+
item_size = 32
|
65
|
+
else
|
66
|
+
item_size = 64
|
67
|
+
end
|
68
|
+
|
69
|
+
s.append_item("START_OF_SCOPE", item_size, :UINT)
|
70
|
+
s.append_item("END_OF_SCOPE", item_size, :UINT)
|
71
|
+
|
72
|
+
s2 = OpenC3::Structure.new(:BIG_ENDIAN)
|
73
|
+
s2.append_item("START_OFFSET", item_size, :UINT)
|
74
|
+
s2.append_item("END_OFFSET", item_size, :UINT)
|
75
|
+
return s, s2
|
76
|
+
end
|
77
|
+
|
78
|
+
def build_nak_pdu_contents(start_of_scope:, end_of_scope:, segment_requests: [])
|
79
|
+
s, s2 = define_nak_pdu_contents()
|
80
|
+
result = ''
|
81
|
+
s.write("START_OF_SCOPE", start_of_scope)
|
82
|
+
s.write("END_OF_SCOPE", end_of_scope)
|
83
|
+
result << s.buffer(false)
|
84
|
+
segment_requests.each do |segment_request|
|
85
|
+
s2.write("START_OFFSET", segment_request[0])
|
86
|
+
s2.write("END_OFFSET", segment_request[1])
|
87
|
+
result << s2.buffer(false)
|
88
|
+
end
|
89
|
+
return result
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,60 @@
|
|
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
|
+
class CfdpPdu < OpenC3::Packet
|
18
|
+
def self.decom_prompt_pdu_contents(pdu, pdu_hash, variable_data)
|
19
|
+
s = pdu.define_prompt_pdu_contents
|
20
|
+
s.buffer = variable_data
|
21
|
+
pdu_hash["RESPONSE_REQUIRED"] = s.read("RESPONSE_REQUIRED")
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.build_prompt_pdu(
|
25
|
+
source_entity:,
|
26
|
+
transaction_seq_num:,
|
27
|
+
destination_entity:,
|
28
|
+
segmentation_control: "NOT_PRESERVED",
|
29
|
+
transmission_mode: nil,
|
30
|
+
response_required:)
|
31
|
+
|
32
|
+
pdu = build_initial_pdu(type: "FILE_DIRECTIVE", destination_entity: destination_entity, transmission_mode: transmission_mode, file_size: 0, segmentation_control: segmentation_control)
|
33
|
+
pdu_header_part_1_length = pdu.length # Measured here before writing variable data
|
34
|
+
pdu_header = pdu.build_variable_header(source_entity_id: source_entity['id'], transaction_seq_num: transaction_seq_num, destination_entity_id: destination_entity['id'], directive_code: "PROMPT")
|
35
|
+
pdu_header_part_2_length = pdu_header.length
|
36
|
+
pdu_contents = pdu.build_prompt_pdu_contents(response_required: response_required)
|
37
|
+
pdu.write("VARIABLE_DATA", pdu_header + pdu_contents)
|
38
|
+
pdu.write("PDU_DATA_LENGTH", pdu.length - pdu_header_part_1_length - pdu_header_part_2_length)
|
39
|
+
if destination_entity['crcs_required']
|
40
|
+
crc16 = OpenC3::Crc16.new
|
41
|
+
pdu.write("CRC", crc16.calc(pdu.buffer(false)[0..-3]))
|
42
|
+
end
|
43
|
+
return pdu.buffer(false)
|
44
|
+
end
|
45
|
+
|
46
|
+
def define_prompt_pdu_contents
|
47
|
+
s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
48
|
+
item = s.append_item("RESPONSE_REQUIRED", 1, :UINT)
|
49
|
+
item.states = {"NAK" => 0, "KEEP_ALIVE" => 1}
|
50
|
+
s.append_item("SPARE", 7, :UINT)
|
51
|
+
return s
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_prompt_pdu_contents(response_required:)
|
55
|
+
s = define_prompt_pdu_contents()
|
56
|
+
s.write("RESPONSE_REQUIRED", response_required)
|
57
|
+
s.write("SPARE", 0)
|
58
|
+
return s.buffer(false)
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,291 @@
|
|
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
|
+
class CfdpPdu < OpenC3::Packet
|
18
|
+
def self.decom_tlv(pdu, pdu_hash, variable_data)
|
19
|
+
if variable_data.length >= 2 # Need at least 2 bytes
|
20
|
+
s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
21
|
+
item = s.append_item("TLV_TYPE", 8, :UINT)
|
22
|
+
item.states = TLV_TYPES
|
23
|
+
s.append_item("TLV_LENGTH", 8, :UINT)
|
24
|
+
s.buffer = variable_data[0..(s.defined_length - 1)]
|
25
|
+
type = s.read("TLV_TYPE")
|
26
|
+
length = s.read("TLV_LENGTH")
|
27
|
+
if length > 0
|
28
|
+
tlv_data = variable_data[0..(length + 1)]
|
29
|
+
variable_data = variable_data[(length + 2)..-1]
|
30
|
+
tlv = {}
|
31
|
+
tlv["TYPE"] = type
|
32
|
+
pdu_hash["TLVS"] ||= []
|
33
|
+
pdu_hash["TLVS"] << tlv
|
34
|
+
|
35
|
+
case type
|
36
|
+
when "FILESTORE_REQUEST"
|
37
|
+
s, s2 = define_filestore_request_tlv()
|
38
|
+
s.buffer = tlv_data
|
39
|
+
first_file_name_length = s.read("FIRST_FILE_NAME_LENGTH")
|
40
|
+
s.buffer = tlv_data[0..(4 + first_file_name_length - 1)]
|
41
|
+
tlv_data = tlv_data[(4 + first_file_name_length)..-1]
|
42
|
+
tlv["ACTION_CODE"] = s.read("ACTION_CODE")
|
43
|
+
tlv["FIRST_FILE_NAME"] = s.read("FIRST_FILE_NAME")
|
44
|
+
if tlv_data.length > 0
|
45
|
+
s2.buffer = tlv_data
|
46
|
+
second_file_name_length = s2.read("SECOND_FILE_NAME_LENGTH")
|
47
|
+
s2.buffer = tlv_data[0..(1 + second_file_name_length - 1)]
|
48
|
+
tlv["SECOND_FILE_NAME"] = s2.read("SECOND_FILE_NAME")
|
49
|
+
end
|
50
|
+
|
51
|
+
when "FILESTORE_RESPONSE"
|
52
|
+
s, s2, s3, status_code_item = define_filestore_response_tlv()
|
53
|
+
s.buffer = tlv_data
|
54
|
+
first_file_name_length = s.read("FIRST_FILE_NAME_LENGTH")
|
55
|
+
s.buffer = tlv_data[0..(4 + first_file_name_length - 1)]
|
56
|
+
tlv_data = tlv_data[(4 + first_file_name_length)..-1]
|
57
|
+
tlv["ACTION_CODE"] = s.read("ACTION_CODE")
|
58
|
+
add_status_code_states(action_code: tlv["ACTION_CODE"], status_code_item: status_code_item)
|
59
|
+
tlv["STATUS_CODE"] = s.read("STATUS_CODE")
|
60
|
+
tlv["FIRST_FILE_NAME"] = s.read("FIRST_FILE_NAME")
|
61
|
+
if tlv_data.length > 0
|
62
|
+
s2.buffer = tlv_data
|
63
|
+
second_file_name_length = s2.read("SECOND_FILE_NAME_LENGTH")
|
64
|
+
s2.buffer = tlv_data[0..(1 + second_file_name_length - 1)]
|
65
|
+
tlv_data = tlv_data[(1 + second_file_name_length)..-1]
|
66
|
+
tlv["SECOND_FILE_NAME"] = s2.read("SECOND_FILE_NAME")
|
67
|
+
if tlv_data.length > 0
|
68
|
+
s3.buffer = tlv_data
|
69
|
+
filestore_message_length = s3.read("FILESTORE_MESSAGE_LENGTH")
|
70
|
+
s3.buffer = tlv_data[0..(1 + filestore_message_length - 1)]
|
71
|
+
tlv_data = tlv_data[(1 + filestore_message_length)..-1]
|
72
|
+
tlv["FILESTORE_MESSAGE"] = s3.read("FILESTORE_MESSAGE")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
when "MESSAGE_TO_USER"
|
77
|
+
s = define_message_to_user_tlv()
|
78
|
+
s.buffer = tlv_data
|
79
|
+
tlv["MESSAGE_TO_USER"] = s.read("MESSAGE_TO_USER")
|
80
|
+
tlv.merge!(pdu.decom_message_to_user(tlv["MESSAGE_TO_USER"]))
|
81
|
+
|
82
|
+
when "FAULT_HANDLER_OVERRIDE"
|
83
|
+
s = define_fault_handler_override_tlv()
|
84
|
+
s.buffer = tlv_data
|
85
|
+
tlv["CONDITION_CODE"] = s.read("CONDITION_CODE")
|
86
|
+
tlv["HANDLER_CODE"] = s.read("HANDLER_CODE")
|
87
|
+
|
88
|
+
when "FLOW_LABEL"
|
89
|
+
s = define_flow_label_tlv()
|
90
|
+
s.buffer = tlv_data
|
91
|
+
tlv["FLOW_LABEL"] = s.read("FLOW_LABEL")
|
92
|
+
|
93
|
+
when "ENTITY_ID"
|
94
|
+
s = define_entity_id_tlv()
|
95
|
+
s.buffer = tlv_data
|
96
|
+
entity_id_string = s.read("ENTITY_ID")
|
97
|
+
s2 = OpenC3::Structure.new(:BIG_ENDIAN)
|
98
|
+
s2.append_item("ENTITY_ID", entity_id_string.length * 8, :UINT)
|
99
|
+
s2.buffer = entity_id_string
|
100
|
+
tlv["ENTITY_ID"] = s2.read("ENTITY_ID")
|
101
|
+
|
102
|
+
end
|
103
|
+
else
|
104
|
+
variable_data = variable_data[2..-1]
|
105
|
+
end
|
106
|
+
return variable_data
|
107
|
+
else
|
108
|
+
return ""
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.build_tlv(tlv, entity_id_length: nil)
|
113
|
+
type = tlv["TYPE"]
|
114
|
+
case type
|
115
|
+
when "FILESTORE_REQUEST"
|
116
|
+
first_file_name = tlv["FIRST_FILE_NAME"].to_s
|
117
|
+
second_file_name = nil
|
118
|
+
length = 2 + first_file_name.length # type + length field + length
|
119
|
+
if tlv.key?("SECOND_FILE_NAME")
|
120
|
+
second_file_name = tlv["SECOND_FILE_NAME"].to_s
|
121
|
+
length += 1 + second_file_name.length # length field + length
|
122
|
+
end
|
123
|
+
|
124
|
+
s, s2 = define_filestore_request_tlv()
|
125
|
+
s.write("TLV_TYPE", "FILESTORE_REQUEST")
|
126
|
+
s.write("TLV_LENGTH", length)
|
127
|
+
s.write("ACTION_CODE", tlv['ACTION_CODE'])
|
128
|
+
s.write("SPARE", 0)
|
129
|
+
s.write("FIRST_FILE_NAME_LENGTH", first_file_name.length)
|
130
|
+
s.write("FIRST_FILE_NAME", first_file_name)
|
131
|
+
if second_file_name
|
132
|
+
s2.write("SECOND_FILE_NAME_LENGTH", second_file_name.length)
|
133
|
+
s2.write("SECOND_FILE_NAME", second_file_name)
|
134
|
+
return s.buffer(false) + s2.buffer(false)
|
135
|
+
else
|
136
|
+
return s.buffer(false)
|
137
|
+
end
|
138
|
+
|
139
|
+
# TODO: Handled by cfdp_receive_transaction.rb, search 'Handle Filestore Requests'
|
140
|
+
# when "FILESTORE_RESPONSE"
|
141
|
+
# first_file_name = tlv["FIRST_FILE_NAME"].to_s
|
142
|
+
# second_file_name = tlv["SECOND_FILE_NAME"].to_s
|
143
|
+
# filestore_message = tlv["FILESTORE_MESSAGE"].to_s
|
144
|
+
|
145
|
+
# s, s2, s3, status_code_item = define_filestore_response_tlv()
|
146
|
+
# add_status_code_states(action_code: tlv["ACTION_CODE"], status_code_item: status_code_item)
|
147
|
+
# s.write("TLV_TYPE", "FILESTORE_REQUEST")
|
148
|
+
# s.write("TLV_LENGTH", 4 + first_file_name.length + second_file_name.length + filestore_message.length)
|
149
|
+
# s.write("ACTION_CODE", tlv['ACTION_CODE'])
|
150
|
+
# s.write("STATUS_CODE", tlv['STATUS_CODE'])
|
151
|
+
# s.write("FIRST_FILE_NAME_LENGTH", first_file_name.length)
|
152
|
+
# s.write("FIRST_FILE_NAME", first_file_name)
|
153
|
+
# s2.write("SECOND_FILE_NAME_LENGTH", second_file_name.length)
|
154
|
+
# s2.write("SECOND_FILE_NAME", second_file_name)
|
155
|
+
# s3.write("FILESTORE_MESSAGE_LENGTH", filestore_message.length)
|
156
|
+
# s3.write("FILESTORE_MESSAGE", filestore_message)
|
157
|
+
# return s.buffer(false) + s2.buffer(false) + s3.buffer(false)
|
158
|
+
|
159
|
+
when "MESSAGE_TO_USER"
|
160
|
+
s = define_message_to_user_tlv()
|
161
|
+
s.write("TLV_TYPE", "MESSAGE_TO_USER")
|
162
|
+
s.write("TLV_LENGTH", tlv["MESSAGE_TO_USER"].length)
|
163
|
+
s.write("MESSAGE_TO_USER", tlv["MESSAGE_TO_USER"])
|
164
|
+
return s.buffer(false)
|
165
|
+
|
166
|
+
when "FAULT_HANDLER_OVERRIDE"
|
167
|
+
s = define_fault_handler_override_tlv()
|
168
|
+
s.write("TLV_TYPE", "FAULT_HANDLER_OVERRIDE")
|
169
|
+
s.write("TLV_LENGTH", 1)
|
170
|
+
s.write("CONDITION_CODE", tlv["CONDITION_CODE"])
|
171
|
+
s.write("HANDLER_CODE", tlv["HANDLER_CODE"])
|
172
|
+
return s.buffer(false)
|
173
|
+
|
174
|
+
when "FLOW_LABEL"
|
175
|
+
s = define_flow_label_tlv()
|
176
|
+
s.write("TLV_TYPE", "FLOW_LABEL")
|
177
|
+
s.write("TLV_LENGTH", tlv["FLOW_LABEL"].length)
|
178
|
+
s.write("FLOW_LABEL", tlv["FLOW_LABEL"])
|
179
|
+
return s.buffer(false)
|
180
|
+
|
181
|
+
when "ENTITY_ID"
|
182
|
+
s = define_entity_id_tlv(entity_id_length: entity_id_length)
|
183
|
+
s.write("TLV_TYPE", "ENTITY_ID")
|
184
|
+
s.write("TLV_LENGTH", entity_id_length)
|
185
|
+
s.write("ENTITY_ID", tlv["ENTITY_ID"])
|
186
|
+
return s.buffer(false)
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Table 5-15
|
192
|
+
def self.define_filestore_request_tlv
|
193
|
+
s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
194
|
+
item = s.append_item("TLV_TYPE", 8, :UINT) # 0x01
|
195
|
+
item.states = TLV_TYPES
|
196
|
+
s.append_item("TLV_LENGTH", 8, :UINT)
|
197
|
+
item = s.append_item("ACTION_CODE", 4, :UINT)
|
198
|
+
item.states = ACTION_CODES
|
199
|
+
s.append_item("SPARE", 4, :UINT)
|
200
|
+
s.append_item("FIRST_FILE_NAME_LENGTH", 8, :UINT)
|
201
|
+
s.append_item("FIRST_FILE_NAME", 0, :BLOCK)
|
202
|
+
|
203
|
+
s2 = OpenC3::Structure.new(:BIG_ENDIAN)
|
204
|
+
s2.append_item("SECOND_FILE_NAME_LENGTH", 8, :UINT)
|
205
|
+
s2.append_item("SECOND_FILE_NAME", 0, :BLOCK)
|
206
|
+
|
207
|
+
return s, s2
|
208
|
+
end
|
209
|
+
|
210
|
+
# Table 5-17
|
211
|
+
def self.define_filestore_response_tlv
|
212
|
+
s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
213
|
+
item = s.append_item("TLV_TYPE", 8, :UINT) # 0x01
|
214
|
+
item.states = TLV_TYPES
|
215
|
+
s.append_item("TLV_LENGTH", 8, :UINT)
|
216
|
+
item = s.append_item("ACTION_CODE", 4, :UINT)
|
217
|
+
item.states = ACTION_CODES
|
218
|
+
status_code_item = s.append_item("STATUS_CODE", 4, :UINT)
|
219
|
+
s.append_item("FIRST_FILE_NAME_LENGTH", 8, :UINT)
|
220
|
+
s.append_item("FIRST_FILE_NAME", 0, :BLOCK)
|
221
|
+
|
222
|
+
s2 = OpenC3::Structure.new(:BIG_ENDIAN)
|
223
|
+
s2.append_item("SECOND_FILE_NAME_LENGTH", 8, :UINT)
|
224
|
+
s2.append_item("SECOND_FILE_NAME", 0, :BLOCK)
|
225
|
+
|
226
|
+
s3 = OpenC3::Structure.new(:BIG_ENDIAN)
|
227
|
+
s3.append_item("FILESTORE_MESSAGE_LENGTH", 8, :UINT)
|
228
|
+
s3.append_item("FILESTORE_MESSAGE", 0, :BLOCK)
|
229
|
+
|
230
|
+
return s, s2, s3, status_code_item
|
231
|
+
end
|
232
|
+
|
233
|
+
# Table 5-18
|
234
|
+
def self.add_status_code_states(action_code:, status_code_item:)
|
235
|
+
if String === action_code
|
236
|
+
states = FILESTORE_RESPONSE_STATUS_CODES[action_code]
|
237
|
+
else
|
238
|
+
states = FILESTORE_RESPONSE_STATUS_CODES[ACTION_CODES.key(action_code)]
|
239
|
+
end
|
240
|
+
states = UNKNOWN_STATUS_CODES unless states
|
241
|
+
status_code_item.states = states
|
242
|
+
end
|
243
|
+
|
244
|
+
# Section 5.4.3
|
245
|
+
def self.define_message_to_user_tlv
|
246
|
+
# Todo: Improve for Proxy support
|
247
|
+
s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
248
|
+
item = s.append_item("TLV_TYPE", 8, :UINT) # 0x02
|
249
|
+
item.states = TLV_TYPES
|
250
|
+
s.append_item("TLV_LENGTH", 8, :UINT)
|
251
|
+
s.append_item("MESSAGE_TO_USER", 0, :BLOCK)
|
252
|
+
return s
|
253
|
+
end
|
254
|
+
|
255
|
+
# Table 5-19
|
256
|
+
def self.define_fault_handler_override_tlv
|
257
|
+
s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
258
|
+
item = s.append_item("TLV_TYPE", 8, :UINT) # 0x04
|
259
|
+
item.states = TLV_TYPES
|
260
|
+
s.append_item("TLV_LENGTH", 8, :UINT)
|
261
|
+
item = s.append_item("CONDITION_CODE", 4, :UINT)
|
262
|
+
item.states = CONDITION_CODES
|
263
|
+
item = s.append_item("HANDLER_CODE", 4, :UINT)
|
264
|
+
item.states = HANDLER_CODES
|
265
|
+
return s
|
266
|
+
end
|
267
|
+
|
268
|
+
# Section 5.4.5
|
269
|
+
def self.define_flow_label_tlv
|
270
|
+
s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
271
|
+
item = s.append_item("TLV_TYPE", 8, :UINT) # 0x05
|
272
|
+
item.states = TLV_TYPES
|
273
|
+
s.append_item("TLV_LENGTH", 8, :UINT)
|
274
|
+
s.append_item("FLOW_LABEL", 0, :BLOCK)
|
275
|
+
return s
|
276
|
+
end
|
277
|
+
|
278
|
+
# See Section 5.4.6
|
279
|
+
def self.define_entity_id_tlv(entity_id_length: nil)
|
280
|
+
s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
|
281
|
+
item = s.append_item("TLV_TYPE", 8, :UINT) # 0x06
|
282
|
+
item.states = TLV_TYPES
|
283
|
+
s.append_item("TLV_LENGTH", 8, :UINT)
|
284
|
+
if entity_id_length
|
285
|
+
s.append_item("ENTITY_ID", entity_id_length * 8, :UINT)
|
286
|
+
else
|
287
|
+
s.append_item("ENTITY_ID", 0, :BLOCK)
|
288
|
+
end
|
289
|
+
return s
|
290
|
+
end
|
291
|
+
end
|