iodine 0.7.41 → 0.7.45

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +24 -0
  5. data/README.md +2 -2
  6. data/SPEC-PubSub-Draft.md +89 -47
  7. data/SPEC-WebSocket-Draft.md +92 -55
  8. data/examples/async_task.ru +92 -0
  9. data/ext/iodine/extconf.rb +21 -16
  10. data/ext/iodine/fio.c +1108 -162
  11. data/ext/iodine/fio.h +49 -13
  12. data/ext/iodine/fio_cli.c +1 -1
  13. data/ext/iodine/fio_tls_missing.c +8 -0
  14. data/ext/iodine/fio_tls_openssl.c +8 -0
  15. data/ext/iodine/fio_tmpfile.h +13 -1
  16. data/ext/iodine/fiobj_data.c +6 -4
  17. data/ext/iodine/fiobj_data.h +2 -1
  18. data/ext/iodine/fiobj_hash.c +32 -6
  19. data/ext/iodine/fiobj_mustache.c +9 -0
  20. data/ext/iodine/fiobj_numbers.c +86 -8
  21. data/ext/iodine/fiobj_str.c +24 -11
  22. data/ext/iodine/fiobject.c +1 -1
  23. data/ext/iodine/fiobject.h +5 -3
  24. data/ext/iodine/http.c +66 -10
  25. data/ext/iodine/http1.c +2 -1
  26. data/ext/iodine/http1_parser.h +1065 -103
  27. data/ext/iodine/http_internal.c +1 -0
  28. data/ext/iodine/http_internal.h +4 -2
  29. data/ext/iodine/iodine.c +66 -1
  30. data/ext/iodine/iodine.h +3 -0
  31. data/ext/iodine/iodine_caller.c +48 -8
  32. data/ext/iodine/iodine_connection.c +24 -8
  33. data/ext/iodine/iodine_http.c +32 -8
  34. data/ext/iodine/iodine_mustache.c +2 -4
  35. data/ext/iodine/iodine_rack_io.c +21 -0
  36. data/ext/iodine/iodine_tcp.c +14 -0
  37. data/ext/iodine/iodine_tls.c +8 -0
  38. data/ext/iodine/mustache_parser.h +4 -0
  39. data/ext/iodine/redis_engine.c +14 -11
  40. data/ext/iodine/websockets.c +7 -3
  41. data/iodine.gemspec +5 -4
  42. data/lib/iodine/version.rb +1 -1
  43. data/lib/rack/handler/iodine.rb +6 -0
  44. metadata +15 -13
@@ -0,0 +1,92 @@
1
+ # This is a task scheduling WebSocket push example application.
2
+ #
3
+ # Benchmark HTTPP with `ab` or `wrk` (a 5 seconds benchmark with 2000 concurrent clients):
4
+ #
5
+ # ab -c 2000 -t 5 -n 1000000 -k http://127.0.0.1:3000/
6
+ # wrk -c2000 -d5 -t12 http://localhost:3000/
7
+ #
8
+ # Test websocket tasks using the browser. For example:
9
+ # ws = new WebSocket("ws://localhost:3000/userID"); ws.onmessage = function(e) {console.log(e.data);}; ws.onclose = function(e) {console.log("closed")};
10
+ # ws.onopen = function(e) {ws.send(JSON.stringify({'task': 'echo', 'data': 'Hello!'}));};
11
+ require 'iodine'
12
+ require 'json'
13
+
14
+ TASK_PUBLISHING_ENGINE = Iodine::PubSub::PROCESS
15
+
16
+ # This module handles tasks and send them back to the frontend
17
+ module TaskHandler
18
+ def echo msg
19
+ msg = Iodine::JSON.parse(msg, symbolize_names: true)
20
+ publish_to = msg.delete(:from)
21
+ Iodine.publish(publish_to, msg.to_json, TASK_PUBLISHING_ENGINE) if publish_to
22
+ puts "performed 'echo' task"
23
+ rescue => e
24
+ puts "JSON task message error? #{e.message} - under attack?"
25
+ end
26
+
27
+ def add msg
28
+ msg = Iodine::JSON.parse(msg, symbolize_names: true)
29
+ raise "addition task requires an array of numbers" unless msg[:data].is_a?(Array)
30
+ msg[:data] = msg[:data].inject(0){|sum,x| sum + x }
31
+ publish_to = msg.delete(:from)
32
+ Iodine.publish(publish_to, msg.to_json, TASK_PUBLISHING_ENGINE) if publish_to
33
+ puts "performed 'add' task"
34
+ rescue => e
35
+ puts
36
+ "JSON task message error? #{e.message} - under attack?"
37
+ end
38
+
39
+ def listen2tasks
40
+ Iodine.subscribe(:echo) {|ch,msg| TaskHandler.echo(msg) }
41
+ Iodine.subscribe(:add) {|ch,msg| TaskHandler.add(msg) }
42
+ end
43
+
44
+ extend self
45
+ end
46
+
47
+ module WebsocketClient
48
+ def on_open client
49
+ # Pub/Sub directly to the client (or use a block to process the messages)
50
+ client.subscribe client.env['PATH_INFO'.freeze]
51
+ end
52
+ def on_message client, data
53
+ # Strings and symbol channel names are equivalent.
54
+ msg = Iodine::JSON.parse(data, symbolize_names: true)
55
+ raise "no valid task" unless ["echo".freeze, "add".freeze].include? msg[:task]
56
+ msg[:from] = client.env['PATH_INFO'.freeze]
57
+ client.publish msg[:task], msg.to_json, TASK_PUBLISHING_ENGINE
58
+ rescue => e
59
+ puts "JSON message error? #{e.message}\n\t#{data}\n\t#{msg}"
60
+ end
61
+ extend self
62
+ end
63
+
64
+ APP = Proc.new do |env|
65
+ if env['rack.upgrade?'.freeze] == :websocket
66
+ env['rack.upgrade'.freeze] = WebsocketClient
67
+ [0,{}, []] # It's possible to set cookies for the response.
68
+ elsif env['rack.upgrade?'.freeze] == :sse
69
+ puts "SSE connections can only receive data from the server, the can't write."
70
+ env['rack.upgrade'.freeze] = WebsocketClient
71
+ [0,{}, []] # It's possible to set cookies for the response.
72
+ else
73
+ [200, {"Content-Type" => "text/plain"}, ["Send messages with WebSockets using JSON.\ni.e.: {\"task\":\"add\", \"data\":[1,2]}"]]
74
+ end
75
+ end
76
+
77
+ # test automatically for Redis extensions.
78
+ if(Iodine::PubSub.default.is_a? Iodine::PubSub::Redis)
79
+ TASK_PUBLISHING_ENGINE = Iodine::PubSub.default
80
+ if(ARGV.include? "worker")
81
+ TaskHandler.listen2tasks
82
+ Iodine.workers = 1
83
+ Iodine.threads = 16 if Iodine.threads == 0
84
+ Iodine.start
85
+ exit(0)
86
+ end
87
+ else
88
+ TaskHandler.listen2tasks
89
+ end
90
+
91
+ # # or in config.ru
92
+ run APP
@@ -36,7 +36,10 @@ int main(void) {
36
36
  EOS
37
37
 
38
38
  # Test for manual selection and then TRY_COMPILE with each polling engine
39
- if ENV['FIO_POLL']
39
+ if Gem.win_platform?
40
+ puts "skipping polling tests, using WSAPOLL on Windows"
41
+ $defs << "-DFIO_ENGINE_WSAPOLL"
42
+ elsif ENV['FIO_POLL']
40
43
  puts "skipping polling tests, enforcing manual selection of: poll"
41
44
  $defs << "-DFIO_ENGINE_POLL"
42
45
  elsif ENV['FIO_FORCE_POLL']
@@ -64,9 +67,10 @@ end
64
67
 
65
68
  iodine_test_polling_support()
66
69
 
67
- # Test for OpenSSL version equal to 1.0.0 or greater.
68
- unless ENV['NO_SSL'] || ENV['NO_TLS'] || ENV["DISABLE_SSL"]
69
- OPENSSL_TEST_CODE = <<EOS
70
+ unless Gem.win_platform?
71
+ # Test for OpenSSL version equal to 1.0.0 or greater.
72
+ unless ENV['NO_SSL'] || ENV['NO_TLS'] || ENV["DISABLE_SSL"]
73
+ OPENSSL_TEST_CODE = <<EOS
70
74
  \#include <openssl/bio.h>
71
75
  \#include <openssl/err.h>
72
76
  \#include <openssl/ssl.h>
@@ -84,18 +88,19 @@ int main(void) {
84
88
  }
85
89
  EOS
86
90
 
87
- dir_config("openssl")
88
- begin
89
- require 'openssl'
90
- rescue LoadError
91
- else
92
- if have_library('crypto') && have_library('ssl')
93
- puts "detected OpenSSL library, testing for version and required functions."
94
- if try_compile(OPENSSL_TEST_CODE)
95
- $defs << "-DHAVE_OPENSSL"
96
- puts "confirmed OpenSSL to be version 1.1.0 or above (#{OpenSSL::OPENSSL_LIBRARY_VERSION})...\n* compiling with HAVE_OPENSSL."
97
- else
98
- puts "FAILED: OpenSSL version not supported (#{OpenSSL::OPENSSL_LIBRARY_VERSION} is too old)."
91
+ dir_config("openssl")
92
+ begin
93
+ require 'openssl'
94
+ rescue LoadError
95
+ else
96
+ if have_library('crypto') && have_library('ssl')
97
+ puts "detected OpenSSL library, testing for version and required functions."
98
+ if try_compile(OPENSSL_TEST_CODE)
99
+ $defs << "-DHAVE_OPENSSL"
100
+ puts "confirmed OpenSSL to be version 1.1.0 or above (#{OpenSSL::OPENSSL_LIBRARY_VERSION})...\n* compiling with HAVE_OPENSSL."
101
+ else
102
+ puts "FAILED: OpenSSL version not supported (#{OpenSSL::OPENSSL_LIBRARY_VERSION} is too old)."
103
+ end
99
104
  end
100
105
  end
101
106
  end