openc3-cosmos-cfdp 2.0.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.md +18 -0
- data/README.md +103 -55
- data/Rakefile +12 -0
- data/lib/cfdp.py +564 -0
- data/lib/cfdp.rb +68 -14
- data/lib/cfdp_api.py +302 -0
- data/lib/cfdp_api.rb +55 -9
- data/microservices/CFDP/Gemfile +18 -4
- data/microservices/CFDP/Gemfile.dev +22 -8
- data/microservices/CFDP/Gemfile.prod +18 -4
- data/microservices/CFDP/Rakefile +13 -2
- data/microservices/CFDP/app/controllers/application_controller.rb +2 -2
- data/microservices/CFDP/app/controllers/cfdp_controller.rb +62 -31
- data/microservices/CFDP/app/models/cfdp_checksum.rb +12 -4
- data/microservices/CFDP/app/models/cfdp_crc_checksum.rb +10 -2
- data/microservices/CFDP/app/models/cfdp_mib.rb +178 -35
- data/microservices/CFDP/app/models/cfdp_null_checksum.rb +10 -2
- data/microservices/CFDP/app/models/cfdp_pdu.rb +96 -20
- data/microservices/CFDP/app/models/cfdp_receive_transaction.rb +147 -11
- data/microservices/CFDP/app/models/cfdp_source_transaction.rb +438 -93
- data/microservices/CFDP/app/models/cfdp_topic.rb +2 -2
- data/microservices/CFDP/app/models/cfdp_transaction.rb +188 -4
- data/microservices/CFDP/app/models/cfdp_user.rb +236 -73
- data/microservices/CFDP/config/routes.rb +1 -0
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_ack.rb +7 -6
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_eof.rb +1 -2
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_file_data.rb +2 -25
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_finished.rb +8 -7
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_keep_alive.rb +7 -6
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_metadata.rb +1 -2
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_nak.rb +7 -6
- data/microservices/CFDP/lib/cfdp_pdu/cfdp_pdu_prompt.rb +1 -2
- data/microservices/CFDP/spec/controllers/cfdp_controller_spec.rb +226 -1
- data/microservices/CFDP/spec/models/cfdp_checksum_spec.rb +239 -0
- data/microservices/CFDP/spec/models/cfdp_crc_checksum_spec.rb +16 -13
- data/microservices/CFDP/spec/models/cfdp_mib_spec.rb +909 -138
- data/microservices/CFDP/spec/models/cfdp_null_checksum_spec.rb +111 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_file_data_spec.rb +48 -0
- data/microservices/CFDP/spec/models/cfdp_pdu_nak_spec.rb +2 -2
- data/microservices/CFDP/spec/models/cfdp_pdu_spec.rb +129 -0
- data/microservices/CFDP/spec/models/cfdp_receive_transaction_spec.rb +117 -10
- data/microservices/CFDP/spec/models/cfdp_source_transaction_spec.rb +382 -0
- data/microservices/CFDP/spec/models/cfdp_transaction_spec.rb +323 -5
- data/microservices/CFDP/spec/models/cfdp_user_spec.rb +553 -21
- data/microservices/CFDP/spec/requests/cfdp_spec.rb +92 -43
- data/microservices/CFDP/spec/spec_helper.rb +34 -3
- data/plugin.txt +55 -4
- data/public/store_img.png +0 -0
- data/pyproject.toml +70 -0
- data/targets/CFDPTEST/procedures/cfdp_test_suite.py +179 -0
- data/targets/CFDPTEST/procedures/cfdp_test_suite.rb +2 -2
- data/targets/CFDPTEST/procedures/interrupt_test.rb +31 -0
- metadata +25 -12
- data/LICENSE.txt +0 -18
data/lib/cfdp.py
ADDED
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
# Copyright 2026 OpenC3, Inc.
|
|
2
|
+
# All Rights Reserved.
|
|
3
|
+
#
|
|
4
|
+
# Licensed for Evaluation and Educational Use
|
|
5
|
+
#
|
|
6
|
+
# This file may only be used commercially under the terms of a commercial license
|
|
7
|
+
# purchased from OpenC3, Inc.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
12
|
+
#
|
|
13
|
+
# The development of this software was funded in-whole or in-part by MethaneSAT LLC.
|
|
14
|
+
|
|
15
|
+
import time
|
|
16
|
+
|
|
17
|
+
from cfdp_api import CfdpApi
|
|
18
|
+
from openc3.environment import OPENC3_SCOPE
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _get_wait():
|
|
22
|
+
# Available when running inside ScriptRunner. Returns the actual time waited;
|
|
23
|
+
# a value less than the requested time means the user hit Go. Imported lazily
|
|
24
|
+
# (mirrors the Ruby `defined? wait`) so simply importing cfdp does not pull in
|
|
25
|
+
# the full openc3.script stack.
|
|
26
|
+
try:
|
|
27
|
+
from openc3.script import wait
|
|
28
|
+
|
|
29
|
+
return wait
|
|
30
|
+
except Exception:
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def cfdp_put(
|
|
35
|
+
destination_entity_id,
|
|
36
|
+
source_file_name=None,
|
|
37
|
+
destination_file_name=None,
|
|
38
|
+
closure_requested=None,
|
|
39
|
+
transmission_mode=None,
|
|
40
|
+
filestore_requests=None,
|
|
41
|
+
fault_handler_overrides=None,
|
|
42
|
+
flow_label=None,
|
|
43
|
+
segmentation_control="NOT_PRESERVED",
|
|
44
|
+
messages_to_user=None,
|
|
45
|
+
remote_entity_id=None, # Used to indicate proxy put
|
|
46
|
+
timeout=600,
|
|
47
|
+
api_timeout=5,
|
|
48
|
+
microservice_name="CFDP",
|
|
49
|
+
prefix="/cfdp",
|
|
50
|
+
schema="http",
|
|
51
|
+
hostname=None,
|
|
52
|
+
port=2905,
|
|
53
|
+
url=None,
|
|
54
|
+
scope=OPENC3_SCOPE,
|
|
55
|
+
):
|
|
56
|
+
api = CfdpApi(
|
|
57
|
+
timeout=api_timeout,
|
|
58
|
+
microservice_name=microservice_name,
|
|
59
|
+
prefix=prefix,
|
|
60
|
+
schema=schema,
|
|
61
|
+
hostname=hostname,
|
|
62
|
+
port=port,
|
|
63
|
+
url=url,
|
|
64
|
+
scope=scope,
|
|
65
|
+
)
|
|
66
|
+
continuation = api.subscribe(scope=scope) if timeout else None
|
|
67
|
+
transaction_id = api.put(
|
|
68
|
+
destination_entity_id=destination_entity_id,
|
|
69
|
+
source_file_name=source_file_name,
|
|
70
|
+
destination_file_name=destination_file_name,
|
|
71
|
+
transmission_mode=transmission_mode,
|
|
72
|
+
closure_requested=closure_requested,
|
|
73
|
+
filestore_requests=filestore_requests,
|
|
74
|
+
fault_handler_overrides=fault_handler_overrides,
|
|
75
|
+
flow_label=flow_label,
|
|
76
|
+
segmentation_control=segmentation_control,
|
|
77
|
+
messages_to_user=messages_to_user,
|
|
78
|
+
remote_entity_id=remote_entity_id, # Used to indicate proxy put
|
|
79
|
+
scope=scope,
|
|
80
|
+
)
|
|
81
|
+
if not timeout:
|
|
82
|
+
return transaction_id
|
|
83
|
+
indication_type = "Proxy-Put-Response" if remote_entity_id else "Transaction-Finished"
|
|
84
|
+
indication = cfdp_wait_for_indication(
|
|
85
|
+
api=api,
|
|
86
|
+
transaction_id=transaction_id,
|
|
87
|
+
indication_type=indication_type,
|
|
88
|
+
continuation=continuation,
|
|
89
|
+
timeout=timeout,
|
|
90
|
+
scope=scope,
|
|
91
|
+
)
|
|
92
|
+
return transaction_id, indication
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def cfdp_put_dir(
|
|
96
|
+
destination_entity_id,
|
|
97
|
+
source_directory_name,
|
|
98
|
+
closure_requested=None,
|
|
99
|
+
transmission_mode=None,
|
|
100
|
+
filestore_requests=None,
|
|
101
|
+
fault_handler_overrides=None,
|
|
102
|
+
flow_label=None,
|
|
103
|
+
segmentation_control="NOT_PRESERVED",
|
|
104
|
+
messages_to_user=None,
|
|
105
|
+
remote_entity_id=None, # Used to indicate proxy put
|
|
106
|
+
timeout=600,
|
|
107
|
+
api_timeout=5,
|
|
108
|
+
microservice_name="CFDP",
|
|
109
|
+
prefix="/cfdp",
|
|
110
|
+
schema="http",
|
|
111
|
+
hostname=None,
|
|
112
|
+
port=2905,
|
|
113
|
+
url=None,
|
|
114
|
+
scope=OPENC3_SCOPE,
|
|
115
|
+
):
|
|
116
|
+
api = CfdpApi(
|
|
117
|
+
timeout=api_timeout,
|
|
118
|
+
microservice_name=microservice_name,
|
|
119
|
+
prefix=prefix,
|
|
120
|
+
schema=schema,
|
|
121
|
+
hostname=hostname,
|
|
122
|
+
port=port,
|
|
123
|
+
url=url,
|
|
124
|
+
scope=scope,
|
|
125
|
+
)
|
|
126
|
+
continuation = api.subscribe(scope=scope) if timeout else None
|
|
127
|
+
transaction_ids = api.put_dir(
|
|
128
|
+
destination_entity_id=destination_entity_id,
|
|
129
|
+
source_directory_name=source_directory_name,
|
|
130
|
+
transmission_mode=transmission_mode,
|
|
131
|
+
closure_requested=closure_requested,
|
|
132
|
+
filestore_requests=filestore_requests,
|
|
133
|
+
fault_handler_overrides=fault_handler_overrides,
|
|
134
|
+
flow_label=flow_label,
|
|
135
|
+
segmentation_control=segmentation_control,
|
|
136
|
+
messages_to_user=messages_to_user,
|
|
137
|
+
remote_entity_id=remote_entity_id, # Used to indicate proxy put
|
|
138
|
+
scope=scope,
|
|
139
|
+
)
|
|
140
|
+
if not timeout:
|
|
141
|
+
return transaction_ids
|
|
142
|
+
indications = []
|
|
143
|
+
for transaction_id in transaction_ids:
|
|
144
|
+
indication_type = "Proxy-Put-Response" if remote_entity_id else "Transaction-Finished"
|
|
145
|
+
indication = cfdp_wait_for_indication(
|
|
146
|
+
api=api,
|
|
147
|
+
transaction_id=transaction_id,
|
|
148
|
+
indication_type=indication_type,
|
|
149
|
+
continuation=continuation,
|
|
150
|
+
timeout=timeout,
|
|
151
|
+
scope=scope,
|
|
152
|
+
)
|
|
153
|
+
indications.append([transaction_id, indication])
|
|
154
|
+
return transaction_ids, indications
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def cfdp_cancel(
|
|
158
|
+
transaction_id,
|
|
159
|
+
remote_entity_id=None,
|
|
160
|
+
timeout=600,
|
|
161
|
+
api_timeout=5,
|
|
162
|
+
microservice_name="CFDP",
|
|
163
|
+
prefix="/cfdp",
|
|
164
|
+
schema="http",
|
|
165
|
+
hostname=None,
|
|
166
|
+
port=2905,
|
|
167
|
+
url=None,
|
|
168
|
+
scope=OPENC3_SCOPE,
|
|
169
|
+
):
|
|
170
|
+
api = CfdpApi(
|
|
171
|
+
timeout=api_timeout,
|
|
172
|
+
microservice_name=microservice_name,
|
|
173
|
+
prefix=prefix,
|
|
174
|
+
schema=schema,
|
|
175
|
+
hostname=hostname,
|
|
176
|
+
port=port,
|
|
177
|
+
url=url,
|
|
178
|
+
scope=scope,
|
|
179
|
+
)
|
|
180
|
+
continuation = api.subscribe(scope=scope) if timeout else None
|
|
181
|
+
transaction_id = api.cancel(
|
|
182
|
+
transaction_id=transaction_id, remote_entity_id=remote_entity_id, scope=scope
|
|
183
|
+
)
|
|
184
|
+
indication = None
|
|
185
|
+
if transaction_id:
|
|
186
|
+
if timeout:
|
|
187
|
+
indication = cfdp_wait_for_indication(
|
|
188
|
+
api=api,
|
|
189
|
+
transaction_id=transaction_id,
|
|
190
|
+
indication_type="Transaction-Finished",
|
|
191
|
+
continuation=continuation,
|
|
192
|
+
timeout=timeout,
|
|
193
|
+
scope=scope,
|
|
194
|
+
)
|
|
195
|
+
if indication is None and remote_entity_id and timeout:
|
|
196
|
+
indication = cfdp_wait_for_indication(
|
|
197
|
+
api=api,
|
|
198
|
+
transaction_id=transaction_id,
|
|
199
|
+
indication_type="Proxy-Put-Response",
|
|
200
|
+
continuation=continuation,
|
|
201
|
+
timeout=timeout,
|
|
202
|
+
scope=scope,
|
|
203
|
+
)
|
|
204
|
+
return indication
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def cfdp_suspend(
|
|
208
|
+
transaction_id,
|
|
209
|
+
remote_entity_id=None,
|
|
210
|
+
timeout=600,
|
|
211
|
+
api_timeout=5,
|
|
212
|
+
microservice_name="CFDP",
|
|
213
|
+
prefix="/cfdp",
|
|
214
|
+
schema="http",
|
|
215
|
+
hostname=None,
|
|
216
|
+
port=2905,
|
|
217
|
+
url=None,
|
|
218
|
+
scope=OPENC3_SCOPE,
|
|
219
|
+
):
|
|
220
|
+
api = CfdpApi(
|
|
221
|
+
timeout=api_timeout,
|
|
222
|
+
microservice_name=microservice_name,
|
|
223
|
+
prefix=prefix,
|
|
224
|
+
schema=schema,
|
|
225
|
+
hostname=hostname,
|
|
226
|
+
port=port,
|
|
227
|
+
url=url,
|
|
228
|
+
scope=scope,
|
|
229
|
+
)
|
|
230
|
+
continuation = api.subscribe(scope=scope) if timeout else None
|
|
231
|
+
transaction_id = api.suspend(
|
|
232
|
+
transaction_id=transaction_id, remote_entity_id=remote_entity_id, scope=scope
|
|
233
|
+
)
|
|
234
|
+
indication = None
|
|
235
|
+
if transaction_id:
|
|
236
|
+
if not remote_entity_id and timeout:
|
|
237
|
+
indication = cfdp_wait_for_indication(
|
|
238
|
+
api=api,
|
|
239
|
+
transaction_id=transaction_id,
|
|
240
|
+
indication_type="Suspended",
|
|
241
|
+
continuation=continuation,
|
|
242
|
+
timeout=timeout,
|
|
243
|
+
scope=scope,
|
|
244
|
+
)
|
|
245
|
+
if indication is None and remote_entity_id and timeout:
|
|
246
|
+
indication = cfdp_wait_for_indication(
|
|
247
|
+
api=api,
|
|
248
|
+
transaction_id=transaction_id,
|
|
249
|
+
indication_type="Remote-Suspend-Response",
|
|
250
|
+
continuation=continuation,
|
|
251
|
+
timeout=timeout,
|
|
252
|
+
scope=scope,
|
|
253
|
+
)
|
|
254
|
+
return indication
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def cfdp_resume(
|
|
258
|
+
transaction_id,
|
|
259
|
+
remote_entity_id=None,
|
|
260
|
+
timeout=600,
|
|
261
|
+
api_timeout=5,
|
|
262
|
+
microservice_name="CFDP",
|
|
263
|
+
prefix="/cfdp",
|
|
264
|
+
schema="http",
|
|
265
|
+
hostname=None,
|
|
266
|
+
port=2905,
|
|
267
|
+
url=None,
|
|
268
|
+
scope=OPENC3_SCOPE,
|
|
269
|
+
):
|
|
270
|
+
api = CfdpApi(
|
|
271
|
+
timeout=api_timeout,
|
|
272
|
+
microservice_name=microservice_name,
|
|
273
|
+
prefix=prefix,
|
|
274
|
+
schema=schema,
|
|
275
|
+
hostname=hostname,
|
|
276
|
+
port=port,
|
|
277
|
+
url=url,
|
|
278
|
+
scope=scope,
|
|
279
|
+
)
|
|
280
|
+
continuation = api.subscribe(scope=scope) if timeout else None
|
|
281
|
+
transaction_id = api.resume(
|
|
282
|
+
transaction_id=transaction_id, remote_entity_id=remote_entity_id, scope=scope
|
|
283
|
+
)
|
|
284
|
+
indication = None
|
|
285
|
+
if transaction_id:
|
|
286
|
+
if not remote_entity_id and timeout:
|
|
287
|
+
indication = cfdp_wait_for_indication(
|
|
288
|
+
api=api,
|
|
289
|
+
transaction_id=transaction_id,
|
|
290
|
+
indication_type="Resumed",
|
|
291
|
+
continuation=continuation,
|
|
292
|
+
timeout=timeout,
|
|
293
|
+
scope=scope,
|
|
294
|
+
)
|
|
295
|
+
if indication is None and remote_entity_id and timeout:
|
|
296
|
+
indication = cfdp_wait_for_indication(
|
|
297
|
+
api=api,
|
|
298
|
+
transaction_id=transaction_id,
|
|
299
|
+
indication_type="Remote-Resume-Response",
|
|
300
|
+
continuation=continuation,
|
|
301
|
+
timeout=timeout,
|
|
302
|
+
scope=scope,
|
|
303
|
+
)
|
|
304
|
+
return indication
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def cfdp_report(
|
|
308
|
+
transaction_id,
|
|
309
|
+
remote_entity_id=None,
|
|
310
|
+
report_file_name=None,
|
|
311
|
+
timeout=600,
|
|
312
|
+
api_timeout=5,
|
|
313
|
+
microservice_name="CFDP",
|
|
314
|
+
prefix="/cfdp",
|
|
315
|
+
schema="http",
|
|
316
|
+
hostname=None,
|
|
317
|
+
port=2905,
|
|
318
|
+
url=None,
|
|
319
|
+
scope=OPENC3_SCOPE,
|
|
320
|
+
):
|
|
321
|
+
api = CfdpApi(
|
|
322
|
+
timeout=api_timeout,
|
|
323
|
+
microservice_name=microservice_name,
|
|
324
|
+
prefix=prefix,
|
|
325
|
+
schema=schema,
|
|
326
|
+
hostname=hostname,
|
|
327
|
+
port=port,
|
|
328
|
+
url=url,
|
|
329
|
+
scope=scope,
|
|
330
|
+
)
|
|
331
|
+
continuation = api.subscribe(scope=scope) if timeout else None
|
|
332
|
+
transaction_id = api.report(
|
|
333
|
+
transaction_id=transaction_id,
|
|
334
|
+
remote_entity_id=remote_entity_id,
|
|
335
|
+
report_file_name=report_file_name,
|
|
336
|
+
scope=scope,
|
|
337
|
+
)
|
|
338
|
+
indication = None
|
|
339
|
+
if transaction_id:
|
|
340
|
+
if not remote_entity_id and timeout:
|
|
341
|
+
indication = cfdp_wait_for_indication(
|
|
342
|
+
api=api,
|
|
343
|
+
transaction_id=transaction_id,
|
|
344
|
+
indication_type="Report",
|
|
345
|
+
continuation=continuation,
|
|
346
|
+
timeout=timeout,
|
|
347
|
+
scope=scope,
|
|
348
|
+
)
|
|
349
|
+
if indication is None and remote_entity_id and timeout:
|
|
350
|
+
indication = cfdp_wait_for_indication(
|
|
351
|
+
api=api,
|
|
352
|
+
transaction_id=transaction_id,
|
|
353
|
+
indication_type="Remote-Report-Response",
|
|
354
|
+
continuation=continuation,
|
|
355
|
+
timeout=timeout,
|
|
356
|
+
scope=scope,
|
|
357
|
+
)
|
|
358
|
+
return indication
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def cfdp_subscribe(
|
|
362
|
+
api_timeout=5,
|
|
363
|
+
microservice_name="CFDP",
|
|
364
|
+
prefix="/cfdp",
|
|
365
|
+
schema="http",
|
|
366
|
+
hostname=None,
|
|
367
|
+
port=2905,
|
|
368
|
+
url=None,
|
|
369
|
+
scope=OPENC3_SCOPE,
|
|
370
|
+
):
|
|
371
|
+
api = CfdpApi(
|
|
372
|
+
timeout=api_timeout,
|
|
373
|
+
microservice_name=microservice_name,
|
|
374
|
+
prefix=prefix,
|
|
375
|
+
schema=schema,
|
|
376
|
+
hostname=hostname,
|
|
377
|
+
port=port,
|
|
378
|
+
url=url,
|
|
379
|
+
scope=scope,
|
|
380
|
+
)
|
|
381
|
+
return api.subscribe(scope=scope)
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def cfdp_indications(
|
|
385
|
+
transaction_id=None,
|
|
386
|
+
indication_type=None,
|
|
387
|
+
continuation=None,
|
|
388
|
+
include_continuation=True,
|
|
389
|
+
timeout=None,
|
|
390
|
+
api_timeout=5,
|
|
391
|
+
limit=100,
|
|
392
|
+
microservice_name="CFDP",
|
|
393
|
+
prefix="/cfdp",
|
|
394
|
+
schema="http",
|
|
395
|
+
hostname=None,
|
|
396
|
+
port=2905,
|
|
397
|
+
url=None,
|
|
398
|
+
scope=OPENC3_SCOPE,
|
|
399
|
+
):
|
|
400
|
+
api = CfdpApi(
|
|
401
|
+
timeout=api_timeout,
|
|
402
|
+
microservice_name=microservice_name,
|
|
403
|
+
prefix=prefix,
|
|
404
|
+
schema=schema,
|
|
405
|
+
hostname=hostname,
|
|
406
|
+
port=port,
|
|
407
|
+
url=url,
|
|
408
|
+
scope=scope,
|
|
409
|
+
)
|
|
410
|
+
return cfdp_wait_for_indication(
|
|
411
|
+
api=api,
|
|
412
|
+
transaction_id=transaction_id,
|
|
413
|
+
indication_type=indication_type,
|
|
414
|
+
continuation=continuation,
|
|
415
|
+
include_continuation=include_continuation,
|
|
416
|
+
timeout=timeout,
|
|
417
|
+
limit=limit,
|
|
418
|
+
scope=scope,
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def cfdp_directory_listing(
|
|
423
|
+
remote_entity_id,
|
|
424
|
+
directory_name,
|
|
425
|
+
directory_file_name,
|
|
426
|
+
timeout=600,
|
|
427
|
+
api_timeout=5,
|
|
428
|
+
microservice_name="CFDP",
|
|
429
|
+
prefix="/cfdp",
|
|
430
|
+
schema="http",
|
|
431
|
+
hostname=None,
|
|
432
|
+
port=2905,
|
|
433
|
+
url=None,
|
|
434
|
+
scope=OPENC3_SCOPE,
|
|
435
|
+
):
|
|
436
|
+
api = CfdpApi(
|
|
437
|
+
timeout=api_timeout,
|
|
438
|
+
microservice_name=microservice_name,
|
|
439
|
+
prefix=prefix,
|
|
440
|
+
schema=schema,
|
|
441
|
+
hostname=hostname,
|
|
442
|
+
port=port,
|
|
443
|
+
url=url,
|
|
444
|
+
scope=scope,
|
|
445
|
+
)
|
|
446
|
+
continuation = api.subscribe(scope=scope) if timeout else None
|
|
447
|
+
transaction_id = api.directory_listing(
|
|
448
|
+
remote_entity_id=remote_entity_id,
|
|
449
|
+
directory_name=directory_name,
|
|
450
|
+
directory_file_name=directory_file_name,
|
|
451
|
+
scope=scope,
|
|
452
|
+
)
|
|
453
|
+
indications = []
|
|
454
|
+
if transaction_id:
|
|
455
|
+
if timeout:
|
|
456
|
+
indications.append(
|
|
457
|
+
cfdp_wait_for_indication(
|
|
458
|
+
api=api,
|
|
459
|
+
transaction_id=transaction_id,
|
|
460
|
+
indication_type="Transaction-Finished",
|
|
461
|
+
continuation=continuation,
|
|
462
|
+
timeout=timeout,
|
|
463
|
+
scope=scope,
|
|
464
|
+
)
|
|
465
|
+
)
|
|
466
|
+
if timeout:
|
|
467
|
+
indications.append(
|
|
468
|
+
cfdp_wait_for_indication(
|
|
469
|
+
api=api,
|
|
470
|
+
transaction_id=transaction_id,
|
|
471
|
+
indication_type="Directory-Listing-Response",
|
|
472
|
+
continuation=continuation,
|
|
473
|
+
timeout=timeout,
|
|
474
|
+
scope=scope,
|
|
475
|
+
)
|
|
476
|
+
)
|
|
477
|
+
return [indication for indication in indications if indication is not None]
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
def cfdp_transactions(
|
|
481
|
+
active=True,
|
|
482
|
+
api_timeout=5,
|
|
483
|
+
microservice_name="CFDP",
|
|
484
|
+
prefix="/cfdp",
|
|
485
|
+
schema="http",
|
|
486
|
+
hostname=None,
|
|
487
|
+
port=2905,
|
|
488
|
+
url=None,
|
|
489
|
+
scope=OPENC3_SCOPE,
|
|
490
|
+
):
|
|
491
|
+
api = CfdpApi(
|
|
492
|
+
timeout=api_timeout,
|
|
493
|
+
microservice_name=microservice_name,
|
|
494
|
+
prefix=prefix,
|
|
495
|
+
schema=schema,
|
|
496
|
+
hostname=hostname,
|
|
497
|
+
port=port,
|
|
498
|
+
url=url,
|
|
499
|
+
scope=scope,
|
|
500
|
+
)
|
|
501
|
+
return api.transactions(active=active, scope=scope)
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
# Helper methods
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def cfdp_wait_for_indication(
|
|
508
|
+
api,
|
|
509
|
+
transaction_id=None,
|
|
510
|
+
indication_type=None,
|
|
511
|
+
continuation=None,
|
|
512
|
+
include_continuation=False,
|
|
513
|
+
timeout=600,
|
|
514
|
+
limit=1000,
|
|
515
|
+
scope=OPENC3_SCOPE,
|
|
516
|
+
):
|
|
517
|
+
if timeout is None:
|
|
518
|
+
timeout = 0
|
|
519
|
+
start_time = time.time()
|
|
520
|
+
end_time = start_time + timeout
|
|
521
|
+
if not continuation:
|
|
522
|
+
continuation = "0-0"
|
|
523
|
+
done = False
|
|
524
|
+
while not done:
|
|
525
|
+
result = api.indications(
|
|
526
|
+
transaction_id=transaction_id, continuation=continuation, limit=limit, scope=scope
|
|
527
|
+
)
|
|
528
|
+
continuation = result["continuation"]
|
|
529
|
+
indications = result["indications"]
|
|
530
|
+
if indications and len(indications) > 0:
|
|
531
|
+
if not indication_type:
|
|
532
|
+
if include_continuation:
|
|
533
|
+
return indications, continuation
|
|
534
|
+
else:
|
|
535
|
+
return indications
|
|
536
|
+
for indication in indications:
|
|
537
|
+
if indication["indication_type"] == indication_type:
|
|
538
|
+
if include_continuation:
|
|
539
|
+
return indication, continuation
|
|
540
|
+
else:
|
|
541
|
+
return indication
|
|
542
|
+
if time.time() >= end_time:
|
|
543
|
+
if timeout > 0:
|
|
544
|
+
raise RuntimeError("CFDP Timeout")
|
|
545
|
+
done = True
|
|
546
|
+
if done:
|
|
547
|
+
break
|
|
548
|
+
wait_func = _get_wait()
|
|
549
|
+
if wait_func is not None:
|
|
550
|
+
wait_time = wait_func(1)
|
|
551
|
+
if wait_time < 1.0: # User hit go
|
|
552
|
+
break
|
|
553
|
+
else:
|
|
554
|
+
time.sleep(1)
|
|
555
|
+
if indication_type:
|
|
556
|
+
if include_continuation:
|
|
557
|
+
return None, continuation
|
|
558
|
+
else:
|
|
559
|
+
return None
|
|
560
|
+
else:
|
|
561
|
+
if include_continuation:
|
|
562
|
+
return [], continuation
|
|
563
|
+
else:
|
|
564
|
+
return []
|
data/lib/cfdp.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
2
|
|
|
3
|
-
# Copyright
|
|
3
|
+
# Copyright 2026 OpenC3, Inc.
|
|
4
4
|
# All Rights Reserved.
|
|
5
5
|
#
|
|
6
6
|
# Licensed for Evaluation and Educational Use
|
|
@@ -54,12 +54,56 @@ def cfdp_put(
|
|
|
54
54
|
remote_entity_id: remote_entity_id, # Used to indicate proxy put
|
|
55
55
|
scope: $openc3_scope)
|
|
56
56
|
return transaction_id unless timeout
|
|
57
|
-
|
|
58
|
-
indication = cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type:
|
|
59
|
-
indication ||= cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Proxy-Put-Response', continuation: continuation, timeout: timeout, scope: scope) if remote_entity_id and timeout
|
|
57
|
+
indication_type = remote_entity_id ? 'Proxy-Put-Response' : 'Transaction-Finished'
|
|
58
|
+
indication = cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: indication_type, continuation: continuation, timeout: timeout, scope: scope)
|
|
60
59
|
return transaction_id, indication
|
|
61
60
|
end
|
|
62
61
|
|
|
62
|
+
def cfdp_put_dir(
|
|
63
|
+
destination_entity_id:,
|
|
64
|
+
source_directory_name:,
|
|
65
|
+
closure_requested: nil,
|
|
66
|
+
transmission_mode: nil,
|
|
67
|
+
filestore_requests: [],
|
|
68
|
+
fault_handler_overrides: [],
|
|
69
|
+
flow_label: nil,
|
|
70
|
+
segmentation_control: "NOT_PRESERVED",
|
|
71
|
+
messages_to_user: [],
|
|
72
|
+
remote_entity_id: nil, # Used to indicate proxy put
|
|
73
|
+
timeout: 600,
|
|
74
|
+
api_timeout: 5,
|
|
75
|
+
microservice_name: 'CFDP',
|
|
76
|
+
prefix: '/cfdp',
|
|
77
|
+
schema: 'http',
|
|
78
|
+
hostname: nil,
|
|
79
|
+
port: 2905,
|
|
80
|
+
url: nil,
|
|
81
|
+
scope: $openc3_scope)
|
|
82
|
+
|
|
83
|
+
api = CfdpApi.new(timeout: api_timeout, microservice_name: microservice_name, prefix: prefix, schema: schema, hostname: hostname, port: port, url: url, scope: scope)
|
|
84
|
+
continuation = api.subscribe(scope: scope) if timeout
|
|
85
|
+
transaction_ids = api.put_dir(
|
|
86
|
+
destination_entity_id: destination_entity_id,
|
|
87
|
+
source_directory_name: source_directory_name,
|
|
88
|
+
transmission_mode: transmission_mode,
|
|
89
|
+
closure_requested: closure_requested,
|
|
90
|
+
filestore_requests: filestore_requests,
|
|
91
|
+
fault_handler_overrides: fault_handler_overrides,
|
|
92
|
+
flow_label: flow_label,
|
|
93
|
+
segmentation_control: segmentation_control,
|
|
94
|
+
messages_to_user: messages_to_user,
|
|
95
|
+
remote_entity_id: remote_entity_id, # Used to indicate proxy put
|
|
96
|
+
scope: $openc3_scope)
|
|
97
|
+
return transaction_ids unless timeout
|
|
98
|
+
indications = []
|
|
99
|
+
transaction_ids.each do |transaction_id|
|
|
100
|
+
indication_type = remote_entity_id ? 'Proxy-Put-Response' : 'Transaction-Finished'
|
|
101
|
+
indication = cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: indication_type, continuation: continuation, timeout: timeout, scope: scope)
|
|
102
|
+
indications << [transaction_id, indication]
|
|
103
|
+
end
|
|
104
|
+
return transaction_ids, indications
|
|
105
|
+
end
|
|
106
|
+
|
|
63
107
|
def cfdp_cancel(
|
|
64
108
|
transaction_id:,
|
|
65
109
|
remote_entity_id: nil,
|
|
@@ -76,8 +120,10 @@ def cfdp_cancel(
|
|
|
76
120
|
continuation = api.subscribe(scope: scope) if timeout
|
|
77
121
|
transaction_id = api.cancel(transaction_id: transaction_id, remote_entity_id: remote_entity_id, scope: scope)
|
|
78
122
|
indication = nil
|
|
79
|
-
|
|
80
|
-
|
|
123
|
+
if transaction_id
|
|
124
|
+
indication = cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Transaction-Finished', continuation: continuation, timeout: timeout, scope: scope) if timeout
|
|
125
|
+
indication ||= cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Proxy-Put-Response', continuation: continuation, timeout: timeout, scope: scope) if remote_entity_id and timeout
|
|
126
|
+
end
|
|
81
127
|
return indication
|
|
82
128
|
end
|
|
83
129
|
|
|
@@ -97,8 +143,10 @@ def cfdp_suspend(
|
|
|
97
143
|
continuation = api.subscribe(scope: scope) if timeout
|
|
98
144
|
transaction_id = api.suspend(transaction_id: transaction_id, remote_entity_id: remote_entity_id, scope: scope)
|
|
99
145
|
indication = nil
|
|
100
|
-
|
|
101
|
-
|
|
146
|
+
if transaction_id
|
|
147
|
+
indication = cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Suspended', continuation: continuation, timeout: timeout, scope: scope) if not remote_entity_id and timeout
|
|
148
|
+
indication ||= cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Remote-Suspend-Response', continuation: continuation, timeout: timeout, scope: scope) if remote_entity_id and timeout
|
|
149
|
+
end
|
|
102
150
|
return indication
|
|
103
151
|
end
|
|
104
152
|
|
|
@@ -118,8 +166,10 @@ def cfdp_resume(
|
|
|
118
166
|
continuation = api.subscribe(scope: scope) if timeout
|
|
119
167
|
transaction_id = api.resume(transaction_id: transaction_id, remote_entity_id: remote_entity_id, scope: scope)
|
|
120
168
|
indication = nil
|
|
121
|
-
|
|
122
|
-
|
|
169
|
+
if transaction_id
|
|
170
|
+
indication = cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Resumed', continuation: continuation, timeout: timeout, scope: scope) if not remote_entity_id and timeout
|
|
171
|
+
indication ||= cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Remote-Resume-Response', continuation: continuation, timeout: timeout, scope: scope) if remote_entity_id and timeout
|
|
172
|
+
end
|
|
123
173
|
return indication
|
|
124
174
|
end
|
|
125
175
|
|
|
@@ -140,8 +190,10 @@ def cfdp_report(
|
|
|
140
190
|
continuation = api.subscribe(scope: scope) if timeout
|
|
141
191
|
transaction_id = api.report(transaction_id: transaction_id, remote_entity_id: remote_entity_id, report_file_name: report_file_name, scope: scope)
|
|
142
192
|
indication = nil
|
|
143
|
-
|
|
144
|
-
|
|
193
|
+
if transaction_id
|
|
194
|
+
indication = cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Report', continuation: continuation, timeout: timeout, scope: scope) if not remote_entity_id and timeout
|
|
195
|
+
indication ||= cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Remote-Report-Response', continuation: continuation, timeout: timeout, scope: scope) if remote_entity_id and timeout
|
|
196
|
+
end
|
|
145
197
|
return indication
|
|
146
198
|
end
|
|
147
199
|
|
|
@@ -196,8 +248,10 @@ def cfdp_directory_listing(
|
|
|
196
248
|
continuation = api.subscribe(scope: scope) if timeout
|
|
197
249
|
transaction_id = api.directory_listing(remote_entity_id: remote_entity_id, directory_name: directory_name, directory_file_name: directory_file_name, scope: scope)
|
|
198
250
|
indications = []
|
|
199
|
-
|
|
200
|
-
|
|
251
|
+
if transaction_id
|
|
252
|
+
indications << cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Transaction-Finished', continuation: continuation, timeout: timeout, scope: scope) if timeout
|
|
253
|
+
indications << cfdp_wait_for_indication(api: api, transaction_id: transaction_id, indication_type: 'Directory-Listing-Response', continuation: continuation, timeout: timeout, scope: scope) if timeout
|
|
254
|
+
end
|
|
201
255
|
return indications.compact
|
|
202
256
|
end
|
|
203
257
|
|