cosmos 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (912) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +48 -48
  4. data/.travis.yml +7 -7
  5. data/CONTRIBUTING.txt +50 -50
  6. data/Gemfile +6 -6
  7. data/Guardfile +27 -27
  8. data/LICENSE.txt +879 -879
  9. data/Manifest.txt +1116 -1114
  10. data/README.md +109 -107
  11. data/Rakefile +214 -214
  12. data/autohotkey/config/data/diamond.STL +57 -57
  13. data/autohotkey/config/system/system.txt +34 -34
  14. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  15. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  16. data/autohotkey/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  17. data/autohotkey/config/targets/COSMOS/target.txt +5 -5
  18. data/autohotkey/config/targets/INST/cmd_tlm/inst_cmds.txt +121 -121
  19. data/autohotkey/config/targets/INST/cmd_tlm/inst_tlm.txt +247 -247
  20. data/autohotkey/config/targets/INST/cmd_tlm_server.txt +5 -5
  21. data/autohotkey/config/targets/INST/lib/example_limits_response.rb +30 -30
  22. data/autohotkey/config/targets/INST/lib/sim_inst.rb +305 -294
  23. data/autohotkey/config/targets/INST/screens/adcs.txt +46 -46
  24. data/autohotkey/config/targets/INST/screens/array.txt +7 -7
  25. data/autohotkey/config/targets/INST/screens/block.txt +8 -8
  26. data/autohotkey/config/targets/INST/screens/commanding.txt +30 -30
  27. data/autohotkey/config/targets/INST/screens/graphs.txt +14 -14
  28. data/autohotkey/config/targets/INST/screens/ground.txt +25 -25
  29. data/autohotkey/config/targets/INST/screens/health_status.txt +33 -33
  30. data/autohotkey/config/targets/INST/screens/hs.txt +49 -49
  31. data/autohotkey/config/targets/INST/screens/image.txt +21 -21
  32. data/autohotkey/config/targets/INST/screens/latest.txt +23 -23
  33. data/autohotkey/config/targets/INST/screens/mech.txt +25 -25
  34. data/autohotkey/config/targets/INST/screens/other.txt +25 -25
  35. data/autohotkey/config/targets/INST/screens/params.txt +25 -25
  36. data/autohotkey/config/targets/INST/screens/tabs.txt +68 -68
  37. data/autohotkey/config/targets/INST/target.txt +26 -26
  38. data/autohotkey/config/targets/META/cmd_tlm/meta_cmd.txt +10 -10
  39. data/autohotkey/config/targets/META/cmd_tlm/meta_tlm.txt +9 -9
  40. data/autohotkey/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  41. data/autohotkey/config/targets/SYSTEM/screens/error.txt +11 -11
  42. data/autohotkey/config/tools/cmd_tlm_server/cmd_tlm_server.txt +22 -22
  43. data/autohotkey/config/tools/data_viewer/data_viewer.txt +11 -11
  44. data/autohotkey/config/tools/handbook_creator/handbook_creator.txt +49 -49
  45. data/autohotkey/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  46. data/autohotkey/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  47. data/autohotkey/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  48. data/autohotkey/config/tools/handbook_creator/templates/header.html.erb +25 -25
  49. data/autohotkey/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  50. data/autohotkey/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  51. data/autohotkey/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  52. data/autohotkey/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  53. data/autohotkey/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  54. data/autohotkey/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  55. data/autohotkey/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  56. data/autohotkey/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  57. data/autohotkey/config/tools/handbook_creator/templates/title.html.erb +1 -1
  58. data/autohotkey/config/tools/launcher/launcher.txt +38 -38
  59. data/autohotkey/config/tools/script_runner/script_runner.txt +3 -3
  60. data/autohotkey/config/tools/table_manager/ConfigTables_def.txt +8 -8
  61. data/autohotkey/config/tools/table_manager/OneDimensionalTable_def.txt +19 -19
  62. data/autohotkey/config/tools/table_manager/TwoDimensionalTable_def.txt +248 -248
  63. data/autohotkey/config/tools/test_runner/test_runner.txt +8 -8
  64. data/autohotkey/config/tools/test_runner/test_runner2.txt +11 -11
  65. data/autohotkey/config/tools/test_runner/test_runner3.txt +6 -6
  66. data/autohotkey/config/tools/test_runner/test_runner4.txt +1 -1
  67. data/autohotkey/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  68. data/autohotkey/config/tools/tlm_extractor/tlm_extractor2.txt +9 -9
  69. data/autohotkey/config/tools/tlm_grapher/bad.txt +50 -50
  70. data/autohotkey/config/tools/tlm_grapher/temp1-4.txt +51 -51
  71. data/autohotkey/config/tools/tlm_grapher/test2.txt +111 -111
  72. data/autohotkey/config/tools/tlm_viewer/tlm_viewer.txt +24 -24
  73. data/autohotkey/config/tools/tlm_viewer/tlm_viewer2.txt +4 -4
  74. data/autohotkey/config/tools/tlm_viewer/tlm_viewer3.txt +3 -3
  75. data/autohotkey/lib/example_background_task.rb +42 -42
  76. data/autohotkey/lib/user_version.rb +3 -3
  77. data/autohotkey/procedures/clear_util.rb +7 -7
  78. data/autohotkey/procedures/collect.rb +18 -18
  79. data/autohotkey/procedures/collect_util.rb +14 -14
  80. data/autohotkey/procedures/example_test.rb +67 -67
  81. data/autohotkey/procedures/example_test2.rb +74 -74
  82. data/autohotkey/procedures/script_test.rb +17 -17
  83. data/autohotkey/procedures/syntax_error.rb +18 -18
  84. data/autohotkey/tools/CmdExtractorAHK +16 -16
  85. data/autohotkey/tools/CmdSender +14 -14
  86. data/autohotkey/tools/CmdSenderAHK +18 -18
  87. data/autohotkey/tools/CmdTlmServer +14 -14
  88. data/autohotkey/tools/CmdTlmServerAHK +28 -28
  89. data/autohotkey/tools/CmdTlmServerAHK2 +17 -17
  90. data/autohotkey/tools/DataViewer +14 -14
  91. data/autohotkey/tools/DataViewerAHK +17 -17
  92. data/autohotkey/tools/HandbookCreatorAHK +20 -20
  93. data/autohotkey/tools/LauncherAHK +17 -17
  94. data/autohotkey/tools/LimitsMonitorAHK +20 -20
  95. data/autohotkey/tools/OpenGLBuilderAHK +20 -20
  96. data/autohotkey/tools/PacketViewer +14 -14
  97. data/autohotkey/tools/PacketViewerAHK +18 -18
  98. data/autohotkey/tools/PacketViewerAHK2 +17 -17
  99. data/autohotkey/tools/Replay +14 -14
  100. data/autohotkey/tools/Replay.bat +59 -59
  101. data/autohotkey/tools/ReplayAHK +17 -17
  102. data/autohotkey/tools/ScriptRunner +14 -14
  103. data/autohotkey/tools/ScriptRunnerAHK +20 -20
  104. data/autohotkey/tools/ScriptRunnerAHK2 +17 -17
  105. data/autohotkey/tools/TableManager +14 -14
  106. data/autohotkey/tools/TableManagerAHK +30 -30
  107. data/autohotkey/tools/TestRunner +15 -15
  108. data/autohotkey/tools/TestRunnerAHK +17 -17
  109. data/autohotkey/tools/TestRunnerAHK2 +17 -17
  110. data/autohotkey/tools/TestRunnerAHK3 +17 -17
  111. data/autohotkey/tools/TestRunnerAHK4 +17 -17
  112. data/autohotkey/tools/TlmExtractor +15 -15
  113. data/autohotkey/tools/TlmExtractorAHK +19 -19
  114. data/autohotkey/tools/TlmExtractorAHK2 +16 -16
  115. data/autohotkey/tools/TlmExtractorAHK3 +16 -16
  116. data/autohotkey/tools/TlmGrapher +14 -14
  117. data/autohotkey/tools/TlmGrapherAHK +19 -19
  118. data/autohotkey/tools/TlmGrapherAHK2 +23 -23
  119. data/autohotkey/tools/TlmGrapherAHK3 +17 -17
  120. data/autohotkey/tools/TlmGrapherAHK4 +17 -17
  121. data/autohotkey/tools/TlmViewer +14 -14
  122. data/autohotkey/tools/TlmViewerAHK +28 -28
  123. data/autohotkey/tools/TlmViewerAHK2 +18 -18
  124. data/autohotkey/tools/TlmViewerAHK3 +18 -18
  125. data/autohotkey/tools/TlmViewerAHK4 +18 -18
  126. data/autohotkey/tools/TlmViewerAHK5 +18 -18
  127. data/autohotkey/tools/autohotkey.rb +37 -37
  128. data/autohotkey/tools/cmd_extractor.ahk +27 -27
  129. data/autohotkey/tools/cmd_sender.ahk +182 -162
  130. data/autohotkey/tools/cmd_tlm_server.ahk +89 -89
  131. data/autohotkey/tools/cmd_tlm_server2.ahk +45 -45
  132. data/autohotkey/tools/data_viewer.ahk +135 -135
  133. data/autohotkey/tools/handbook_creator.ahk +23 -23
  134. data/autohotkey/tools/launcher.ahk +41 -41
  135. data/autohotkey/tools/limits_monitor.ahk +70 -70
  136. data/autohotkey/tools/open_gl_builder.ahk +134 -134
  137. data/autohotkey/tools/packet_viewer.ahk +143 -143
  138. data/autohotkey/tools/packet_viewer2.ahk +9 -9
  139. data/autohotkey/tools/replay.ahk +98 -98
  140. data/autohotkey/tools/script_runner.ahk +589 -589
  141. data/autohotkey/tools/script_runner2.ahk +34 -31
  142. data/autohotkey/tools/table_manager.ahk +220 -220
  143. data/autohotkey/tools/test_runner.ahk +262 -259
  144. data/autohotkey/tools/test_runner2.ahk +52 -52
  145. data/autohotkey/tools/test_runner3.ahk +13 -13
  146. data/autohotkey/tools/tlm_extractor.ahk +272 -272
  147. data/autohotkey/tools/tlm_grapher.ahk +642 -642
  148. data/autohotkey/tools/tlm_grapher2.ahk +115 -115
  149. data/autohotkey/tools/tlm_grapher3.ahk +24 -24
  150. data/autohotkey/tools/tlm_viewer.ahk +133 -133
  151. data/autohotkey/tools/tlm_viewer2.ahk +50 -49
  152. data/autohotkey/tools/tlm_viewer4.ahk +4 -4
  153. data/autohotkey/tools/tlm_viewer5.ahk +20 -20
  154. data/bin/cosmos +96 -96
  155. data/bin/cstol_converter +1166 -1166
  156. data/bin/rubysloc +85 -85
  157. data/cosmos.gemspec +98 -97
  158. data/data/about.txt +4 -4
  159. data/data/crc.txt +306 -305
  160. data/data/diamond.STL +57 -57
  161. data/data/legal.txt +9 -9
  162. data/demo/Gemfile +6 -6
  163. data/demo/Launcher +15 -15
  164. data/demo/Launcher.bat +59 -59
  165. data/demo/Rakefile +61 -61
  166. data/demo/config/data/crc.txt +222 -206
  167. data/demo/config/data/diamond.STL +57 -57
  168. data/demo/config/data/meta_init.txt +4 -4
  169. data/demo/config/system/system.txt +34 -34
  170. data/demo/config/system/system2.txt +33 -33
  171. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  172. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  173. data/demo/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  174. data/demo/config/targets/COSMOS/screens/limits_change.txt +20 -20
  175. data/demo/config/targets/COSMOS/screens/version.txt +19 -19
  176. data/demo/config/targets/COSMOS/target.txt +11 -11
  177. data/demo/config/targets/EXAMPLE/cmd_tlm/example_cmds.txt +2 -2
  178. data/demo/config/targets/EXAMPLE/cmd_tlm/example_tlm.txt +3 -3
  179. data/demo/config/targets/EXAMPLE/cmd_tlm_server.txt +6 -6
  180. data/demo/config/targets/EXAMPLE/lib/example_interface.rb +22 -22
  181. data/demo/config/targets/EXAMPLE/target.txt +6 -6
  182. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +121 -121
  183. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +247 -247
  184. data/demo/config/targets/INST/cmd_tlm_server.txt +5 -5
  185. data/demo/config/targets/INST/lib/example_limits_response.rb +30 -30
  186. data/demo/config/targets/INST/lib/sim_inst.rb +305 -294
  187. data/demo/config/targets/INST/screens/adcs.txt +46 -46
  188. data/demo/config/targets/INST/screens/array.txt +15 -15
  189. data/demo/config/targets/INST/screens/block.txt +8 -8
  190. data/demo/config/targets/INST/screens/commanding.txt +30 -30
  191. data/demo/config/targets/INST/screens/graphs.txt +14 -14
  192. data/demo/config/targets/INST/screens/ground.txt +25 -25
  193. data/demo/config/targets/INST/screens/hs.txt +44 -44
  194. data/demo/config/targets/INST/screens/latest.txt +23 -23
  195. data/demo/config/targets/INST/screens/other.txt +29 -29
  196. data/demo/config/targets/INST/screens/tabs.txt +70 -70
  197. data/demo/config/targets/INST/target.txt +33 -33
  198. data/demo/config/targets/META/cmd_tlm/meta_cmd.txt +10 -10
  199. data/demo/config/targets/META/cmd_tlm/meta_tlm.txt +13 -13
  200. data/demo/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  201. data/demo/config/targets/SYSTEM/cmd_tlm/override.txt +29 -29
  202. data/demo/config/targets/SYSTEM/screens/status.txt +12 -12
  203. data/demo/config/targets/TEMPLATED/cmd_tlm/templated_cmds.txt +13 -12
  204. data/demo/config/targets/TEMPLATED/cmd_tlm/templated_tlm.txt +3 -3
  205. data/demo/config/targets/TEMPLATED/cmd_tlm_server.txt +6 -6
  206. data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +54 -48
  207. data/demo/config/targets/TEMPLATED/target.txt +6 -6
  208. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +33 -33
  209. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +29 -29
  210. data/demo/config/tools/data_viewer/data_viewer.txt +11 -11
  211. data/demo/config/tools/handbook_creator/handbook_creator.txt +66 -66
  212. data/demo/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  213. data/demo/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  214. data/demo/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  215. data/demo/config/tools/handbook_creator/templates/header.html.erb +25 -25
  216. data/demo/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  217. data/demo/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  218. data/demo/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  219. data/demo/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  220. data/demo/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  221. data/demo/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  222. data/demo/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  223. data/demo/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  224. data/demo/config/tools/handbook_creator/templates/title.html.erb +1 -1
  225. data/demo/config/tools/launcher/launcher.txt +45 -45
  226. data/demo/config/tools/launcher/launcher2.txt +45 -45
  227. data/demo/config/tools/script_runner/script_runner.txt +3 -3
  228. data/demo/config/tools/table_manager/ConfigTables_def.txt +8 -8
  229. data/demo/config/tools/table_manager/ExampleTableDefinition.txt +24 -24
  230. data/demo/config/tools/table_manager/MCConfigurationTable_fsw1_def.txt +25 -25
  231. data/demo/config/tools/table_manager/MCConfigurationTable_fsw2_def.txt +25 -25
  232. data/demo/config/tools/table_manager/PPSSelectionTable_def.txt +8 -8
  233. data/demo/config/tools/table_manager/TLMMonitoringTable_def.txt +248 -248
  234. data/demo/config/tools/test_runner/test_runner.txt +17 -17
  235. data/demo/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  236. data/demo/config/tools/tlm_extractor/tlm_extractor2.txt +2 -2
  237. data/demo/config/tools/tlm_extractor/tlm_extractor3.txt +2 -2
  238. data/demo/config/tools/tlm_extractor/tlm_extractor4.txt +2 -2
  239. data/demo/config/tools/tlm_viewer/tlm_viewer.txt +41 -41
  240. data/demo/lib/example_background_task.rb +57 -52
  241. data/demo/lib/example_target.rb +113 -108
  242. data/demo/lib/scpi_target.rb +74 -74
  243. data/demo/lib/user_version.rb +3 -3
  244. data/demo/procedures/checks.rb +11 -11
  245. data/demo/procedures/clear_util.rb +7 -7
  246. data/demo/procedures/collect.rb +18 -18
  247. data/demo/procedures/collect_util.rb +14 -14
  248. data/demo/procedures/cosmos_api_test.rb +293 -293
  249. data/demo/procedures/disconnect.rb +29 -29
  250. data/demo/procedures/example_test.rb +182 -182
  251. data/demo/procedures/plot_test.rb +8 -8
  252. data/demo/procedures/run_example_test.rb +3 -3
  253. data/demo/procedures/test.rb +51 -51
  254. data/demo/tools/CmdExtractor +15 -15
  255. data/demo/tools/CmdExtractor.bat +59 -59
  256. data/demo/tools/CmdSender +15 -15
  257. data/demo/tools/CmdSender.bat +59 -59
  258. data/demo/tools/CmdTlmServer +15 -15
  259. data/demo/tools/CmdTlmServer.bat +59 -59
  260. data/demo/tools/DataViewer +15 -15
  261. data/demo/tools/DataViewer.bat +59 -59
  262. data/demo/tools/ExampleTarget +15 -15
  263. data/demo/tools/ExampleTarget.bat +59 -59
  264. data/demo/tools/HandbookCreator +15 -15
  265. data/demo/tools/HandbookCreator.bat +61 -61
  266. data/demo/tools/Launcher +15 -15
  267. data/demo/tools/Launcher.bat +59 -59
  268. data/demo/tools/LimitsMonitor +15 -15
  269. data/demo/tools/LimitsMonitor.bat +59 -59
  270. data/demo/tools/OpenGLBuilder +15 -15
  271. data/demo/tools/OpenGLBuilder.bat +59 -59
  272. data/demo/tools/PacketViewer +15 -15
  273. data/demo/tools/PacketViewer.bat +59 -59
  274. data/demo/tools/Replay +15 -15
  275. data/demo/tools/Replay.bat +59 -59
  276. data/demo/tools/ScpiTarget +15 -15
  277. data/demo/tools/ScpiTarget.bat +59 -59
  278. data/demo/tools/ScriptRunner +15 -15
  279. data/demo/tools/ScriptRunner.bat +59 -59
  280. data/demo/tools/TableManager +15 -15
  281. data/demo/tools/TableManager.bat +59 -59
  282. data/demo/tools/TestRunner +15 -15
  283. data/demo/tools/TestRunner.bat +59 -59
  284. data/demo/tools/TlmExtractor +15 -15
  285. data/demo/tools/TlmExtractor.bat +59 -59
  286. data/demo/tools/TlmGrapher +15 -15
  287. data/demo/tools/TlmGrapher.bat +59 -59
  288. data/demo/tools/TlmViewer +15 -15
  289. data/demo/tools/TlmViewer.bat +59 -59
  290. data/demo/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  291. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +15 -15
  292. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +6 -6
  293. data/demo/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  294. data/demo/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +15 -15
  295. data/demo/tools/mac/CmdSender.app/Contents/MacOS/main.sh +6 -6
  296. data/demo/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  297. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +15 -15
  298. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +6 -6
  299. data/demo/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  300. data/demo/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +15 -15
  301. data/demo/tools/mac/DataViewer.app/Contents/MacOS/main.sh +6 -6
  302. data/demo/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  303. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +15 -15
  304. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +6 -6
  305. data/demo/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  306. data/demo/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +15 -15
  307. data/demo/tools/mac/Launcher.app/Contents/MacOS/main.sh +6 -6
  308. data/demo/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  309. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +15 -15
  310. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +6 -6
  311. data/demo/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  312. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +15 -15
  313. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +6 -6
  314. data/demo/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  315. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +15 -15
  316. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +6 -6
  317. data/demo/tools/mac/Replay.app/Contents/Info.plist +38 -38
  318. data/demo/tools/mac/Replay.app/Contents/MacOS/Replay.rb +15 -15
  319. data/demo/tools/mac/Replay.app/Contents/MacOS/main.sh +6 -6
  320. data/demo/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  321. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +15 -15
  322. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +6 -6
  323. data/demo/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  324. data/demo/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +15 -15
  325. data/demo/tools/mac/TableManager.app/Contents/MacOS/main.sh +6 -6
  326. data/demo/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  327. data/demo/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +15 -15
  328. data/demo/tools/mac/TestRunner.app/Contents/MacOS/main.sh +6 -6
  329. data/demo/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  330. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +15 -15
  331. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +6 -6
  332. data/demo/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  333. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +15 -15
  334. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +6 -6
  335. data/demo/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  336. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +15 -15
  337. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +6 -6
  338. data/ext/cosmos/ext/array/array.c +111 -111
  339. data/ext/cosmos/ext/array/extconf.rb +13 -13
  340. data/ext/cosmos/ext/buffered_file/buffered_file.c +167 -167
  341. data/ext/cosmos/ext/buffered_file/extconf.rb +13 -13
  342. data/ext/cosmos/ext/config_parser/config_parser.c +237 -237
  343. data/ext/cosmos/ext/config_parser/extconf.rb +13 -13
  344. data/ext/cosmos/ext/cosmos_io/cosmos_io.c +117 -117
  345. data/ext/cosmos/ext/cosmos_io/extconf.rb +13 -13
  346. data/ext/cosmos/ext/crc/crc.c +341 -341
  347. data/ext/cosmos/ext/crc/extconf.rb +12 -12
  348. data/ext/cosmos/ext/line_graph/extconf.rb +13 -13
  349. data/ext/cosmos/ext/line_graph/line_graph.c +501 -501
  350. data/ext/cosmos/ext/low_fragmentation_array/extconf.rb +12 -12
  351. data/ext/cosmos/ext/low_fragmentation_array/low_fragmentation_array.c +261 -261
  352. data/ext/cosmos/ext/packet/extconf.rb +13 -13
  353. data/ext/cosmos/ext/packet/packet.c +339 -339
  354. data/ext/cosmos/ext/platform/extconf.rb +13 -13
  355. data/ext/cosmos/ext/platform/platform.c +81 -81
  356. data/ext/cosmos/ext/polynomial_conversion/extconf.rb +13 -13
  357. data/ext/cosmos/ext/polynomial_conversion/polynomial_conversion.c +73 -73
  358. data/ext/cosmos/ext/string/extconf.rb +13 -13
  359. data/ext/cosmos/ext/string/string.c +49 -49
  360. data/ext/cosmos/ext/structure/structure.c +894 -894
  361. data/ext/cosmos/ext/tabbed_plots_config/extconf.rb +13 -13
  362. data/ext/cosmos/ext/tabbed_plots_config/tabbed_plots_config.c +51 -51
  363. data/ext/cosmos/ext/telemetry/extconf.rb +13 -13
  364. data/ext/cosmos/ext/telemetry/telemetry.c +306 -306
  365. data/ext/mkrf_conf.rb +40 -40
  366. data/install/Gemfile +6 -6
  367. data/install/Launcher +14 -14
  368. data/install/Launcher.bat +59 -59
  369. data/install/Rakefile +61 -61
  370. data/install/config/data/crc.txt +134 -133
  371. data/install/config/system/system.txt +29 -29
  372. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  373. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  374. data/install/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  375. data/install/config/targets/COSMOS/screens/limits_change.txt +20 -20
  376. data/install/config/targets/COSMOS/screens/version.txt +19 -19
  377. data/install/config/targets/COSMOS/target.txt +8 -8
  378. data/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +2 -2
  379. data/install/config/tools/data_viewer/data_viewer.txt +3 -3
  380. data/install/config/tools/handbook_creator/handbook_creator.txt +49 -49
  381. data/install/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  382. data/install/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  383. data/install/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  384. data/install/config/tools/handbook_creator/templates/header.html.erb +25 -25
  385. data/install/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  386. data/install/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  387. data/install/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  388. data/install/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  389. data/install/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  390. data/install/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  391. data/install/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  392. data/install/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  393. data/install/config/tools/handbook_creator/templates/title.html.erb +1 -1
  394. data/install/config/tools/launcher/launcher.txt +39 -39
  395. data/install/config/tools/script_runner/script_runner.txt +3 -3
  396. data/install/config/tools/test_runner/test_runner.txt +8 -8
  397. data/install/config/tools/tlm_viewer/tlm_viewer.txt +5 -5
  398. data/install/lib/user_version.rb +3 -3
  399. data/install/tools/CmdExtractor +15 -15
  400. data/install/tools/CmdExtractor.bat +59 -59
  401. data/install/tools/CmdSender +15 -15
  402. data/install/tools/CmdSender.bat +59 -59
  403. data/install/tools/CmdTlmServer +15 -15
  404. data/install/tools/CmdTlmServer.bat +59 -59
  405. data/install/tools/DataViewer +15 -15
  406. data/install/tools/DataViewer.bat +59 -59
  407. data/install/tools/HandbookCreator +15 -15
  408. data/install/tools/HandbookCreator.bat +61 -61
  409. data/install/tools/Launcher +15 -15
  410. data/install/tools/Launcher.bat +59 -59
  411. data/install/tools/LimitsMonitor +15 -15
  412. data/install/tools/LimitsMonitor.bat +59 -59
  413. data/install/tools/OpenGLBuilder +15 -15
  414. data/install/tools/OpenGLBuilder.bat +59 -59
  415. data/install/tools/PacketViewer +15 -15
  416. data/install/tools/PacketViewer.bat +59 -59
  417. data/install/tools/Replay +15 -15
  418. data/install/tools/Replay.bat +59 -59
  419. data/install/tools/ScriptRunner +15 -15
  420. data/install/tools/ScriptRunner.bat +59 -59
  421. data/install/tools/TableManager +15 -15
  422. data/install/tools/TableManager.bat +59 -59
  423. data/install/tools/TestRunner +15 -15
  424. data/install/tools/TestRunner.bat +59 -59
  425. data/install/tools/TlmExtractor +15 -15
  426. data/install/tools/TlmExtractor.bat +59 -59
  427. data/install/tools/TlmGrapher +15 -15
  428. data/install/tools/TlmGrapher.bat +59 -59
  429. data/install/tools/TlmViewer +15 -15
  430. data/install/tools/TlmViewer.bat +59 -59
  431. data/install/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  432. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +15 -15
  433. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +6 -6
  434. data/install/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  435. data/install/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +15 -15
  436. data/install/tools/mac/CmdSender.app/Contents/MacOS/main.sh +6 -6
  437. data/install/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  438. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +15 -15
  439. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +6 -6
  440. data/install/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  441. data/install/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +15 -15
  442. data/install/tools/mac/DataViewer.app/Contents/MacOS/main.sh +6 -6
  443. data/install/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  444. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +15 -15
  445. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +6 -6
  446. data/install/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  447. data/install/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +15 -15
  448. data/install/tools/mac/Launcher.app/Contents/MacOS/main.sh +6 -6
  449. data/install/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  450. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +15 -15
  451. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +6 -6
  452. data/install/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  453. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +15 -15
  454. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +6 -6
  455. data/install/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  456. data/install/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +15 -15
  457. data/install/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +6 -6
  458. data/install/tools/mac/Replay.app/Contents/Info.plist +38 -38
  459. data/install/tools/mac/Replay.app/Contents/MacOS/Replay.rb +15 -15
  460. data/install/tools/mac/Replay.app/Contents/MacOS/main.sh +6 -6
  461. data/install/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  462. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +15 -15
  463. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +6 -6
  464. data/install/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  465. data/install/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +15 -15
  466. data/install/tools/mac/TableManager.app/Contents/MacOS/main.sh +6 -6
  467. data/install/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  468. data/install/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +15 -15
  469. data/install/tools/mac/TestRunner.app/Contents/MacOS/main.sh +6 -6
  470. data/install/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  471. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +15 -15
  472. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +6 -6
  473. data/install/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  474. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +15 -15
  475. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +6 -6
  476. data/install/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  477. data/install/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +15 -15
  478. data/install/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +6 -6
  479. data/lib/cosmos.rb +63 -63
  480. data/lib/cosmos/ccsds/ccsds_packet.rb +63 -63
  481. data/lib/cosmos/ccsds/ccsds_parser.rb +143 -143
  482. data/lib/cosmos/config/config_parser.rb +324 -324
  483. data/lib/cosmos/conversions.rb +13 -13
  484. data/lib/cosmos/conversions/conversion.rb +47 -47
  485. data/lib/cosmos/conversions/generic_conversion.rb +55 -55
  486. data/lib/cosmos/conversions/new_packet_log_conversion.rb +45 -45
  487. data/lib/cosmos/conversions/polynomial_conversion.rb +57 -57
  488. data/lib/cosmos/conversions/processor_conversion.rb +46 -46
  489. data/lib/cosmos/conversions/received_count_conversion.rb +33 -33
  490. data/lib/cosmos/conversions/received_time_formatted_conversion.rb +37 -37
  491. data/lib/cosmos/conversions/received_time_seconds_conversion.rb +37 -37
  492. data/lib/cosmos/conversions/segmented_polynomial_conversion.rb +128 -128
  493. data/lib/cosmos/conversions/unix_time_conversion.rb +50 -50
  494. data/lib/cosmos/conversions/unix_time_formatted_conversion.rb +44 -44
  495. data/lib/cosmos/conversions/unix_time_seconds_conversion.rb +44 -44
  496. data/lib/cosmos/core_ext.rb +18 -18
  497. data/lib/cosmos/core_ext/array.rb +354 -354
  498. data/lib/cosmos/core_ext/class.rb +51 -51
  499. data/lib/cosmos/core_ext/cosmos_io.rb +29 -29
  500. data/lib/cosmos/core_ext/exception.rb +52 -52
  501. data/lib/cosmos/core_ext/file.rb +75 -75
  502. data/lib/cosmos/core_ext/hash.rb +28 -28
  503. data/lib/cosmos/core_ext/io.rb +75 -75
  504. data/lib/cosmos/core_ext/kernel.rb +38 -38
  505. data/lib/cosmos/core_ext/math.rb +119 -119
  506. data/lib/cosmos/core_ext/matrix.rb +146 -146
  507. data/lib/cosmos/core_ext/objectspace.rb +29 -29
  508. data/lib/cosmos/core_ext/range.rb +22 -22
  509. data/lib/cosmos/core_ext/socket.rb +32 -32
  510. data/lib/cosmos/core_ext/string.rb +310 -310
  511. data/lib/cosmos/core_ext/stringio.rb +24 -24
  512. data/lib/cosmos/core_ext/time.rb +446 -446
  513. data/lib/cosmos/gui/choosers/combobox_chooser.rb +130 -130
  514. data/lib/cosmos/gui/choosers/file_chooser.rb +68 -68
  515. data/lib/cosmos/gui/choosers/float_chooser.rb +82 -82
  516. data/lib/cosmos/gui/choosers/integer_chooser.rb +80 -80
  517. data/lib/cosmos/gui/choosers/string_chooser.rb +53 -53
  518. data/lib/cosmos/gui/choosers/telemetry_chooser.rb +317 -317
  519. data/lib/cosmos/gui/dialogs/about_dialog.rb +128 -128
  520. data/lib/cosmos/gui/dialogs/calendar_dialog.rb +136 -136
  521. data/lib/cosmos/gui/dialogs/cmd_details_dialog.rb +52 -52
  522. data/lib/cosmos/gui/dialogs/cmd_tlm_raw_dialog.rb +149 -149
  523. data/lib/cosmos/gui/dialogs/details_dialog.rb +174 -174
  524. data/lib/cosmos/gui/dialogs/exception_dialog.rb +97 -97
  525. data/lib/cosmos/gui/dialogs/exception_list_dialog.rb +59 -59
  526. data/lib/cosmos/gui/dialogs/find_replace_dialog.rb +196 -196
  527. data/lib/cosmos/gui/dialogs/legal_dialog.rb +169 -168
  528. data/lib/cosmos/gui/dialogs/packet_log_dialog.rb +118 -118
  529. data/lib/cosmos/gui/dialogs/progress_dialog.rb +270 -262
  530. data/lib/cosmos/gui/dialogs/pry_dialog.rb +165 -161
  531. data/lib/cosmos/gui/dialogs/scroll_text_dialog.rb +37 -37
  532. data/lib/cosmos/gui/dialogs/select_dialog.rb +54 -54
  533. data/lib/cosmos/gui/dialogs/set_tlm_dialog.rb +131 -131
  534. data/lib/cosmos/gui/dialogs/splash.rb +113 -113
  535. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +206 -206
  536. data/lib/cosmos/gui/dialogs/tlm_edit_dialog.rb +81 -81
  537. data/lib/cosmos/gui/line_graph/line_graph.rb +456 -456
  538. data/lib/cosmos/gui/line_graph/line_graph_dialog.rb +34 -34
  539. data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +494 -494
  540. data/lib/cosmos/gui/line_graph/line_graph_popups.rb +116 -116
  541. data/lib/cosmos/gui/line_graph/line_graph_scaling.rb +460 -460
  542. data/lib/cosmos/gui/line_graph/line_graph_script.rb +26 -26
  543. data/lib/cosmos/gui/line_graph/lines.rb +290 -290
  544. data/lib/cosmos/gui/line_graph/overview_graph.rb +459 -459
  545. data/lib/cosmos/gui/opengl/earth_model.rb +22 -22
  546. data/lib/cosmos/gui/opengl/gl_bounds.rb +67 -67
  547. data/lib/cosmos/gui/opengl/gl_light.rb +39 -39
  548. data/lib/cosmos/gui/opengl/gl_material.rb +29 -29
  549. data/lib/cosmos/gui/opengl/gl_scene.rb +72 -72
  550. data/lib/cosmos/gui/opengl/gl_shape.rb +146 -146
  551. data/lib/cosmos/gui/opengl/gl_viewer.rb +724 -712
  552. data/lib/cosmos/gui/opengl/gl_viewport.rb +35 -35
  553. data/lib/cosmos/gui/opengl/moon_model.rb +22 -22
  554. data/lib/cosmos/gui/opengl/opengl.rb +8 -8
  555. data/lib/cosmos/gui/opengl/stl_reader.rb +211 -211
  556. data/lib/cosmos/gui/opengl/stl_shape.rb +124 -124
  557. data/lib/cosmos/gui/opengl/texture_mapped_sphere.rb +202 -202
  558. data/lib/cosmos/gui/qt.rb +813 -786
  559. data/lib/cosmos/gui/qt_tool.rb +378 -373
  560. data/lib/cosmos/gui/text/completion.rb +381 -381
  561. data/lib/cosmos/gui/text/completion_line_edit.rb +30 -30
  562. data/lib/cosmos/gui/text/completion_text_edit.rb +179 -179
  563. data/lib/cosmos/gui/text/ruby_editor.rb +395 -395
  564. data/lib/cosmos/gui/utilities/screenshot.rb +25 -25
  565. data/lib/cosmos/gui/utilities/script_module_gui.rb +203 -203
  566. data/lib/cosmos/gui/widgets/full_text_search_line_edit.rb +161 -161
  567. data/lib/cosmos/gui/widgets/packet_log_frame.rb +305 -305
  568. data/lib/cosmos/gui/widgets/realtime_button_bar.rb +98 -98
  569. data/lib/cosmos/interfaces.rb +11 -11
  570. data/lib/cosmos/interfaces/cmd_tlm_server_interface.rb +153 -149
  571. data/lib/cosmos/interfaces/interface.rb +213 -213
  572. data/lib/cosmos/interfaces/linc_interface.rb +360 -360
  573. data/lib/cosmos/interfaces/serial_interface.rb +76 -76
  574. data/lib/cosmos/interfaces/simulated_target_interface.rb +129 -128
  575. data/lib/cosmos/interfaces/stream_interface.rb +156 -156
  576. data/lib/cosmos/interfaces/tcpip_client_interface.rb +60 -60
  577. data/lib/cosmos/interfaces/tcpip_server_interface.rb +154 -154
  578. data/lib/cosmos/interfaces/udp_interface.rb +173 -173
  579. data/lib/cosmos/io/buffered_file.rb +11 -11
  580. data/lib/cosmos/io/cosmos_snmp.rb +50 -50
  581. data/lib/cosmos/io/io_multiplexer.rb +89 -89
  582. data/lib/cosmos/io/json_drb.rb +344 -320
  583. data/lib/cosmos/io/json_drb_object.rb +137 -137
  584. data/lib/cosmos/io/json_rpc.rb +365 -365
  585. data/lib/cosmos/io/posix_serial_driver.rb +145 -145
  586. data/lib/cosmos/io/raw_logger.rb +174 -174
  587. data/lib/cosmos/io/raw_logger_pair.rb +71 -71
  588. data/lib/cosmos/io/serial_driver.rb +85 -85
  589. data/lib/cosmos/io/stderr.rb +36 -36
  590. data/lib/cosmos/io/stdout.rb +36 -36
  591. data/lib/cosmos/io/tcpip_server.rb +583 -532
  592. data/lib/cosmos/io/udp_sockets.rb +152 -152
  593. data/lib/cosmos/io/win32_serial_driver.rb +147 -147
  594. data/lib/cosmos/packet_logs.rb +6 -6
  595. data/lib/cosmos/packet_logs/meta_packet_log_writer.rb +107 -107
  596. data/lib/cosmos/packet_logs/packet_log_reader.rb +441 -439
  597. data/lib/cosmos/packet_logs/packet_log_writer.rb +321 -309
  598. data/lib/cosmos/packet_logs/packet_log_writer_pair.rb +30 -30
  599. data/lib/cosmos/packets/binary_accessor.rb +921 -921
  600. data/lib/cosmos/packets/commands.rb +291 -291
  601. data/lib/cosmos/packets/limits.rb +263 -263
  602. data/lib/cosmos/packets/limits_response.rb +38 -38
  603. data/lib/cosmos/packets/packet.rb +714 -699
  604. data/lib/cosmos/packets/packet_config.rb +1034 -1034
  605. data/lib/cosmos/packets/packet_item.rb +317 -317
  606. data/lib/cosmos/packets/packet_item_limits.rb +128 -128
  607. data/lib/cosmos/packets/structure.rb +421 -386
  608. data/lib/cosmos/packets/structure_item.rb +233 -233
  609. data/lib/cosmos/packets/telemetry.rb +317 -317
  610. data/lib/cosmos/processors.rb +6 -6
  611. data/lib/cosmos/processors/new_packet_log_processor.rb +34 -34
  612. data/lib/cosmos/processors/processor.rb +71 -71
  613. data/lib/cosmos/processors/statistics_processor.rb +65 -65
  614. data/lib/cosmos/processors/watermark_processor.rb +44 -44
  615. data/lib/cosmos/script.rb +9 -9
  616. data/lib/cosmos/script/extract.rb +115 -115
  617. data/lib/cosmos/script/script.rb +1513 -1493
  618. data/lib/cosmos/streams/burst_stream_protocol.rb +25 -25
  619. data/lib/cosmos/streams/fixed_stream_protocol.rb +111 -111
  620. data/lib/cosmos/streams/length_stream_protocol.rb +140 -140
  621. data/lib/cosmos/streams/preidentified_stream_protocol.rb +118 -118
  622. data/lib/cosmos/streams/serial_stream.rb +152 -143
  623. data/lib/cosmos/streams/stream.rb +57 -57
  624. data/lib/cosmos/streams/stream_protocol.rb +369 -369
  625. data/lib/cosmos/streams/tcpip_client_stream.rb +77 -77
  626. data/lib/cosmos/streams/tcpip_socket_stream.rb +139 -139
  627. data/lib/cosmos/streams/template_stream_protocol.rb +140 -140
  628. data/lib/cosmos/streams/terminated_stream_protocol.rb +81 -81
  629. data/lib/cosmos/system.rb +4 -4
  630. data/lib/cosmos/system/system.rb +558 -558
  631. data/lib/cosmos/system/target.rb +178 -178
  632. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +254 -253
  633. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +716 -716
  634. data/lib/cosmos/tools/cmd_sender/cmd_sender_item_delegate.rb +77 -77
  635. data/lib/cosmos/tools/cmd_sender/cmd_sender_text_edit.rb +70 -70
  636. data/lib/cosmos/tools/cmd_tlm_server/api.rb +936 -940
  637. data/lib/cosmos/tools/cmd_tlm_server/background_task.rb +46 -46
  638. data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +67 -63
  639. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +511 -497
  640. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +241 -241
  641. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +1033 -1008
  642. data/lib/cosmos/tools/cmd_tlm_server/commanding.rb +112 -112
  643. data/lib/cosmos/tools/cmd_tlm_server/connections.rb +176 -176
  644. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +241 -221
  645. data/lib/cosmos/tools/cmd_tlm_server/interfaces.rb +127 -127
  646. data/lib/cosmos/tools/cmd_tlm_server/packet_logging.rb +132 -132
  647. data/lib/cosmos/tools/cmd_tlm_server/router_thread.rb +66 -66
  648. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +97 -97
  649. data/lib/cosmos/tools/data_viewer/data_viewer.rb +628 -600
  650. data/lib/cosmos/tools/data_viewer/data_viewer_component.rb +167 -167
  651. data/lib/cosmos/tools/data_viewer/dump_component.rb +40 -40
  652. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +149 -149
  653. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +360 -360
  654. data/lib/cosmos/tools/launcher/launcher.rb +184 -184
  655. data/lib/cosmos/tools/launcher/launcher_config.rb +175 -167
  656. data/lib/cosmos/tools/launcher/launcher_multitool.rb +40 -41
  657. data/lib/cosmos/tools/launcher/launcher_tool.rb +104 -104
  658. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +796 -768
  659. data/lib/cosmos/tools/opengl_builder/opengl_builder.rb +416 -416
  660. data/lib/cosmos/tools/opengl_builder/scene_config.rb +118 -118
  661. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +525 -525
  662. data/lib/cosmos/tools/replay/replay.rb +495 -488
  663. data/lib/cosmos/tools/replay/replay_server.rb +91 -91
  664. data/lib/cosmos/tools/script_runner/script_audit.rb +147 -139
  665. data/lib/cosmos/tools/script_runner/script_runner.rb +914 -914
  666. data/lib/cosmos/tools/script_runner/script_runner_config.rb +40 -40
  667. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +1892 -1859
  668. data/lib/cosmos/tools/table_manager/table.rb +70 -70
  669. data/lib/cosmos/tools/table_manager/table_config.rb +764 -764
  670. data/lib/cosmos/tools/table_manager/table_item.rb +74 -74
  671. data/lib/cosmos/tools/table_manager/table_manager.rb +1065 -1065
  672. data/lib/cosmos/tools/table_manager/table_manager_core.rb +539 -539
  673. data/lib/cosmos/tools/test_runner/results_writer.rb +283 -283
  674. data/lib/cosmos/tools/test_runner/test.rb +480 -480
  675. data/lib/cosmos/tools/test_runner/test_runner.rb +1157 -1157
  676. data/lib/cosmos/tools/test_runner/test_runner_chooser.rb +338 -338
  677. data/lib/cosmos/tools/tlm_extractor/text_item_chooser.rb +60 -60
  678. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +1008 -1008
  679. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +371 -371
  680. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +60 -60
  681. data/lib/cosmos/tools/tlm_grapher/data_object_adders/housekeeping_data_object_adder.rb +75 -75
  682. data/lib/cosmos/tools/tlm_grapher/data_object_adders/singlexy_data_object_adder.rb +44 -44
  683. data/lib/cosmos/tools/tlm_grapher/data_object_adders/xy_data_object_adder.rb +94 -94
  684. data/lib/cosmos/tools/tlm_grapher/data_object_editors/data_object_editor.rb +61 -61
  685. data/lib/cosmos/tools/tlm_grapher/data_object_editors/housekeeping_data_object_editor.rb +180 -180
  686. data/lib/cosmos/tools/tlm_grapher/data_object_editors/linegraph_data_object_editor.rb +141 -141
  687. data/lib/cosmos/tools/tlm_grapher/data_object_editors/singlexy_data_object_editor.rb +30 -30
  688. data/lib/cosmos/tools/tlm_grapher/data_object_editors/xy_data_object_editor.rb +173 -173
  689. data/lib/cosmos/tools/tlm_grapher/data_objects/data_object.rb +177 -177
  690. data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +412 -409
  691. data/lib/cosmos/tools/tlm_grapher/data_objects/linegraph_data_object.rb +176 -176
  692. data/lib/cosmos/tools/tlm_grapher/data_objects/singlexy_data_object.rb +25 -25
  693. data/lib/cosmos/tools/tlm_grapher/data_objects/xy_data_object.rb +323 -320
  694. data/lib/cosmos/tools/tlm_grapher/plot_editors/linegraph_plot_editor.rb +181 -181
  695. data/lib/cosmos/tools/tlm_grapher/plot_editors/plot_editor.rb +28 -28
  696. data/lib/cosmos/tools/tlm_grapher/plot_editors/singlexy_plot_editor.rb +30 -30
  697. data/lib/cosmos/tools/tlm_grapher/plot_editors/xy_plot_editor.rb +59 -59
  698. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/linegraph_plot_gui_object.rb +172 -172
  699. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/singlexy_plot_gui_object.rb +27 -27
  700. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/xy_plot_gui_object.rb +74 -74
  701. data/lib/cosmos/tools/tlm_grapher/plots/linegraph_plot.rb +201 -201
  702. data/lib/cosmos/tools/tlm_grapher/plots/plot.rb +69 -69
  703. data/lib/cosmos/tools/tlm_grapher/plots/singlexy_plot.rb +20 -20
  704. data/lib/cosmos/tools/tlm_grapher/plots/xy_plot.rb +61 -61
  705. data/lib/cosmos/tools/tlm_grapher/tabbed_plots/overview_tabbed_plots.rb +1278 -1278
  706. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +430 -430
  707. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_data_object_editor.rb +107 -107
  708. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_logfile_thread.rb +111 -95
  709. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_plot_editor.rb +101 -101
  710. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +72 -66
  711. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tab.rb +57 -57
  712. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +1004 -1004
  713. data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +87 -87
  714. data/lib/cosmos/tools/tlm_viewer/screen.rb +486 -458
  715. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +563 -544
  716. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +287 -287
  717. data/lib/cosmos/tools/tlm_viewer/widgets.rb +53 -53
  718. data/lib/cosmos/tools/tlm_viewer/widgets/aging_widget.rb +110 -110
  719. data/lib/cosmos/tools/tlm_viewer/widgets/array_widget.rb +70 -70
  720. data/lib/cosmos/tools/tlm_viewer/widgets/block_widget.rb +61 -61
  721. data/lib/cosmos/tools/tlm_viewer/widgets/button_widget.rb +39 -39
  722. data/lib/cosmos/tools/tlm_viewer/widgets/canvas_widget.rb +62 -62
  723. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimage_widget.rb +41 -41
  724. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimagevalue_widget.rb +57 -57
  725. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabel_widget.rb +37 -37
  726. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabelvalue_widget.rb +56 -56
  727. data/lib/cosmos/tools/tlm_viewer/widgets/canvasline_widget.rb +55 -55
  728. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslinevalue_widget.rb +66 -66
  729. data/lib/cosmos/tools/tlm_viewer/widgets/canvasvalue_widget.rb +124 -124
  730. data/lib/cosmos/tools/tlm_viewer/widgets/checkbutton_widget.rb +31 -31
  731. data/lib/cosmos/tools/tlm_viewer/widgets/combobox_widget.rb +30 -30
  732. data/lib/cosmos/tools/tlm_viewer/widgets/formatfontvalue_widget.rb +36 -36
  733. data/lib/cosmos/tools/tlm_viewer/widgets/formatvalue_widget.rb +35 -35
  734. data/lib/cosmos/tools/tlm_viewer/widgets/horizontal_widget.rb +27 -27
  735. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalbox_widget.rb +31 -31
  736. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalline_widget.rb +26 -26
  737. data/lib/cosmos/tools/tlm_viewer/widgets/label_widget.rb +29 -29
  738. data/lib/cosmos/tools/tlm_viewer/widgets/labelformatvalue_widget.rb +39 -39
  739. data/lib/cosmos/tools/tlm_viewer/widgets/labelprogressbar_widget.rb +38 -38
  740. data/lib/cosmos/tools/tlm_viewer/widgets/labeltrendlimitsbar_widget.rb +38 -38
  741. data/lib/cosmos/tools/tlm_viewer/widgets/labelvalue_widget.rb +39 -39
  742. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluedesc_widget.rb +42 -42
  743. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluelimitsbar_widget.rb +37 -37
  744. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluerangebar_widget.rb +37 -37
  745. data/lib/cosmos/tools/tlm_viewer/widgets/layout_widget.rb +34 -34
  746. data/lib/cosmos/tools/tlm_viewer/widgets/limitsbar_widget.rb +178 -178
  747. data/lib/cosmos/tools/tlm_viewer/widgets/linegraph_widget.rb +54 -54
  748. data/lib/cosmos/tools/tlm_viewer/widgets/matrixbycolumns_widget.rb +47 -47
  749. data/lib/cosmos/tools/tlm_viewer/widgets/multi_widget.rb +116 -116
  750. data/lib/cosmos/tools/tlm_viewer/widgets/progressbar_widget.rb +34 -34
  751. data/lib/cosmos/tools/tlm_viewer/widgets/radiobutton_widget.rb +30 -30
  752. data/lib/cosmos/tools/tlm_viewer/widgets/rangebar_widget.rb +57 -57
  753. data/lib/cosmos/tools/tlm_viewer/widgets/screenshotbutton_widget.rb +34 -34
  754. data/lib/cosmos/tools/tlm_viewer/widgets/scrollwindow_widget.rb +35 -35
  755. data/lib/cosmos/tools/tlm_viewer/widgets/sectionheader_widget.rb +33 -33
  756. data/lib/cosmos/tools/tlm_viewer/widgets/tabbook_widget.rb +26 -26
  757. data/lib/cosmos/tools/tlm_viewer/widgets/tabitem_widget.rb +28 -28
  758. data/lib/cosmos/tools/tlm_viewer/widgets/textbox_widget.rb +47 -47
  759. data/lib/cosmos/tools/tlm_viewer/widgets/textfield_widget.rb +26 -26
  760. data/lib/cosmos/tools/tlm_viewer/widgets/timegraph_widget.rb +88 -88
  761. data/lib/cosmos/tools/tlm_viewer/widgets/title_widget.rb +27 -27
  762. data/lib/cosmos/tools/tlm_viewer/widgets/trendbar_widget.rb +130 -130
  763. data/lib/cosmos/tools/tlm_viewer/widgets/trendlimitsbar_widget.rb +46 -46
  764. data/lib/cosmos/tools/tlm_viewer/widgets/value_widget.rb +43 -43
  765. data/lib/cosmos/tools/tlm_viewer/widgets/valuelimitsbar_widget.rb +37 -37
  766. data/lib/cosmos/tools/tlm_viewer/widgets/valuerangebar_widget.rb +37 -37
  767. data/lib/cosmos/tools/tlm_viewer/widgets/vertical_widget.rb +35 -35
  768. data/lib/cosmos/tools/tlm_viewer/widgets/verticalbox_widget.rb +37 -37
  769. data/lib/cosmos/tools/tlm_viewer/widgets/widget.rb +257 -257
  770. data/lib/cosmos/top_level.rb +647 -596
  771. data/lib/cosmos/utilities.rb +11 -10
  772. data/lib/cosmos/utilities/crc.rb +166 -166
  773. data/lib/cosmos/utilities/csv.rb +83 -83
  774. data/lib/cosmos/utilities/logger.rb +137 -137
  775. data/lib/cosmos/utilities/low_fragmentation_array.rb +11 -11
  776. data/lib/cosmos/utilities/message_log.rb +74 -74
  777. data/lib/cosmos/utilities/quaternion.rb +258 -258
  778. data/lib/cosmos/utilities/ruby_lex_utils.rb +313 -313
  779. data/lib/cosmos/utilities/simulated_target.rb +99 -99
  780. data/lib/cosmos/utilities/sleeper.rb +44 -0
  781. data/lib/cosmos/version.rb +12 -12
  782. data/lib/cosmos/win32/excel.rb +66 -66
  783. data/lib/cosmos/win32/win32.rb +387 -387
  784. data/lib/cosmos/win32/win32_main.rb +311 -311
  785. data/roodi.yml +24 -24
  786. data/run_gui_tests.bat +32 -32
  787. data/spec/ccsds/ccsds_packet_spec.rb +67 -67
  788. data/spec/ccsds/ccsds_parser_spec.rb +148 -148
  789. data/spec/config/config_parser_spec.rb +322 -322
  790. data/spec/conversions/conversion_spec.rb +31 -31
  791. data/spec/conversions/generic_conversion_spec.rb +45 -45
  792. data/spec/conversions/new_packet_log_conversion_spec.rb +39 -39
  793. data/spec/conversions/polynomial_conversion_spec.rb +40 -40
  794. data/spec/conversions/processor_conversion_spec.rb +45 -45
  795. data/spec/conversions/received_count_conversion_spec.rb +43 -43
  796. data/spec/conversions/received_time_formatted_conversion_spec.rb +49 -49
  797. data/spec/conversions/received_time_seconds_conversion_spec.rb +50 -50
  798. data/spec/conversions/segmented_polynomial_conversion_spec.rb +51 -51
  799. data/spec/conversions/unix_time_formatted_conversion_spec.rb +74 -74
  800. data/spec/conversions/unix_time_seconds_conversion_spec.rb +76 -76
  801. data/spec/core_ext/array_spec.rb +186 -186
  802. data/spec/core_ext/class_spec.rb +36 -36
  803. data/spec/core_ext/cosmos_io_spec.rb +77 -77
  804. data/spec/core_ext/exception_spec.rb +91 -91
  805. data/spec/core_ext/file_spec.rb +72 -72
  806. data/spec/core_ext/hash_spec.rb +24 -24
  807. data/spec/core_ext/io_spec.rb +46 -46
  808. data/spec/core_ext/kernel_spec.rb +54 -54
  809. data/spec/core_ext/math_spec.rb +116 -116
  810. data/spec/core_ext/matrix_spec.rb +66 -66
  811. data/spec/core_ext/objectspace_spec.rb +29 -29
  812. data/spec/core_ext/range_spec.rb +21 -21
  813. data/spec/core_ext/socket_spec.rb +32 -32
  814. data/spec/core_ext/string_spec.rb +223 -223
  815. data/spec/core_ext/stringio_spec.rb +21 -21
  816. data/spec/core_ext/time_spec.rb +151 -151
  817. data/spec/gui/line_graph/line_clip_spec.rb +322 -322
  818. data/spec/install/config/system/system.txt +33 -33
  819. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  820. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  821. data/spec/install/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  822. data/spec/install/config/targets/COSMOS/screens/limits_change.txt +20 -20
  823. data/spec/install/config/targets/COSMOS/screens/version.txt +19 -19
  824. data/spec/install/config/targets/COSMOS/target.txt +5 -5
  825. data/spec/install/config/targets/INST/cmd_tlm/inst_cmd_linc.txt +30 -30
  826. data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +111 -111
  827. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm.txt +236 -236
  828. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm_linc.txt +25 -25
  829. data/spec/install/config/targets/INST/cmd_tlm_server.txt +5 -5
  830. data/spec/install/config/targets/INST/lib/sim_inst.rb +305 -294
  831. data/spec/install/config/targets/INST/target.txt +10 -10
  832. data/spec/install/config/targets/META/cmd_tlm/meta_cmd.txt +4 -4
  833. data/spec/install/config/targets/META/cmd_tlm/meta_tlm.txt +4 -4
  834. data/spec/install/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  835. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +150 -150
  836. data/spec/interfaces/interface_spec.rb +130 -131
  837. data/spec/interfaces/linc_interface_spec.rb +199 -199
  838. data/spec/interfaces/serial_interface_spec.rb +56 -56
  839. data/spec/interfaces/simulated_target_interface_spec.rb +128 -128
  840. data/spec/interfaces/stream_interface_spec.rb +157 -157
  841. data/spec/interfaces/tcpip_client_interface_spec.rb +54 -54
  842. data/spec/interfaces/tcpip_server_interface_spec.rb +151 -151
  843. data/spec/interfaces/udp_interface_spec.rb +175 -177
  844. data/spec/io/buffered_file_spec.rb +113 -113
  845. data/spec/io/io_multiplexer_spec.rb +94 -94
  846. data/spec/io/json_drb_object_spec.rb +99 -99
  847. data/spec/io/json_drb_spec.rb +311 -311
  848. data/spec/io/json_rpc_spec.rb +264 -264
  849. data/spec/io/raw_logger_pair_spec.rb +76 -76
  850. data/spec/io/raw_logger_spec.rb +133 -133
  851. data/spec/io/serial_driver_spec.rb +61 -61
  852. data/spec/io/stderr_spec.rb +32 -32
  853. data/spec/io/stdout_spec.rb +32 -32
  854. data/spec/io/tcpip_server_spec.rb +338 -338
  855. data/spec/io/udp_sockets_spec.rb +94 -94
  856. data/spec/io/win32_serial_driver_spec.rb +88 -88
  857. data/spec/packet_logs/meta_packet_log_writer_spec.rb +170 -170
  858. data/spec/packet_logs/packet_log_reader_spec.rb +408 -408
  859. data/spec/packet_logs/packet_log_writer_pair_spec.rb +30 -30
  860. data/spec/packet_logs/packet_log_writer_spec.rb +223 -223
  861. data/spec/packets/binary_accessor_spec.rb +2073 -2073
  862. data/spec/packets/commands_spec.rb +369 -369
  863. data/spec/packets/limits_response_spec.rb +25 -25
  864. data/spec/packets/limits_spec.rb +326 -326
  865. data/spec/packets/packet_config_spec.rb +1620 -1620
  866. data/spec/packets/packet_item_limits_spec.rb +161 -161
  867. data/spec/packets/packet_item_spec.rb +386 -386
  868. data/spec/packets/packet_spec.rb +1057 -949
  869. data/spec/packets/structure_item_spec.rb +195 -195
  870. data/spec/packets/structure_spec.rb +419 -419
  871. data/spec/packets/telemetry_spec.rb +535 -535
  872. data/spec/processors/new_packet_log_processor_spec.rb +39 -39
  873. data/spec/processors/processor_spec.rb +55 -55
  874. data/spec/processors/statistics_processor_spec.rb +60 -60
  875. data/spec/processors/watermark_processor_spec.rb +51 -51
  876. data/spec/script/script_spec.rb +654 -654
  877. data/spec/spec_helper.rb +154 -148
  878. data/spec/streams/burst_stream_protocol_spec.rb +32 -32
  879. data/spec/streams/fixed_stream_protocol_spec.rb +110 -110
  880. data/spec/streams/length_stream_protocol_spec.rb +297 -297
  881. data/spec/streams/preidentified_stream_protocol_spec.rb +118 -118
  882. data/spec/streams/serial_stream_spec.rb +105 -105
  883. data/spec/streams/stream_protocol_spec.rb +332 -332
  884. data/spec/streams/stream_spec.rb +29 -29
  885. data/spec/streams/tcpip_client_stream_spec.rb +54 -54
  886. data/spec/streams/tcpip_socket_stream_spec.rb +146 -146
  887. data/spec/streams/template_stream_protocol_spec.rb +151 -151
  888. data/spec/streams/terminated_stream_protocol_spec.rb +123 -123
  889. data/spec/system/system_spec.rb +645 -645
  890. data/spec/system/target_spec.rb +248 -248
  891. data/spec/tools/cmd_tlm_server/api_spec.rb +1087 -1113
  892. data/spec/tools/cmd_tlm_server/background_task_spec.rb +32 -32
  893. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +81 -81
  894. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +411 -411
  895. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +415 -415
  896. data/spec/tools/cmd_tlm_server/commanding_spec.rb +123 -123
  897. data/spec/tools/cmd_tlm_server/connections_spec.rb +147 -147
  898. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +306 -306
  899. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +252 -238
  900. data/spec/tools/cmd_tlm_server/packet_logging_spec.rb +143 -143
  901. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +98 -101
  902. data/spec/tools/cmd_tlm_server/routers_spec.rb +223 -208
  903. data/spec/top_level/top_level_spec.rb +334 -321
  904. data/spec/utilities/crc_spec.rb +45 -45
  905. data/spec/utilities/csv_spec.rb +97 -97
  906. data/spec/utilities/logger_spec.rb +102 -102
  907. data/spec/utilities/message_log_spec.rb +89 -89
  908. data/spec/utilities/quaternion_spec.rb +107 -107
  909. data/spec/utilities/ruby_lex_utils_spec.rb +86 -86
  910. data/tasks/manifest.rake +22 -22
  911. data/tasks/spec.rake +23 -23
  912. metadata +18 -2
@@ -1,532 +1,583 @@
1
- # encoding: ascii-8bit
2
-
3
- # Copyright 2014 Ball Aerospace & Technologies Corp.
4
- # All Rights Reserved.
5
- #
6
- # This program is free software; you can modify and/or redistribute it
7
- # under the terms of the GNU General Public License
8
- # as published by the Free Software Foundation; version 3 with
9
- # attribution addendums as found in the LICENSE.txt
10
-
11
- require 'socket'
12
- require 'thread' # For Mutex
13
- require 'timeout' # For Timeout::Error
14
- require 'cosmos/streams/tcpip_socket_stream'
15
- require 'cosmos/config/config_parser'
16
-
17
- module Cosmos
18
-
19
- # TCP/IP Server which can both read and write on a single port or two
20
- # independent ports. A listen thread is setup which waits for client
21
- # connections. For each connection to the read port, a thread is spawned that
22
- # calls the read method from the stream protocol. This data is then
23
- # available by calling the TcpipServer read method. For each connection to the
24
- # write port, a thread is spawned that calls the write method from the stream
25
- # protocol when data is send to the TcpipServer via the write method.
26
- class TcpipServer
27
-
28
- # Callback method to call when a new client connects to the write port.
29
- # This method will be called with the StreamProtocol as the only argument.
30
- attr_accessor :write_connection_callback
31
- # Callback method to call when a new client connects to the read port.
32
- # This method will be called with the StreamProtocol as the only argument.
33
- attr_accessor :read_connection_callback
34
- # The number of bytes read from all connected sockets
35
- attr_accessor :bytes_read
36
- # The number of bytes written to the TcpipServer. This number does not vary
37
- # with the number of clients connected to the write port.
38
- attr_accessor :bytes_written
39
- # @return [RawLoggerPair] RawLoggerPair instance or nil
40
- attr_accessor :raw_logger_pair
41
- # @return [String] The ip address to bind to. Default to ANY (0.0.0.0)
42
- attr_accessor :listen_address
43
-
44
- # @param write_port [Integer] The server write port. Clients should connect
45
- # and expect to receive data from this port.
46
- # @param read_port [Integer] The server read port. Clients should connect
47
- # and expect to send data to this port.
48
- # @param write_timeout [Float|nil] The number of seconds to wait for the
49
- # write to complete. Pass nil to block until the write is complete.
50
- # @param read_timeout [Float|nil] The number of seconds to wait for the
51
- # read to complete. Pass nil to block until the read is complete.
52
- # @param stream_protocol_type [String] The name of the stream protocol to
53
- # use for both the read and write ports. This name is combined with
54
- # 'StreamProtocol' to result in a COSMOS StreamProtocol class.
55
- # @param stream_protocol_args [Array] The arguments to pass to the
56
- # StreamProtocol class constructor
57
- def initialize(write_port,
58
- read_port,
59
- write_timeout,
60
- read_timeout,
61
- stream_protocol_type,
62
- *stream_protocol_args)
63
- @write_port = ConfigParser.handle_nil(write_port)
64
- @write_port = Integer(write_port) if @write_port
65
- @read_port = ConfigParser.handle_nil(read_port)
66
- @read_port = Integer(read_port) if @read_port
67
- @write_timeout = ConfigParser.handle_nil(write_timeout)
68
- @write_timeout = @write_timeout.to_f if @write_timeout
69
- @read_timeout = ConfigParser.handle_nil(read_timeout)
70
- @read_timeout = @read_timeout.to_f if @read_timeout
71
-
72
- stream_protocol_class = stream_protocol_type.to_s.capitalize << 'StreamProtocol'
73
- @stream_protocol_class = stream_protocol_class.to_class
74
- unless @stream_protocol_class
75
- begin
76
- require "cosmos/streams/#{stream_protocol_class.class_name_to_filename}"
77
- @stream_protocol_class = stream_protocol_class.to_class
78
- rescue LoadError => err
79
- Logger.instance.error "Unable to require #{stream_protocol_class.class_name_to_filename} due to #{err.message}. Ensure #{stream_protocol_class.class_name_to_filename} is in the COSMOS lib directory."
80
- raise "Unable to require #{stream_protocol_class.class_name_to_filename} due to #{err.message}. Ensure #{stream_protocol_class.class_name_to_filename} is in the COSMOS lib directory."
81
- end
82
- end
83
-
84
- @stream_protocol_args = stream_protocol_args
85
-
86
- @listen_sockets = []
87
- @listen_threads = []
88
- @read_threads = []
89
- @write_stream_protocols = []
90
- @read_stream_protocols = []
91
- @write_queue = nil
92
- @write_queue = Queue.new if @write_port
93
- @read_queue = nil
94
- @read_queue = Queue.new if @read_port
95
- @write_mutex = nil
96
- @write_mutex = Mutex.new if @write_port
97
- @write_condition_variable = nil
98
- @write_condition_variable = ConditionVariable.new if @write_port
99
- @write_connection_callback = nil
100
- @read_connection_callback = nil
101
- @bytes_read = 0
102
- @bytes_written = 0
103
- @raw_logger_pair = nil
104
- @raw_logging_enabled = false
105
- @interface = nil
106
- @connection_mutex = Mutex.new
107
- @listen_address = Socket::INADDR_ANY
108
-
109
- @connected = false
110
- end
111
-
112
- # @param interface [Interface] Sets the higher level interface which is
113
- # using this TcpipServer. If the interface defines post_read_data,
114
- # post_read_packet, or pre_write_packet, then these methods will be
115
- # called over any subclass implementations within the stream protocol.
116
- def interface=(interface)
117
- @interface = interface
118
- end
119
-
120
- # Create the read and write port listen threads. Incoming connections will
121
- # spawn separate threads to process the reads and writes.
122
- def connect
123
- if @write_port == @read_port
124
- # Handle one socket case
125
- start_listen_thread(@read_port, true, true)
126
- else
127
- if @write_port
128
- start_listen_thread(@write_port, true, false)
129
- end
130
-
131
- if @read_port
132
- start_listen_thread(@read_port, false, true)
133
- end
134
- end
135
-
136
- if @write_port
137
- # Start write thread
138
- @write_thread = Thread.new do
139
- begin
140
- while true
141
- write_thread_body()
142
- end
143
- rescue Exception => err
144
- @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
145
- stream_protocol.disconnect
146
- stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
147
- end
148
- @write_stream_protocols.clear
149
- Logger.instance.error("Tcpip server write thread unexpectedly died")
150
- Logger.instance.error(err.formatted)
151
- end
152
- end
153
- else
154
- @write_thread = nil
155
- end
156
- @connected = true
157
- end
158
-
159
- # @return [Boolean] Whether the server is listening for connections
160
- def connected?
161
- @connected
162
- end
163
-
164
- # Shutdowns the listener threads for both the read and write ports as well
165
- # as any client connections. As a part of shutting down client connections,
166
- # the {StreamProtocol#disconnect} method is called.
167
- def disconnect
168
- # Shutdown Listen Thread(s)
169
- @listen_threads.each do |listen_thread|
170
- listen_thread.kill
171
- end
172
- @listen_threads.clear
173
-
174
- # Shutdown Listen Socket(s)
175
- @listen_sockets.each do |listen_socket|
176
- listen_socket.close unless listen_socket.closed?
177
- end
178
- @listen_sockets.clear
179
-
180
- # Shutdown Read Threads
181
- @read_threads.each do |thread|
182
- thread.kill
183
- end
184
- @read_threads.clear
185
-
186
- # Shutdown Write Thread
187
- if @write_thread
188
- @write_thread.kill
189
- @write_thread = nil
190
- end
191
-
192
- # Shutdown Write Stream Protocols
193
- @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
194
- stream_protocol.disconnect
195
- stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
196
- end
197
- @write_stream_protocols.clear
198
-
199
- # Shutdown Read Stream Protocols
200
- @read_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
201
- stream_protocol.disconnect
202
- stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
203
- end
204
- @read_stream_protocols.clear
205
-
206
- @connected = false
207
- end
208
-
209
- # @return [Packet] Latest packet read from any of the connected clients.
210
- # Note this method blocks until data is available.
211
- def read
212
- return nil unless @read_queue
213
- packet = @read_queue.pop
214
- @bytes_read += packet.buffer.length
215
- packet
216
- end
217
-
218
- # @param packet [Packet] Packet to write to all clients connected to the
219
- # write port.
220
- def write(packet)
221
- return unless @write_queue
222
- @write_queue << packet.clone
223
- @bytes_written += packet.buffer.length
224
- @write_condition_variable.broadcast
225
- end
226
-
227
- # @param data [String] Data to write to all clients connected to the
228
- # write port.
229
- def write_raw(data)
230
- return unless @write_queue
231
- packet = Packet.new(nil, nil)
232
- packet.buffer = data
233
- @write_queue << packet
234
- @bytes_written += data.length
235
- @write_condition_variable.broadcast
236
- end
237
-
238
- # @return [Integer] The number of packets waiting on the read queue
239
- def read_queue_size
240
- if @read_queue
241
- @read_queue.size
242
- else
243
- 0
244
- end
245
- end
246
-
247
- # @return [Integer] The number of packets waiting on the write queue
248
- def write_queue_size
249
- if @write_queue
250
- @write_queue.size
251
- else
252
- 0
253
- end
254
- end
255
-
256
- # @return [Integer] The number of connected clients
257
- def num_clients
258
- clients = []
259
- @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
260
- clients << [host_ip, port]
261
- end
262
- @read_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
263
- clients << [host_ip, port]
264
- end
265
- clients.uniq.length
266
- end
267
-
268
- # Start raw logging for this interface
269
- def start_raw_logging
270
- @raw_logging_enabled = true
271
- if @raw_logger_pair
272
- @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
273
- stream_protocol.stream.raw_logger_pair.start if stream_protocol.stream.raw_logger_pair
274
- end
275
- @read_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
276
- stream_protocol.stream.raw_logger_pair.start if stream_protocol.stream.raw_logger_pair
277
- end
278
- end
279
- end
280
-
281
- # Stop raw logging for this interface
282
- def stop_raw_logging
283
- @raw_logging_enabled = false
284
- if @raw_logger_pair
285
- @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
286
- stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
287
- end
288
- @read_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
289
- stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
290
- end
291
- end
292
- end
293
-
294
- protected
295
-
296
- def start_listen_thread(port, listen_write = false, listen_read = false)
297
- # Create a socket to accept connections from clients
298
- addr = Socket.pack_sockaddr_in(port, @listen_address)
299
- listen_socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
300
- listen_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1) unless Kernel.is_windows?
301
- begin
302
- listen_socket.bind(addr)
303
- rescue Errno::EADDRINUSE
304
- raise "Error binding to port #{port}.\n" +
305
- "Either another application is using this port\n" +
306
- "or the operating system is being slow cleaning up.\n" +
307
- "Make sure all sockets/streams are closed in all applications,\n" +
308
- "wait 1 minute and try again."
309
- end
310
-
311
- listen_socket.listen(5)
312
-
313
- @listen_sockets << listen_socket
314
-
315
- # Start Listen Thread
316
- @listen_threads << Thread.new do
317
- begin
318
- while true
319
- listen_thread_body(listen_socket, listen_write, listen_read)
320
- end
321
- rescue Exception => err
322
- Logger.instance.error("Tcpip server listen thread unexpectedly died")
323
- Logger.instance.error(err.formatted)
324
- end
325
- end
326
- end
327
-
328
- def listen_thread_body(listen_socket, listen_write = false, listen_read = false)
329
- socket, address = listen_socket.accept()
330
- port, host_ip = Socket.unpack_sockaddr_in(address)
331
- hostname = ''
332
- hostname = Socket.lookup_hostname_from_ip(host_ip) if System.instance.use_dns
333
- if System.instance.acl
334
- addr = ["AF_INET", 10, "lc630", host_ip.to_s]
335
- if not System.instance.acl.allow_addr?(addr)
336
- # Reject connection
337
- if not socket.closed?
338
- socket.close()
339
- end
340
- Logger.instance.info "Tcpip server rejected connection from #{hostname}(#{host_ip}):#{port}"
341
- return
342
- end
343
- end
344
-
345
- # Configure TCP_NODELAY option
346
- socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
347
-
348
- # Accept Connection
349
- write_socket = nil
350
- read_socket = nil
351
- write_socket = socket if listen_write
352
- read_socket = socket if listen_read
353
- stream = TcpipSocketStream.new(write_socket, read_socket, @write_timeout, @read_timeout)
354
- if @raw_logger_pair
355
- stream.raw_logger_pair = @raw_logger_pair.clone
356
- stream.raw_logger_pair.start if @raw_logging_enabled
357
- end
358
-
359
- stream_protocol = @stream_protocol_class.new(*@stream_protocol_args)
360
- stream_protocol.interface = @interface if @interface
361
- stream_protocol.connect(stream)
362
-
363
- if listen_write
364
- @write_connection_callback.call(stream_protocol) if @write_connection_callback
365
- @connection_mutex.synchronize do
366
- @write_stream_protocols << [stream_protocol, hostname, host_ip, port]
367
- end
368
- end
369
- if listen_read
370
- @read_connection_callback.call(stream_protocol) if @read_connection_callback
371
- @connection_mutex.synchronize do
372
- @read_stream_protocols << [stream_protocol, hostname, host_ip, port]
373
- end
374
-
375
- # Start read thread
376
- @read_threads << Thread.new do
377
- index_to_delete = nil
378
- begin
379
- begin
380
- read_thread_body(stream_protocol)
381
- rescue Exception => err
382
- Logger.instance.error "Tcpip server read thread unexpectedly died"
383
- Logger.instance.error err.formatted
384
- end
385
- Logger.instance.info "Tcpip server lost read connection to #{hostname}(#{host_ip}):#{port}"
386
- @read_threads.delete(Thread.current)
387
-
388
- index_to_delete = nil
389
- @connection_mutex.synchronize do
390
- begin
391
- index = 0
392
- @read_stream_protocols.each do |read_stream_protocol, _, _, _|
393
- if read_stream_protocol == stream_protocol
394
- index_to_delete = index
395
- read_stream_protocol.disconnect
396
- read_stream_protocol.stream.raw_logger_pair.stop if read_stream_protocol.stream.raw_logger_pair
397
- break
398
- end
399
- index += 1
400
- end
401
- ensure
402
- if index_to_delete
403
- @read_stream_protocols.delete_at(index_to_delete)
404
- end
405
- end
406
- end
407
- rescue Exception => err
408
- Logger.instance.error "Tcpip server read thread unexpectedly died"
409
- Logger.instance.error err.formatted
410
- end
411
- end
412
- end
413
-
414
- Logger.instance.info "Tcpip server accepted connection from #{hostname}(#{host_ip}):#{port}"
415
- end
416
-
417
- def write_thread_body
418
- # Retrive the next packet to be sent out to clients
419
- # Handles disconnected clients even when packets aren't flowing
420
- packet = nil
421
-
422
- loop do
423
- begin
424
- packet = @write_queue.pop(true)
425
- break
426
- rescue ThreadError
427
- # Timeout waiting for send - check for dead clients
428
- indexes_to_delete = []
429
- index = 0
430
-
431
- @connection_mutex.synchronize do
432
- @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
433
- begin
434
- if (@write_port != @read_port)
435
- # Socket should return EWOULDBLOCK if it is still cleanly connected
436
- stream_protocol.stream.write_socket.recvfrom_nonblock(10)
437
- elsif (!stream_protocol.stream.write_socket.closed?)
438
- # Let read thread detect disconnect
439
- next
440
- end
441
-
442
- # Client has disconnected (or is invalidly sending data on the socket)
443
- Logger.instance.info "Tcpip server lost write connection to #{hostname}(#{host_ip}):#{port}"
444
- stream_protocol.disconnect
445
- stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
446
- indexes_to_delete.unshift(index) # Put later indexes at front of array
447
- rescue Errno::ECONNRESET, Errno::ECONNABORTED
448
- # Client has disconnected
449
- Logger.instance.info "Tcpip server lost write connection to #{hostname}(#{host_ip}):#{port}"
450
- stream_protocol.disconnect
451
- stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
452
- indexes_to_delete.unshift(index) # Put later indexes at front of array
453
- rescue Errno::EWOULDBLOCK
454
- # Client is still cleanly connected as far as we can tell without writing to the socket
455
- ensure
456
- index += 1
457
- end
458
- end
459
-
460
- # Delete any dead sockets
461
- indexes_to_delete.each do |index_to_delete|
462
- @write_stream_protocols.delete_at(index_to_delete)
463
- end
464
- end # @connection_mutex.synchronize
465
-
466
- # Sleep until we receive a packet or for 100ms
467
- @write_mutex.synchronize do
468
- @write_condition_variable.wait(@write_mutex, 0.1)
469
- end
470
- end
471
- end
472
-
473
- packet = write_thread_hook(packet)
474
-
475
- if packet
476
- @connection_mutex.synchronize do
477
- # Send data to each client - On error drop the client
478
- indexes_to_delete = []
479
- index = 0
480
- @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
481
- need_disconnect = false
482
- begin
483
- stream_protocol.write(packet)
484
- rescue Errno::EPIPE, Errno::ECONNABORTED, IOError, Errno::ECONNRESET
485
- # Client has normally disconnected
486
- need_disconnect = true
487
- rescue Exception => err
488
- if err.message != "Stream not connected for write_raw"
489
- Logger.instance.error "Error sending to client: #{err.class} #{err.message}"
490
- end
491
- need_disconnect = true
492
- end
493
-
494
- if need_disconnect
495
- Logger.instance.info "Tcpip server lost write connection to #{hostname}(#{host_ip}):#{port}"
496
- stream_protocol.disconnect
497
- stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
498
- indexes_to_delete.unshift(index) # Put later indexes at front of array
499
- end
500
-
501
- index += 1
502
- end
503
-
504
- # Delete any dead sockets
505
- indexes_to_delete.each do |index_to_delete|
506
- @write_stream_protocols.delete_at(index_to_delete)
507
- end
508
- end # @connection_mutex.synchronize
509
- end
510
- end
511
-
512
- def write_thread_hook(packet)
513
- return packet # By default just return the packet
514
- end
515
-
516
- def read_thread_body(stream_protocol)
517
- loop do
518
- packet = stream_protocol.read
519
- return unless packet
520
-
521
- # Do work on received packet
522
- read_thread_hook(packet)
523
- end # loop do
524
- end
525
-
526
- def read_thread_hook(packet)
527
- @read_queue << packet.clone
528
- end
529
-
530
- end # class TcpipServerStream
531
-
532
- end # module Cosmos
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'socket'
12
+ require 'thread' # For Mutex
13
+ require 'timeout' # For Timeout::Error
14
+ require 'cosmos/streams/tcpip_socket_stream'
15
+ require 'cosmos/config/config_parser'
16
+
17
+ module Cosmos
18
+
19
+ # TCP/IP Server which can both read and write on a single port or two
20
+ # independent ports. A listen thread is setup which waits for client
21
+ # connections. For each connection to the read port, a thread is spawned that
22
+ # calls the read method from the stream protocol. This data is then
23
+ # available by calling the TcpipServer read method. For each connection to the
24
+ # write port, a thread is spawned that calls the write method from the stream
25
+ # protocol when data is send to the TcpipServer via the write method.
26
+ class TcpipServer
27
+
28
+ # Callback method to call when a new client connects to the write port.
29
+ # This method will be called with the StreamProtocol as the only argument.
30
+ attr_accessor :write_connection_callback
31
+ # Callback method to call when a new client connects to the read port.
32
+ # This method will be called with the StreamProtocol as the only argument.
33
+ attr_accessor :read_connection_callback
34
+ # The number of bytes read from all connected sockets
35
+ attr_accessor :bytes_read
36
+ # The number of bytes written to the TcpipServer. This number does not vary
37
+ # with the number of clients connected to the write port.
38
+ attr_accessor :bytes_written
39
+ # @return [RawLoggerPair] RawLoggerPair instance or nil
40
+ attr_accessor :raw_logger_pair
41
+ # @return [String] The ip address to bind to. Default to ANY (0.0.0.0)
42
+ attr_accessor :listen_address
43
+
44
+ # @param write_port [Integer] The server write port. Clients should connect
45
+ # and expect to receive data from this port.
46
+ # @param read_port [Integer] The server read port. Clients should connect
47
+ # and expect to send data to this port.
48
+ # @param write_timeout [Float|nil] The number of seconds to wait for the
49
+ # write to complete. Pass nil to block until the write is complete.
50
+ # @param read_timeout [Float|nil] The number of seconds to wait for the
51
+ # read to complete. Pass nil to block until the read is complete.
52
+ # @param stream_protocol_type [String] The name of the stream protocol to
53
+ # use for both the read and write ports. This name is combined with
54
+ # 'StreamProtocol' to result in a COSMOS StreamProtocol class.
55
+ # @param stream_protocol_args [Array] The arguments to pass to the
56
+ # StreamProtocol class constructor
57
+ def initialize(write_port,
58
+ read_port,
59
+ write_timeout,
60
+ read_timeout,
61
+ stream_protocol_type,
62
+ *stream_protocol_args)
63
+ @write_port = ConfigParser.handle_nil(write_port)
64
+ @write_port = Integer(write_port) if @write_port
65
+ @read_port = ConfigParser.handle_nil(read_port)
66
+ @read_port = Integer(read_port) if @read_port
67
+ @write_timeout = ConfigParser.handle_nil(write_timeout)
68
+ @write_timeout = @write_timeout.to_f if @write_timeout
69
+ @read_timeout = ConfigParser.handle_nil(read_timeout)
70
+ @read_timeout = @read_timeout.to_f if @read_timeout
71
+
72
+ stream_protocol_class = stream_protocol_type.to_s.capitalize << 'StreamProtocol'
73
+ @stream_protocol_class = stream_protocol_class.to_class
74
+ unless @stream_protocol_class
75
+ begin
76
+ require "cosmos/streams/#{stream_protocol_class.class_name_to_filename}"
77
+ @stream_protocol_class = stream_protocol_class.to_class
78
+ rescue LoadError => err
79
+ Logger.instance.error "Unable to require #{stream_protocol_class.class_name_to_filename} due to #{err.message}. Ensure #{stream_protocol_class.class_name_to_filename} is in the COSMOS lib directory."
80
+ raise "Unable to require #{stream_protocol_class.class_name_to_filename} due to #{err.message}. Ensure #{stream_protocol_class.class_name_to_filename} is in the COSMOS lib directory."
81
+ end
82
+ end
83
+
84
+ @stream_protocol_args = stream_protocol_args
85
+
86
+ @listen_sockets = []
87
+ @listen_pipes = []
88
+ @listen_threads = []
89
+ @read_threads = []
90
+ @write_stream_protocols = []
91
+ @read_stream_protocols = []
92
+ @write_queue = nil
93
+ @write_queue = Queue.new if @write_port
94
+ @read_queue = nil
95
+ @read_queue = Queue.new if @read_port
96
+ @write_mutex = nil
97
+ @write_mutex = Mutex.new if @write_port
98
+ @write_condition_variable = nil
99
+ @write_condition_variable = ConditionVariable.new if @write_port
100
+ @write_connection_callback = nil
101
+ @read_connection_callback = nil
102
+ @bytes_read = 0
103
+ @bytes_written = 0
104
+ @raw_logger_pair = nil
105
+ @raw_logging_enabled = false
106
+ @interface = nil
107
+ @connection_mutex = Mutex.new
108
+ @listen_address = Socket::INADDR_ANY
109
+
110
+ @connected = false
111
+ end
112
+
113
+ # @param interface [Interface] Sets the higher level interface which is
114
+ # using this TcpipServer. If the interface defines post_read_data,
115
+ # post_read_packet, or pre_write_packet, then these methods will be
116
+ # called over any subclass implementations within the stream protocol.
117
+ def interface=(interface)
118
+ @interface = interface
119
+ end
120
+
121
+ # Create the read and write port listen threads. Incoming connections will
122
+ # spawn separate threads to process the reads and writes.
123
+ def connect
124
+ @cancel_threads = false
125
+ if @read_queue
126
+ # Empty the read queue of any residual
127
+ begin
128
+ @read_queue.pop(true) while @read_queue.length > 0
129
+ rescue
130
+ end
131
+ end
132
+ if @write_port == @read_port
133
+ # Handle one socket case
134
+ start_listen_thread(@read_port, true, true)
135
+ else
136
+ if @write_port
137
+ start_listen_thread(@write_port, true, false)
138
+ end
139
+
140
+ if @read_port
141
+ start_listen_thread(@read_port, false, true)
142
+ end
143
+ end
144
+
145
+ if @write_port
146
+ # Start write thread
147
+ @write_thread = Thread.new do
148
+ begin
149
+ while true
150
+ write_thread_body()
151
+ break if @cancel_threads
152
+ end
153
+ rescue Exception => err
154
+ @connection_mutex.synchronize do
155
+ @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
156
+ stream_protocol.disconnect
157
+ stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
158
+ end
159
+ @write_stream_protocols.clear
160
+ end
161
+ Logger.instance.error("Tcpip server write thread unexpectedly died")
162
+ Logger.instance.error(err.formatted)
163
+ end
164
+ end
165
+ else
166
+ @write_thread = nil
167
+ end
168
+ @connected = true
169
+ end
170
+
171
+ # @return [Boolean] Whether the server is listening for connections
172
+ def connected?
173
+ @connected
174
+ end
175
+
176
+ # Shutdowns the listener threads for both the read and write ports as well
177
+ # as any client connections. As a part of shutting down client connections,
178
+ # the {StreamProtocol#disconnect} method is called.
179
+ def disconnect
180
+ @cancel_threads = true
181
+ @read_queue << nil if @read_queue
182
+ @listen_pipes.each do |pipe|
183
+ begin
184
+ pipe.write('.')
185
+ rescue Exception
186
+ # Oh well
187
+ end
188
+ end
189
+ @listen_pipes.clear
190
+
191
+ # Shutdown Listen Thread(s)
192
+ @listen_threads.each do |listen_thread|
193
+ Cosmos.kill_thread(self, listen_thread)
194
+ end
195
+ @listen_threads.clear
196
+
197
+ # Shutdown Listen Socket(s)
198
+ @listen_sockets.each do |listen_socket|
199
+ begin
200
+ listen_socket.close unless listen_socket.closed?
201
+ rescue IOError
202
+ # Ok may have been closed by the thread
203
+ end
204
+ end
205
+ @listen_sockets.clear
206
+
207
+ # Shutdown Read Stream Protocols - This should unblock read threads
208
+ @connection_mutex.synchronize do
209
+ @read_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
210
+ stream_protocol.disconnect
211
+ stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
212
+ end
213
+ @read_stream_protocols.clear
214
+ end
215
+
216
+ # Shutdown Read Threads
217
+ @read_threads.each do |thread|
218
+ Cosmos.kill_thread(self, thread)
219
+ end
220
+ @read_threads.clear
221
+
222
+ # Shutdown Write Thread
223
+ if @write_thread
224
+ Cosmos.kill_thread(self, @write_thread)
225
+ @write_thread = nil
226
+ end
227
+
228
+ # Shutdown Write Stream Protocols
229
+ @connection_mutex.synchronize do
230
+ @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
231
+ stream_protocol.disconnect
232
+ stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
233
+ end
234
+ @write_stream_protocols.clear
235
+ end
236
+
237
+ @connected = false
238
+ end
239
+
240
+ # Gracefully kill all the threads
241
+ def graceful_kill
242
+ # This method is just here to prevent warnings
243
+ end
244
+
245
+ # @return [Packet] Latest packet read from any of the connected clients.
246
+ # Note this method blocks until data is available.
247
+ def read
248
+ return nil unless @read_queue
249
+ packet = @read_queue.pop
250
+ return nil unless packet
251
+ @bytes_read += packet.buffer.length
252
+ packet
253
+ end
254
+
255
+ # @param packet [Packet] Packet to write to all clients connected to the
256
+ # write port.
257
+ def write(packet)
258
+ return unless @write_queue
259
+ @write_queue << packet.clone
260
+ @bytes_written += packet.buffer.length
261
+ @write_condition_variable.broadcast
262
+ end
263
+
264
+ # @param data [String] Data to write to all clients connected to the
265
+ # write port.
266
+ def write_raw(data)
267
+ return unless @write_queue
268
+ packet = Packet.new(nil, nil)
269
+ packet.buffer = data
270
+ @write_queue << packet
271
+ @bytes_written += data.length
272
+ @write_condition_variable.broadcast
273
+ end
274
+
275
+ # @return [Integer] The number of packets waiting on the read queue
276
+ def read_queue_size
277
+ if @read_queue
278
+ @read_queue.size
279
+ else
280
+ 0
281
+ end
282
+ end
283
+
284
+ # @return [Integer] The number of packets waiting on the write queue
285
+ def write_queue_size
286
+ if @write_queue
287
+ @write_queue.size
288
+ else
289
+ 0
290
+ end
291
+ end
292
+
293
+ # @return [Integer] The number of connected clients
294
+ def num_clients
295
+ clients = []
296
+ @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
297
+ clients << [host_ip, port]
298
+ end
299
+ @read_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
300
+ clients << [host_ip, port]
301
+ end
302
+ clients.uniq.length
303
+ end
304
+
305
+ # Start raw logging for this interface
306
+ def start_raw_logging
307
+ @raw_logging_enabled = true
308
+ if @raw_logger_pair
309
+ @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
310
+ stream_protocol.stream.raw_logger_pair.start if stream_protocol.stream.raw_logger_pair
311
+ end
312
+ @read_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
313
+ stream_protocol.stream.raw_logger_pair.start if stream_protocol.stream.raw_logger_pair
314
+ end
315
+ end
316
+ end
317
+
318
+ # Stop raw logging for this interface
319
+ def stop_raw_logging
320
+ @raw_logging_enabled = false
321
+ if @raw_logger_pair
322
+ @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
323
+ stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
324
+ end
325
+ @read_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
326
+ stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
327
+ end
328
+ end
329
+ end
330
+
331
+ protected
332
+
333
+ def start_listen_thread(port, listen_write = false, listen_read = false)
334
+ # Create a socket to accept connections from clients
335
+ addr = Socket.pack_sockaddr_in(port, @listen_address)
336
+ listen_socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
337
+ listen_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1) unless Kernel.is_windows?
338
+ begin
339
+ listen_socket.bind(addr)
340
+ rescue Errno::EADDRINUSE
341
+ raise "Error binding to port #{port}.\n" +
342
+ "Either another application is using this port\n" +
343
+ "or the operating system is being slow cleaning up.\n" +
344
+ "Make sure all sockets/streams are closed in all applications,\n" +
345
+ "wait 1 minute and try again."
346
+ end
347
+
348
+ listen_socket.listen(5)
349
+
350
+ @listen_sockets << listen_socket
351
+
352
+ # Start Listen Thread
353
+ @listen_threads << Thread.new do
354
+ begin
355
+ thread_reader, thread_writer = IO.pipe
356
+ @listen_pipes << thread_writer
357
+ while true
358
+ listen_thread_body(listen_socket, listen_write, listen_read, thread_reader)
359
+ break if @cancel_threads
360
+ end
361
+ rescue Exception => err
362
+ Logger.instance.error("Tcpip server listen thread unexpectedly died")
363
+ Logger.instance.error(err.formatted)
364
+ end
365
+ end
366
+ end
367
+
368
+ def listen_thread_body(listen_socket, listen_write, listen_read, thread_reader)
369
+ begin
370
+ socket, address = listen_socket.accept_nonblock
371
+ rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EINTR, Errno::EWOULDBLOCK
372
+ read_ready, _ = IO.select([listen_socket, thread_reader])
373
+ if read_ready and read_ready.include?(thread_reader)
374
+ return
375
+ else
376
+ retry
377
+ end
378
+ end
379
+
380
+ port, host_ip = Socket.unpack_sockaddr_in(address)
381
+ hostname = ''
382
+ hostname = Socket.lookup_hostname_from_ip(host_ip) if System.instance.use_dns
383
+ if System.instance.acl
384
+ addr = ["AF_INET", 10, "lc630", host_ip.to_s]
385
+ if not System.instance.acl.allow_addr?(addr)
386
+ # Reject connection
387
+ if not socket.closed?
388
+ socket.close()
389
+ end
390
+ Logger.instance.info "Tcpip server rejected connection from #{hostname}(#{host_ip}):#{port}"
391
+ return
392
+ end
393
+ end
394
+
395
+ # Configure TCP_NODELAY option
396
+ socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
397
+
398
+ # Accept Connection
399
+ write_socket = nil
400
+ read_socket = nil
401
+ write_socket = socket if listen_write
402
+ read_socket = socket if listen_read
403
+ stream = TcpipSocketStream.new(write_socket, read_socket, @write_timeout, @read_timeout)
404
+ if @raw_logger_pair
405
+ stream.raw_logger_pair = @raw_logger_pair.clone
406
+ stream.raw_logger_pair.start if @raw_logging_enabled
407
+ end
408
+
409
+ stream_protocol = @stream_protocol_class.new(*@stream_protocol_args)
410
+ stream_protocol.interface = @interface if @interface
411
+ stream_protocol.connect(stream)
412
+
413
+ if listen_write
414
+ @write_connection_callback.call(stream_protocol) if @write_connection_callback
415
+ @connection_mutex.synchronize do
416
+ @write_stream_protocols << [stream_protocol, hostname, host_ip, port]
417
+ end
418
+ end
419
+ if listen_read
420
+ @read_connection_callback.call(stream_protocol) if @read_connection_callback
421
+ @connection_mutex.synchronize do
422
+ @read_stream_protocols << [stream_protocol, hostname, host_ip, port]
423
+ end
424
+
425
+ # Start read thread
426
+ @read_threads << Thread.new do
427
+ index_to_delete = nil
428
+ begin
429
+ begin
430
+ read_thread_body(stream_protocol)
431
+ rescue Exception => err
432
+ Logger.instance.error "Tcpip server read thread unexpectedly died"
433
+ Logger.instance.error err.formatted
434
+ end
435
+ Logger.instance.info "Tcpip server lost read connection to #{hostname}(#{host_ip}):#{port}"
436
+ @read_threads.delete(Thread.current)
437
+
438
+ index_to_delete = nil
439
+ @connection_mutex.synchronize do
440
+ begin
441
+ index = 0
442
+ @read_stream_protocols.each do |read_stream_protocol, _, _, _|
443
+ if read_stream_protocol == stream_protocol
444
+ index_to_delete = index
445
+ read_stream_protocol.disconnect
446
+ read_stream_protocol.stream.raw_logger_pair.stop if read_stream_protocol.stream.raw_logger_pair
447
+ break
448
+ end
449
+ index += 1
450
+ end
451
+ ensure
452
+ if index_to_delete
453
+ @read_stream_protocols.delete_at(index_to_delete)
454
+ end
455
+ end
456
+ end
457
+ rescue Exception => err
458
+ Logger.instance.error "Tcpip server read thread unexpectedly died"
459
+ Logger.instance.error err.formatted
460
+ end
461
+ end
462
+ end
463
+
464
+ Logger.instance.info "Tcpip server accepted connection from #{hostname}(#{host_ip}):#{port}"
465
+ end
466
+
467
+ def write_thread_body
468
+ # Retrieve the next packet to be sent out to clients
469
+ # Handles disconnected clients even when packets aren't flowing
470
+ packet = nil
471
+
472
+ loop do
473
+ break if @cancel_threads
474
+ begin
475
+ packet = @write_queue.pop(true)
476
+ break
477
+ rescue ThreadError
478
+ # Timeout waiting for send - check for dead clients
479
+ indexes_to_delete = []
480
+ index = 0
481
+
482
+ @connection_mutex.synchronize do
483
+ @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
484
+ begin
485
+ if (@write_port != @read_port)
486
+ # Socket should return EWOULDBLOCK if it is still cleanly connected
487
+ stream_protocol.stream.write_socket.recvfrom_nonblock(10)
488
+ elsif (!stream_protocol.stream.write_socket.closed?)
489
+ # Let read thread detect disconnect
490
+ next
491
+ end
492
+
493
+ # Client has disconnected (or is invalidly sending data on the socket)
494
+ Logger.instance.info "Tcpip server lost write connection to #{hostname}(#{host_ip}):#{port}"
495
+ stream_protocol.disconnect
496
+ stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
497
+ indexes_to_delete.unshift(index) # Put later indexes at front of array
498
+ rescue Errno::ECONNRESET, Errno::ECONNABORTED
499
+ # Client has disconnected
500
+ Logger.instance.info "Tcpip server lost write connection to #{hostname}(#{host_ip}):#{port}"
501
+ stream_protocol.disconnect
502
+ stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
503
+ indexes_to_delete.unshift(index) # Put later indexes at front of array
504
+ rescue Errno::EWOULDBLOCK
505
+ # Client is still cleanly connected as far as we can tell without writing to the socket
506
+ ensure
507
+ index += 1
508
+ end
509
+ end
510
+
511
+ # Delete any dead sockets
512
+ indexes_to_delete.each do |index_to_delete|
513
+ @write_stream_protocols.delete_at(index_to_delete)
514
+ end
515
+ end # @connection_mutex.synchronize
516
+
517
+ # Sleep until we receive a packet or for 100ms
518
+ @write_mutex.synchronize do
519
+ @write_condition_variable.wait(@write_mutex, 0.1)
520
+ end
521
+ end
522
+ end
523
+
524
+ packet = write_thread_hook(packet)
525
+
526
+ if packet
527
+ @connection_mutex.synchronize do
528
+ # Send data to each client - On error drop the client
529
+ indexes_to_delete = []
530
+ index = 0
531
+ @write_stream_protocols.each do |stream_protocol, hostname, host_ip, port|
532
+ need_disconnect = false
533
+ begin
534
+ stream_protocol.write(packet)
535
+ rescue Errno::EPIPE, Errno::ECONNABORTED, IOError, Errno::ECONNRESET
536
+ # Client has normally disconnected
537
+ need_disconnect = true
538
+ rescue Exception => err
539
+ if err.message != "Stream not connected for write_raw"
540
+ Logger.instance.error "Error sending to client: #{err.class} #{err.message}"
541
+ end
542
+ need_disconnect = true
543
+ end
544
+
545
+ if need_disconnect
546
+ Logger.instance.info "Tcpip server lost write connection to #{hostname}(#{host_ip}):#{port}"
547
+ stream_protocol.disconnect
548
+ stream_protocol.stream.raw_logger_pair.stop if stream_protocol.stream.raw_logger_pair
549
+ indexes_to_delete.unshift(index) # Put later indexes at front of array
550
+ end
551
+
552
+ index += 1
553
+ end
554
+
555
+ # Delete any dead sockets
556
+ indexes_to_delete.each do |index_to_delete|
557
+ @write_stream_protocols.delete_at(index_to_delete)
558
+ end
559
+ end # @connection_mutex.synchronize
560
+ end
561
+ end
562
+
563
+ def write_thread_hook(packet)
564
+ return packet # By default just return the packet
565
+ end
566
+
567
+ def read_thread_body(stream_protocol)
568
+ loop do
569
+ packet = stream_protocol.read
570
+ return if !packet or @cancel_threads
571
+
572
+ # Do work on received packet
573
+ read_thread_hook(packet)
574
+ end # loop do
575
+ end
576
+
577
+ def read_thread_hook(packet)
578
+ @read_queue << packet.clone
579
+ end
580
+
581
+ end # class TcpipServerStream
582
+
583
+ end # module Cosmos