kinetic_sdk 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. checksums.yaml +7 -0
  2. data/GettingStarted.md +64 -0
  3. data/README.md +383 -0
  4. data/bin/console +12 -0
  5. data/bin/setup +8 -0
  6. data/gems/kontena-websocket-client-0.1.1/Gemfile +4 -0
  7. data/gems/kontena-websocket-client-0.1.1/LICENSE +190 -0
  8. data/gems/kontena-websocket-client-0.1.1/README.md +138 -0
  9. data/gems/kontena-websocket-client-0.1.1/Rakefile +6 -0
  10. data/gems/kontena-websocket-client-0.1.1/benchmark/benchmark-client.rb +45 -0
  11. data/gems/kontena-websocket-client-0.1.1/benchmark/benchmark-em.rb +66 -0
  12. data/gems/kontena-websocket-client-0.1.1/benchmark/benchmark.rb +161 -0
  13. data/gems/kontena-websocket-client-0.1.1/benchmark/benchmark.sh +17 -0
  14. data/gems/kontena-websocket-client-0.1.1/benchmark/websocket-echo-server.go +207 -0
  15. data/gems/kontena-websocket-client-0.1.1/examples/websocket-echo-client.rb +80 -0
  16. data/gems/kontena-websocket-client-0.1.1/kontena-websocket-client.gemspec +24 -0
  17. data/gems/kontena-websocket-client-0.1.1/lib/kontena/websocket/client/connection.rb +119 -0
  18. data/gems/kontena-websocket-client-0.1.1/lib/kontena/websocket/client/version.rb +13 -0
  19. data/gems/kontena-websocket-client-0.1.1/lib/kontena/websocket/client.rb +848 -0
  20. data/gems/kontena-websocket-client-0.1.1/lib/kontena/websocket/error.rb +81 -0
  21. data/gems/kontena-websocket-client-0.1.1/lib/kontena/websocket/logging.rb +55 -0
  22. data/gems/kontena-websocket-client-0.1.1/lib/kontena/websocket/openssl_patch.rb +10 -0
  23. data/gems/kontena-websocket-client-0.1.1/lib/kontena-websocket-client.rb +15 -0
  24. data/gems/mime-types-3.1/Code-of-Conduct.rdoc +74 -0
  25. data/gems/mime-types-3.1/Contributing.rdoc +130 -0
  26. data/gems/mime-types-3.1/History.rdoc +658 -0
  27. data/gems/mime-types-3.1/Licence.rdoc +25 -0
  28. data/gems/mime-types-3.1/Manifest.txt +31 -0
  29. data/gems/mime-types-3.1/README.rdoc +202 -0
  30. data/gems/mime-types-3.1/Rakefile +254 -0
  31. data/gems/mime-types-3.1/lib/mime/type/columnar.rb +55 -0
  32. data/gems/mime-types-3.1/lib/mime/type.rb +573 -0
  33. data/gems/mime-types-3.1/lib/mime/types/_columnar.rb +135 -0
  34. data/gems/mime-types-3.1/lib/mime/types/cache.rb +56 -0
  35. data/gems/mime-types-3.1/lib/mime/types/columnar.rb +1 -0
  36. data/gems/mime-types-3.1/lib/mime/types/container.rb +30 -0
  37. data/gems/mime-types-3.1/lib/mime/types/deprecations.rb +32 -0
  38. data/gems/mime-types-3.1/lib/mime/types/full.rb +17 -0
  39. data/gems/mime-types-3.1/lib/mime/types/loader.rb +148 -0
  40. data/gems/mime-types-3.1/lib/mime/types/logger.rb +37 -0
  41. data/gems/mime-types-3.1/lib/mime/types/registry.rb +81 -0
  42. data/gems/mime-types-3.1/lib/mime/types.rb +228 -0
  43. data/gems/mime-types-3.1/lib/mime-types.rb +1 -0
  44. data/gems/mime-types-3.1/test/bad-fixtures/malformed +9 -0
  45. data/gems/mime-types-3.1/test/fixture/json.json +1 -0
  46. data/gems/mime-types-3.1/test/fixture/old-data +9 -0
  47. data/gems/mime-types-3.1/test/fixture/yaml.yaml +55 -0
  48. data/gems/mime-types-3.1/test/minitest_helper.rb +13 -0
  49. data/gems/mime-types-3.1/test/test_mime_type.rb +603 -0
  50. data/gems/mime-types-3.1/test/test_mime_types.rb +161 -0
  51. data/gems/mime-types-3.1/test/test_mime_types_cache.rb +109 -0
  52. data/gems/mime-types-3.1/test/test_mime_types_class.rb +155 -0
  53. data/gems/mime-types-3.1/test/test_mime_types_lazy.rb +43 -0
  54. data/gems/mime-types-3.1/test/test_mime_types_loader.rb +32 -0
  55. data/gems/mime-types-data-3.2016.0521/Code-of-Conduct.md +75 -0
  56. data/gems/mime-types-data-3.2016.0521/Contributing.md +157 -0
  57. data/gems/mime-types-data-3.2016.0521/History.md +351 -0
  58. data/gems/mime-types-data-3.2016.0521/Licence.md +25 -0
  59. data/gems/mime-types-data-3.2016.0521/Manifest.txt +18 -0
  60. data/gems/mime-types-data-3.2016.0521/README.md +61 -0
  61. data/gems/mime-types-data-3.2016.0521/Rakefile +80 -0
  62. data/gems/mime-types-data-3.2016.0521/data/mime-types.json +1 -0
  63. data/gems/mime-types-data-3.2016.0521/data/mime.content_type.column +1964 -0
  64. data/gems/mime-types-data-3.2016.0521/data/mime.docs.column +1964 -0
  65. data/gems/mime-types-data-3.2016.0521/data/mime.encoding.column +1964 -0
  66. data/gems/mime-types-data-3.2016.0521/data/mime.flags.column +1964 -0
  67. data/gems/mime-types-data-3.2016.0521/data/mime.friendly.column +1964 -0
  68. data/gems/mime-types-data-3.2016.0521/data/mime.pext.column +1964 -0
  69. data/gems/mime-types-data-3.2016.0521/data/mime.use_instead.column +1964 -0
  70. data/gems/mime-types-data-3.2016.0521/data/mime.xrefs.column +1964 -0
  71. data/gems/mime-types-data-3.2016.0521/lib/mime/types/data.rb +21 -0
  72. data/gems/mime-types-data-3.2016.0521/lib/mime-types-data.rb +3 -0
  73. data/gems/multipart-post-2.0.0/Gemfile +14 -0
  74. data/gems/multipart-post-2.0.0/History.txt +60 -0
  75. data/gems/multipart-post-2.0.0/Manifest.txt +9 -0
  76. data/gems/multipart-post-2.0.0/README.md +77 -0
  77. data/gems/multipart-post-2.0.0/Rakefile +9 -0
  78. data/gems/multipart-post-2.0.0/lib/composite_io.rb +108 -0
  79. data/gems/multipart-post-2.0.0/lib/multipart_post.rb +9 -0
  80. data/gems/multipart-post-2.0.0/lib/multipartable.rb +29 -0
  81. data/gems/multipart-post-2.0.0/lib/net/http/post/multipart.rb +27 -0
  82. data/gems/multipart-post-2.0.0/lib/parts.rb +96 -0
  83. data/gems/multipart-post-2.0.0/multipart-post.gemspec +22 -0
  84. data/gems/multipart-post-2.0.0/test/multibyte.txt +1 -0
  85. data/gems/multipart-post-2.0.0/test/net/http/post/test_multipart.rb +110 -0
  86. data/gems/multipart-post-2.0.0/test/test_composite_io.rb +115 -0
  87. data/gems/multipart-post-2.0.0/test/test_parts.rb +86 -0
  88. data/gems/parallel-1.12.1/MIT-LICENSE.txt +20 -0
  89. data/gems/parallel-1.12.1/lib/parallel/processor_count.rb +93 -0
  90. data/gems/parallel-1.12.1/lib/parallel/version.rb +3 -0
  91. data/gems/parallel-1.12.1/lib/parallel.rb +500 -0
  92. data/gems/ruby-progressbar-1.9.0/LICENSE.txt +19 -0
  93. data/gems/ruby-progressbar-1.9.0/README.md +38 -0
  94. data/gems/ruby-progressbar-1.9.0/Rakefile +2 -0
  95. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/base.rb +183 -0
  96. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/calculators/length.rb +99 -0
  97. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/calculators/running_average.rb +9 -0
  98. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/components/bar.rb +96 -0
  99. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/components/percentage.rb +29 -0
  100. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/components/rate.rb +43 -0
  101. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/components/time.rb +107 -0
  102. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/components/title.rb +13 -0
  103. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/components.rb +5 -0
  104. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/errors/invalid_progress_error.rb +4 -0
  105. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/format/formatter.rb +27 -0
  106. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/format/molecule.rb +59 -0
  107. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/format/string.rb +36 -0
  108. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/format.rb +3 -0
  109. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/output.rb +68 -0
  110. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/outputs/non_tty.rb +47 -0
  111. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/outputs/null.rb +33 -0
  112. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/outputs/tty.rb +32 -0
  113. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/progress.rb +118 -0
  114. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/refinements/enumerator.rb +25 -0
  115. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/refinements.rb +1 -0
  116. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/throttle.rb +25 -0
  117. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/time.rb +30 -0
  118. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/timer.rb +72 -0
  119. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar/version.rb +3 -0
  120. data/gems/ruby-progressbar-1.9.0/lib/ruby-progressbar.rb +18 -0
  121. data/gems/slugify-1.0.7/README +18 -0
  122. data/gems/slugify-1.0.7/lib/slugify.rb +1012 -0
  123. data/gems/slugify-1.0.7/lib/slugify_string.rb +11 -0
  124. data/gems/slugify-1.0.7/tests/slugify_test.rb +116 -0
  125. data/gems/slugify-1.0.7/tests/string_slugify_test.rb +23 -0
  126. data/gems/websocket-driver-0.6.5/CHANGELOG.md +123 -0
  127. data/gems/websocket-driver-0.6.5/LICENSE.md +22 -0
  128. data/gems/websocket-driver-0.6.5/README.md +369 -0
  129. data/gems/websocket-driver-0.6.5/examples/tcp_server.rb +28 -0
  130. data/gems/websocket-driver-0.6.5/ext/websocket-driver/Makefile +264 -0
  131. data/gems/websocket-driver-0.6.5/ext/websocket-driver/WebsocketMaskService.java +55 -0
  132. data/gems/websocket-driver-0.6.5/ext/websocket-driver/extconf.rb +4 -0
  133. data/gems/websocket-driver-0.6.5/ext/websocket-driver/websocket_mask.bundle +0 -0
  134. data/gems/websocket-driver-0.6.5/ext/websocket-driver/websocket_mask.c +41 -0
  135. data/gems/websocket-driver-0.6.5/ext/websocket-driver/websocket_mask.o +0 -0
  136. data/gems/websocket-driver-0.6.5/lib/websocket/driver/client.rb +140 -0
  137. data/gems/websocket-driver-0.6.5/lib/websocket/driver/draft75.rb +102 -0
  138. data/gems/websocket-driver-0.6.5/lib/websocket/driver/draft76.rb +96 -0
  139. data/gems/websocket-driver-0.6.5/lib/websocket/driver/event_emitter.rb +54 -0
  140. data/gems/websocket-driver-0.6.5/lib/websocket/driver/headers.rb +45 -0
  141. data/gems/websocket-driver-0.6.5/lib/websocket/driver/hybi/frame.rb +20 -0
  142. data/gems/websocket-driver-0.6.5/lib/websocket/driver/hybi/message.rb +31 -0
  143. data/gems/websocket-driver-0.6.5/lib/websocket/driver/hybi.rb +406 -0
  144. data/gems/websocket-driver-0.6.5/lib/websocket/driver/proxy.rb +68 -0
  145. data/gems/websocket-driver-0.6.5/lib/websocket/driver/server.rb +80 -0
  146. data/gems/websocket-driver-0.6.5/lib/websocket/driver/stream_reader.rb +55 -0
  147. data/gems/websocket-driver-0.6.5/lib/websocket/driver.rb +199 -0
  148. data/gems/websocket-driver-0.6.5/lib/websocket/http/headers.rb +112 -0
  149. data/gems/websocket-driver-0.6.5/lib/websocket/http/request.rb +45 -0
  150. data/gems/websocket-driver-0.6.5/lib/websocket/http/response.rb +29 -0
  151. data/gems/websocket-driver-0.6.5/lib/websocket/http.rb +15 -0
  152. data/gems/websocket-driver-0.6.5/lib/websocket/mask.rb +14 -0
  153. data/gems/websocket-driver-0.6.5/lib/websocket/websocket_mask.rb +2 -0
  154. data/gems/websocket-driver-0.6.5/lib/websocket_mask.bundle +0 -0
  155. data/gems/websocket-driver-0.6.5-java/CHANGELOG.md +123 -0
  156. data/gems/websocket-driver-0.6.5-java/LICENSE.md +22 -0
  157. data/gems/websocket-driver-0.6.5-java/README.md +369 -0
  158. data/gems/websocket-driver-0.6.5-java/examples/tcp_server.rb +28 -0
  159. data/gems/websocket-driver-0.6.5-java/ext/websocket-driver/WebsocketMaskService.java +55 -0
  160. data/gems/websocket-driver-0.6.5-java/ext/websocket-driver/extconf.rb +4 -0
  161. data/gems/websocket-driver-0.6.5-java/ext/websocket-driver/websocket_mask.c +41 -0
  162. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/client.rb +140 -0
  163. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/draft75.rb +102 -0
  164. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/draft76.rb +96 -0
  165. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/event_emitter.rb +54 -0
  166. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/headers.rb +45 -0
  167. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/hybi/frame.rb +20 -0
  168. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/hybi/message.rb +31 -0
  169. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/hybi.rb +406 -0
  170. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/proxy.rb +68 -0
  171. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/server.rb +80 -0
  172. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver/stream_reader.rb +55 -0
  173. data/gems/websocket-driver-0.6.5-java/lib/websocket/driver.rb +199 -0
  174. data/gems/websocket-driver-0.6.5-java/lib/websocket/http/headers.rb +112 -0
  175. data/gems/websocket-driver-0.6.5-java/lib/websocket/http/request.rb +45 -0
  176. data/gems/websocket-driver-0.6.5-java/lib/websocket/http/response.rb +29 -0
  177. data/gems/websocket-driver-0.6.5-java/lib/websocket/http.rb +15 -0
  178. data/gems/websocket-driver-0.6.5-java/lib/websocket/mask.rb +14 -0
  179. data/gems/websocket-driver-0.6.5-java/lib/websocket/websocket_mask.rb +2 -0
  180. data/gems/websocket-driver-0.6.5-java/lib/websocket_mask.jar +0 -0
  181. data/gems/websocket-extensions-0.1.3/CHANGELOG.md +15 -0
  182. data/gems/websocket-extensions-0.1.3/LICENSE.md +20 -0
  183. data/gems/websocket-extensions-0.1.3/README.md +313 -0
  184. data/gems/websocket-extensions-0.1.3/lib/websocket/extensions/parser.rb +111 -0
  185. data/gems/websocket-extensions-0.1.3/lib/websocket/extensions.rb +181 -0
  186. data/lib/kinetic-sdk.rb +1 -0
  187. data/lib/kinetic_sdk/bridgehub/bridgehub-sdk.rb +80 -0
  188. data/lib/kinetic_sdk/bridgehub/lib/access_keys.rb +67 -0
  189. data/lib/kinetic_sdk/bridgehub/lib/bridge.rb +69 -0
  190. data/lib/kinetic_sdk/discussions/discussions-sdk.rb +165 -0
  191. data/lib/kinetic_sdk/discussions/lib/discussions.rb +107 -0
  192. data/lib/kinetic_sdk/discussions/lib/invitations.rb +120 -0
  193. data/lib/kinetic_sdk/discussions/lib/messages.rb +190 -0
  194. data/lib/kinetic_sdk/discussions/lib/meta.rb +14 -0
  195. data/lib/kinetic_sdk/discussions/lib/participants.rb +64 -0
  196. data/lib/kinetic_sdk/discussions/lib/related_items.rb +54 -0
  197. data/lib/kinetic_sdk/discussions/lib/websockets.rb +96 -0
  198. data/lib/kinetic_sdk/filehub/filehub-sdk.rb +80 -0
  199. data/lib/kinetic_sdk/filehub/lib/access_keys.rb +67 -0
  200. data/lib/kinetic_sdk/filehub/lib/filestores.rb +67 -0
  201. data/lib/kinetic_sdk/request_ce/lib/attribute_definitions.rb +153 -0
  202. data/lib/kinetic_sdk/request_ce/lib/bridges.rb +66 -0
  203. data/lib/kinetic_sdk/request_ce/lib/categories.rb +34 -0
  204. data/lib/kinetic_sdk/request_ce/lib/datastore_form.rb +110 -0
  205. data/lib/kinetic_sdk/request_ce/lib/datastore_submissions.rb +157 -0
  206. data/lib/kinetic_sdk/request_ce/lib/form.rb +99 -0
  207. data/lib/kinetic_sdk/request_ce/lib/form_types.rb +51 -0
  208. data/lib/kinetic_sdk/request_ce/lib/jwt.rb +55 -0
  209. data/lib/kinetic_sdk/request_ce/lib/kapp.rb +93 -0
  210. data/lib/kinetic_sdk/request_ce/lib/meta.rb +14 -0
  211. data/lib/kinetic_sdk/request_ce/lib/oauth.rb +37 -0
  212. data/lib/kinetic_sdk/request_ce/lib/security_policy_definitions.rb +157 -0
  213. data/lib/kinetic_sdk/request_ce/lib/space.rb +89 -0
  214. data/lib/kinetic_sdk/request_ce/lib/submissions.rb +215 -0
  215. data/lib/kinetic_sdk/request_ce/lib/system_api.rb +69 -0
  216. data/lib/kinetic_sdk/request_ce/lib/teams.rb +113 -0
  217. data/lib/kinetic_sdk/request_ce/lib/users.rb +245 -0
  218. data/lib/kinetic_sdk/request_ce/lib/webhook_jobs.rb +142 -0
  219. data/lib/kinetic_sdk/request_ce/lib/webhooks.rb +192 -0
  220. data/lib/kinetic_sdk/request_ce/request-ce-sdk.rb +153 -0
  221. data/lib/kinetic_sdk/task/lib/access_keys.rb +94 -0
  222. data/lib/kinetic_sdk/task/lib/categories.rb +190 -0
  223. data/lib/kinetic_sdk/task/lib/config.rb +202 -0
  224. data/lib/kinetic_sdk/task/lib/engine.rb +42 -0
  225. data/lib/kinetic_sdk/task/lib/environment.rb +14 -0
  226. data/lib/kinetic_sdk/task/lib/errors.rb +165 -0
  227. data/lib/kinetic_sdk/task/lib/groups.rb +112 -0
  228. data/lib/kinetic_sdk/task/lib/handlers.rb +105 -0
  229. data/lib/kinetic_sdk/task/lib/health.rb +28 -0
  230. data/lib/kinetic_sdk/task/lib/license.rb +52 -0
  231. data/lib/kinetic_sdk/task/lib/policy_rules.rb +166 -0
  232. data/lib/kinetic_sdk/task/lib/setup.rb +56 -0
  233. data/lib/kinetic_sdk/task/lib/sources.rb +134 -0
  234. data/lib/kinetic_sdk/task/lib/tasks.rb +17 -0
  235. data/lib/kinetic_sdk/task/lib/trees.rb +274 -0
  236. data/lib/kinetic_sdk/task/lib/users.rb +75 -0
  237. data/lib/kinetic_sdk/task/task-sdk.rb +92 -0
  238. data/lib/kinetic_sdk/utils/kinetic-http-headers.rb +150 -0
  239. data/lib/kinetic_sdk/utils/kinetic-http-response.rb +75 -0
  240. data/lib/kinetic_sdk/utils/kinetic-http.rb +552 -0
  241. data/lib/kinetic_sdk/utils/logger.rb +70 -0
  242. data/lib/kinetic_sdk/utils/random.rb +30 -0
  243. data/lib/kinetic_sdk/version.rb +7 -0
  244. data/lib/kinetic_sdk.rb +57 -0
  245. metadata +414 -0
@@ -0,0 +1,406 @@
1
+ module WebSocket
2
+ class Driver
3
+
4
+ class Hybi < Driver
5
+ root = File.expand_path('../hybi', __FILE__)
6
+
7
+ autoload :Frame, root + '/frame'
8
+ autoload :Message, root + '/message'
9
+
10
+ def self.generate_accept(key)
11
+ Base64.strict_encode64(Digest::SHA1.digest(key + GUID))
12
+ end
13
+
14
+ GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
15
+
16
+ BYTE = 0b11111111
17
+ FIN = MASK = 0b10000000
18
+ RSV1 = 0b01000000
19
+ RSV2 = 0b00100000
20
+ RSV3 = 0b00010000
21
+ OPCODE = 0b00001111
22
+ LENGTH = 0b01111111
23
+
24
+ OPCODES = {
25
+ :continuation => 0,
26
+ :text => 1,
27
+ :binary => 2,
28
+ :close => 8,
29
+ :ping => 9,
30
+ :pong => 10
31
+ }
32
+
33
+ OPCODE_CODES = OPCODES.values
34
+ MESSAGE_OPCODES = OPCODES.values_at(:continuation, :text, :binary)
35
+ OPENING_OPCODES = OPCODES.values_at(:text, :binary)
36
+
37
+ ERRORS = {
38
+ :normal_closure => 1000,
39
+ :going_away => 1001,
40
+ :protocol_error => 1002,
41
+ :unacceptable => 1003,
42
+ :encoding_error => 1007,
43
+ :policy_violation => 1008,
44
+ :too_large => 1009,
45
+ :extension_error => 1010,
46
+ :unexpected_condition => 1011
47
+ }
48
+
49
+ ERROR_CODES = ERRORS.values
50
+ DEFAULT_ERROR_CODE = 1000
51
+ MIN_RESERVED_ERROR = 3000
52
+ MAX_RESERVED_ERROR = 4999
53
+
54
+ PACK_FORMATS = {2 => 'n', 8 => 'Q>'}
55
+
56
+ def initialize(socket, options = {})
57
+ super
58
+
59
+ @extensions = ::WebSocket::Extensions.new
60
+ @stage = 0
61
+ @masking = options[:masking]
62
+ @protocols = options[:protocols] || []
63
+ @protocols = @protocols.strip.split(/ *, */) if String === @protocols
64
+ @require_masking = options[:require_masking]
65
+ @ping_callbacks = {}
66
+
67
+ @frame = @message = nil
68
+
69
+ return unless @socket.respond_to?(:env)
70
+
71
+ sec_key = @socket.env['HTTP_SEC_WEBSOCKET_KEY']
72
+ protos = @socket.env['HTTP_SEC_WEBSOCKET_PROTOCOL']
73
+
74
+ @headers['Upgrade'] = 'websocket'
75
+ @headers['Connection'] = 'Upgrade'
76
+ @headers['Sec-WebSocket-Accept'] = Hybi.generate_accept(sec_key)
77
+
78
+ if protos = @socket.env['HTTP_SEC_WEBSOCKET_PROTOCOL']
79
+ protos = protos.split(/ *, */) if String === protos
80
+ @protocol = protos.find { |p| @protocols.include?(p) }
81
+ @headers['Sec-WebSocket-Protocol'] = @protocol if @protocol
82
+ end
83
+ end
84
+
85
+ def version
86
+ "hybi-#{@socket.env['HTTP_SEC_WEBSOCKET_VERSION']}"
87
+ end
88
+
89
+ def add_extension(extension)
90
+ @extensions.add(extension)
91
+ true
92
+ end
93
+
94
+ def parse(chunk)
95
+ @reader.put(chunk)
96
+ buffer = true
97
+ while buffer
98
+ case @stage
99
+ when 0 then
100
+ buffer = @reader.read(1)
101
+ parse_opcode(buffer.getbyte(0)) if buffer
102
+
103
+ when 1 then
104
+ buffer = @reader.read(1)
105
+ parse_length(buffer.getbyte(0)) if buffer
106
+
107
+ when 2 then
108
+ buffer = @reader.read(@frame.length_bytes)
109
+ parse_extended_length(buffer) if buffer
110
+
111
+ when 3 then
112
+ buffer = @reader.read(4)
113
+ if buffer
114
+ @stage = 4
115
+ @frame.masking_key = buffer
116
+ end
117
+
118
+ when 4 then
119
+ buffer = @reader.read(@frame.length)
120
+
121
+ if buffer
122
+ @stage = 0
123
+ emit_frame(buffer)
124
+ end
125
+
126
+ else
127
+ buffer = nil
128
+ end
129
+ end
130
+ end
131
+
132
+ def binary(message)
133
+ frame(message, :binary)
134
+ end
135
+
136
+ def ping(message = '', &callback)
137
+ @ping_callbacks[message] = callback if callback
138
+ frame(message, :ping)
139
+ end
140
+
141
+ def pong(message = '')
142
+ frame(message, :pong)
143
+ end
144
+
145
+ def close(reason = nil, code = nil)
146
+ reason ||= ''
147
+ code ||= ERRORS[:normal_closure]
148
+
149
+ if @ready_state <= 0
150
+ @ready_state = 3
151
+ emit(:close, CloseEvent.new(code, reason))
152
+ true
153
+ elsif @ready_state == 1
154
+ frame(reason, :close, code)
155
+ @ready_state = 2
156
+ true
157
+ else
158
+ false
159
+ end
160
+ end
161
+
162
+ def frame(buffer, type = nil, code = nil)
163
+ return queue([buffer, type, code]) if @ready_state <= 0
164
+ return false unless @ready_state == 1
165
+
166
+ message = Message.new
167
+ frame = Frame.new
168
+ is_text = String === buffer
169
+
170
+ message.rsv1 = message.rsv2 = message.rsv3 = false
171
+ message.opcode = OPCODES[type || (is_text ? :text : :binary)]
172
+
173
+ payload = is_text ? buffer.bytes.to_a : buffer
174
+ payload = [code].pack(PACK_FORMATS[2]).bytes.to_a + payload if code
175
+ message.data = payload.pack('C*')
176
+
177
+ if MESSAGE_OPCODES.include?(message.opcode)
178
+ message = @extensions.process_outgoing_message(message)
179
+ end
180
+
181
+ frame.final = true
182
+ frame.rsv1 = message.rsv1
183
+ frame.rsv2 = message.rsv2
184
+ frame.rsv3 = message.rsv3
185
+ frame.opcode = message.opcode
186
+ frame.masked = !!@masking
187
+ frame.masking_key = SecureRandom.random_bytes(4) if frame.masked
188
+ frame.length = message.data.bytesize
189
+ frame.payload = message.data
190
+
191
+ send_frame(frame)
192
+ true
193
+
194
+ rescue ::WebSocket::Extensions::ExtensionError => error
195
+ fail(:extension_error, error.message)
196
+ end
197
+
198
+ private
199
+
200
+ def send_frame(frame)
201
+ length = frame.length
202
+ buffer = []
203
+ masked = frame.masked ? MASK : 0
204
+
205
+ buffer[0] = (frame.final ? FIN : 0) |
206
+ (frame.rsv1 ? RSV1 : 0) |
207
+ (frame.rsv2 ? RSV2 : 0) |
208
+ (frame.rsv3 ? RSV3 : 0) |
209
+ frame.opcode
210
+
211
+ if length <= 125
212
+ buffer[1] = masked | length
213
+ elsif length <= 65535
214
+ buffer[1] = masked | 126
215
+ buffer[2..3] = [length].pack(PACK_FORMATS[2]).bytes.to_a
216
+ else
217
+ buffer[1] = masked | 127
218
+ buffer[2..9] = [length].pack(PACK_FORMATS[8]).bytes.to_a
219
+ end
220
+
221
+ if frame.masked
222
+ buffer.concat(frame.masking_key.bytes.to_a)
223
+ buffer.concat(Mask.mask(frame.payload, frame.masking_key).bytes.to_a)
224
+ else
225
+ buffer.concat(frame.payload.bytes.to_a)
226
+ end
227
+
228
+ @socket.write(buffer.pack('C*'))
229
+ end
230
+
231
+ def handshake_response
232
+ begin
233
+ extensions = @extensions.generate_response(@socket.env['HTTP_SEC_WEBSOCKET_EXTENSIONS'])
234
+ rescue => error
235
+ fail(:protocol_error, error.message)
236
+ return nil
237
+ end
238
+
239
+ @headers['Sec-WebSocket-Extensions'] = extensions if extensions
240
+
241
+ start = 'HTTP/1.1 101 Switching Protocols'
242
+ headers = [start, @headers.to_s, '']
243
+ headers.join("\r\n")
244
+ end
245
+
246
+ def shutdown(code, reason, error = false)
247
+ @frame = @message = nil
248
+ @stage = 5
249
+ @extensions.close
250
+
251
+ frame(reason, :close, code) if @ready_state < 2
252
+ @ready_state = 3
253
+
254
+ emit(:error, ProtocolError.new(reason)) if error
255
+ emit(:close, CloseEvent.new(code, reason))
256
+ end
257
+
258
+ def fail(type, message)
259
+ return if @ready_state > 1
260
+ shutdown(ERRORS[type], message, true)
261
+ end
262
+
263
+ def parse_opcode(octet)
264
+ rsvs = [RSV1, RSV2, RSV3].map { |rsv| (octet & rsv) == rsv }
265
+
266
+ @frame = Frame.new
267
+
268
+ @frame.final = (octet & FIN) == FIN
269
+ @frame.rsv1 = rsvs[0]
270
+ @frame.rsv2 = rsvs[1]
271
+ @frame.rsv3 = rsvs[2]
272
+ @frame.opcode = (octet & OPCODE)
273
+
274
+ @stage = 1
275
+
276
+ unless @extensions.valid_frame_rsv?(@frame)
277
+ return fail(:protocol_error,
278
+ "One or more reserved bits are on: reserved1 = #{@frame.rsv1 ? 1 : 0}" +
279
+ ", reserved2 = #{@frame.rsv2 ? 1 : 0 }" +
280
+ ", reserved3 = #{@frame.rsv3 ? 1 : 0 }")
281
+ end
282
+
283
+ unless OPCODES.values.include?(@frame.opcode)
284
+ return fail(:protocol_error, "Unrecognized frame opcode: #{@frame.opcode}")
285
+ end
286
+
287
+ unless MESSAGE_OPCODES.include?(@frame.opcode) or @frame.final
288
+ return fail(:protocol_error, "Received fragmented control frame: opcode = #{@frame.opcode}")
289
+ end
290
+
291
+ if @message and OPENING_OPCODES.include?(@frame.opcode)
292
+ return fail(:protocol_error, 'Received new data frame but previous continuous frame is unfinished')
293
+ end
294
+ end
295
+
296
+ def parse_length(octet)
297
+ @frame.masked = (octet & MASK) == MASK
298
+ @frame.length = (octet & LENGTH)
299
+
300
+ if @frame.length >= 0 and @frame.length <= 125
301
+ @stage = @frame.masked ? 3 : 4
302
+ return unless check_frame_length
303
+ else
304
+ @stage = 2
305
+ @frame.length_bytes = (@frame.length == 126) ? 2 : 8
306
+ end
307
+
308
+ if @require_masking and not @frame.masked
309
+ return fail(:unacceptable, 'Received unmasked frame but masking is required')
310
+ end
311
+ end
312
+
313
+ def parse_extended_length(buffer)
314
+ @frame.length = buffer.unpack(PACK_FORMATS[buffer.bytesize]).first
315
+ @stage = @frame.masked ? 3 : 4
316
+
317
+ unless MESSAGE_OPCODES.include?(@frame.opcode) or @frame.length <= 125
318
+ return fail(:protocol_error, "Received control frame having too long payload: #{@frame.length}")
319
+ end
320
+
321
+ return unless check_frame_length
322
+ end
323
+
324
+ def check_frame_length
325
+ length = @message ? @message.data.bytesize : 0
326
+
327
+ if length + @frame.length > @max_length
328
+ fail(:too_large, 'WebSocket frame length too large')
329
+ false
330
+ else
331
+ true
332
+ end
333
+ end
334
+
335
+ def emit_frame(buffer)
336
+ frame = @frame
337
+ opcode = frame.opcode
338
+ payload = frame.payload = Mask.mask(buffer, @frame.masking_key)
339
+ bytesize = payload.bytesize
340
+ bytes = payload.bytes.to_a
341
+
342
+ @frame = nil
343
+
344
+ case opcode
345
+ when OPCODES[:continuation] then
346
+ return fail(:protocol_error, 'Received unexpected continuation frame') unless @message
347
+ @message << frame
348
+
349
+ when OPCODES[:text], OPCODES[:binary] then
350
+ @message = Message.new
351
+ @message << frame
352
+
353
+ when OPCODES[:close] then
354
+ code = (bytesize >= 2) ? payload.unpack(PACK_FORMATS[2]).first : nil
355
+ reason = (bytesize > 2) ? Driver.encode(bytes[2..-1] || [], UNICODE) : nil
356
+
357
+ unless (bytesize == 0) or
358
+ (code && code >= MIN_RESERVED_ERROR && code <= MAX_RESERVED_ERROR) or
359
+ ERROR_CODES.include?(code)
360
+ code = ERRORS[:protocol_error]
361
+ end
362
+
363
+ if bytesize > 125 or (bytesize > 2 and reason.nil?)
364
+ code = ERRORS[:protocol_error]
365
+ end
366
+
367
+ shutdown(code || DEFAULT_ERROR_CODE, reason || '')
368
+
369
+ when OPCODES[:ping] then
370
+ frame(payload, :pong)
371
+
372
+ when OPCODES[:pong] then
373
+ message = Driver.encode(payload, UNICODE)
374
+ callback = @ping_callbacks[message]
375
+ @ping_callbacks.delete(message)
376
+ callback.call if callback
377
+ end
378
+
379
+ emit_message if frame.final and MESSAGE_OPCODES.include?(opcode)
380
+ end
381
+
382
+ def emit_message
383
+ message = @extensions.process_incoming_message(@message)
384
+ @message = nil
385
+
386
+ payload = message.data
387
+
388
+ case message.opcode
389
+ when OPCODES[:text] then
390
+ payload = Driver.encode(payload, UNICODE)
391
+ when OPCODES[:binary]
392
+ payload = payload.bytes.to_a
393
+ end
394
+
395
+ if payload
396
+ emit(:message, MessageEvent.new(payload))
397
+ else
398
+ fail(:encoding_error, 'Could not decode a text frame as UTF-8')
399
+ end
400
+ rescue ::WebSocket::Extensions::ExtensionError => error
401
+ fail(:extension_error, error.message)
402
+ end
403
+ end
404
+
405
+ end
406
+ end
@@ -0,0 +1,68 @@
1
+ module WebSocket
2
+ class Driver
3
+
4
+ class Proxy
5
+ include EventEmitter
6
+
7
+ PORTS = {'ws' => 80, 'wss' => 443}
8
+
9
+ attr_reader :status, :headers
10
+
11
+ def initialize(client, origin, options)
12
+ super()
13
+
14
+ @client = client
15
+ @http = HTTP::Response.new
16
+ @socket = client.instance_variable_get(:@socket)
17
+ @origin = URI.parse(@socket.url)
18
+ @url = URI.parse(origin)
19
+ @options = options
20
+ @state = 0
21
+
22
+ @headers = Headers.new
23
+ @headers['Host'] = @origin.host + (@origin.port ? ":#{@origin.port}" : '')
24
+ @headers['Connection'] = 'keep-alive'
25
+ @headers['Proxy-Connection'] = 'keep-alive'
26
+
27
+ if @url.user
28
+ auth = Base64.strict_encode64([@url.user, @url.password] * ':')
29
+ @headers['Proxy-Authorization'] = 'Basic ' + auth
30
+ end
31
+ end
32
+
33
+ def set_header(name, value)
34
+ return false unless @state == 0
35
+ @headers[name] = value
36
+ true
37
+ end
38
+
39
+ def start
40
+ return false unless @state == 0
41
+ @state = 1
42
+
43
+ port = @origin.port || PORTS[@origin.scheme]
44
+ start = "CONNECT #{@origin.host}:#{port} HTTP/1.1"
45
+ headers = [start, @headers.to_s, '']
46
+
47
+ @socket.write(headers.join("\r\n"))
48
+ true
49
+ end
50
+
51
+ def parse(chunk)
52
+ @http.parse(chunk)
53
+ return unless @http.complete?
54
+
55
+ @status = @http.code
56
+ @headers = Headers.new(@http.headers)
57
+
58
+ if @status == 200
59
+ emit(:connect, ConnectEvent.new)
60
+ else
61
+ message = "Can't establish a connection to the server at #{@socket.url}"
62
+ emit(:error, ProtocolError.new(message))
63
+ end
64
+ end
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,80 @@
1
+ module WebSocket
2
+ class Driver
3
+
4
+ class Server < Driver
5
+ EVENTS = %w[open message error close]
6
+
7
+ def initialize(socket, options = {})
8
+ super
9
+ @http = HTTP::Request.new
10
+ @delegate = nil
11
+ end
12
+
13
+ def env
14
+ @http.complete? ? @http.env : nil
15
+ end
16
+
17
+ def url
18
+ return nil unless e = env
19
+
20
+ url = "ws://#{e['HTTP_HOST']}"
21
+ url << e['PATH_INFO']
22
+ url << "?#{e['QUERY_STRING']}" unless e['QUERY_STRING'] == ''
23
+ url
24
+ end
25
+
26
+ %w[add_extension set_header start frame text binary ping close].each do |method|
27
+ define_method(method) do |*args, &block|
28
+ if @delegate
29
+ @delegate.__send__(method, *args, &block)
30
+ else
31
+ @queue << [method, args, block]
32
+ true
33
+ end
34
+ end
35
+ end
36
+
37
+ %w[protocol version].each do |method|
38
+ define_method(method) do
39
+ @delegate && @delegate.__send__(method)
40
+ end
41
+ end
42
+
43
+ def parse(chunk)
44
+ return @delegate.parse(chunk) if @delegate
45
+
46
+ @http.parse(chunk)
47
+ return fail_request('Invalid HTTP request') if @http.error?
48
+ return unless @http.complete?
49
+
50
+ @delegate = Driver.rack(self, @options)
51
+ open
52
+
53
+ EVENTS.each do |event|
54
+ @delegate.on(event) { |e| emit(event, e) }
55
+ end
56
+
57
+ emit(:connect, ConnectEvent.new)
58
+ end
59
+
60
+ def write(buffer)
61
+ @socket.write(buffer)
62
+ end
63
+
64
+ private
65
+
66
+ def fail_request(message)
67
+ emit(:error, ProtocolError.new(message))
68
+ emit(:close, CloseEvent.new(Hybi::ERRORS[:protocol_error], message))
69
+ end
70
+
71
+ def open
72
+ @queue.each do |method, args, block|
73
+ @delegate.__send__(method, *args, &block)
74
+ end
75
+ @queue = []
76
+ end
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,55 @@
1
+ module WebSocket
2
+ class Driver
3
+
4
+ class StreamReader
5
+ # Try to minimise the number of reallocations done:
6
+ MINIMUM_AUTOMATIC_PRUNE_OFFSET = 128
7
+
8
+ def initialize
9
+ @buffer = String.new('').force_encoding(BINARY)
10
+ @offset = 0
11
+ end
12
+
13
+ def put(chunk)
14
+ return unless chunk and chunk.bytesize > 0
15
+ @buffer << chunk.force_encoding(BINARY)
16
+ end
17
+
18
+ # Read bytes from the data:
19
+ def read(length)
20
+ return nil if (@offset + length) > @buffer.bytesize
21
+
22
+ chunk = @buffer.byteslice(@offset, length)
23
+ @offset += chunk.bytesize
24
+
25
+ prune if @offset > MINIMUM_AUTOMATIC_PRUNE_OFFSET
26
+
27
+ return chunk
28
+ end
29
+
30
+ def each_byte
31
+ prune
32
+
33
+ @buffer.each_byte do |octet|
34
+ @offset += 1
35
+ yield octet
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def prune
42
+ buffer_size = @buffer.bytesize
43
+
44
+ if @offset > buffer_size
45
+ @buffer = String.new('').force_encoding(BINARY)
46
+ else
47
+ @buffer = @buffer.byteslice(@offset, buffer_size - @offset)
48
+ end
49
+
50
+ @offset = 0
51
+ end
52
+ end
53
+
54
+ end
55
+ end