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,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
@@ -0,0 +1,199 @@
1
+ # Protocol references:
2
+ #
3
+ # * http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75
4
+ # * http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
5
+ # * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
6
+
7
+ require 'base64'
8
+ require 'digest/md5'
9
+ require 'digest/sha1'
10
+ require 'securerandom'
11
+ require 'set'
12
+ require 'stringio'
13
+ require 'uri'
14
+ require 'websocket/extensions'
15
+
16
+ module WebSocket
17
+ autoload :HTTP, File.expand_path('../http', __FILE__)
18
+
19
+ class Driver
20
+
21
+ root = File.expand_path('../driver', __FILE__)
22
+
23
+ begin
24
+ # Load C native extension
25
+ require 'websocket_mask'
26
+ rescue LoadError
27
+ # Fall back to pure-Ruby implementation
28
+ require 'websocket/mask'
29
+ end
30
+
31
+
32
+ if RUBY_PLATFORM =~ /java/
33
+ require 'jruby'
34
+ com.jcoglan.websocket.WebsocketMaskService.new.basicLoad(JRuby.runtime)
35
+ end
36
+
37
+ unless Mask.respond_to?(:mask)
38
+ def Mask.mask(payload, mask)
39
+ @instance ||= new
40
+ @instance.mask(payload, mask)
41
+ end
42
+ end
43
+
44
+ MAX_LENGTH = 0x3ffffff
45
+ STATES = [:connecting, :open, :closing, :closed]
46
+
47
+ BINARY = 'ASCII-8BIT'
48
+ UNICODE = 'UTF-8'
49
+
50
+ ConnectEvent = Struct.new(nil)
51
+ OpenEvent = Struct.new(nil)
52
+ MessageEvent = Struct.new(:data)
53
+ CloseEvent = Struct.new(:code, :reason)
54
+
55
+ ProtocolError = Class.new(StandardError)
56
+ URIError = Class.new(ArgumentError)
57
+ ConfigurationError = Class.new(ArgumentError)
58
+
59
+ autoload :Client, root + '/client'
60
+ autoload :Draft75, root + '/draft75'
61
+ autoload :Draft76, root + '/draft76'
62
+ autoload :EventEmitter, root + '/event_emitter'
63
+ autoload :Headers, root + '/headers'
64
+ autoload :Hybi, root + '/hybi'
65
+ autoload :Proxy, root + '/proxy'
66
+ autoload :Server, root + '/server'
67
+ autoload :StreamReader, root + '/stream_reader'
68
+
69
+ include EventEmitter
70
+ attr_reader :protocol, :ready_state
71
+
72
+ def initialize(socket, options = {})
73
+ super()
74
+ Driver.validate_options(options, [:max_length, :masking, :require_masking, :protocols])
75
+
76
+ @socket = socket
77
+ @reader = StreamReader.new
78
+ @options = options
79
+ @max_length = options[:max_length] || MAX_LENGTH
80
+ @headers = Headers.new
81
+ @queue = []
82
+ @ready_state = 0
83
+ end
84
+
85
+ def state
86
+ return nil unless @ready_state >= 0
87
+ STATES[@ready_state]
88
+ end
89
+
90
+ def add_extension(extension)
91
+ false
92
+ end
93
+
94
+ def set_header(name, value)
95
+ return false unless @ready_state <= 0
96
+ @headers[name] = value
97
+ true
98
+ end
99
+
100
+ def start
101
+ return false unless @ready_state == 0
102
+ response = handshake_response
103
+ return false unless response
104
+ @socket.write(response)
105
+ open unless @stage == -1
106
+ true
107
+ end
108
+
109
+ def text(message)
110
+ message = message.encode(UNICODE) unless message.encoding.name == UNICODE
111
+ frame(message, :text)
112
+ end
113
+
114
+ def binary(message)
115
+ false
116
+ end
117
+
118
+ def ping(*args)
119
+ false
120
+ end
121
+
122
+ def pong(*args)
123
+ false
124
+ end
125
+
126
+ def close(reason = nil, code = nil)
127
+ return false unless @ready_state == 1
128
+ @ready_state = 3
129
+ emit(:close, CloseEvent.new(nil, nil))
130
+ true
131
+ end
132
+
133
+ private
134
+
135
+ def open
136
+ @ready_state = 1
137
+ @queue.each { |message| frame(*message) }
138
+ @queue = []
139
+ emit(:open, OpenEvent.new)
140
+ end
141
+
142
+ def queue(message)
143
+ @queue << message
144
+ true
145
+ end
146
+
147
+ def self.client(socket, options = {})
148
+ Client.new(socket, options.merge(:masking => true))
149
+ end
150
+
151
+ def self.server(socket, options = {})
152
+ Server.new(socket, options.merge(:require_masking => true))
153
+ end
154
+
155
+ def self.rack(socket, options = {})
156
+ env = socket.env
157
+ if env['HTTP_SEC_WEBSOCKET_VERSION']
158
+ Hybi.new(socket, options.merge(:require_masking => true))
159
+ elsif env['HTTP_SEC_WEBSOCKET_KEY1']
160
+ Draft76.new(socket, options)
161
+ else
162
+ Draft75.new(socket, options)
163
+ end
164
+ end
165
+
166
+ def self.encode(string, encoding = nil)
167
+ case string
168
+ when Array then
169
+ string = string.pack('C*')
170
+ encoding ||= BINARY
171
+ when String then
172
+ encoding ||= UNICODE
173
+ end
174
+ unless string.encoding.name == encoding
175
+ string = string.dup if string.frozen?
176
+ string.force_encoding(encoding)
177
+ end
178
+ string.valid_encoding? ? string : nil
179
+ end
180
+
181
+ def self.validate_options(options, valid_keys)
182
+ options.keys.each do |key|
183
+ unless valid_keys.include?(key)
184
+ raise ConfigurationError, "Unrecognized option: #{key.inspect}"
185
+ end
186
+ end
187
+ end
188
+
189
+ def self.websocket?(env)
190
+ connection = env['HTTP_CONNECTION'] || ''
191
+ upgrade = env['HTTP_UPGRADE'] || ''
192
+
193
+ env['REQUEST_METHOD'] == 'GET' and
194
+ connection.downcase.split(/ *, */).include?('upgrade') and
195
+ upgrade.downcase == 'websocket'
196
+ end
197
+
198
+ end
199
+ end
@@ -0,0 +1,112 @@
1
+ module WebSocket
2
+ module HTTP
3
+
4
+ module Headers
5
+ MAX_LINE_LENGTH = 4096
6
+ CR = 0x0D
7
+ LF = 0x0A
8
+
9
+ # RFC 2616 grammar rules:
10
+ #
11
+ # CHAR = <any US-ASCII character (octets 0 - 127)>
12
+ #
13
+ # CTL = <any US-ASCII control character
14
+ # (octets 0 - 31) and DEL (127)>
15
+ #
16
+ # SP = <US-ASCII SP, space (32)>
17
+ #
18
+ # HT = <US-ASCII HT, horizontal-tab (9)>
19
+ #
20
+ # token = 1*<any CHAR except CTLs or separators>
21
+ #
22
+ # separators = "(" | ")" | "<" | ">" | "@"
23
+ # | "," | ";" | ":" | "\" | <">
24
+ # | "/" | "[" | "]" | "?" | "="
25
+ # | "{" | "}" | SP | HT
26
+ #
27
+ # Or, as redefined in RFC 7230:
28
+ #
29
+ # token = 1*tchar
30
+ #
31
+ # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
32
+ # / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
33
+ # / DIGIT / ALPHA
34
+ # ; any VCHAR, except delimiters
35
+
36
+ HEADER_LINE = /^([!#\$%&'\*\+\-\.\^_`\|~0-9a-z]+):\s*([\x20-\x7e]*?)\s*$/i
37
+
38
+ attr_reader :headers
39
+
40
+ def initialize
41
+ @buffer = []
42
+ @env = {}
43
+ @headers = {}
44
+ @stage = 0
45
+ end
46
+
47
+ def complete?
48
+ @stage == 2
49
+ end
50
+
51
+ def error?
52
+ @stage == -1
53
+ end
54
+
55
+ def parse(chunk)
56
+ chunk.each_byte do |octet|
57
+ if octet == LF and @stage < 2
58
+ @buffer.pop if @buffer.last == CR
59
+ if @buffer.empty?
60
+ complete if @stage == 1
61
+ else
62
+ result = case @stage
63
+ when 0 then start_line(string_buffer)
64
+ when 1 then header_line(string_buffer)
65
+ end
66
+
67
+ if result
68
+ @stage = 1
69
+ else
70
+ error
71
+ end
72
+ end
73
+ @buffer = []
74
+ else
75
+ @buffer << octet if @stage >= 0
76
+ error if @stage < 2 and @buffer.size > MAX_LINE_LENGTH
77
+ end
78
+ end
79
+ @env['rack.input'] = StringIO.new(string_buffer)
80
+ end
81
+
82
+ private
83
+
84
+ def complete
85
+ @stage = 2
86
+ end
87
+
88
+ def error
89
+ @stage = -1
90
+ end
91
+
92
+ def header_line(line)
93
+ return false unless parsed = line.scan(HEADER_LINE).first
94
+
95
+ key = HTTP.normalize_header(parsed[0])
96
+ value = parsed[1].strip
97
+
98
+ if @headers.has_key?(key)
99
+ @headers[key] << ', ' << value
100
+ else
101
+ @headers[key] = value
102
+ end
103
+ true
104
+ end
105
+
106
+ def string_buffer
107
+ @buffer.pack('C*')
108
+ end
109
+ end
110
+
111
+ end
112
+ end
@@ -0,0 +1,45 @@
1
+ module WebSocket
2
+ module HTTP
3
+
4
+ class Request
5
+ include Headers
6
+
7
+ REQUEST_LINE = /^(OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT) ([\x21-\x7e]+) (HTTP\/[0-9]+\.[0-9]+)$/
8
+ REQUEST_TARGET = /^(.*?)(\?(.*))?$/
9
+ RESERVED_HEADERS = %w[content-length content-type]
10
+
11
+ attr_reader :env
12
+
13
+ private
14
+
15
+ def start_line(line)
16
+ return false unless parsed = line.scan(REQUEST_LINE).first
17
+
18
+ target = parsed[1].scan(REQUEST_TARGET).first
19
+
20
+ @env = {
21
+ 'REQUEST_METHOD' => parsed[0],
22
+ 'SCRIPT_NAME' => '',
23
+ 'PATH_INFO' => target[0],
24
+ 'QUERY_STRING' => target[2] || ''
25
+ }
26
+ true
27
+ end
28
+
29
+ def complete
30
+ super
31
+ @headers.each do |name, value|
32
+ rack_name = name.upcase.gsub(/-/, '_')
33
+ rack_name = "HTTP_#{rack_name}" unless RESERVED_HEADERS.include?(name)
34
+ @env[rack_name] = value
35
+ end
36
+ if host = @env['HTTP_HOST']
37
+ uri = URI.parse("http://#{host}")
38
+ @env['SERVER_NAME'] = uri.host
39
+ @env['SERVER_PORT'] = uri.port.to_s
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ module WebSocket
2
+ module HTTP
3
+
4
+ class Response
5
+ include Headers
6
+
7
+ STATUS_LINE = /^(HTTP\/[0-9]+\.[0-9]+) ([0-9]{3}) ([\x20-\x7e]+)$/
8
+
9
+ attr_reader :code
10
+
11
+ def [](name)
12
+ @headers[HTTP.normalize_header(name)]
13
+ end
14
+
15
+ def body
16
+ @buffer.pack('C*')
17
+ end
18
+
19
+ private
20
+
21
+ def start_line(line)
22
+ return false unless parsed = line.scan(STATUS_LINE).first
23
+ @code = parsed[1].to_i
24
+ true
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ module WebSocket
2
+ module HTTP
3
+
4
+ root = File.expand_path('../http', __FILE__)
5
+
6
+ autoload :Headers, root + '/headers'
7
+ autoload :Request, root + '/request'
8
+ autoload :Response, root + '/response'
9
+
10
+ def self.normalize_header(name)
11
+ name.to_s.strip.downcase.gsub(/^http_/, '').gsub(/_/, '-')
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ module WebSocket
2
+ module Mask
3
+ def self.mask(payload, mask)
4
+ return payload if mask.nil? || payload.empty?
5
+
6
+ payload.tap do |result|
7
+ payload.bytesize.times do |i|
8
+ result.setbyte(i, payload.getbyte(i) ^ mask.getbyte(i % 4))
9
+ end
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,2 @@
1
+ # Load C native extension
2
+ require "websocket-driver/websocket_mask"