cosmos 4.4.0 → 4.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. checksums.yaml +5 -5
  2. data/.dockerignore +2 -0
  3. data/.gitignore +1 -0
  4. data/.travis.yml +6 -6
  5. data/Dockerfile +70 -0
  6. data/Manifest.txt +37 -2
  7. data/README.md +9 -0
  8. data/Rakefile +55 -5
  9. data/appveyor.yml +18 -8
  10. data/autohotkey/config/tools/cmd_sequence/cmd_sequence.txt +2 -0
  11. data/autohotkey/lib/cmd_sequence_exporter.rb +52 -0
  12. data/autohotkey/procedures/collect.rb +2 -2
  13. data/autohotkey/procedures/collect_util.rb +1 -1
  14. data/autohotkey/procedures/script_test.rb +1 -1
  15. data/autohotkey/tools/CmdSenderAHK2 +18 -0
  16. data/autohotkey/tools/cmd_extractor.ahk +11 -9
  17. data/autohotkey/tools/cmd_sender.ahk +35 -7
  18. data/autohotkey/tools/cmd_sender2.ahk +4 -0
  19. data/autohotkey/tools/cmd_sequence.ahk +22 -9
  20. data/autohotkey/tools/config_editor.ahk +4 -4
  21. data/autohotkey/tools/data_viewer.ahk +1 -1
  22. data/autohotkey/tools/limits_monitor.ahk +1 -1
  23. data/autohotkey/tools/packet_viewer.ahk +1 -1
  24. data/autohotkey/tools/script_runner.ahk +1 -1
  25. data/autohotkey/tools/test_runner2.ahk +1 -1
  26. data/autohotkey/tools/tlm_grapher.ahk +1 -1
  27. data/autohotkey/tools/tlm_grapher3.ahk +1 -1
  28. data/autohotkey/tools/tlm_viewer.ahk +1 -1
  29. data/autohotkey/tools/tlm_viewer2.ahk +1 -1
  30. data/autohotkey/tools/tlm_viewer5.ahk +1 -1
  31. data/bin/cstol_converter +1 -1
  32. data/bin/rubysloc +73 -28
  33. data/bin/xtce_converter +1 -1
  34. data/cosmos.gemspec +2 -2
  35. data/data/config/command_modifiers.yaml +16 -1
  36. data/data/config/interface_modifiers.yaml +3 -2
  37. data/data/config/param_item_modifiers.yaml +5 -0
  38. data/data/config/system.yaml +110 -23
  39. data/data/config/telemetry_modifiers.yaml +16 -1
  40. data/data/crc.txt +416 -411
  41. data/demo/Rakefile +4 -4
  42. data/demo/config/dart/Gemfile +1 -6
  43. data/demo/config/data/crc.txt +233 -232
  44. data/demo/config/system/system.txt +17 -6
  45. data/demo/config/system/system2.txt +17 -6
  46. data/demo/config/system/system_alt_ports.txt +17 -6
  47. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +4 -4
  48. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +4 -0
  49. data/demo/config/targets/INST/cmd_tlm/inst_tlm_override.txt +12 -0
  50. data/demo/config/targets/INST/lib/sim_inst.rb +2 -2
  51. data/demo/config/targets/INST/target.txt +1 -0
  52. data/demo/config/tools/handbook_creator/default_toc.xsl +59 -59
  53. data/demo/procedures/cosmos_api_test.rb +8 -8
  54. data/ext/cosmos/ext/buffered_file/buffered_file.c +2 -2
  55. data/ext/cosmos/ext/config_parser/config_parser.c +1 -2
  56. data/ext/cosmos/ext/line_graph/line_graph.c +53 -94
  57. data/ext/cosmos/ext/platform/platform.c +56 -21
  58. data/ext/cosmos/ext/polynomial_conversion/polynomial_conversion.c +4 -8
  59. data/ext/cosmos/ext/structure/structure.c +12 -0
  60. data/extensions/vscode/.gitignore +4 -0
  61. data/extensions/vscode/.vscode/launch.json +32 -0
  62. data/extensions/vscode/.vscode/settings.json +13 -0
  63. data/extensions/vscode/.vscode/tasks.json +79 -0
  64. data/extensions/vscode/License.txt +879 -0
  65. data/extensions/vscode/README.md +9 -0
  66. data/extensions/vscode/client/License.txt +879 -0
  67. data/extensions/vscode/client/README.md +39 -0
  68. data/extensions/vscode/client/cosmos.configuration.json +23 -0
  69. data/extensions/vscode/client/images/icon.png +0 -0
  70. data/extensions/vscode/client/package-lock.json +414 -0
  71. data/extensions/vscode/client/package.json +105 -0
  72. data/extensions/vscode/client/src/extension.ts +132 -0
  73. data/extensions/vscode/client/src/screen_preview.rb +25 -0
  74. data/extensions/vscode/client/syntaxes/cosmos.tmLanguage.json +219 -0
  75. data/extensions/vscode/client/tsconfig.json +17 -0
  76. data/extensions/vscode/package-lock.json +26 -0
  77. data/extensions/vscode/package.json +35 -0
  78. data/extensions/vscode/server/License.txt +879 -0
  79. data/extensions/vscode/server/package-lock.json +236 -0
  80. data/extensions/vscode/server/package.json +29 -0
  81. data/extensions/vscode/server/src/server.ts +59 -0
  82. data/extensions/vscode/server/tsconfig.json +16 -0
  83. data/install/Rakefile +4 -4
  84. data/install/config/dart/Gemfile +2 -7
  85. data/install/config/data/crc.txt +137 -137
  86. data/install/config/system/system.txt +17 -6
  87. data/install/config/tools/handbook_creator/default_toc.xsl +59 -59
  88. data/lib/cosmos/config/config_parser.rb +2 -10
  89. data/lib/cosmos/core_ext/class.rb +10 -0
  90. data/lib/cosmos/core_ext/time.rb +5 -3
  91. data/lib/cosmos/dart/config/boot.rb +1 -1
  92. data/lib/cosmos/dart/config/database.yml +2 -0
  93. data/lib/cosmos/dart/examples/dart_decom_client.rb +1 -1
  94. data/lib/cosmos/dart/lib/dart_common.rb +12 -5
  95. data/lib/cosmos/dart/lib/dart_constants.rb +15 -0
  96. data/lib/cosmos/dart/lib/dart_decom_query.rb +5 -6
  97. data/lib/cosmos/dart/lib/dart_decommutator.rb +64 -54
  98. data/lib/cosmos/dart/lib/dart_master_query.rb +71 -0
  99. data/lib/cosmos/dart/lib/dart_reducer_worker_thread.rb +165 -134
  100. data/lib/cosmos/dart/processes/dart.rb +4 -2
  101. data/lib/cosmos/dart/processes/dart_decom_server.rb +3 -3
  102. data/lib/cosmos/dart/processes/dart_ingester.rb +38 -1
  103. data/lib/cosmos/dart/processes/dart_master.rb +44 -0
  104. data/lib/cosmos/dart/processes/dart_util.rb +115 -0
  105. data/lib/cosmos/dart/spec/dart/dart_database_cleaner_spec.rb +2 -2
  106. data/lib/cosmos/gui/qt.rb +10 -10
  107. data/lib/cosmos/gui/qt_tool.rb +17 -12
  108. data/lib/cosmos/gui/text/completion_text_edit.rb +2 -0
  109. data/lib/cosmos/gui/widgets/dart_meta_frame.rb +22 -3
  110. data/lib/cosmos/interfaces/dart_status_interface.rb +1 -1
  111. data/lib/cosmos/interfaces/linc_interface.rb +3 -3
  112. data/lib/cosmos/interfaces/protocols/burst_protocol.rb +1 -1
  113. data/lib/cosmos/interfaces/protocols/crc_protocol.rb +1 -1
  114. data/lib/cosmos/interfaces/protocols/length_protocol.rb +5 -0
  115. data/lib/cosmos/interfaces/protocols/template_protocol.rb +3 -3
  116. data/lib/cosmos/interfaces/serial_interface.rb +7 -1
  117. data/lib/cosmos/interfaces/stream_interface.rb +1 -1
  118. data/lib/cosmos/interfaces/tcpip_server_interface.rb +16 -16
  119. data/lib/cosmos/io/io_multiplexer.rb +6 -2
  120. data/lib/cosmos/io/json_drb.rb +5 -5
  121. data/lib/cosmos/io/json_drb_object.rb +7 -2
  122. data/lib/cosmos/io/json_drb_rack.rb +25 -5
  123. data/lib/cosmos/io/json_rpc.rb +1 -1
  124. data/lib/cosmos/io/posix_serial_driver.rb +60 -22
  125. data/lib/cosmos/io/serial_driver.rb +11 -8
  126. data/lib/cosmos/io/win32_serial_driver.rb +31 -3
  127. data/lib/cosmos/packet_logs/packet_log_reader.rb +2 -2
  128. data/lib/cosmos/packets/packet.rb +9 -9
  129. data/lib/cosmos/packets/packet_config.rb +27 -9
  130. data/lib/cosmos/packets/parsers/xtce_converter.rb +10 -10
  131. data/lib/cosmos/packets/parsers/xtce_parser.rb +3 -0
  132. data/lib/cosmos/packets/structure.rb +35 -5
  133. data/lib/cosmos/packets/structure_item.rb +5 -1
  134. data/lib/cosmos/packets/telemetry.rb +7 -1
  135. data/lib/cosmos/script/api_shared.rb +18 -1
  136. data/lib/cosmos/script/extract.rb +1 -1
  137. data/lib/cosmos/script/script.rb +4 -11
  138. data/lib/cosmos/streams/serial_stream.rb +11 -6
  139. data/lib/cosmos/system/system.rb +155 -57
  140. data/lib/cosmos/tools/cmd_sender/cmd_param_table_item_delegate.rb +15 -0
  141. data/lib/cosmos/tools/cmd_sender/cmd_params.rb +382 -0
  142. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +29 -318
  143. data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +14 -17
  144. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +38 -331
  145. data/lib/cosmos/tools/cmd_sequence/sequence_list.rb +16 -11
  146. data/lib/cosmos/tools/cmd_tlm_server/api.rb +10 -8
  147. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +2 -2
  148. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +1 -0
  149. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +1 -1
  150. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +29 -26
  151. data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +1 -1
  152. data/lib/cosmos/tools/cmd_tlm_server/router_thread.rb +5 -0
  153. data/lib/cosmos/tools/config_editor/config_editor.rb +34 -3
  154. data/lib/cosmos/tools/config_editor/config_editor_frame.rb +8 -9
  155. data/lib/cosmos/tools/config_editor/system_config_dialog.rb +158 -0
  156. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +1 -1
  157. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +1 -1
  158. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +7 -4
  159. data/lib/cosmos/tools/test_runner/test.rb +6 -3
  160. data/lib/cosmos/tools/test_runner/test_runner.rb +6 -6
  161. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +3 -3
  162. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +1 -4
  163. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +20 -16
  164. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_dart_thread.rb +21 -17
  165. data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +18 -11
  166. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +17 -6
  167. data/lib/cosmos/tools/tlm_viewer/widgets/canvasdot_widget.rb +2 -0
  168. data/lib/cosmos/top_level.rb +1 -1
  169. data/lib/cosmos/utilities/ruby_lex_utils.rb +34 -30
  170. data/lib/cosmos/utilities/simulated_target.rb +1 -1
  171. data/lib/cosmos/version.rb +5 -5
  172. data/lib/cosmos/win32/excel.rb +23 -17
  173. data/run_gui_tests.bat +1 -0
  174. data/spec/core_ext/class_spec.rb +54 -0
  175. data/spec/core_ext/socket_spec.rb +1 -1
  176. data/spec/core_ext/time_spec.rb +4 -0
  177. data/spec/install/yaml_docs_spec.rb +26 -6
  178. data/spec/interfaces/linc_interface_spec.rb +1 -1
  179. data/spec/interfaces/protocols/length_protocol_spec.rb +39 -0
  180. data/spec/interfaces/serial_interface_spec.rb +1 -5
  181. data/spec/io/json_drb_rack_spec.rb +166 -0
  182. data/spec/io/json_drb_spec.rb +14 -0
  183. data/spec/io/json_rpc_spec.rb +4 -5
  184. data/spec/io/posix_serial_driver_spec.rb +81 -0
  185. data/spec/io/win32_serial_driver_spec.rb +33 -3
  186. data/spec/packet_logs/packet_log_reader_spec.rb +36 -37
  187. data/spec/packets/structure_spec.rb +52 -2
  188. data/spec/packets/telemetry_spec.rb +29 -1
  189. data/spec/script/extract_spec.rb +4 -1
  190. data/spec/system/system_spec.rb +111 -3
  191. data/spec/tools/cmd_tlm_server/api_spec.rb +12 -12
  192. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +2 -2
  193. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +4 -3
  194. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +2 -3
  195. data/spec/utilities/logger_spec.rb +3 -3
  196. data/spec/utilities/message_log_spec.rb +6 -3
  197. data/tasks/gemfile_stats.rake +22 -13
  198. data/test/performance/Rakefile +4 -4
  199. data/test/performance/config/data/crc.txt +67 -48
  200. metadata +52 -11
  201. data/demo/outputs/dart/logs/README.txt +0 -1
  202. data/lib/cosmos/dart/Gemfile +0 -69
@@ -132,7 +132,7 @@ module Cosmos
132
132
  end
133
133
  rescue Exception => err
134
134
  shutdown_interfaces(@write_interface_infos)
135
- Logger.instance.error("Tcpip server write thread unexpectedly died")
135
+ Logger.instance.error("#{@name}: Tcpip server write thread unexpectedly died")
136
136
  Logger.instance.error(err.formatted)
137
137
  end
138
138
  end
@@ -144,7 +144,7 @@ module Cosmos
144
144
  end
145
145
  rescue Exception => err
146
146
  shutdown_interfaces(@write_interface_infos)
147
- Logger.instance.error("Tcpip server write raw thread unexpectedly died")
147
+ Logger.instance.error("#{@name}: Tcpip server write raw thread unexpectedly died")
148
148
  Logger.instance.error(err.formatted)
149
149
  end
150
150
  end
@@ -298,10 +298,10 @@ module Cosmos
298
298
  def change_raw_logging(method)
299
299
  if @raw_logger_pair
300
300
  @write_interface_infos.each do |interface_info|
301
- interface_info.interface.raw_logger_pair.send(method) if interface_info.interface.raw_logger_pair
301
+ interface_info.interface.raw_logger_pair.public_send(method) if interface_info.interface.raw_logger_pair
302
302
  end
303
303
  @read_interface_infos.each do |interface_info|
304
- interface_info.interface.raw_logger_pair.send(method) if interface_info.interface.raw_logger_pair
304
+ interface_info.interface.raw_logger_pair.public_send(method) if interface_info.interface.raw_logger_pair
305
305
  end
306
306
  end
307
307
  end
@@ -346,7 +346,7 @@ module Cosmos
346
346
  break if @cancel_threads
347
347
  end
348
348
  rescue => err
349
- Logger.instance.error("Tcpip server listen thread unexpectedly died")
349
+ Logger.instance.error("#{@name}: Tcpip server listen thread unexpectedly died")
350
350
  Logger.instance.error(err.formatted)
351
351
  end
352
352
  end
@@ -372,7 +372,7 @@ module Cosmos
372
372
  if not System.instance.acl.allow_addr?(addr)
373
373
  # Reject connection
374
374
  Cosmos.close_socket(socket)
375
- Logger.instance.info "Tcpip server rejected connection from #{hostname}(#{host_ip}):#{port}"
375
+ Logger.instance.info "#{@name}: Tcpip server rejected connection from #{hostname}(#{host_ip}):#{port}"
376
376
  return
377
377
  end
378
378
  end
@@ -417,7 +417,7 @@ module Cosmos
417
417
  end
418
418
  start_read_thread(@read_interface_infos[-1])
419
419
  end
420
- Logger.instance.info "Tcpip server accepted connection from #{hostname}(#{host_ip}):#{port}"
420
+ Logger.instance.info "#{@name}: Tcpip server accepted connection from #{hostname}(#{host_ip}):#{port}"
421
421
  end
422
422
 
423
423
  def start_read_thread(interface_info)
@@ -427,10 +427,10 @@ module Cosmos
427
427
  begin
428
428
  read_thread_body(interface_info.interface)
429
429
  rescue Exception => err
430
- Logger.instance.error "Tcpip server read thread unexpectedly died"
430
+ Logger.instance.error "#{@name}: Tcpip server read thread unexpectedly died"
431
431
  Logger.instance.error err.formatted
432
432
  end
433
- Logger.instance.info "Tcpip server lost read connection to #{interface_info.hostname}(#{interface_info.host_ip}):#{interface_info.port}"
433
+ Logger.instance.info "#{@name}: Tcpip server lost read connection to #{interface_info.hostname}(#{interface_info.host_ip}):#{interface_info.port}"
434
434
  @read_threads.delete(Thread.current)
435
435
 
436
436
  index_to_delete = nil
@@ -453,7 +453,7 @@ module Cosmos
453
453
  end
454
454
  end
455
455
  rescue Exception => err
456
- Logger.instance.error "Tcpip server read thread unexpectedly died"
456
+ Logger.instance.error "#{@name}: Tcpip server read thread unexpectedly died"
457
457
  Logger.instance.error err.formatted
458
458
  end
459
459
  end
@@ -500,7 +500,7 @@ module Cosmos
500
500
  end
501
501
 
502
502
  def interface_disconnect(interface_info)
503
- Logger.instance.info "Tcpip server lost write connection to "\
503
+ Logger.instance.info "#{@name}: Tcpip server lost write connection to "\
504
504
  "#{interface_info.hostname}(#{interface_info.host_ip}):#{interface_info.port}"
505
505
  interface_info.interface.disconnect
506
506
  interface_info.interface.raw_logger_pair.stop if interface_info.interface.raw_logger_pair
@@ -552,13 +552,13 @@ module Cosmos
552
552
  next
553
553
  end
554
554
  # Client has disconnected (or is invalidly sending data on the socket)
555
- Logger.instance.info "Tcpip server lost write connection to #{interface_info.hostname}(#{interface_info.host_ip}):#{interface_info.port}"
555
+ Logger.instance.info "#{@name}: Tcpip server lost write connection to #{interface_info.hostname}(#{interface_info.host_ip}):#{interface_info.port}"
556
556
  interface_info.interface.disconnect
557
557
  interface_info.interface.raw_logger_pair.stop if interface_info.interface.raw_logger_pair
558
558
  indexes_to_delete.unshift(index) # Put later indexes at front of array
559
559
  rescue Errno::ECONNRESET, Errno::ECONNABORTED, IOError
560
560
  # Client has disconnected
561
- Logger.instance.info "Tcpip server lost write connection to #{interface_info.hostname}(#{interface_info.host_ip}):#{interface_info.port}"
561
+ Logger.instance.info "#{@name}: Tcpip server lost write connection to #{interface_info.hostname}(#{interface_info.host_ip}):#{interface_info.port}"
562
562
  interface_info.interface.disconnect
563
563
  interface_info.interface.raw_logger_pair.stop if interface_info.interface.raw_logger_pair
564
564
  indexes_to_delete.unshift(index) # Put later indexes at front of array
@@ -590,7 +590,7 @@ module Cosmos
590
590
  need_disconnect = false
591
591
  begin
592
592
  interface_bytes_written = interface_info.interface.bytes_written
593
- interface_info.interface.send(method, packet_or_data)
593
+ interface_info.interface.public_send(method, packet_or_data)
594
594
  diff = interface_info.interface.bytes_written - interface_bytes_written
595
595
  @written_raw_data_time = interface_info.interface.written_raw_data_time
596
596
  @written_raw_data = interface_info.interface.written_raw_data
@@ -600,13 +600,13 @@ module Cosmos
600
600
  need_disconnect = true
601
601
  rescue Exception => err
602
602
  if err.message != "Stream not connected for write_raw"
603
- Logger.instance.error "Error sending to client: #{err.class} #{err.message}"
603
+ Logger.instance.error "#{@name}: Error sending to client: #{err.class} #{err.message}"
604
604
  end
605
605
  need_disconnect = true
606
606
  end
607
607
 
608
608
  if need_disconnect
609
- Logger.instance.info "Tcpip server lost write connection to #{interface_info.hostname}(#{interface_info.host_ip}):#{interface_info.port}"
609
+ Logger.instance.info "#{@name}: Tcpip server lost write connection to #{interface_info.hostname}(#{interface_info.host_ip}):#{interface_info.port}"
610
610
  interface_info.interface.disconnect
611
611
  interface_info.interface.raw_logger_pair.stop if interface_info.interface.raw_logger_pair
612
612
  indexes_to_delete.unshift(index) # Put later indexes at front of array
@@ -40,11 +40,15 @@ module Cosmos
40
40
  result = nil
41
41
  @streams.each do |stream|
42
42
  if first
43
- result = stream.send(method_name, *args)
43
+ # Fortify Access Specifier Manipulation
44
+ # We're forwarding only public methods to the stream
45
+ result = stream.public_send(method_name, *args)
44
46
  result = self if result == stream
45
47
  first = false
46
48
  else
47
- stream.send(method_name, *args)
49
+ # Fortify Access Specifier Manipulation
50
+ # We're forwarding only public methods to the stream
51
+ stream.public_send(method_name, *args)
48
52
  end
49
53
  end
50
54
  result
@@ -123,7 +123,7 @@ module Cosmos
123
123
  # @param object [Object] The object to send the DRb requests to. This
124
124
  # object must either include the Cosmos::Script module or be the
125
125
  # CmdTlmServer.
126
- def start_service(hostname = nil, port = nil, object = nil, max_threads = 1000)
126
+ def start_service(hostname = nil, port = nil, object = nil, max_threads = 1000, system = nil)
127
127
  server_started = false
128
128
  @server_mutex.synchronize do
129
129
  server_started = true if @server
@@ -147,7 +147,7 @@ module Cosmos
147
147
  }
148
148
 
149
149
  # The run call will block until the server is stopped.
150
- Rack::Handler::Puma.run(JsonDrbRack.new(self), server_config) do |server|
150
+ Rack::Handler::Puma.run(JsonDrbRack.new(self, system), server_config) do |server|
151
151
  @server_mutex.synchronize do
152
152
  @server = server
153
153
  end
@@ -259,10 +259,10 @@ module Cosmos
259
259
  error_code = nil
260
260
  response_data = nil
261
261
 
262
- if (@method_whitelist and @method_whitelist.include?(request.method)) or
263
- (!@method_whitelist and !JsonRpcRequest::DANGEROUS_METHODS.include?(request.method))
262
+ if (@method_whitelist and @method_whitelist.include?(request.method.downcase())) or
263
+ (!@method_whitelist and !JsonRpcRequest::DANGEROUS_METHODS.include?(request.method.downcase()))
264
264
  begin
265
- result = @object.send(request.method.intern, *request.params)
265
+ result = @object.public_send(request.method.downcase().intern, *request.params)
266
266
  if request.id
267
267
  response = JsonRpcSuccessResponse.new(result, request.id)
268
268
  end
@@ -38,7 +38,7 @@ module Cosmos
38
38
  # @param hostname [String] The name of the machine which has started
39
39
  # the JSON service
40
40
  # @param port [Integer] The port number of the JSON service
41
- def initialize(hostname, port, connect_timeout = 1.0)
41
+ def initialize(hostname, port, connect_timeout = 1.0, x_csrf_token = nil)
42
42
  hostname = '127.0.0.1' if (hostname.to_s.upcase == 'LOCALHOST')
43
43
  begin
44
44
  Socket.pack_sockaddr_in(port, hostname)
@@ -61,6 +61,7 @@ module Cosmos
61
61
  @connect_timeout = connect_timeout
62
62
  @connect_timeout = @connect_timeout.to_f if @connect_timeout
63
63
  @shutdown = false
64
+ @x_csrf_token = x_csrf_token
64
65
  end
65
66
 
66
67
  # Disconnects from http server
@@ -127,7 +128,11 @@ module Cosmos
127
128
  STDOUT.puts "\nRequest:\n" if JsonDRb.debug?
128
129
  STDOUT.puts @request_data if JsonDRb.debug?
129
130
  @request_in_progress = true
130
- headers = {'Content-Type' => 'application/json-rpc'}
131
+ if @x_csrf_token
132
+ headers = {'Content-Type' => 'application/json-rpc', 'X-Csrf-Token' => @x_csrf_token}
133
+ else
134
+ headers = {'Content-Type' => 'application/json-rpc'}
135
+ end
131
136
  res = @http.post(@uri,
132
137
  :body => @request_data,
133
138
  :header => headers)
@@ -17,8 +17,9 @@ module Cosmos
17
17
  class JsonDrbRack
18
18
  # @param drb [JsonDRb] - An instance of the JsonDRb class that'll be used
19
19
  # to process the JSON request and generate a response
20
- def initialize(drb)
20
+ def initialize(drb, system = nil)
21
21
  @drb = drb
22
+ @system = system
22
23
  end
23
24
 
24
25
  # Handles a request.
@@ -32,22 +33,41 @@ module Cosmos
32
33
  # ACL allow_addr? function takes address in the form returned by
33
34
  # IPSocket.peeraddr.
34
35
  req_addr = ["AF_INET", request.port, request.host.to_s, request.ip.to_s]
36
+ status = nil
35
37
 
36
38
  if @drb.acl and !@drb.acl.allow_addr?(req_addr)
37
39
  status = 403
38
40
  content_type = "text/plain"
39
41
  body = "Forbidden"
40
42
  elsif request.post?
41
- status, content_type, body = handle_post(request)
43
+ if @system
44
+ if @system.x_csrf_token and (request.env['HTTP_X_CSRF_TOKEN'] != @system.x_csrf_token)
45
+ status = 403
46
+ content_type = "text/plain"
47
+ body = "Forbidden: Bad X-Csrf-Token: #{request.env['HTTP_X_CSRF_TOKEN']}"
48
+ end
49
+ if !@system.allowed_hosts.include?(request.env['HTTP_HOST'])
50
+ status = 403
51
+ content_type = "text/plain"
52
+ body = "Forbidden: #{request.env['HTTP_HOST']} not in allowed hosts"
53
+ end
54
+ if request.env['HTTP_ORIGIN'] and !@system.allowed_origins.include?(request.env['HTTP_ORIGIN'])
55
+ status = 403
56
+ content_type = "text/plain"
57
+ body = "Forbidden: #{request.env['HTTP_ORIGIN']} not in allowed origins"
58
+ end
59
+ end
60
+
61
+ status, content_type, body = handle_post(request) unless status
42
62
  else
43
63
  status = 405
44
64
  content_type = "text/plain"
45
65
  body = "Request not allowed"
46
66
  end
47
-
67
+
48
68
  return status, {'Content-Type' => content_type}, [body]
49
69
  end
50
-
70
+
51
71
  # Handles an http post.
52
72
  #
53
73
  # @param request [Rack::Request] - A rack post request
@@ -57,7 +77,7 @@ module Cosmos
57
77
  request_data = request.body.read
58
78
  start_time = Time.now.sys
59
79
  response_data, error_code = @drb.process_request(request_data, start_time)
60
-
80
+
61
81
  # Convert json error code into html status code
62
82
  # see http://www.jsonrpc.org/historical/json-rpc-over-http.html#errors
63
83
  if error_code
@@ -269,7 +269,7 @@ module Cosmos
269
269
  # @param response_data [String] JSON encoded string representing the response
270
270
  # @return [JsonRpcResponse]
271
271
  def self.from_json(response_data)
272
- msg = "Invalid JSON-RPC 2.0 Response"
272
+ msg = "Invalid JSON-RPC 2.0 Response: #{response_data.inspect}"
273
273
  begin
274
274
  hash = JSON.parse(response_data, :allow_nan => true, :create_additions => true)
275
275
  rescue
@@ -25,19 +25,20 @@ module Cosmos
25
25
  write_timeout = 10.0,
26
26
  read_timeout = nil,
27
27
  flow_control = :NONE,
28
- data_bits = 8)
28
+ data_bits = 8,
29
+ struct = [])
29
30
 
30
31
  # Convert Baud Rate into Termios constant
31
32
  begin
32
33
  baud_rate = Object.const_get("Termios::B#{baud_rate}")
33
34
  rescue NameError
34
- raise(ArgumentError, "Invalid Baud Rate, Not Defined by Termios: #{baud_rate}")
35
+ raise(ArgumentError, "Invalid baud rate: #{baud_rate}")
35
36
  end
36
37
 
37
38
  # Verify Parameters
38
- raise(ArgumentError, "Invalid Data Bits: #{data_bits}") unless [5,6,7,8].include?(data_bits)
39
+ raise(ArgumentError, "Invalid data bits: #{data_bits}") unless [5,6,7,8].include?(data_bits)
39
40
  raise(ArgumentError, "Invalid parity: #{parity}") if parity and !SerialDriver::VALID_PARITY.include?(parity)
40
- raise(ArgumentError, "Invalid Stop Bits: #{stop_bits}") unless [1,2].include?(stop_bits)
41
+ raise(ArgumentError, "Invalid stop bits: #{stop_bits}") unless [1,2].include?(stop_bits)
41
42
  @write_timeout = write_timeout
42
43
  @read_timeout = read_timeout
43
44
 
@@ -51,22 +52,61 @@ module Cosmos
51
52
 
52
53
  # Configure the serial Port
53
54
  tio = Termios::new_termios()
54
- iflags = 0
55
- iflags |= Termios::IGNPAR unless parity
56
- cflags = 0
57
- cflags |= Termios::CREAD # Enable receiver
58
- cflags |= Termios.const_get("CS#{data_bits}") # data bits
59
- cflags |= Termios::CLOCAL # Ignore Modem Control Lines
60
- cflags |= Termios::CSTOPB if stop_bits == 2
61
- cflags |= Termios::PARENB if parity
62
- cflags |= Termios::PADODD if parity == :ODD
63
- cflags |= Termios::CRTSCTS if flow_control == :RTSCTS
64
- tio.iflag = iflags
65
- tio.oflag = 0
66
- tio.cflag = cflags
67
- tio.lflag = 0
55
+ iflag = 0
56
+ iflag |= Termios::IGNPAR unless parity
57
+ oflag = 0
58
+ cflag = 0
59
+ cflag |= Termios::CREAD # Enable receiver
60
+ cflag |= Termios.const_get("CS#{data_bits}") # data bits
61
+ cflag |= Termios::CLOCAL # Ignore Modem Control Lines
62
+ cflag |= Termios::CSTOPB if stop_bits == 2
63
+ cflag |= Termios::PARENB if parity
64
+ cflag |= Termios::PARODD if parity == :ODD
65
+ cflag |= Termios::CRTSCTS if flow_control == :RTSCTS
66
+ lflag = 0
68
67
  tio.cc[Termios::VTIME] = 0
69
68
  tio.cc[Termios::VMIN] = 1
69
+ unless struct.empty?
70
+ struct.each do |field, key, value|
71
+ case field
72
+ when 'iflag'
73
+ if value == "0"
74
+ iflag &= ~Termios.const_get(key)
75
+ else
76
+ iflag |= Termios.const_get(key)
77
+ end
78
+ when 'oflag'
79
+ if value == "0"
80
+ oflag &= ~Termios.const_get(key)
81
+ else
82
+ oflag |= Termios.const_get(key)
83
+ end
84
+ when 'cflag'
85
+ if value == "0"
86
+ cflag &= ~Termios.const_get(key)
87
+ else
88
+ cflag |= Termios.const_get(key)
89
+ end
90
+ when 'lflag'
91
+ if value == "0"
92
+ lflag &= ~Termios.const_get(key)
93
+ else
94
+ lflag |= Termios.const_get(key)
95
+ end
96
+ when 'cc'
97
+ begin
98
+ value = Integer(value) # Try to convert to int
99
+ rescue ArgumentError
100
+ # Ignore this error and use the string
101
+ end
102
+ tio.cc[Termios.const_get(key)] = value
103
+ end
104
+ end
105
+ end
106
+ tio.iflag = iflag
107
+ tio.oflag = oflag
108
+ tio.cflag = cflag
109
+ tio.lflag = lflag
70
110
  tio.ispeed = baud_rate
71
111
  tio.ospeed = baud_rate
72
112
  @handle.tcflush(Termios::TCIOFLUSH)
@@ -143,7 +183,5 @@ module Cosmos
143
183
 
144
184
  data
145
185
  end
146
-
147
- end # class PosixSerialDriver
148
-
149
- end # module Cosmos
186
+ end
187
+ end
@@ -32,8 +32,10 @@ module Cosmos
32
32
  # complete or nil to block
33
33
  # @param read_timeout [Float|nil] Number of seconds to wait for the read to
34
34
  # complete or nil to block
35
- # @param flow_control [Symbol] Currently supported :NONE and :RTSCTS (default :NONE)
35
+ # @param flow_control [Symbol] Currently supported :NONE, :RTSCTS (default :NONE)
36
36
  # @param data_bits [Integer] Number of data bits (default 8)
37
+ # @param struct [Array] Array of arrays of fields and values to set in the
38
+ # Windows DCB or POSIX structure
37
39
  def initialize(port_name,
38
40
  baud_rate,
39
41
  parity = :NONE,
@@ -41,7 +43,8 @@ module Cosmos
41
43
  write_timeout = 10.0,
42
44
  read_timeout = nil,
43
45
  flow_control = :NONE,
44
- data_bits = 8)
46
+ data_bits = 8,
47
+ struct = [])
45
48
  raise(ArgumentError, "Invalid parity: #{parity}") unless VALID_PARITY.include? parity
46
49
  if Kernel.is_windows?
47
50
  @driver = Win32SerialDriver.new(port_name,
@@ -53,7 +56,8 @@ module Cosmos
53
56
  0.01,
54
57
  1000,
55
58
  flow_control,
56
- data_bits)
59
+ data_bits,
60
+ struct)
57
61
  elsif RUBY_ENGINE == 'ruby'
58
62
  @driver = PosixSerialDriver.new(port_name,
59
63
  baud_rate,
@@ -62,7 +66,8 @@ module Cosmos
62
66
  write_timeout,
63
67
  read_timeout,
64
68
  flow_control,
65
- data_bits)
69
+ data_bits,
70
+ struct)
66
71
  else
67
72
  @driver = nil # JRuby Serial on Linux not currently supported
68
73
  end
@@ -92,7 +97,5 @@ module Cosmos
92
97
  def read_nonblock
93
98
  @driver.read_nonblock
94
99
  end
95
-
96
- end # class SerialDriver
97
-
98
- end # module Cosmos
100
+ end
101
+ end
@@ -24,7 +24,8 @@ module Cosmos
24
24
  read_polling_period = 0.01,
25
25
  read_max_length = 1000,
26
26
  flow_control = :NONE,
27
- data_bits = 8)
27
+ data_bits = 8,
28
+ struct = [])
28
29
 
29
30
  # Verify Parameters
30
31
  port_name = '\\\\.\\' + port_name if port_name =~ /^COM[0-9]{2,3}$/
@@ -78,10 +79,37 @@ module Cosmos
78
79
  # 0x03 - RTS_CONTROL_TOGGLE - Specifies that the RTS line will be high if bytes are available for transmission. After all buffered bytes have been sent, the RTS line will be low.
79
80
  dcb.write('fRtsControl', 0x03)
80
81
  end
82
+ # Allow the end user to write arbitrary values into the Windows DCB structure
83
+ unless struct.empty?
84
+ struct.each do |key, value|
85
+ dcb.write(key, value.to_i)
86
+ end
87
+ end
81
88
  Win32.set_comm_state(@handle, dcb)
82
89
 
83
- # Configure Timeouts
84
- Win32.set_comm_timeouts(@handle, 4294967295, 0, 0, 0, 0)
90
+ # Configure Timeouts, the WinAPI structure is COMMTIMEOUTS:
91
+ # DWORD ReadIntervalTimeout;
92
+ # DWORD ReadTotalTimeoutMultiplier;
93
+ # DWORD ReadTotalTimeoutConstant;
94
+ # DWORD WriteTotalTimeoutMultiplier;
95
+ # DWORD WriteTotalTimeoutConstant;
96
+ # 0xFFFFFFFF, 0, 0 specifies that the read operation is to return immediately
97
+ # with the bytes that have already been received, even if no bytes have been received.
98
+ # The WriteTotalTimeoutMultiplier is multiplied by the number of bytes to be written
99
+ # and the WriteTotalTimeoutConstant is added to that total (both are in milliseconds).
100
+ bits_per_symbol = data_bits + 1 # 1 start bit
101
+ case stop_bits
102
+ when Win32::ONESTOPBIT
103
+ bits_per_symbol += 1
104
+ when Win32::TWOSTOPBITS
105
+ bits_per_symbol += 2
106
+ end
107
+ case parity
108
+ when Win32::ODDPARITY, Win32::EVENPARITY
109
+ bits_per_symbol += 1
110
+ end
111
+ delay = (1000.0 / (baud_rate / bits_per_symbol.to_f)).ceil
112
+ Win32.set_comm_timeouts(@handle, 0xFFFFFFFF, 0, 0, delay, 1000)
85
113
  end
86
114
 
87
115
  # (see SerialDriver#close)
@@ -152,7 +152,7 @@ module Cosmos
152
152
 
153
153
  # Read Packet Data
154
154
  packet_data = @file.read_length_bytes(4, @max_read_size)
155
- return nil unless packet_data and packet_data.length > 0
155
+ return nil unless packet_data and packet_data.length >= 0
156
156
 
157
157
  if identify_and_define
158
158
  packet = identify_and_define_packet_data(target_name, packet_name, received_time, packet_data)
@@ -275,7 +275,7 @@ module Cosmos
275
275
  end
276
276
  packet.buffer = packet_data
277
277
  packet.set_received_time_fast(received_time)
278
- rescue
278
+ rescue Exception => error
279
279
  # Could not find a definition for this packet
280
280
  Logger.instance.error "Unknown packet #{target_name} #{packet_name}"
281
281
  packet = Packet.new(target_name, packet_name, :BIG_ENDIAN, nil, packet_data)
@@ -186,9 +186,9 @@ module Cosmos
186
186
  @read_conversion_cache.clear if @read_conversion_cache
187
187
  @received_count
188
188
  end
189
-
190
- end # if RUBY_ENGINE != 'ruby' or ENV['COSMOS_NO_EXT']
191
-
189
+
190
+ end # if RUBY_ENGINE != 'ruby' or ENV['COSMOS_NO_EXT']
191
+
192
192
  # Tries to identify if a buffer represents the currently defined packet. It
193
193
  # does this by iterating over all the packet items that were created with
194
194
  # an ID value and checking whether that ID value is present at the correct
@@ -216,7 +216,7 @@ module Cosmos
216
216
 
217
217
  true
218
218
  end
219
-
219
+
220
220
  # Reads the values from a buffer at the position of each id_item defined
221
221
  # in the packet.
222
222
  #
@@ -226,7 +226,7 @@ module Cosmos
226
226
  return [] unless buffer
227
227
  return [] unless @id_items
228
228
  values = []
229
-
229
+
230
230
  @id_items.each do |item|
231
231
  begin
232
232
  values << read_item(item, :RAW, buffer)
@@ -234,10 +234,10 @@ module Cosmos
234
234
  values << nil
235
235
  end
236
236
  end
237
-
237
+
238
238
  values
239
239
  end
240
-
240
+
241
241
  # Returns @received_time unless a packet item called PACKET_TIME exists that returns
242
242
  # a Ruby Time object that represents a different timestamp for the packet
243
243
  def packet_time
@@ -259,7 +259,7 @@ module Cosmos
259
259
  end
260
260
 
261
261
  # Use the hashing algorithm established by Cosmos::System
262
- digest = Digest.const_get(System.hashing_algorithm).send('new')
262
+ digest = Digest.const_get(System.hashing_algorithm).public_send('new')
263
263
  digest << string
264
264
  @config_name = digest.hexdigest
265
265
  @config_name
@@ -341,7 +341,7 @@ module Cosmos
341
341
  previous_item = nil
342
342
  warnings = []
343
343
  @sorted_items.each do |item|
344
- if expected_next_offset and item.bit_offset < expected_next_offset
344
+ if expected_next_offset and (item.bit_offset < expected_next_offset) and !item.overlap
345
345
  msg = "Bit definition overlap at bit offset #{item.bit_offset} for packet #{@target_name} #{@packet_name} items #{item.name} and #{previous_item.name}"
346
346
  Logger.instance.warn(msg)
347
347
  warnings << msg
@@ -198,14 +198,22 @@ module Cosmos
198
198
  #######################################################################
199
199
  # All the following keywords must have a current packet defined
200
200
  #######################################################################
201
- when 'SELECT_ITEM', 'SELECT_PARAMETER', 'ITEM', 'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER', 'APPEND_ITEM', 'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM', 'APPEND_ARRAY_PARAMETER', 'MACRO_APPEND_START', 'MACRO_APPEND_END', 'ALLOW_SHORT', 'HAZARDOUS', 'PROCESSOR', 'META', 'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED'
201
+ when 'SELECT_ITEM', 'SELECT_PARAMETER', 'DELETE_ITEM', 'DELETE_PARAMETER', 'ITEM',\
202
+ 'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER', 'APPEND_ITEM',\
203
+ 'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM',\
204
+ 'APPEND_ARRAY_PARAMETER', 'MACRO_APPEND_START', 'MACRO_APPEND_END', 'ALLOW_SHORT',\
205
+ 'HAZARDOUS', 'PROCESSOR', 'META', 'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED'
202
206
  raise parser.error("No current packet for #{keyword}") unless @current_packet
203
207
  process_current_packet(parser, keyword, params)
204
208
 
205
209
  #######################################################################
206
210
  # All the following keywords must have a current item defined
207
211
  #######################################################################
208
- when 'STATE', 'READ_CONVERSION', 'WRITE_CONVERSION', 'POLY_READ_CONVERSION', 'POLY_WRITE_CONVERSION', 'SEG_POLY_READ_CONVERSION', 'SEG_POLY_WRITE_CONVERSION', 'GENERIC_READ_CONVERSION_START', 'GENERIC_WRITE_CONVERSION_START', 'REQUIRED', 'LIMITS', 'LIMITS_RESPONSE', 'UNITS', 'FORMAT_STRING', 'DESCRIPTION', 'MINIMUM_VALUE', 'MAXIMUM_VALUE', 'DEFAULT_VALUE', 'OVERFLOW'
212
+ when 'STATE', 'READ_CONVERSION', 'WRITE_CONVERSION', 'POLY_READ_CONVERSION',\
213
+ 'POLY_WRITE_CONVERSION', 'SEG_POLY_READ_CONVERSION', 'SEG_POLY_WRITE_CONVERSION',\
214
+ 'GENERIC_READ_CONVERSION_START', 'GENERIC_WRITE_CONVERSION_START', 'REQUIRED',\
215
+ 'LIMITS', 'LIMITS_RESPONSE', 'UNITS', 'FORMAT_STRING', 'DESCRIPTION',\
216
+ 'MINIMUM_VALUE', 'MAXIMUM_VALUE', 'DEFAULT_VALUE', 'OVERFLOW', 'OVERLAP'
209
217
  raise parser.error("No current item for #{keyword}") unless @current_item
210
218
  process_current_item(parser, keyword, params)
211
219
 
@@ -327,25 +335,31 @@ module Cosmos
327
335
  def process_current_packet(parser, keyword, params)
328
336
  case keyword
329
337
 
330
- # Select an item in the current telemetry packet for editing
331
- when 'SELECT_PARAMETER', 'SELECT_ITEM'
338
+ # Select or delete an item in the current packet
339
+ when 'SELECT_PARAMETER', 'SELECT_ITEM', 'DELETE_PARAMETER', 'DELETE_ITEM'
332
340
  if (@current_cmd_or_tlm == COMMAND) && (keyword.split('_')[1] == 'ITEM')
333
- raise parser.error("SELECT_ITEM only applies to telemetry packets")
341
+ raise parser.error("#{keyword} only applies to telemetry packets")
334
342
  end
335
343
  if (@current_cmd_or_tlm == TELEMETRY) && (keyword.split('_')[1] == 'PARAMETER')
336
- raise parser.error("SELECT_PARAMETER only applies to command packets")
344
+ raise parser.error("#{keyword} only applies to command packets")
337
345
  end
338
346
  usage = "#{keyword} <#{keyword.split('_')[1]} NAME>"
339
347
  finish_item()
340
348
  parser.verify_num_parameters(1, 1, usage)
341
349
  begin
342
- @current_item = @current_packet.get_item(params[0])
350
+ if keyword.include?("SELECT")
351
+ @current_item = @current_packet.get_item(params[0])
352
+ else # DELETE
353
+ @current_packet.delete_item(params[0])
354
+ end
343
355
  rescue # Rescue the default execption to provide a nicer error message
344
356
  raise parser.error("#{params[0]} not found in #{@current_cmd_or_tlm.downcase} packet #{@current_packet.target_name} #{@current_packet.packet_name}", usage)
345
357
  end
346
358
 
347
359
  # Start a new telemetry item in the current packet
348
- when 'ITEM', 'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER', 'APPEND_ITEM', 'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM', 'APPEND_ARRAY_PARAMETER'
360
+ when 'ITEM', 'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER',\
361
+ 'APPEND_ITEM', 'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER',\
362
+ 'APPEND_ARRAY_ITEM', 'APPEND_ARRAY_PARAMETER'
349
363
  start_item(parser)
350
364
 
351
365
  # Start the creation of a macro-expanded list of items
@@ -429,7 +443,7 @@ module Cosmos
429
443
  klass = params[0].filename_to_class_name.to_class
430
444
  raise parser.error("#{params[0].filename_to_class_name} class not found. Did you require the file in target.txt?", usage) unless klass
431
445
  conversion = klass.new(*params[1..(params.length - 1)])
432
- @current_item.send("#{keyword.downcase}=".to_sym, conversion)
446
+ @current_item.public_send("#{keyword.downcase}=".to_sym, conversion)
433
447
  if klass != ProcessorConversion and (conversion.converted_type.nil? or conversion.converted_bit_size.nil?)
434
448
  msg = "Read Conversion #{params[0].filename_to_class_name} on item #{@current_item.name} does not specify converted type or bit size. Will not be supported by DART"
435
449
  @warnings << msg
@@ -570,6 +584,10 @@ module Cosmos
570
584
  parser.verify_num_parameters(1, 1, usage)
571
585
  @current_item.overflow = params[0].to_s.upcase.intern
572
586
 
587
+ when 'OVERLAP'
588
+ parser.verify_num_parameters(0, 0, 'OVERLAP')
589
+ @current_item.overlap = true
590
+
573
591
  end
574
592
  end
575
593