cosmos 4.4.1 → 4.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_v4.yml +33 -0
  3. data/Dockerfile +10 -4
  4. data/Gemfile +1 -1
  5. data/Manifest.txt +26 -2
  6. data/README.md +4 -1
  7. data/Rakefile +33 -27
  8. data/autohotkey/tools/cmd_extractor.ahk +11 -9
  9. data/autohotkey/tools/cmd_sender.ahk +1 -1
  10. data/autohotkey/tools/cmd_sequence.ahk +1 -1
  11. data/autohotkey/tools/data_viewer.ahk +1 -1
  12. data/autohotkey/tools/limits_monitor.ahk +1 -1
  13. data/autohotkey/tools/packet_viewer.ahk +1 -1
  14. data/autohotkey/tools/script_runner.ahk +1 -1
  15. data/autohotkey/tools/test_runner2.ahk +1 -1
  16. data/autohotkey/tools/tlm_grapher.ahk +1 -1
  17. data/autohotkey/tools/tlm_grapher3.ahk +1 -1
  18. data/autohotkey/tools/tlm_viewer.ahk +1 -1
  19. data/autohotkey/tools/tlm_viewer2.ahk +1 -1
  20. data/autohotkey/tools/tlm_viewer5.ahk +1 -1
  21. data/bin/rubysloc +73 -28
  22. data/bin/xtce_converter +1 -1
  23. data/cosmos.gemspec +6 -12
  24. data/data/config/interface_modifiers.yaml +3 -2
  25. data/data/config/system.yaml +81 -24
  26. data/data/crc.txt +435 -435
  27. data/demo/Rakefile +4 -4
  28. data/demo/config/data/crc.txt +250 -250
  29. data/demo/config/system/system.txt +15 -7
  30. data/demo/config/system/system2.txt +15 -7
  31. data/demo/config/system/system_alt_ports.txt +15 -7
  32. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +1 -1
  33. data/demo/config/tools/handbook_creator/default_toc.xsl +59 -59
  34. data/ext/cosmos/ext/buffered_file/buffered_file.c +2 -2
  35. data/ext/cosmos/ext/config_parser/config_parser.c +1 -2
  36. data/ext/cosmos/ext/line_graph/line_graph.c +53 -94
  37. data/ext/cosmos/ext/packet/packet.c +0 -6
  38. data/ext/cosmos/ext/platform/platform.c +56 -21
  39. data/ext/cosmos/ext/polynomial_conversion/polynomial_conversion.c +4 -8
  40. data/ext/cosmos/ext/structure/structure.c +12 -0
  41. data/extensions/vscode/.gitignore +4 -0
  42. data/extensions/vscode/.vscode/launch.json +32 -0
  43. data/extensions/vscode/.vscode/settings.json +13 -0
  44. data/extensions/vscode/.vscode/tasks.json +79 -0
  45. data/extensions/vscode/License.txt +879 -0
  46. data/extensions/vscode/README.md +9 -0
  47. data/extensions/vscode/client/License.txt +879 -0
  48. data/extensions/vscode/client/README.md +39 -0
  49. data/extensions/vscode/client/cosmos.configuration.json +23 -0
  50. data/extensions/vscode/client/images/icon.png +0 -0
  51. data/extensions/vscode/client/package-lock.json +414 -0
  52. data/extensions/vscode/client/package.json +105 -0
  53. data/extensions/vscode/client/src/extension.ts +132 -0
  54. data/extensions/vscode/client/src/screen_preview.rb +25 -0
  55. data/extensions/vscode/client/syntaxes/cosmos.tmLanguage.json +219 -0
  56. data/extensions/vscode/client/tsconfig.json +17 -0
  57. data/extensions/vscode/package-lock.json +26 -0
  58. data/extensions/vscode/package.json +35 -0
  59. data/extensions/vscode/server/License.txt +879 -0
  60. data/extensions/vscode/server/package-lock.json +236 -0
  61. data/extensions/vscode/server/package.json +29 -0
  62. data/extensions/vscode/server/src/server.ts +59 -0
  63. data/extensions/vscode/server/tsconfig.json +16 -0
  64. data/install/Rakefile +4 -4
  65. data/install/config/data/crc.txt +145 -145
  66. data/install/config/system/system.txt +15 -7
  67. data/install/config/tools/handbook_creator/default_toc.xsl +59 -59
  68. data/lib/cosmos/config/config_parser.rb +2 -10
  69. data/lib/cosmos/core_ext/class.rb +10 -0
  70. data/lib/cosmos/core_ext/time.rb +5 -3
  71. data/lib/cosmos/dart/examples/dart_decom_client.rb +1 -1
  72. data/lib/cosmos/dart/lib/dart_common.rb +3 -3
  73. data/lib/cosmos/dart/lib/dart_decommutator.rb +4 -4
  74. data/lib/cosmos/dart/processes/dart_decom_server.rb +1 -1
  75. data/lib/cosmos/dart/processes/dart_master.rb +1 -1
  76. data/lib/cosmos/dart/spec/dart/dart_database_cleaner_spec.rb +2 -2
  77. data/lib/cosmos/gui/qt.rb +10 -10
  78. data/lib/cosmos/gui/qt_tool.rb +17 -12
  79. data/lib/cosmos/gui/text/completion_text_edit.rb +2 -0
  80. data/lib/cosmos/gui/widgets/dart_meta_frame.rb +1 -1
  81. data/lib/cosmos/interfaces/dart_status_interface.rb +1 -1
  82. data/lib/cosmos/interfaces/linc_interface.rb +3 -3
  83. data/lib/cosmos/interfaces/protocols/burst_protocol.rb +1 -1
  84. data/lib/cosmos/interfaces/protocols/crc_protocol.rb +1 -1
  85. data/lib/cosmos/interfaces/protocols/template_protocol.rb +3 -3
  86. data/lib/cosmos/interfaces/serial_interface.rb +7 -1
  87. data/lib/cosmos/interfaces/stream_interface.rb +1 -1
  88. data/lib/cosmos/interfaces/tcpip_server_interface.rb +16 -16
  89. data/lib/cosmos/io/io_multiplexer.rb +6 -2
  90. data/lib/cosmos/io/json_drb.rb +3 -11
  91. data/lib/cosmos/io/json_drb_object.rb +7 -2
  92. data/lib/cosmos/io/json_drb_rack.rb +25 -5
  93. data/lib/cosmos/io/json_rpc.rb +1 -1
  94. data/lib/cosmos/io/posix_serial_driver.rb +60 -22
  95. data/lib/cosmos/io/serial_driver.rb +11 -8
  96. data/lib/cosmos/io/win32_serial_driver.rb +8 -1
  97. data/lib/cosmos/packets/packet.rb +8 -8
  98. data/lib/cosmos/packets/packet_config.rb +1 -1
  99. data/lib/cosmos/packets/packet_item_limits.rb +2 -14
  100. data/lib/cosmos/packets/parsers/xtce_converter.rb +10 -10
  101. data/lib/cosmos/packets/parsers/xtce_parser.rb +3 -0
  102. data/lib/cosmos/packets/structure.rb +18 -5
  103. data/lib/cosmos/packets/structure_item.rb +4 -21
  104. data/lib/cosmos/script/api_shared.rb +18 -1
  105. data/lib/cosmos/script/extract.rb +1 -1
  106. data/lib/cosmos/script/script.rb +4 -11
  107. data/lib/cosmos/streams/serial_stream.rb +11 -6
  108. data/lib/cosmos/system/system.rb +47 -13
  109. data/lib/cosmos/tools/cmd_sender/cmd_param_table_item_delegate.rb +15 -0
  110. data/lib/cosmos/tools/cmd_sender/cmd_params.rb +25 -3
  111. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +7 -0
  112. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +0 -5
  113. data/lib/cosmos/tools/cmd_tlm_server/api.rb +10 -8
  114. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +2 -2
  115. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +1 -1
  116. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +29 -26
  117. data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +1 -1
  118. data/lib/cosmos/tools/cmd_tlm_server/router_thread.rb +5 -0
  119. data/lib/cosmos/tools/config_editor/config_editor.rb +1 -1
  120. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +1 -1
  121. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +1 -1
  122. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +5 -2
  123. data/lib/cosmos/tools/test_runner/test.rb +1 -1
  124. data/lib/cosmos/tools/test_runner/test_runner.rb +4 -4
  125. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +3 -3
  126. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +1 -4
  127. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +3 -3
  128. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_dart_thread.rb +1 -1
  129. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +2 -2
  130. data/lib/cosmos/tools/tlm_viewer/widgets/canvasdot_widget.rb +2 -0
  131. data/lib/cosmos/top_level.rb +1 -1
  132. data/lib/cosmos/utilities/simulated_target.rb +1 -1
  133. data/lib/cosmos/version.rb +5 -5
  134. data/make_gems.sh +1 -1
  135. data/spec/core_ext/class_spec.rb +54 -0
  136. data/spec/core_ext/time_spec.rb +4 -0
  137. data/spec/gui/qt_spec.rb +1 -1
  138. data/spec/gui/utilities/script_module_gui_spec.rb +1 -1
  139. data/spec/interfaces/linc_interface_spec.rb +1 -1
  140. data/spec/interfaces/serial_interface_spec.rb +1 -5
  141. data/spec/io/json_drb_rack_spec.rb +166 -0
  142. data/spec/io/json_rpc_spec.rb +4 -5
  143. data/spec/io/posix_serial_driver_spec.rb +87 -0
  144. data/spec/io/win32_serial_driver_spec.rb +17 -1
  145. data/spec/packet_logs/packet_log_reader_spec.rb +34 -35
  146. data/spec/packets/packet_item_limits_spec.rb +6 -33
  147. data/spec/packets/structure_item_spec.rb +3 -21
  148. data/spec/script/extract_spec.rb +4 -1
  149. data/spec/system/system_spec.rb +109 -1
  150. data/spec/tools/cmd_tlm_server/api_spec.rb +12 -12
  151. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +2 -2
  152. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +4 -3
  153. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +2 -3
  154. data/spec/top_level/top_level_spec.rb +2 -2
  155. data/spec/utilities/logger_spec.rb +3 -3
  156. data/test/performance/Rakefile +4 -4
  157. data/test/performance/config/data/crc.txt +67 -48
  158. metadata +59 -9
  159. data/.coveralls.yml +0 -1
  160. data/.travis.yml +0 -16
@@ -76,9 +76,18 @@ module Cosmos
76
76
  instance_attr_reader :classificiation_banner
77
77
  # @return [String] Which hashing algorithm is in use
78
78
  instance_attr_reader :hashing_algorithm
79
+ # @return [Boolean] Allow router commanding - defaults to false
80
+ instance_attr_reader :allow_router_commanding
81
+ # @return [String] API access secret using X-Csrf-Token - defaults to SuperSecret
82
+ instance_attr_reader :x_csrf_token
83
+ # @return [Array<String>] Allowed origins in http origin header - defaults to no origin header only
84
+ instance_attr_reader :allowed_origins
85
+ # @return [Array<String>] Allowed hosts in http host header - defaults to '127.0.0.1:7777' only
86
+ instance_attr_reader :allowed_hosts
79
87
 
80
88
  # Known COSMOS ports
81
89
  KNOWN_PORTS = ['CTS_API', 'TLMVIEWER_API', 'CTS_PREIDENTIFIED', 'CTS_CMD_ROUTER', 'REPLAY_API', 'REPLAY_PREIDENTIFIED', 'REPLAY_CMD_ROUTER', 'DART_STREAM', 'DART_DECOM', 'DART_MASTER']
90
+ API_PORTS = ['CTS_API', 'TLMVIEWER_API', 'REPLAY_API', 'DART_DECOM', 'DART_MASTER']
82
91
  # Known COSMOS hosts
83
92
  KNOWN_HOSTS = ['CTS_API', 'TLMVIEWER_API', 'CTS_PREIDENTIFIED', 'CTS_CMD_ROUTER', 'REPLAY_API', 'REPLAY_PREIDENTIFIED', 'REPLAY_CMD_ROUTER', 'DART_STREAM', 'DART_DECOM', 'DART_MASTER']
84
93
  # Known COSMOS paths
@@ -88,6 +97,7 @@ module Cosmos
88
97
 
89
98
  @@instance = nil
90
99
  @@instance_mutex = Mutex.new
100
+ @@instance_filename = nil
91
101
 
92
102
  # Create a new System object. Note, this should not be called directly but
93
103
  # you should instead use System.instance and treat this class as a
@@ -97,6 +107,7 @@ module Cosmos
97
107
  # read. Be default this is <Cosmos::USERPATH>/config/system/system.txt
98
108
  def initialize(filename = nil)
99
109
  raise "Cosmos::System created twice" unless @@instance.nil?
110
+ @@instance_filename = filename
100
111
  reset_variables(filename)
101
112
  @@instance = self
102
113
  end
@@ -217,6 +228,7 @@ module Cosmos
217
228
  parser.verify_num_parameters(2, 2, usage)
218
229
  port_name = parameters[0].to_s.upcase
219
230
  @ports[port_name] = Integer(parameters[1])
231
+ @allowed_hosts << "127.0.0.1:#{parameters[1]}" if API_PORTS.include?(port_name)
220
232
  Logger.warn("Unknown port name given: #{port_name}") unless KNOWN_PORTS.include?(port_name)
221
233
 
222
234
  when 'LISTEN_HOST', 'CONNECT_HOST'
@@ -373,6 +385,22 @@ module Cosmos
373
385
  @classificiation_banner = {'display_text' => parameters[0],
374
386
  'color' => color}
375
387
 
388
+ when 'ALLOW_ROUTER_COMMANDING'
389
+ parser.verify_num_parameters(0, 0, "#{keyword}")
390
+ @allow_router_commanding = true
391
+
392
+ when 'X_CSRF_TOKEN'
393
+ parser.verify_num_parameters(1, 1, "#{keyword} <Token>")
394
+ @x_csrf_token = ConfigParser.handle_nil(parameters[0])
395
+
396
+ when 'ALLOW_ORIGIN'
397
+ parser.verify_num_parameters(1, 1, "#{keyword} <Origin>")
398
+ @allowed_origins << parameters[0]
399
+
400
+ when 'ALLOW_HOST'
401
+ parser.verify_num_parameters(1, 1, "#{keyword} <Host:Port>")
402
+ @allowed_hosts << parameters[0]
403
+
376
404
  else
377
405
  # blank lines will have a nil keyword and should not raise an exception
378
406
  raise parser.error("Unknown keyword '#{keyword}'") if keyword
@@ -521,7 +549,7 @@ module Cosmos
521
549
  # Zip file configuration so unzip and reset configuration path
522
550
  configuration = unzip(configuration)
523
551
  end
524
-
552
+
525
553
  Logger.info "Switching to configuration: #{name}"
526
554
  process_file(File.join(configuration, 'system.txt'), configuration)
527
555
  load_packets(name, false)
@@ -547,7 +575,7 @@ module Cosmos
547
575
  Logger.info "Switching to initial configuration: #{@initial_config.name}"
548
576
  update_config(@initial_config)
549
577
  end
550
-
578
+
551
579
  return @config.name, nil
552
580
  end
553
581
  end
@@ -596,16 +624,14 @@ module Cosmos
596
624
  @listen_hosts = {}
597
625
  @listen_hosts['CTS_API'] = '127.0.0.1'
598
626
  @listen_hosts['TLMVIEWER_API'] = '127.0.0.1'
599
- # Localhost would be more secure but historically these are open to allow for chaining servers by default
600
- @listen_hosts['CTS_PREIDENTIFIED'] = '0.0.0.0'
601
- @listen_hosts['CTS_CMD_ROUTER'] = '0.0.0.0'
627
+ @listen_hosts['CTS_PREIDENTIFIED'] = '127.0.0.1'
628
+ @listen_hosts['CTS_CMD_ROUTER'] = '127.0.0.1'
602
629
  @listen_hosts['REPLAY_API'] = '127.0.0.1'
603
- # Localhost would be more secure but historically these are open to allow for chaining servers by default
604
- @listen_hosts['REPLAY_PREIDENTIFIED'] = '0.0.0.0'
605
- @listen_hosts['REPLAY_CMD_ROUTER'] = '0.0.0.0'
606
- @listen_hosts['DART_STREAM'] = '0.0.0.0'
607
- @listen_hosts['DART_DECOM'] = '0.0.0.0'
608
- @listen_hosts['DART_MASTER'] = '0.0.0.0'
630
+ @listen_hosts['REPLAY_PREIDENTIFIED'] = '127.0.0.1'
631
+ @listen_hosts['REPLAY_CMD_ROUTER'] = '127.0.0.1'
632
+ @listen_hosts['DART_STREAM'] = '127.0.0.1'
633
+ @listen_hosts['DART_DECOM'] = '127.0.0.1'
634
+ @listen_hosts['DART_MASTER'] = '127.0.0.1'
609
635
 
610
636
  @connect_hosts = {}
611
637
  @connect_hosts['CTS_API'] = '127.0.0.1'
@@ -630,6 +656,11 @@ module Cosmos
630
656
  @paths['DART_DATA'] = File.join(USERPATH, 'outputs', 'dart', 'data')
631
657
  @paths['DART_LOGS'] = File.join(USERPATH, 'outputs', 'dart', 'logs')
632
658
 
659
+ @allow_router_commanding = false
660
+ @x_csrf_token = 'SuperSecret'
661
+ @allowed_origins = []
662
+ @allowed_hosts = ['127.0.0.1:7777', '127.0.0.1:7778', '127.0.0.1:7877', '127.0.0.1:8779', '127.0.0.1:8780']
663
+
633
664
  unless filename
634
665
  system_arg = false
635
666
  ARGV.each do |arg|
@@ -650,7 +681,7 @@ module Cosmos
650
681
  end
651
682
 
652
683
  # Reset variables and load packets
653
- def reset(filename = nil)
684
+ def reset(filename = @@instance_filename)
654
685
  reset_variables(filename)
655
686
  load_packets()
656
687
  end
@@ -961,7 +992,10 @@ module Cosmos
961
992
  cmd_meta.disabled = true
962
993
  tlm_meta = @telemetry.packet('SYSTEM', 'META')
963
994
  tlm_meta.sorted_items.each do |item|
964
- next if item.name.include?("RECEIVED") # Tlm only items
995
+ # Ignore reserved items as these are all DERIVED and thus will throw an exception
996
+ # in CommandSender since they don't have write conversions due to:
997
+ # commands.build_cmd -> packet.restore_defaults -> packet.write_item
998
+ next if Packet::RESERVED_ITEM_NAMES.include?(item.name)
965
999
  cmd_meta.define(item.clone)
966
1000
  end
967
1001
  @config.commands['SYSTEM'] ||= {}
@@ -42,6 +42,9 @@ module Cosmos
42
42
  def paint(painter, option, index)
43
43
  packet_item, _, _ = @widgets[index.row]
44
44
  if index.column == 1 and packet_item and packet_item.states
45
+ painter.save
46
+ option = Qt::StyleOptionViewItemV4.new(option)
47
+ initStyleOption(option, index)
45
48
  # This code simply draws the current combo box text inside a button to
46
49
  # give the user an idea that they have to click it to activate it
47
50
  opt = Qt::StyleOptionButton.new
@@ -49,6 +52,18 @@ module Cosmos
49
52
  opt.text = @table.item(index.row, index.column).text.to_s
50
53
  Qt::Application.style.drawControl(Qt::Style::CE_PushButton, opt, painter)
51
54
  opt.dispose
55
+ painter.restore
56
+ # Not sure why but once we re-implement paint() the word wrapping
57
+ # doesn't work when we simply call super(painter, option, index)
58
+ # Thus we implement this to support word wrapping on the description
59
+ elsif index.column == 4
60
+ painter.save
61
+ option = Qt::StyleOptionViewItemV4.new(option)
62
+ initStyleOption(option, index)
63
+ option.text = index.data().toString()
64
+ option.features = Qt::StyleOptionViewItemV2::WrapText
65
+ self.parent().style().drawControl(Qt::Style.CE_ItemViewItem, option, painter)
66
+ painter.restore
52
67
  else
53
68
  super(painter, option, index)
54
69
  end
@@ -67,7 +67,7 @@ module Cosmos
67
67
  # @return [Hash] Hash keyed by parameter name with String formatted value
68
68
  def params_text(raw = false)
69
69
  params = {}
70
- Qt.execute_in_main_thread do
70
+ Qt.execute_in_main_thread do
71
71
  @param_widgets.each do |packet_item, value_item, state_value_item|
72
72
  text = value_item.text
73
73
  text = state_value_item.text if state_value_item && (text == MANUALLY or raw)
@@ -197,7 +197,7 @@ module Cosmos
197
197
  end
198
198
  end
199
199
 
200
- private
200
+ private
201
201
 
202
202
  def get_params(show_ignored)
203
203
  params = {}
@@ -322,7 +322,7 @@ module Cosmos
322
322
  value_text = "0x" + value_text.simple_formatted
323
323
  # Add quotes around STRING or BLOCK defaults so they are interpreted correctly
324
324
  elsif (packet_item.data_type == :STRING or packet_item.data_type == :BLOCK)
325
- value_text = "'#{packet_item.default}'"
325
+ value_text = "'#{value_text}'"
326
326
  end
327
327
  value_item = Qt::TableWidgetItem.new(value_text)
328
328
  value_item.setTextAlignment(Qt::AlignRight | Qt::AlignVCenter)
@@ -338,6 +338,14 @@ module Cosmos
338
338
  if item.column == 1
339
339
  if packet_item.states
340
340
  value = packet_item.states[value_item.text]
341
+ if packet_item.hazardous && packet_item.hazardous.key?(value_item.text)
342
+ desc = packet_item.hazardous[value]
343
+ # Hazardous states aren't required to have a description so use the item description
344
+ desc = packet_item.description unless desc
345
+ @table.item(item.row, 4).setText("(Hazardous) #{desc}")
346
+ else
347
+ @table.item(item.row, 4).setText(packet_item.description)
348
+ end
341
349
  @table.blockSignals(true)
342
350
  if CmdParams.states_in_hex && value.kind_of?(Integer)
343
351
  state_value_item.setText(sprintf("0x%X", value))
@@ -351,10 +359,24 @@ module Cosmos
351
359
  @table.item(item.row, 1).setText(MANUALLY)
352
360
  @table.blockSignals(false)
353
361
  end
362
+ calculate_height()
354
363
  emit modified()
355
364
  end
365
+ calculate_height()
366
+ end
367
+
368
+ def calculate_height
356
369
  @table.resizeColumnsToContents()
357
370
  @table.resizeRowsToContents()
371
+ height = @table.horizontalHeader.height + 2 # 2 = Header frame?
372
+ @table.rowCount.times do |i|
373
+ # TODO: rowHeight does not reflect word wrapping ... it's always 37
374
+ height += @table.rowHeight(i)
375
+ # NOTE: Checking the fontMetrics boundingRect also does not refect word wrapping
376
+ # e.g. Cosmos.getFontMetrics(@table.font).boundingRect(@table.item(x,y).text).height
377
+ end
378
+ @table.setMaximumHeight(height)
379
+ @table.setMinimumHeight(height)
358
380
  end
359
381
  end
360
382
  end
@@ -491,6 +491,13 @@ module Cosmos
491
491
  packet_name = @cmd_select.text
492
492
  if target_name && packet_name
493
493
  packet = System.commands.packet(target_name, packet_name)
494
+ # Directly update packet description ... safe because always in GUI thread
495
+ hazardous, _ = System.commands.cmd_hazardous?(target_name, packet_name)
496
+ if hazardous
497
+ @description.text = "(Hazardous) #{packet.description}"
498
+ else
499
+ @description.text = packet.description
500
+ end
494
501
  table = @cmd_params.update_cmd_params(packet, show_ignored: checked)
495
502
  @table_layout.addWidget(table, 500) if table
496
503
  end
@@ -56,11 +56,6 @@ module Cosmos
56
56
 
57
57
  def add_table(table)
58
58
  return unless table
59
- table.setSizePolicy(Qt::SizePolicy.Minimum, Qt::SizePolicy.Minimum)
60
- table.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff)
61
- table.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff)
62
- table.setFixedSize(table.horizontalHeader.length + table.verticalHeader.width,
63
- 2 + table.verticalHeader.length + table.horizontalHeader.height)
64
59
  @table_layout.addWidget(table)
65
60
  end
66
61
 
@@ -591,14 +591,16 @@ module Cosmos
591
591
  end
592
592
 
593
593
  # Update current value table
594
- cvt_packet.buffer = packet.buffer(false)
595
- cvt_packet.received_time = received_time
596
-
597
- # The interface does the following line, but I don't think inject_tlm should because it could confuse the interface
598
- target.tlm_cnt += 1
599
- packet.received_count += 1
600
- cvt_packet.received_count += 1
601
- CmdTlmServer.instance.identified_packet_callback(packet)
594
+ cvt_packet.synchronize do
595
+ cvt_packet.buffer = packet.buffer(false)
596
+ cvt_packet.received_time = received_time
597
+
598
+ # The interface does the following line, but I don't think inject_tlm should because it could confuse the interface
599
+ target.tlm_cnt += 1
600
+ packet.received_count += 1
601
+ cvt_packet.received_count += 1
602
+ CmdTlmServer.instance.identified_packet_callback(cvt_packet)
603
+ end
602
604
 
603
605
  # Find the interface for this target
604
606
  interface = target.interface
@@ -201,9 +201,9 @@ module Cosmos
201
201
  @json_drb.method_whitelist = @api_whitelist
202
202
  begin
203
203
  if @mode == :CMD_TLM_SERVER
204
- @json_drb.start_service(System.listen_hosts['CTS_API'], System.ports['CTS_API'], self)
204
+ @json_drb.start_service(System.listen_hosts['CTS_API'], System.ports['CTS_API'], self, 1000, System)
205
205
  else
206
- @json_drb.start_service(System.listen_hosts['REPLAY_API'], System.ports['REPLAY_API'], self)
206
+ @json_drb.start_service(System.listen_hosts['REPLAY_API'], System.ports['REPLAY_API'], self, 1000, System)
207
207
  end
208
208
  rescue Exception
209
209
  # Call packet_logging shutdown here to explicitly kill the logging
@@ -96,7 +96,7 @@ module Cosmos
96
96
  button_layout.addWidget(button, location[0], location[1])
97
97
  button.connect(SIGNAL('clicked()')) do
98
98
  begin
99
- CmdTlmServer.instance.send(method, 'ALL')
99
+ CmdTlmServer.instance.public_send(method, 'ALL')
100
100
  rescue Exception => error
101
101
  statusBar.showMessage(error.message)
102
102
  end
@@ -148,51 +148,54 @@ module Cosmos
148
148
  if packet.identified?
149
149
  begin
150
150
  # Preidentifed packet - place it into the current value table
151
- identified_packet = System.telemetry.update!(packet.target_name,
152
- packet.packet_name,
153
- packet.buffer)
151
+ identified_packet = System.telemetry.packet(packet.target_name, packet.packet_name)
154
152
  rescue RuntimeError
155
153
  # Packet identified but we don't know about it
156
154
  # Clear packet_name and target_name and try to identify
157
155
  Logger.warn "Received unknown identified telemetry: #{packet.target_name} #{packet.packet_name}"
158
156
  packet.target_name = nil
159
157
  packet.packet_name = nil
160
- identified_packet = System.telemetry.identify!(packet.buffer,
161
- @interface.target_names)
158
+ identified_packet = System.telemetry.identify(packet.buffer, @interface.target_names)
162
159
  end
163
160
  else
164
161
  # Packet needs to be identified
165
- identified_packet = System.telemetry.identify!(packet.buffer,
166
- @interface.target_names)
162
+ identified_packet = System.telemetry.identify(packet.buffer, @interface.target_names)
167
163
  end
168
164
  end
169
165
 
170
- if identified_packet
166
+ unknown = false
167
+ unless identified_packet
168
+ unknown = true
169
+ identified_packet = System.telemetry.packet('UNKNOWN', 'UNKNOWN')
170
+ end
171
+
172
+ identified_packet.synchronize do
173
+ identified_packet.buffer = packet.buffer unless packet.stored
171
174
  identified_packet.received_time = packet.received_time
172
175
  identified_packet.stored = packet.stored
173
176
  identified_packet.extra = packet.extra
174
177
  packet = identified_packet
175
- else
176
- unknown_packet = System.telemetry.update!('UNKNOWN', 'UNKNOWN', packet.buffer)
177
- unknown_packet.received_time = packet.received_time
178
- unknown_packet.stored = packet.stored
179
- unknown_packet.extra = packet.extra
180
- packet = unknown_packet
181
- data_length = packet.length
182
- string = "#{@interface.name} - Unknown #{data_length} byte packet starting: "
183
- num_bytes_to_print = [UNKNOWN_BYTES_TO_PRINT, data_length].min
184
- data_to_print = packet.buffer(false)[0..(num_bytes_to_print - 1)]
185
- data_to_print.each_byte do |byte|
186
- string << sprintf("%02X", byte)
178
+
179
+ if unknown
180
+ data_length = packet.length
181
+ string = "#{@interface.name} - Unknown #{data_length} byte packet starting: "
182
+ num_bytes_to_print = [UNKNOWN_BYTES_TO_PRINT, data_length].min
183
+ data_to_print = packet.buffer(false)[0..(num_bytes_to_print - 1)]
184
+ data_to_print.each_byte do |byte|
185
+ string << sprintf("%02X", byte)
186
+ end
187
+ Logger.error string
187
188
  end
188
- Logger.error string
189
- end
190
189
 
191
- target = System.targets[packet.target_name]
192
- target.tlm_cnt += 1 if target
193
- packet.received_count += 1
194
- @identified_packet_callback.call(packet) if @identified_packet_callback
190
+ target = System.targets[packet.target_name]
191
+ target.tlm_cnt += 1 if target
192
+ packet.received_count += 1
193
+ @identified_packet_callback.call(packet) if @identified_packet_callback
195
194
 
195
+ # So we can release the mutex
196
+ packet = packet.clone
197
+ end
198
+
196
199
  # Write to routers
197
200
  @interface.routers.each do |router|
198
201
  begin
@@ -86,7 +86,7 @@ module Cosmos
86
86
  return if @sleeper.sleep(@initial_delay)
87
87
  loop do
88
88
  start = Time.now
89
- check_methods.each {|method| self.send(method.intern) }
89
+ check_methods.each {|method| self.public_send(method.intern) }
90
90
  now = Time.now
91
91
  @status = "#{now.formatted}: Checking groups took #{now - start}s"
92
92
  sleep_time = @task_delay - (now - start)
@@ -19,6 +19,11 @@ module Cosmos
19
19
  protected
20
20
 
21
21
  def handle_packet(packet)
22
+ unless System.allow_router_commanding
23
+ Logger.error "Router received command with router commanding disabled"
24
+ return
25
+ end
26
+
22
27
  # Start out assuming we will route to all associated interfaces
23
28
  interfaces = @interface.interfaces
24
29
 
@@ -653,7 +653,7 @@ module Cosmos
653
653
  end
654
654
  File.open(File.join(target_folder, 'procedures', "#{target.downcase}_noop.rb"), 'w') do |file|
655
655
  file.puts "require 'cosmos'"
656
- file.puts "require '#{File.basename(lib_filename)}'"
656
+ file.puts "load_utility '#{File.basename(lib_filename)}'"
657
657
  file.puts "\n"
658
658
  file.puts "#{target.downcase} = #{lib_filename.filename_to_class_name}.new"
659
659
  file.puts "#{target.downcase}.noop"
@@ -156,7 +156,7 @@ module Cosmos
156
156
  msg << "PDF Handbooks created successfully"
157
157
  progress_dialog.append_text(msg)
158
158
  else
159
- progress_dialog.append_text("\nPDF Handbooks could not be created.\n\nIs wkhtmltopdf in your PATH and are all existing pdfs closed?\n\nUsing version 0.11.0_rc1 of wkhtmltox is recommended which can be found at: http://download.gna.org/wkhtmltopdf/obsolete/\n\nVersion 0.12.x has shown issues with Handbook Creator's default templates.")
159
+ progress_dialog.append_text("\nPDF Handbooks could not be created.\n\nIs wkhtmltopdf in your PATH and are all existing pdfs closed?\n\nwkhtmltopdf can be found at: https://wkhtmltopdf.org/downloads.html.")
160
160
  end
161
161
  rescue => error
162
162
  progress_dialog.append_text("\n\nError processing:\n#{error.formatted}")
@@ -115,7 +115,7 @@ module Cosmos
115
115
  cover, cover_file = make_pdf_detail('cover', @pdf_cover_filename, @pdf_cover_title, target_name)
116
116
  header, header_file = make_pdf_detail('--header-spacing 3 --header-html', @pdf_header_filename, @pdf_header_title, target_name)
117
117
  footer, footer_file = make_pdf_detail('--footer-spacing 3 --footer-html', @pdf_footer_filename, @pdf_footer_title, target_name)
118
- system_call = "wkhtmltopdf -L #{@pdf_side_margin} -R #{@pdf_side_margin} -T #{@pdf_top_margin} -B #{@pdf_bottom_margin} -s Letter #{header} #{footer} #{cover} #{@pdf_toc} \"#{tmp_html_file.path}\" \"#{File.dirname(filename)}/#{File.basename(filename, '.*')}.pdf\""
118
+ system_call = "wkhtmltopdf --enable-local-file-access -L #{@pdf_side_margin} -R #{@pdf_side_margin} -T #{@pdf_top_margin} -B #{@pdf_bottom_margin} -s Letter #{header} #{footer} #{cover} #{@pdf_toc} \"#{tmp_html_file.path}\" \"#{File.dirname(filename)}/#{File.basename(filename, '.*')}.pdf\""
119
119
  status = nil
120
120
  begin
121
121
  Cosmos.set_working_dir(System.paths['HANDBOOKS']) do
@@ -973,8 +973,10 @@ module Cosmos
973
973
  if debug_text =~ /^@\S+$/ || @script_binding.local_variables.include?(debug_text.to_sym)
974
974
  debug_text = "puts #{debug_text}" # Automatically add puts to print it
975
975
  end
976
+ # Fortify: Dynamic Code Evaluation: Code Injection
976
977
  eval(debug_text, @script_binding, 'debug', 1)
977
978
  else
979
+ # Fortify: Dynamic Code Evaluation: Code Injection
978
980
  Object.class_eval(debug_text, 'debug', 1)
979
981
  end
980
982
  handle_output_io()
@@ -1489,7 +1491,7 @@ module Cosmos
1489
1491
  @@output_thread = nil
1490
1492
  end
1491
1493
 
1492
- @script.setReadOnly(false)
1494
+ @script.setReadOnly(false) unless @script.read_only
1493
1495
  @script.stop_highlight unless uncaught_exception
1494
1496
  select_tab_and_destroy_tabs_after_index(0)
1495
1497
  remove_tabs()
@@ -1722,7 +1724,8 @@ module Cosmos
1722
1724
  @active_script.setPlainText(data)
1723
1725
  end
1724
1726
  mark_breakpoints(filename)
1725
-
1727
+ @active_script.read_only = !File.writable?(filename)
1728
+ @active_script.setReadOnly(@active_script.read_only)
1726
1729
  @active_script.stop_highlight
1727
1730
  end
1728
1731
 
@@ -176,7 +176,7 @@ module Cosmos
176
176
  end
177
177
  end
178
178
 
179
- object.send(method_name)
179
+ object.public_send(method_name)
180
180
  result.result = :PASS
181
181
 
182
182
  if defined? ScriptRunnerFrame
@@ -865,13 +865,13 @@ module Cosmos
865
865
  suite = CustomTestSuite.new
866
866
  begin
867
867
  # Remove any previously defined suite setup methods
868
- CustomTestSuite.send(:remove_method, :setup)
868
+ CustomTestSuite.public_send(:remove_method, :setup)
869
869
  rescue NameError
870
870
  # NameError is raised if no setup method was defined
871
871
  end
872
872
  begin
873
873
  # Remove any previously defined suite teardown methods
874
- CustomTestSuite.send(:remove_method, :teardown)
874
+ CustomTestSuite.public_send(:remove_method, :teardown)
875
875
  rescue NameError
876
876
  # NameError is raised if no teardown method was defined
877
877
  end
@@ -884,7 +884,7 @@ module Cosmos
884
884
  inst = @@test_suites.detect {|my_suite| my_suite.class.to_s == suite_node.text}
885
885
  # Create a lambda which will call that one setup method
886
886
  body = lambda { inst.setup }
887
- CustomTestSuite.send(:define_method, :setup, &body)
887
+ CustomTestSuite.public_send(:define_method, :setup, &body)
888
888
  end
889
889
  if test_node.text == 'teardown'
890
890
  cur_suite.teardown = true
@@ -892,7 +892,7 @@ module Cosmos
892
892
  inst = @@test_suites.detect {|my_suite| my_suite.class.to_s == suite_node.text}
893
893
  # Create a lambda which will call that one teardown method
894
894
  body = lambda { inst.teardown}
895
- CustomTestSuite.send(:define_method, :teardown, &body)
895
+ CustomTestSuite.public_send(:define_method, :teardown, &body)
896
896
  end
897
897
  end
898
898
 
@@ -455,7 +455,7 @@ module Cosmos
455
455
  def self.post_options_parsed_hook(options)
456
456
  if options.input_files or options.dart
457
457
  normalize_config_options(options)
458
-
458
+
459
459
  # Process config file
460
460
  raise "Configuration File must be specified for command line processing" unless options.config_file
461
461
 
@@ -675,7 +675,7 @@ module Cosmos
675
675
  process_args = [batch_name, @input_filenames, @log_dir, output_extension, @batch_filenames, @packet_log_frame.time_start, @packet_log_frame.time_end]
676
676
  end
677
677
 
678
- @tlm_extractor_processor.send(process_method, *process_args) do |input_file_index, packet_count, file_progress|
678
+ @tlm_extractor_processor.public_send(process_method, *process_args) do |input_file_index, packet_count, file_progress|
679
679
  # Handle Cancel
680
680
  break if @cancel
681
681
 
@@ -760,7 +760,7 @@ module Cosmos
760
760
  process_args = [batch_name, @log_dir, output_extension, @batch_filenames, @packet_log_frame.time_start, @packet_log_frame.time_end, @dart_meta_frame.meta_filters]
761
761
  end
762
762
 
763
- @tlm_extractor_processor.send(process_method, *process_args) do |percentage, message|
763
+ @tlm_extractor_processor.public_send(process_method, *process_args) do |percentage, message|
764
764
  # Handle Cancel
765
765
  break if @cancel
766
766
  progress_dialog.append_text(message)
@@ -385,10 +385,7 @@ module Cosmos
385
385
 
386
386
  # Print column headings to output file
387
387
  @output_file.print "%" if @matlab_header
388
- column_names().each do |column_name|
389
- @output_file.print column_name
390
- @output_file.print @delimiter
391
- end
388
+ @output_file.print column_names.join(@delimiter)
392
389
  @output_file.puts ""
393
390
  @row_index += 1
394
391
  end
@@ -72,13 +72,13 @@ module Cosmos
72
72
  items = []
73
73
  configs.each { |config| config.mode = :dart; items.concat(config.normal_items); config.open_output_file }
74
74
  items.uniq!
75
-
75
+
76
76
  time_start = Time.utc(1970, 1, 1) unless time_start
77
77
  time_end = Time.now unless time_end
78
78
 
79
79
  results = {}
80
80
  begin
81
- server = JsonDRbObject.new(System.connect_hosts['DART_DECOM'], System.ports['DART_DECOM'])
81
+ server = JsonDRbObject.new(System.connect_hosts['DART_DECOM'], System.ports['DART_DECOM'], 1.0, Cosmos::System.x_csrf_token)
82
82
 
83
83
  index = 0
84
84
  items.each do |item_type, target_name, packet_name, item_name, value_type, dart_reduction, dart_reduced_type|
@@ -116,7 +116,7 @@ module Cosmos
116
116
  rescue Exception => error
117
117
  yield(index.to_f / items.length, "Error querying #{query_string} : #{error.class}:#{error.message}\n#{error.backtrace.join("\n")}\n") if block_given?
118
118
  return # Bail out because something bad happened
119
- end
119
+ end
120
120
  end
121
121
 
122
122
  configs.each { |config| config.process_dart(results) }
@@ -45,7 +45,7 @@ module Cosmos
45
45
 
46
46
  # Execute each query
47
47
  results = {}
48
- server = JsonDRbObject.new(System.connect_hosts['DART_DECOM'], System.ports['DART_DECOM'])
48
+ server = JsonDRbObject.new(System.connect_hosts['DART_DECOM'], System.ports['DART_DECOM'], 1.0, Cosmos::System.x_csrf_token)
49
49
  time_start = Time.utc(1970, 1, 1) unless time_start
50
50
  time_end = Time.now unless time_end
51
51
  progress_dialog.set_step_progress(0) if progress_dialog
@@ -146,7 +146,7 @@ module Cosmos
146
146
  'clear_all']
147
147
  @json_drb.method_whitelist = whitelist
148
148
  begin
149
- @json_drb.start_service System.listen_hosts['TLMVIEWER_API'], port, self
149
+ @json_drb.start_service System.listen_hosts['TLMVIEWER_API'], port, self, 1000, System
150
150
  rescue Exception
151
151
  raise FatalError.new("Error starting JsonDRb on port #{port}.\nPerhaps a Telemetry Viewer is already running?")
152
152
  end
@@ -171,7 +171,7 @@ module Cosmos
171
171
 
172
172
  ConfigParser.splash = nil
173
173
  end
174
-
174
+
175
175
  hide() unless options.show_main
176
176
  end
177
177
 
@@ -61,6 +61,8 @@ module Cosmos
61
61
  end
62
62
 
63
63
  def eval_str(string_to_eval)
64
+ # Fortify: Dynamic Code Evaluation: Code Injection
65
+ # TODO: Not sure how to sanitize this string
64
66
  @screen.instance_eval(string_to_eval)
65
67
  end
66
68
 
@@ -397,7 +397,7 @@ module Cosmos
397
397
  # @param hashing_algorithm [String] Hashing algorithm to use
398
398
  # @return [Digest::<algorithm>] The hashing sum object
399
399
  def self.hash_files(filenames, additional_data = nil, hashing_algorithm = 'MD5')
400
- digest = Digest.const_get(hashing_algorithm).send('new')
400
+ digest = Digest.const_get(hashing_algorithm).public_send('new')
401
401
 
402
402
  Cosmos.set_working_dir do
403
403
  filenames.each do |filename|
@@ -37,7 +37,7 @@ module Cosmos
37
37
  @tlm_packets.each do |name, packet|
38
38
  ids = packet.id_items
39
39
  ids.each do |id|
40
- packet.send((id.name + '=').to_sym, id.id_value)
40
+ packet.public_send((id.name + '=').to_sym, id.id_value)
41
41
  end
42
42
  end
43
43