openc3-cosmos-cfdp 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +18 -0
  3. data/README.md +181 -0
  4. data/Rakefile +40 -0
  5. data/lib/cfdp.rb +283 -0
  6. data/lib/cfdp_api.rb +204 -0
  7. data/microservices/CFDP/Gemfile +37 -0
  8. data/microservices/CFDP/Rakefile +6 -0
  9. data/microservices/CFDP/app/controllers/application_controller.rb +46 -0
  10. data/microservices/CFDP/app/controllers/cfdp_controller.rb +222 -0
  11. data/microservices/CFDP/app/models/cfdp_checksum.rb +52 -0
  12. data/microservices/CFDP/app/models/cfdp_crc_checksum.rb +41 -0
  13. data/microservices/CFDP/app/models/cfdp_mib.rb +613 -0
  14. data/microservices/CFDP/app/models/cfdp_model.rb +25 -0
  15. data/microservices/CFDP/app/models/cfdp_null_checksum.rb +29 -0
  16. data/microservices/CFDP/app/models/cfdp_pdu.rb +202 -0
  17. data/microservices/CFDP/app/models/cfdp_receive_transaction.rb +590 -0
  18. data/microservices/CFDP/app/models/cfdp_source_transaction.rb +449 -0
  19. data/microservices/CFDP/app/models/cfdp_topic.rb +58 -0
  20. data/microservices/CFDP/app/models/cfdp_transaction.rb +188 -0
  21. data/microservices/CFDP/app/models/cfdp_user.rb +601 -0
  22. data/microservices/CFDP/bin/rails +4 -0
  23. data/microservices/CFDP/bin/rake +4 -0
  24. data/microservices/CFDP/bin/setup +25 -0
  25. data/microservices/CFDP/config/application.rb +55 -0
  26. data/microservices/CFDP/config/boot.rb +4 -0
  27. data/microservices/CFDP/config/credentials.yml.enc +1 -0
  28. data/microservices/CFDP/config/environment.rb +5 -0
  29. data/microservices/CFDP/config/environments/development.rb +53 -0
  30. data/microservices/CFDP/config/environments/production.rb +75 -0
  31. data/microservices/CFDP/config/environments/test.rb +50 -0
  32. data/microservices/CFDP/config/initializers/application_controller_renderer.rb +8 -0
  33. data/microservices/CFDP/config/initializers/backtrace_silencers.rb +7 -0
  34. data/microservices/CFDP/config/initializers/cfdp_initializer.rb +26 -0
  35. data/microservices/CFDP/config/initializers/cors.rb +16 -0
  36. data/microservices/CFDP/config/initializers/filter_parameter_logging.rb +8 -0
  37. data/microservices/CFDP/config/initializers/inflections.rb +16 -0
  38. data/microservices/CFDP/config/initializers/mime_types.rb +4 -0
  39. data/microservices/CFDP/config/initializers/wrap_parameters.rb +9 -0
  40. data/microservices/CFDP/config/locales/en.yml +29 -0
  41. data/microservices/CFDP/config/puma.rb +38 -0
  42. data/microservices/CFDP/config/routes.rb +16 -0
  43. data/microservices/CFDP/config.ru +5 -0
  44. data/microservices/CFDP/init.sh +9 -0
  45. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_ack.rb +82 -0
  46. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_enum.rb +237 -0
  47. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_eof.rb +87 -0
  48. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_file_data.rb +98 -0
  49. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_finished.rb +114 -0
  50. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_keep_alive.rb +65 -0
  51. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_metadata.rb +116 -0
  52. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_nak.rb +91 -0
  53. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_prompt.rb +60 -0
  54. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_tlv.rb +291 -0
  55. data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_user_ops.rb +749 -0
  56. data/microservices/CFDP/public/robots.txt +1 -0
  57. data/microservices/CFDP/spec/models/cfdp_pdu_ack_spec.rb +114 -0
  58. data/microservices/CFDP/spec/models/cfdp_pdu_eof_spec.rb +159 -0
  59. data/microservices/CFDP/spec/models/cfdp_pdu_file_data_spec.rb +76 -0
  60. data/microservices/CFDP/spec/models/cfdp_pdu_finished_spec.rb +192 -0
  61. data/microservices/CFDP/spec/models/cfdp_pdu_keep_alive_spec.rb +69 -0
  62. data/microservices/CFDP/spec/models/cfdp_pdu_metadata_spec.rb +346 -0
  63. data/microservices/CFDP/spec/models/cfdp_pdu_nak_spec.rb +126 -0
  64. data/microservices/CFDP/spec/models/cfdp_pdu_prompt_spec.rb +94 -0
  65. data/microservices/CFDP/spec/models/cfdp_pdu_spec.rb +111 -0
  66. data/microservices/CFDP/spec/rails_helper.rb +71 -0
  67. data/microservices/CFDP/spec/requests/cfdp_spec.rb +1965 -0
  68. data/microservices/CFDP/spec/spec_helper.rb +200 -0
  69. data/plugin.txt +67 -0
  70. data/targets/CFDPTEST/cmd_tlm/cmd.txt +5 -0
  71. data/targets/CFDPTEST/cmd_tlm/tlm.txt +4 -0
  72. data/targets/CFDPTEST/procedures/cfdp_test_suite.rb +130 -0
  73. data/targets/CFDPTEST/target.txt +4 -0
  74. metadata +118 -0
@@ -0,0 +1,237 @@
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
+ # Table 5-4: Directive Codes
19
+ DIRECTIVE_CODES = {
20
+ "EOF" => 4,
21
+ "FINISHED" => 5,
22
+ "ACK" => 6,
23
+ "METADATA" => 7,
24
+ "NAK" => 8,
25
+ "PROMPT" => 9,
26
+ "KEEP_ALIVE" => 0x0C
27
+ # 0D-FF are Reserved
28
+ }
29
+
30
+ # Table 5-5: Condition Codes
31
+ CONDITION_CODES = {
32
+ "NO_ERROR" => 0, # Not a fault
33
+ "ACK_LIMIT_REACHED" => 1,
34
+ "KEEP_ALIVE_LIMIT_REACHED" => 2,
35
+ "INVALID_TRANSMISSION_MODE" => 3, # Not implemented because we support both modes
36
+ "FILESTORE_REJECTION" => 4,
37
+ "FILE_CHECKSUM_FAILURE" => 5,
38
+ "FILE_SIZE_ERROR" => 6,
39
+ "NAK_LIMIT_REACHED" => 7,
40
+ "INACTIVITY_DETECTED" => 8,
41
+ "INVALID_FILE_STRUCTURE" => 9, # Not implemented because no segmentation control
42
+ "CHECK_LIMIT_REACHED" => 10,
43
+ "UNSUPPORTED_CHECKSUM_TYPE" => 11,
44
+ "SUSPEND_REQUEST_RECEIVED" => 14, # Not a fault
45
+ "CANCEL_REQUEST_RECEIVED" => 15 # Not a fault
46
+ }
47
+
48
+ # Table 5-7: Finished PDU Contents
49
+ DELIVERY_CODES = {
50
+ "DATA_COMPLETE" => 0,
51
+ "DATA_INCOMPLETE" => 1
52
+ }
53
+
54
+ # Table 5-7: Finished PDU Contents
55
+ FILE_STATUS_CODES = {
56
+ "FILE_DISCARDED" => 0,
57
+ "FILESTORE_REJECTION" => 1,
58
+ "FILESTORE_SUCCESS" => 2,
59
+ "UNREPORTED" => 3
60
+ }
61
+
62
+ # Paragraph 5.2.4 ACK PDU
63
+ TRANSACTION_STATUS_CODES = {
64
+ "UNDEFINED" => 0,
65
+ "ACTIVE" => 1,
66
+ "TERMINATED" => 2,
67
+ "UNRECOGNIZED" => 3
68
+ }
69
+
70
+ # Table 5-16: Filestore Request TLV Action Codes
71
+ ACTION_CODES = {
72
+ "CREATE_FILE" => 0,
73
+ "DELETE_FILE" => 1,
74
+ "RENAME_FILE" => 2,
75
+ "APPEND_FILE" => 3,
76
+ "REPLACE_FILE" => 4,
77
+ "CREATE_DIRECTORY" => 5,
78
+ "REMOVE_DIRECTORY" => 6,
79
+ "DENY_FILE" => 7,
80
+ "DENY_DIRECTORY" => 8
81
+ }
82
+
83
+ # Table 5-18: Filestore Response Status Codes
84
+ CREATE_FILE_STATUS_CODES = {
85
+ "SUCCESSFUL" => 0,
86
+ "NOT_ALLOWED" => 1,
87
+ "NOT_PERFORMED" => 15
88
+ }
89
+
90
+ # Table 5-18: Filestore Response Status Codes
91
+ DELETE_FILE_STATUS_CODES = {
92
+ "SUCCESSFUL" => 0,
93
+ "FILE_DOES_NOT_EXIST" => 1,
94
+ "NOT_ALLOWED" => 2,
95
+ "NOT_PERFORMED" => 15
96
+ }
97
+
98
+ # Table 5-18: Filestore Response Status Codes
99
+ RENAME_FILE_STATUS_CODES = {
100
+ "SUCCESSFUL" => 0,
101
+ "OLD_FILE_DOES_NOT_EXIST" => 1,
102
+ "NEW_FILE_ALREADY_EXISTS" => 2,
103
+ "NOT_ALLOWED" => 3,
104
+ "NOT_PERFORMED" => 15
105
+ }
106
+
107
+ # Table 5-18: Filestore Response Status Codes
108
+ APPEND_FILE_STATUS_CODES = {
109
+ "SUCCESSFUL" => 0,
110
+ "FILE_1_DOES_NOT_EXIST" => 1,
111
+ "FILE_2_DOES_NOT_EXIST" => 2,
112
+ "NOT_ALLOWED" => 3,
113
+ "NOT_PERFORMED" => 15
114
+ }
115
+
116
+ # Table 5-18: Filestore Response Status Codes
117
+ REPLACE_FILE_STATUS_CODES = {
118
+ "SUCCESSFUL" => 0,
119
+ "FILE_1_DOES_NOT_EXIST" => 1,
120
+ "FILE_2_DOES_NOT_EXIST" => 2,
121
+ "NOT_ALLOWED" => 3,
122
+ "NOT_PERFORMED" => 15
123
+ }
124
+
125
+ # Table 5-18: Filestore Response Status Codes
126
+ CREATE_DIRECTORY_STATUS_CODES = {
127
+ "SUCCESSFUL" => 0,
128
+ "CANNOT_BE_CREATED" => 1,
129
+ "NOT_PERFORMED" => 15
130
+ }
131
+
132
+ # Table 5-18: Filestore Response Status Codes
133
+ REMOVE_DIRECTORY_STATUS_CODES = {
134
+ "SUCCESSFUL" => 0,
135
+ "DOES_NOT_EXIST" => 1,
136
+ "NOT_ALLOWED" => 2,
137
+ "NOT_PERFORMED" => 15
138
+ }
139
+
140
+ # Table 5-18: Filestore Response Status Codes
141
+ DENY_FILE_STATUS_CODES = {
142
+ "SUCCESSFUL" => 0,
143
+ "NOT_ALLOWED" => 2,
144
+ "NOT_PERFORMED" => 15
145
+ }
146
+
147
+ # Table 5-18: Filestore Response Status Codes
148
+ DENY_DIRECTORY_STATUS_CODES = {
149
+ "SUCCESSFUL" => 0,
150
+ "NOT_ALLOWED" => 2,
151
+ "NOT_PERFORMED" => 15
152
+ }
153
+
154
+ # Special for unknown action codes
155
+ UNKNOWN_STATUS_CODES = {
156
+ "NOT_PERFORMED" => 15
157
+ }
158
+
159
+ # Table 5-18: Filestore Response Status Codes
160
+ FILESTORE_RESPONSE_STATUS_CODES = {
161
+ "CREATE_FILE" => CREATE_FILE_STATUS_CODES,
162
+ "DELETE_FILE" => DELETE_FILE_STATUS_CODES,
163
+ "RENAME_FILE" => RENAME_FILE_STATUS_CODES,
164
+ "APPEND_FILE" => APPEND_FILE_STATUS_CODES,
165
+ "REPLACE_FILE" => REPLACE_FILE_STATUS_CODES,
166
+ "CREATE_DIRECTORY" => CREATE_DIRECTORY_STATUS_CODES,
167
+ "REMOVE_DIRECTORY" => REMOVE_DIRECTORY_STATUS_CODES,
168
+ "DENY_FILE" => DENY_FILE_STATUS_CODES,
169
+ "DENY_DIRECTORY" => DENY_DIRECTORY_STATUS_CODES
170
+ }
171
+
172
+ # Table 5-14: File Data PDU Contents
173
+ RECORD_CONTINUATION_STATES = {
174
+ "NEITHER_START_NOR_END" => 0,
175
+ "START" => 1,
176
+ "END" => 2,
177
+ "START_AND_END" => 3
178
+ }
179
+
180
+ # Defined in Section 5.4
181
+ TLV_TYPES = {
182
+ "FILESTORE_REQUEST" => 0,
183
+ "FILESTORE_RESPONSE" => 1,
184
+ "MESSAGE_TO_USER" => 2,
185
+ "FAULT_HANDLER_OVERRIDE" => 4,
186
+ "FLOW_LABEL" => 5,
187
+ "ENTITY_ID" => 6
188
+ }
189
+
190
+ # Table 5-19
191
+ HANDLER_CODES = {
192
+ "ISSUE_NOTICE_OF_CANCELLATION" => 1,
193
+ "ISSUE_NOTICE_OF_SUSPENSION" => 2,
194
+ "IGNORE_ERROR" => 3,
195
+ "ABONDON_TRANSACTION" => 4
196
+ }
197
+
198
+ # 6.1.5, Table 6-3, Table 6-14, Table 6-17, Table 6-20, Table 6-23,
199
+ USER_MESSAGE_TYPES = {
200
+ "PROXY_PUT_REQUEST" => 0x00,
201
+ "PROXY_MESSAGE_TO_USER" => 0x01,
202
+ "PROXY_FILESTORE_REQUEST" => 0x02,
203
+ "PROXY_FAULT_HANDLER_OVERRIDE" => 0x03,
204
+ "PROXY_TRANSMISSION_MODE" => 0x04,
205
+ "PROXY_FLOW_LABEL" => 0x05,
206
+ "PROXY_SEGMENTATION_CONTROL" => 0x06,
207
+ "PROXY_PUT_RESPONSE" => 0x07,
208
+ "PROXY_FILESTORE_RESPONSE" => 0x08,
209
+ "PROXY_PUT_CANCEL" => 0x09,
210
+ "ORIGINATING_TRANSACTION_ID" => 0x0A,
211
+ "PROXY_CLOSURE_REQUEST" => 0x0B,
212
+ "DIRECTORY_LISTING_REQUEST" => 0x10,
213
+ "DIRECTORY_LISTING_RESPONSE" => 0x11,
214
+ "REMOTE_STATUS_REPORT_REQUEST" => 0x20,
215
+ "REMOTE_STATUS_REPORT_RESPONSE" => 0x21,
216
+ "REMOTE_SUSPEND_REQUEST" => 0x30,
217
+ "REMOTE_SUSPEND_RESPONSE" => 0x31,
218
+ "REMOTE_RESUME_REQUEST" => 0x38,
219
+ "REMOTE_RESUME_RESPONSE" => 0x39,
220
+ }
221
+
222
+ # Table 5-1
223
+ TRANSMISSION_MODES = {
224
+ "ACKNOWLEDGED" => 0,
225
+ "UNACKNOWLEDGED" => 1
226
+ }
227
+
228
+ CLOSURE_MODES = {
229
+ "CLOSURE_NOT_REQUESTED" => 0,
230
+ "CLOSURE_REQUESTED" => 1
231
+ }
232
+
233
+ SEGMENTATION_MODES = {
234
+ "NOT_PRESERVED" => 0,
235
+ "PRESERVED" => 1
236
+ }
237
+ end
@@ -0,0 +1,87 @@
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_eof_pdu_contents(pdu, pdu_hash, variable_data)
19
+ s = pdu.define_eof_pdu_contents()
20
+ s.buffer = variable_data[0..(s.defined_length - 1)]
21
+ pdu_hash["CONDITION_CODE"] = s.read("CONDITION_CODE")
22
+ pdu_hash["FILE_CHECKSUM"] = s.read("FILE_CHECKSUM")
23
+ pdu_hash["FILE_SIZE"] = s.read("FILE_SIZE")
24
+ if pdu_hash['CONDITION_CODE'] != "NO_ERROR"
25
+ variable_data = variable_data[s.defined_length..-1]
26
+ decom_tlv(pdu, pdu_hash, variable_data)
27
+ end
28
+ end
29
+
30
+ def self.build_eof_pdu(
31
+ source_entity:,
32
+ transaction_seq_num:,
33
+ destination_entity:,
34
+ file_size:,
35
+ file_checksum:,
36
+ condition_code:,
37
+ segmentation_control: "NOT_PRESERVED",
38
+ transmission_mode: nil,
39
+ canceling_entity_id: nil)
40
+
41
+ pdu = build_initial_pdu(type: "FILE_DIRECTIVE", destination_entity: destination_entity, transmission_mode: transmission_mode, file_size: file_size, segmentation_control: segmentation_control)
42
+ pdu_header_part_1_length = pdu.length # Measured here before writing variable data
43
+ 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: "EOF")
44
+ pdu_header_part_2_length = pdu_header.length
45
+ pdu_contents = pdu.build_eof_pdu_contents(condition_code: condition_code, file_checksum: file_checksum, file_size: file_size, canceling_entity_id: canceling_entity_id)
46
+ pdu.write("VARIABLE_DATA", pdu_header + pdu_contents)
47
+ pdu.write("PDU_DATA_LENGTH", pdu.length - pdu_header_part_1_length - pdu_header_part_2_length)
48
+ if destination_entity['crcs_required']
49
+ crc16 = OpenC3::Crc16.new
50
+ pdu.write("CRC", crc16.calc(pdu.buffer(false)[0..-3]))
51
+ end
52
+ return pdu.buffer(false)
53
+ end
54
+
55
+ def define_eof_pdu_contents
56
+ s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
57
+ item = s.append_item("CONDITION_CODE", 4, :UINT)
58
+ item.states = CONDITION_CODES
59
+ s.append_item("SPARE", 4, :UINT)
60
+ s.append_item("FILE_CHECKSUM", 32, :UINT)
61
+ large_file = read("LARGE_FILE_FLAG")
62
+ if large_file == "SMALL_FILE"
63
+ s.append_item("FILE_SIZE", 32, :UINT)
64
+ else
65
+ s.append_item("FILE_SIZE", 64, :UINT)
66
+ end
67
+ return s
68
+ end
69
+
70
+ def build_eof_pdu_contents(condition_code:, file_checksum:, file_size:, canceling_entity_id: nil)
71
+ s = define_eof_pdu_contents()
72
+ s.write("CONDITION_CODE", condition_code)
73
+ s.write("SPARE", 0)
74
+ s.write("FILE_CHECKSUM", file_checksum)
75
+ s.write("FILE_SIZE", file_size)
76
+ if canceling_entity_id
77
+ entity_id_length = read("ENTITY_ID_LENGTH") + 1
78
+ s2 = CfdpPdu.define_entity_id_tlv(entity_id_length: entity_id_length)
79
+ s2.write("TLV_TYPE", 0x06)
80
+ s2.write("TLV_LENGTH", entity_id_length)
81
+ s2.write("ENTITY_ID", canceling_entity_id)
82
+ return s.buffer(false) + s2.buffer(false)
83
+ else
84
+ return s.buffer(false)
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,98 @@
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_file_data_pdu_contents(pdu, pdu_hash, variable_data)
19
+ s, s2 = pdu.define_file_data_pdu_contents
20
+ if s
21
+ s.buffer = variable_data
22
+ pdu_hash["RECORD_CONTINUATION_STATE"] = s.read("RECORD_CONTINUATION_STATE")
23
+ pdu_hash["SEGMENT_METADATA_LENGTH"] = s.read("SEGMENT_METADATA_LENGTH")
24
+ s.buffer = variable_data[0..pdu_hash["SEGMENT_METADATA_LENGTH"]]
25
+ pdu_hash["SEGMENT_METADATA"] = s.read("SEGMENT_METADATA")
26
+ variable_data = variable_data[(s.length)..-1]
27
+ end
28
+ s2.buffer = variable_data
29
+ pdu_hash['OFFSET'] = s2.read("OFFSET")
30
+ pdu_hash['FILE_DATA'] = s2.read("FILE_DATA")
31
+ end
32
+
33
+ def self.build_file_data_pdu(
34
+ source_entity:,
35
+ transaction_seq_num:,
36
+ destination_entity:,
37
+ file_size:,
38
+ segmentation_control: "NOT_PRESERVED",
39
+ transmission_mode: nil,
40
+ offset:,
41
+ file_data:,
42
+ record_continuation_state: nil,
43
+ segment_metadata: nil)
44
+
45
+ pdu = build_initial_pdu(type: "FILE_DATA", destination_entity: destination_entity, file_size: file_size, segmentation_control: segmentation_control, transmission_mode: transmission_mode)
46
+ pdu_header_part_1_length = pdu.length # Measured here before writing variable data
47
+ pdu_header = pdu.build_variable_header(source_entity_id: source_entity['id'], transaction_seq_num: transaction_seq_num, destination_entity_id: destination_entity['id'])
48
+ pdu_header_part_2_length = pdu_header.length
49
+ pdu_contents = pdu.build_file_data_pdu_contents(offset: offset, file_data: file_data, record_continuation_state: record_continuation_state, segment_metadata: segment_metadata)
50
+ pdu.write("VARIABLE_DATA", pdu_header + pdu_contents)
51
+ pdu.write("PDU_DATA_LENGTH", pdu.length - pdu_header_part_1_length - pdu_header_part_2_length)
52
+ if destination_entity['crcs_required']
53
+ crc16 = OpenC3::Crc16.new
54
+ pdu.write("CRC", crc16.calc(pdu.buffer(false)[0..-3]))
55
+ end
56
+ return pdu.buffer(false)
57
+ end
58
+
59
+ def define_file_data_pdu_contents
60
+ smf = read("SEGMENT_METADATA_FLAG")
61
+
62
+ s = nil
63
+ if smf == "PRESENT"
64
+ s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
65
+ item = s.append_item("RECORD_CONTINUATION_STATE", 2, :UINT)
66
+ item.states = RECORD_CONTINUATION_STATES
67
+ s.append_item("SEGMENT_METADATA_LENGTH", 6, :UINT)
68
+ s.append_item("SEGMENT_METADATA", 0, :BLOCK)
69
+ end
70
+
71
+ s2 = OpenC3::Structure.new(:BIG_ENDIAN)
72
+ large_file = read("LARGE_FILE_FLAG")
73
+ if large_file == "SMALL_FILE"
74
+ item_size = 32
75
+ else
76
+ item_size = 64
77
+ end
78
+ s2.append_item("OFFSET", item_size, :UINT)
79
+ s2.append_item("FILE_DATA", 0, :BLOCK)
80
+
81
+ return s, s2
82
+ end
83
+
84
+ def build_file_data_pdu_contents(offset:, file_data:, record_continuation_state: nil, segment_metadata: nil)
85
+ s, s2 = define_file_data_pdu_contents()
86
+ s2.write("OFFSET", offset)
87
+ s2.write("FILE_DATA", file_data.to_s)
88
+
89
+ if s
90
+ s.write("RECORD_CONTINUATION_STATE", record_continuation_state)
91
+ s.write("SEGMENT_METADATA_LENGTH", segment_metadata.to_s.length)
92
+ s.write("SEGMENT_METADATA", segment_metadata.to_s)
93
+ return s.buffer(false) + s2.buffer(false)
94
+ else
95
+ return s2.buffer(false)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,114 @@
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_finished_pdu_contents(pdu, pdu_hash, variable_data)
19
+ s = pdu.define_finished_pdu_contents
20
+ s.buffer = variable_data[0..(s.defined_length - 1)]
21
+ pdu_hash["CONDITION_CODE"] = s.read("CONDITION_CODE")
22
+ pdu_hash["DELIVERY_CODE"] = s.read("DELIVERY_CODE")
23
+ pdu_hash["FILE_STATUS"] = s.read("FILE_STATUS")
24
+ variable_data = variable_data[s.defined_length..-1]
25
+ while variable_data.length > 0
26
+ variable_data = decom_tlv(pdu, pdu_hash, variable_data)
27
+ end
28
+ end
29
+
30
+ def self.build_finished_pdu(
31
+ source_entity:,
32
+ transaction_seq_num:,
33
+ destination_entity:,
34
+ condition_code:,
35
+ segmentation_control: "NOT_PRESERVED",
36
+ transmission_mode: nil,
37
+ delivery_code:,
38
+ file_status:,
39
+ filestore_responses: [],
40
+ fault_location_entity_id: nil)
41
+
42
+ pdu = build_initial_pdu(type: "FILE_DIRECTIVE", destination_entity: destination_entity, transmission_mode: transmission_mode, file_size: 0, segmentation_control: segmentation_control)
43
+ pdu.write("DIRECTION", "TOWARD_FILE_SENDER")
44
+ pdu_header_part_1_length = pdu.length # Measured here before writing variable data
45
+ 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: "FINISHED")
46
+ pdu_header_part_2_length = pdu_header.length
47
+ pdu_contents = pdu.build_finished_pdu_contents(condition_code: condition_code, delivery_code: delivery_code, file_status: file_status, filestore_responses: filestore_responses, fault_location_entity_id: fault_location_entity_id)
48
+ pdu.write("VARIABLE_DATA", pdu_header + pdu_contents)
49
+ pdu.write("PDU_DATA_LENGTH", pdu.length - pdu_header_part_1_length - pdu_header_part_2_length)
50
+ if destination_entity['crcs_required']
51
+ crc16 = OpenC3::Crc16.new
52
+ pdu.write("CRC", crc16.calc(pdu.buffer(false)[0..-3]))
53
+ end
54
+ return pdu.buffer(false)
55
+ end
56
+
57
+ def define_finished_pdu_contents
58
+ s = OpenC3::Packet.new(nil, nil, :BIG_ENDIAN)
59
+ item = s.append_item("CONDITION_CODE", 4, :UINT)
60
+ item.states = CONDITION_CODES
61
+ s.append_item("SPARE", 1, :UINT)
62
+ item = s.append_item("DELIVERY_CODE", 1, :UINT)
63
+ item.states = DELIVERY_CODES
64
+ item = s.append_item("FILE_STATUS", 2, :UINT)
65
+ item.states = FILE_STATUS_CODES
66
+ return s
67
+ end
68
+
69
+ def build_finished_pdu_contents(condition_code:, delivery_code:, file_status:, filestore_responses: [], fault_location_entity_id: nil)
70
+ structures = []
71
+ s = define_finished_pdu_contents()
72
+ s.write("CONDITION_CODE", condition_code)
73
+ s.write("SPARE", 0)
74
+ s.write("DELIVERY_CODE", delivery_code)
75
+ s.write("FILE_STATUS", file_status)
76
+ structures << s
77
+
78
+ filestore_responses.each do |filestore_response|
79
+ action_code = filestore_response['ACTION_CODE']
80
+ status_code = filestore_response['STATUS_CODE']
81
+ first_file_name = filestore_response['FIRST_FILE_NAME']
82
+ second_file_name = filestore_response['SECOND_FILE_NAME']
83
+ filestore_message = filestore_response['FILESTORE_MESSAGE']
84
+ s, s2, s3, status_code_item = CfdpPdu.define_filestore_response_tlv()
85
+ CfdpPdu.add_status_code_states(action_code: action_code, status_code_item: status_code_item)
86
+ s.write("TLV_TYPE", 0x01)
87
+ s.write("TLV_LENGTH", 4 + first_file_name.to_s.length + second_file_name.to_s.length + filestore_message.to_s.length)
88
+ s.write("ACTION_CODE", action_code)
89
+ s.write("STATUS_CODE", status_code)
90
+ s.write("FIRST_FILE_NAME_LENGTH", first_file_name.to_s.length)
91
+ s.write("FIRST_FILE_NAME", first_file_name.to_s) if first_file_name.to_s.length > 0
92
+ s2.write("SECOND_FILE_NAME_LENGTH", second_file_name.to_s.length)
93
+ s2.write("SECOND_FILE_NAME", second_file_name.to_s) if second_file_name.to_s.length > 0
94
+ s3.write("FILESTORE_MESSAGE_LENGTH", filestore_message.to_s.length)
95
+ s3.write("FILESTORE_MESSAGE", filestore_message.to_s) if filestore_message.to_s.length > 0
96
+ structures << s
97
+ structures << s2
98
+ structures << s3
99
+ end
100
+ if fault_location_entity_id
101
+ entity_id_length = read("ENTITY_ID_LENGTH") + 1
102
+ s = CfdpPdu.define_entity_id_tlv(entity_id_length: entity_id_length)
103
+ s.write("TLV_TYPE", 0x06)
104
+ s.write("TLV_LENGTH", entity_id_length)
105
+ s.write("ENTITY_ID", fault_location_entity_id)
106
+ structures << s
107
+ end
108
+ result = ''
109
+ structures.each do |s|
110
+ result << s.buffer(false)
111
+ end
112
+ return result
113
+ end
114
+ end
@@ -0,0 +1,65 @@
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_keep_alive_pdu_contents(pdu, pdu_hash, variable_data)
19
+ s = pdu.define_keep_alive_pdu_contents
20
+ s.buffer = variable_data
21
+ pdu_hash["PROGRESS"] = s.read("PROGRESS")
22
+ end
23
+
24
+ def self.build_keep_alive_pdu(
25
+ source_entity:,
26
+ transaction_seq_num:,
27
+ destination_entity:,
28
+ file_size:,
29
+ segmentation_control: "NOT_PRESERVED",
30
+ transmission_mode: nil,
31
+ progress:)
32
+
33
+ pdu = build_initial_pdu(type: "FILE_DIRECTIVE", destination_entity: destination_entity, transmission_mode: transmission_mode, file_size: file_size, segmentation_control: segmentation_control)
34
+ pdu.write("DIRECTION", "TOWARD_FILE_SENDER")
35
+ pdu_header_part_1_length = pdu.length # Measured here before writing variable data
36
+ 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: "KEEP_ALIVE")
37
+ pdu_header_part_2_length = pdu_header.length
38
+ pdu_contents = pdu.build_keep_alive_pdu_contents(progress: progress)
39
+ pdu.write("VARIABLE_DATA", pdu_header + pdu_contents)
40
+ pdu.write("PDU_DATA_LENGTH", pdu.length - pdu_header_part_1_length - pdu_header_part_2_length)
41
+ if destination_entity['crcs_required']
42
+ crc16 = OpenC3::Crc16.new
43
+ pdu.write("CRC", crc16.calc(pdu.buffer(false)[0..-3]))
44
+ end
45
+ return pdu.buffer(false)
46
+ end
47
+
48
+ def define_keep_alive_pdu_contents
49
+ s = OpenC3::Structure.new(:BIG_ENDIAN)
50
+ large_file = read("LARGE_FILE_FLAG")
51
+ if large_file == "SMALL_FILE"
52
+ item_size = 32
53
+ else
54
+ item_size = 64
55
+ end
56
+ s.append_item("PROGRESS", item_size, :UINT)
57
+ return s
58
+ end
59
+
60
+ def build_keep_alive_pdu_contents(progress:)
61
+ s = define_keep_alive_pdu_contents()
62
+ s.write("PROGRESS", progress)
63
+ return s.buffer(false)
64
+ end
65
+ end