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
data/lib/cfdp_api.rb ADDED
@@ -0,0 +1,204 @@
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/utilities/authentication'
18
+ require 'openc3/io/json_api'
19
+
20
+ # Usage:
21
+ #
22
+ # Note: Recommend using the methods in cfdp.rb rather than this file directly
23
+ #
24
+ # In ScriptRunner:
25
+ # require 'cfdp_api'
26
+ # api = CfdpApi.new
27
+ # api.put(...)
28
+ #
29
+ # Outside cluster - Open Source:
30
+ # require 'cfdp_api'
31
+ # $openc3_scope = 'DEFAULT'
32
+ # ENV['OPENC3_API_PASSWORD'] = 'password'
33
+ # api = CfdpApi.new(hostname: '127.0.0.1', port: 2900)
34
+ # api.put(...)
35
+ #
36
+ # Outside cluster - Enterprise
37
+ # require 'cfdp_api'
38
+ # $openc3_scope = 'DEFAULT'
39
+ # ENV['OPENC3_KEYCLOAK_URL'] = '127.0.0.1:2900'
40
+ # ENV['OPENC3_API_USER'] = 'operator'
41
+ # ENV['OPENC3_API_PASSWORD'] = 'operator'
42
+ # api = CfdpApi.new(hostname: '127.0.0.1', port: 2900)
43
+ # api.put(...)
44
+ #
45
+ class CfdpApi < OpenC3::JsonApi
46
+ def put(
47
+ destination_entity_id:,
48
+ source_file_name:,
49
+ destination_file_name:,
50
+ transmission_mode: nil,
51
+ closure_requested: nil,
52
+ filestore_requests: [],
53
+ fault_handler_overrides: [],
54
+ flow_label: nil,
55
+ segmentation_control: "NOT_PRESERVED",
56
+ messages_to_user: [],
57
+ remote_entity_id: nil, # Used to indicate proxy put
58
+ scope: $openc3_scope)
59
+
60
+ begin
61
+ endpoint = "/put"
62
+ data = {
63
+ "destination_entity_id" => destination_entity_id.to_i,
64
+ "source_file_name" => source_file_name,
65
+ "destination_file_name" => destination_file_name,
66
+ "transmission_mode" => transmission_mode,
67
+ "closure_requested" => closure_requested,
68
+ "filestore_requests" => filestore_requests,
69
+ "fault_handler_overrides" => fault_handler_overrides,
70
+ "messages_to_user" => messages_to_user,
71
+ "flow_label" => flow_label,
72
+ "segmentation_control" => segmentation_control
73
+ }
74
+ data["remote_entity_id"] = remote_entity_id.to_i if remote_entity_id
75
+ response = _request('post', endpoint, data: data, scope: scope)
76
+ if response.nil? || response.code != 200
77
+ if response
78
+ raise "CFDP put error: #{response.code}: #{response.body}"
79
+ else
80
+ raise "CFDP put failed"
81
+ end
82
+ end
83
+ return response.body
84
+ rescue => error
85
+ raise "CFDP put failed due to #{error.formatted}"
86
+ end
87
+ end
88
+
89
+ def cancel(transaction_id:, remote_entity_id: nil, scope: $openc3_scope)
90
+ transaction_id_post(method_name: "cancel", transaction_id: transaction_id, remote_entity_id: remote_entity_id, scope: $openc3_scope)
91
+ end
92
+
93
+ def suspend(transaction_id:, remote_entity_id: nil, scope: $openc3_scope)
94
+ transaction_id_post(method_name: "suspend", transaction_id: transaction_id, remote_entity_id: remote_entity_id, scope: $openc3_scope)
95
+ end
96
+
97
+ def resume(transaction_id:, remote_entity_id: nil, scope: $openc3_scope)
98
+ transaction_id_post(method_name: "resume", transaction_id: transaction_id, remote_entity_id: remote_entity_id, scope: $openc3_scope)
99
+ end
100
+
101
+ def report(transaction_id:, remote_entity_id: nil, report_file_name: nil, scope: $openc3_scope)
102
+ transaction_id_post(method_name: "report", transaction_id: transaction_id, remote_entity_id: remote_entity_id, report_file_name: report_file_name, scope: $openc3_scope)
103
+ end
104
+
105
+ def subscribe(scope: $openc3_scope)
106
+ begin
107
+ endpoint = "/subscribe"
108
+ response = _request('get', endpoint, scope: scope)
109
+ if response.nil? || response.code != 200
110
+ if response
111
+ raise "CFDP subscribe error: #{response.code}: #{response.body}"
112
+ else
113
+ raise "CFDP subscribe failed"
114
+ end
115
+ end
116
+ # Most recent topic id
117
+ return response.body
118
+ rescue => error
119
+ raise "CFDP subscribe failed due to #{error.formatted}"
120
+ end
121
+ end
122
+
123
+ def indications(transaction_id: nil, continuation: nil, limit: 100, scope: $openc3_scope)
124
+ begin
125
+ endpoint = "/indications"
126
+ endpoint << ('/' + transaction_id.to_s) if transaction_id
127
+ query = {}
128
+ query[:continuation] = continuation if continuation
129
+ query[:limit] = limit if limit
130
+ response = _request('get', endpoint, query: query, scope: scope)
131
+ if response.nil? || response.code != 200
132
+ if response
133
+ raise "CFDP indications error: #{response.code}: #{response.body}"
134
+ else
135
+ raise "CFDP indications failed"
136
+ end
137
+ end
138
+ # Hash of continuation, and indications array
139
+ return JSON.parse(response.body)
140
+ rescue => error
141
+ raise "CFDP indications failed due to #{error.formatted}"
142
+ end
143
+ end
144
+
145
+ def directory_listing(remote_entity_id:, directory_name:, directory_file_name:, scope: $openc3_scope)
146
+ begin
147
+ endpoint = "/directorylisting"
148
+ data = { "remote_entity_id" => remote_entity_id, "directory_name" => directory_name, "directory_file_name" => directory_file_name }
149
+ response = _request('post', endpoint, data: data, scope: scope)
150
+ if response.nil? || response.code != 200
151
+ if response
152
+ raise "CFDP directory listing error: #{response.code}: #{response.body}"
153
+ else
154
+ raise "CFDP directory listing failed"
155
+ end
156
+ end
157
+ return response.body
158
+ rescue => error
159
+ raise "CFDP directory listing failed due to #{error.formatted}"
160
+ end
161
+ end
162
+
163
+ def transactions(active: true, scope: $openc3_scope)
164
+ begin
165
+ endpoint = "/transactions"
166
+ query = {}
167
+ query[:active] = active if active
168
+ response = _request('get', endpoint, query: query, scope: scope)
169
+ if response.nil? || response.code != 200
170
+ if response
171
+ raise "CFDP transactions error: #{response.code}: #{response.body}"
172
+ else
173
+ raise "CFDP transactions failed"
174
+ end
175
+ end
176
+ # Array of Transaction Hashes
177
+ return JSON.parse(response.body)
178
+ rescue => error
179
+ raise "CFDP transactions failed due to #{error.formatted}"
180
+ end
181
+ end
182
+
183
+ # private
184
+
185
+ def transaction_id_post(method_name:, transaction_id:, remote_entity_id: nil, report_file_name: nil, scope: $openc3_scope)
186
+ begin
187
+ endpoint = "/#{method_name}"
188
+ data = { "transaction_id" => transaction_id.to_s }
189
+ data['remote_entity_id'] = remote_entity_id if remote_entity_id
190
+ data['report_file_name'] = report_file_name if report_file_name
191
+ response = _request('post', endpoint, data: data, scope: scope)
192
+ if response.nil? || response.code != 200
193
+ if response
194
+ raise "CFDP #{method_name} error: #{response.code}: #{response.body}"
195
+ else
196
+ raise "CFDP #{method_name} failed"
197
+ end
198
+ end
199
+ return response.body
200
+ rescue => error
201
+ raise "CFDP #{method_name} failed due to #{error.formatted}"
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,37 @@
1
+ source ENV['RUBYGEMS_URL'] || "https://rubygems.org"
2
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
+
4
+ # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
5
+ gem 'rails', '>= 7.0.0'
6
+
7
+ # Reduces boot times through caching; required in config/boot.rb
8
+ gem 'bootsnap', '>= 1.9.3', require: false
9
+
10
+ # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
11
+ gem 'rack-cors', '>= 1.1'
12
+
13
+ # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
14
+ gem 'tzinfo-data'
15
+
16
+ # Run against this stable release
17
+ group :development, :test do
18
+ gem 'rspec-rails', '~> 6.0'
19
+ gem 'simplecov', '~> 0.20'
20
+ gem 'simplecov-cobertura', '~> 2.1'
21
+ end
22
+
23
+ group :test do
24
+ gem 'mock_redis'
25
+ end
26
+
27
+ if ENV['OPENC3_DEVEL']
28
+ gem 'openc3', :path => ENV['OPENC3_DEVEL']
29
+ elsif ENV['OPENC3_PATH']
30
+ gem 'openc3', :path => ENV['OPENC3_PATH']
31
+ else
32
+ gem 'openc3', '>= 5.4.2.pre'
33
+ end
34
+
35
+ if ENV['OPENC3_ENTERPRISE_TAG']
36
+ gem 'openc3-enterprise', '>= 5.4.2.pre'
37
+ end
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require_relative 'config/application'
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,46 @@
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/utilities/authorization'
18
+
19
+ class ApplicationController < ActionController::API
20
+ include OpenC3::Authorization
21
+
22
+ private
23
+
24
+ # Authorize and rescue the possible execeptions
25
+ # @return [Boolean] true if authorize successful
26
+ def authorization(permission, target_name: nil, packet_name: nil, interface_name: nil, router_name: nil)
27
+ begin
28
+ authorize(
29
+ permission: permission,
30
+ target_name: target_name,
31
+ packet_name: packet_name,
32
+ interface_name: interface_name,
33
+ router_name: router_name,
34
+ scope: params[:scope],
35
+ token: request.headers['HTTP_AUTHORIZATION'],
36
+ )
37
+ rescue OpenC3::AuthError => e
38
+ render(json: { status: 'error', message: e.message }, status: 401) and
39
+ return false
40
+ rescue OpenC3::ForbiddenError => e
41
+ render(json: { status: 'error', message: e.message }, status: 403) and
42
+ return false
43
+ end
44
+ true
45
+ end
46
+ end
@@ -0,0 +1,222 @@
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/config/config_parser'
18
+
19
+ class CfdpController < ApplicationController
20
+ # Put.request (destination CFDP entity ID,
21
+ # [source file name],
22
+ # [destination file name],
23
+ # [segmentation control], # Not supported
24
+ # [fault handler overrides],
25
+ # [flow label], # Not supported
26
+ # [transmission mode],
27
+ # [closure requested],
28
+ # [messages to user],
29
+ # [filestore requests])
30
+ def put
31
+ params.require([:destination_entity_id])
32
+ return unless check_authorization()
33
+ transaction = $cfdp_user.start_source_transaction(params)
34
+ render json: transaction.id
35
+ rescue ActionController::ParameterMissing => error
36
+ render :json => { :status => 'error', :message => error.message }, :status => 400
37
+ rescue => error
38
+ render :json => { :status => 'error', :message => error.message }, :status => 500
39
+ end
40
+
41
+ # Cancel.request (transaction ID)
42
+ def cancel
43
+ params.require([:transaction_id])
44
+ return unless check_authorization()
45
+ transaction = $cfdp_user.cancel(params)
46
+ if transaction
47
+ render json: transaction.id
48
+ else
49
+ render :json => { :status => 'error', :message => "Transaction #{params[:transaction_id]} not found" }, :status => 404
50
+ end
51
+ rescue => error
52
+ render :json => { :status => 'error', :message => error.message }, :status => 500
53
+ end
54
+
55
+ # Suspend.request (transaction ID)
56
+ def suspend
57
+ params.require([:transaction_id])
58
+ return unless check_authorization()
59
+ transaction = $cfdp_user.suspend(params)
60
+ if transaction
61
+ render json: transaction.id
62
+ else
63
+ render :json => { :status => 'error', :message => "Transaction #{params[:transaction_id]} not found" }, :status => 404
64
+ end
65
+ rescue => error
66
+ render :json => { :status => 'error', :message => error.message }, :status => 500
67
+ end
68
+
69
+ # Resume.request (transaction ID)
70
+ def resume
71
+ params.require([:transaction_id])
72
+ return unless check_authorization()
73
+ transaction = $cfdp_user.resume(params)
74
+ if transaction
75
+ render json: transaction.id
76
+ else
77
+ render :json => { :status => 'error', :message => "Transaction #{params[:transaction_id]} not found" }, :status => 404
78
+ end
79
+ rescue => error
80
+ render :json => { :status => 'error', :message => error.message }, :status => 500
81
+ end
82
+
83
+ # Report.request (transaction ID)
84
+ def report
85
+ params.require([:transaction_id])
86
+ return unless check_authorization()
87
+ transaction = $cfdp_user.report(params)
88
+ if transaction
89
+ render json: transaction.id
90
+ else
91
+ render :json => { :status => 'error', :message => "Transaction #{params[:transaction_id]} not found" }, :status => 404
92
+ end
93
+ rescue => error
94
+ render :json => { :status => 'error', :message => error.message }, :status => 500
95
+ end
96
+
97
+ def directory_listing
98
+ params.require([:remote_entity_id, :directory_name, :directory_file_name])
99
+ return unless check_authorization()
100
+ transaction = $cfdp_user.start_directory_listing(params)
101
+ render json: transaction.id
102
+ rescue ActionController::ParameterMissing => error
103
+ render :json => { :status => 'error', :message => error.message }, :status => 400
104
+ rescue => error
105
+ render :json => { :status => 'error', :message => error.message }, :status => 500
106
+ end
107
+
108
+ def subscribe
109
+ return unless check_authorization()
110
+ result = CfdpTopic.subscribe_indications
111
+ render json: result
112
+ rescue => error
113
+ render :json => { :status => 'error', :message => error.message }, :status => 500
114
+ end
115
+
116
+ # Transaction.indication (transaction ID)
117
+ # EOF-Sent.indication (transaction ID)
118
+ # Transaction-Finished.indication (transaction ID,
119
+ # [filestore responses],
120
+ # [status report],
121
+ # condition code,
122
+ # file status,
123
+ # delivery code)
124
+ # Metadata-Recv.indication (transaction ID,
125
+ # source CFDP entity ID,
126
+ # [file size],
127
+ # [source file name],
128
+ # [destination file name],
129
+ # [messages to user])
130
+ # File-Segment-Recv.indication (transaction ID,
131
+ # offset,
132
+ # length,
133
+ # [record continuation state,
134
+ # length of segment metadata,
135
+ # segment metadata])
136
+ # Suspended.indication (transaction ID,
137
+ # condition code)
138
+ # Resumed.indication (transaction ID,
139
+ # progress)
140
+ # Report.indication (transaction ID,
141
+ # status report)
142
+ # Fault.indication (transaction ID,
143
+ # condition code,
144
+ # progress)
145
+ # Abandoned.indication (transaction ID,
146
+ # condition code,
147
+ # progress)
148
+ # EOF-Recv.indication (transaction ID)
149
+ def indications
150
+ return unless check_authorization()
151
+ result = CfdpTopic.read_indications(transaction_id: params[:transaction_id], continuation: params[:continuation], limit: params[:limit])
152
+ render json: result
153
+ rescue => error
154
+ render :json => { :status => 'error', :message => error.message }, :status => 500
155
+ end
156
+
157
+ def transactions
158
+ return unless check_authorization()
159
+ active = false
160
+ active = true if OpenC3::ConfigParser.handle_true_false_nil(params[:active])
161
+ result = []
162
+ transactions = CfdpMib.transactions.dup
163
+ transactions.each do |t_id, t|
164
+ if not active or t.transaction_status == "ACTIVE"
165
+ result << t
166
+ end
167
+ end
168
+ result = result.sort {|a, b| a.id <=> b.id}
169
+ render json: result
170
+ rescue => error
171
+ render :json => { :status => 'error', :message => error.message }, :status => 500
172
+ end
173
+
174
+ # private
175
+
176
+ def check_authorization
177
+ cmd_entity_id = nil
178
+ cmd_entity = nil
179
+
180
+ if params[:remote_entity_id]
181
+ if params[:remote_entity_id].to_i.to_s != params[:remote_entity_id].to_s
182
+ render :json => { :status => 'error', :message => "remote_entity_id must be numeric" }, :status => 400
183
+ return false
184
+ end
185
+ cmd_entity_id = Integer(params[:remote_entity_id])
186
+ cmd_entity = CfdpMib.entity(cmd_entity_id)
187
+ elsif params[:destination_entity_id]
188
+ if params[:destination_entity_id].to_i.to_s != params[:destination_entity_id].to_s
189
+ render :json => { :status => 'error', :message => "destination_entity_id must be numeric" }, :status => 400
190
+ return
191
+ end
192
+ cmd_entity_id = Integer(params[:destination_entity_id])
193
+ cmd_entity = CfdpMib.entity(cmd_entity_id)
194
+ else
195
+ cmd_entity_id = CfdpMib.source_entity_id
196
+ cmd_entity = CfdpMib.entity(cmd_entity_id)
197
+ end
198
+
199
+ if cmd_entity
200
+ target_name, packet_name, item_name = cmd_entity["cmd_info"]
201
+ unless target_name and packet_name and item_name
202
+ tlm_packets = cmd_entity["tlm_info"]
203
+ tlm_packets ||= []
204
+ target_name, packet_name, item_name = tlm_packets[0]
205
+ end
206
+ if target_name and packet_name and item_name
207
+ # Caller must be able to send this command
208
+ return false unless authorization('cmd', target_name: target_name, packet_name: packet_name)
209
+ else
210
+ render :json => { :status => 'error', :message => "info not configured for entity: #{cmd_entity_id}" }, :status => 400
211
+ return false
212
+ end
213
+ else
214
+ render :json => { :status => 'error', :message => "Unknown entity: #{cmd_entity_id}" }, :status => 400
215
+ return false
216
+ end
217
+
218
+ # Authorized
219
+ return true
220
+ end
221
+
222
+ end
@@ -0,0 +1,52 @@
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 CfdpChecksum
18
+ def initialize
19
+ @checksum = 0
20
+ end
21
+
22
+ def add(offset, data)
23
+ front_pad_bytes = offset % 4
24
+ if front_pad_bytes != 0
25
+ data = ("\x00" * front_pad_bytes) << data
26
+ end
27
+ end_pad_bytes = 4 - data.length % 4
28
+ if end_pad_bytes != 4
29
+ data = data + ("\x00" * end_pad_bytes)
30
+ end
31
+ values = data.unpack('N*')
32
+ values.each do |value|
33
+ @checksum += value
34
+ end
35
+ return @checksum
36
+ end
37
+
38
+ # Expected to be calculated as we go using add, so file unused
39
+ def checksum(file, full_checksum_needed)
40
+ if full_checksum_needed
41
+ file.rewind
42
+ data = file.read
43
+ @checksum = 0
44
+ add(0, data)
45
+ end
46
+ return @checksum & 0xFFFFFFFF
47
+ end
48
+
49
+ def check(file, other_checksum, full_checksum_needed)
50
+ checksum(file, full_checksum_needed) == other_checksum
51
+ end
52
+ end
@@ -0,0 +1,41 @@
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/utilities/crc'
18
+
19
+ class CfdpCrcChecksum
20
+ def initialize(poly, seed, xor, reflect)
21
+ @crc = OpenC3::Crc32.new(poly, seed, xor, reflect)
22
+ @checksum = 0
23
+ end
24
+
25
+ # Incremental not supported so add ignored
26
+ def add(offset, data)
27
+ return 0
28
+ end
29
+
30
+ # Uses file because incremental add is not supported
31
+ def checksum(file, full_checksum_needed)
32
+ file.rewind
33
+ data = file.read
34
+ @checksum = @crc.calc(data)
35
+ return @checksum & 0xFFFFFFFF
36
+ end
37
+
38
+ def check(file, other_checksum, full_checksum_needed)
39
+ checksum(file, full_checksum_needed) == other_checksum
40
+ end
41
+ end