iodine 0.1.21 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -2
  3. data/.travis.yml +23 -2
  4. data/CHANGELOG.md +9 -2
  5. data/README.md +232 -179
  6. data/Rakefile +13 -1
  7. data/bin/config.ru +63 -0
  8. data/bin/console +6 -0
  9. data/bin/echo +42 -32
  10. data/bin/http-hello +62 -0
  11. data/bin/http-playground +124 -0
  12. data/bin/playground +62 -0
  13. data/bin/poc/Gemfile.lock +23 -0
  14. data/bin/poc/README.md +37 -0
  15. data/bin/poc/config.ru +66 -0
  16. data/bin/poc/gemfile +1 -0
  17. data/bin/poc/www/index.html +57 -0
  18. data/bin/raw-rbhttp +35 -0
  19. data/bin/raw_broadcast +66 -0
  20. data/bin/test_with_faye +40 -0
  21. data/bin/ws-broadcast +108 -0
  22. data/bin/ws-echo +108 -0
  23. data/exe/iodine +59 -0
  24. data/ext/iodine/base64.c +264 -0
  25. data/ext/iodine/base64.h +72 -0
  26. data/ext/iodine/bscrypt-common.h +109 -0
  27. data/ext/iodine/bscrypt.h +49 -0
  28. data/ext/iodine/extconf.rb +41 -0
  29. data/ext/iodine/hex.c +123 -0
  30. data/ext/iodine/hex.h +70 -0
  31. data/ext/iodine/http.c +200 -0
  32. data/ext/iodine/http.h +128 -0
  33. data/ext/iodine/http1.c +402 -0
  34. data/ext/iodine/http1.h +56 -0
  35. data/ext/iodine/http1_simple_parser.c +473 -0
  36. data/ext/iodine/http1_simple_parser.h +59 -0
  37. data/ext/iodine/http_request.h +128 -0
  38. data/ext/iodine/http_response.c +1606 -0
  39. data/ext/iodine/http_response.h +393 -0
  40. data/ext/iodine/http_response_http1.h +374 -0
  41. data/ext/iodine/iodine_core.c +641 -0
  42. data/ext/iodine/iodine_core.h +70 -0
  43. data/ext/iodine/iodine_http.c +615 -0
  44. data/ext/iodine/iodine_http.h +19 -0
  45. data/ext/iodine/iodine_websocket.c +430 -0
  46. data/ext/iodine/iodine_websocket.h +21 -0
  47. data/ext/iodine/libasync.c +552 -0
  48. data/ext/iodine/libasync.h +117 -0
  49. data/ext/iodine/libreact.c +347 -0
  50. data/ext/iodine/libreact.h +244 -0
  51. data/ext/iodine/libserver.c +912 -0
  52. data/ext/iodine/libserver.h +435 -0
  53. data/ext/iodine/libsock.c +950 -0
  54. data/ext/iodine/libsock.h +478 -0
  55. data/ext/iodine/misc.c +181 -0
  56. data/ext/iodine/misc.h +76 -0
  57. data/ext/iodine/random.c +193 -0
  58. data/ext/iodine/random.h +48 -0
  59. data/ext/iodine/rb-call.c +127 -0
  60. data/ext/iodine/rb-call.h +60 -0
  61. data/ext/iodine/rb-libasync.h +79 -0
  62. data/ext/iodine/rb-rack-io.c +389 -0
  63. data/ext/iodine/rb-rack-io.h +17 -0
  64. data/ext/iodine/rb-registry.c +213 -0
  65. data/ext/iodine/rb-registry.h +33 -0
  66. data/ext/iodine/sha1.c +359 -0
  67. data/ext/iodine/sha1.h +85 -0
  68. data/ext/iodine/sha2.c +825 -0
  69. data/ext/iodine/sha2.h +138 -0
  70. data/ext/iodine/siphash.c +136 -0
  71. data/ext/iodine/siphash.h +15 -0
  72. data/ext/iodine/spnlock.h +235 -0
  73. data/ext/iodine/websockets.c +696 -0
  74. data/ext/iodine/websockets.h +120 -0
  75. data/ext/iodine/xor-crypt.c +189 -0
  76. data/ext/iodine/xor-crypt.h +107 -0
  77. data/iodine.gemspec +25 -18
  78. data/lib/iodine.rb +57 -58
  79. data/lib/iodine/http.rb +0 -189
  80. data/lib/iodine/protocol.rb +36 -245
  81. data/lib/iodine/version.rb +1 -1
  82. data/lib/rack/handler/iodine.rb +145 -2
  83. metadata +115 -37
  84. data/bin/core_http_test +0 -51
  85. data/bin/em playground +0 -56
  86. data/bin/hello_world +0 -75
  87. data/bin/setup +0 -7
  88. data/lib/iodine/client.rb +0 -5
  89. data/lib/iodine/core.rb +0 -102
  90. data/lib/iodine/core_init.rb +0 -143
  91. data/lib/iodine/http/hpack.rb +0 -553
  92. data/lib/iodine/http/http1.rb +0 -251
  93. data/lib/iodine/http/http2.rb +0 -507
  94. data/lib/iodine/http/rack_support.rb +0 -108
  95. data/lib/iodine/http/request.rb +0 -462
  96. data/lib/iodine/http/response.rb +0 -474
  97. data/lib/iodine/http/session.rb +0 -143
  98. data/lib/iodine/http/websocket_client.rb +0 -335
  99. data/lib/iodine/http/websocket_handler.rb +0 -101
  100. data/lib/iodine/http/websockets.rb +0 -336
  101. data/lib/iodine/io.rb +0 -56
  102. data/lib/iodine/logging.rb +0 -46
  103. data/lib/iodine/settings.rb +0 -158
  104. data/lib/iodine/ssl_connector.rb +0 -48
  105. data/lib/iodine/timers.rb +0 -95
@@ -1,46 +0,0 @@
1
- module Iodine
2
- public
3
-
4
- # Gets the logging object and allows you to call logging methods (i.e. `Iodine.log.info "Running"`).
5
- def logger
6
- @logger
7
- end
8
-
9
- # logs info
10
- # @return [String, Exception, Object] always returns the Object sent to the log.
11
- def info data, &block
12
- @logger.info data, &block if @logger
13
- data
14
- end
15
- # logs debug info
16
- # @return [String, Exception, Object] always returns the Object sent to the log.
17
- def debug data, &block
18
- @logger.debug data, &block if @logger
19
- data
20
- end
21
- # logs warning
22
- # @return [String, Exception, Object] always returns the Object sent to the log.
23
- def warn data, &block
24
- @logger.warn data, &block if @logger
25
- data
26
- end
27
- # logs errors
28
- # @return [String, Exception, Object] always returns the Object sent to the log.
29
- def error data, &block
30
- @logger.error data, &block if @logger
31
- data
32
- end
33
- # logs a fatal error
34
- # @return [String, Exception, Object] always returns the Object sent to the log.
35
- def fatal data, &block
36
- @logger.fatal data, &block if @logger
37
- data
38
- end
39
- # logs a raw text
40
- # @return [String] always returns the Object sent to the log.
41
- def log raw_text
42
- @logger << raw_text if @logger
43
- raw_text
44
- end
45
-
46
- end
@@ -1,158 +0,0 @@
1
- module Iodine
2
- public
3
-
4
- #######################
5
- ## Settings - methods that change the way Iodine behaves should go here.
6
-
7
- # Sets the logging object, which needs to act like `Logger`. The default logger is `Logger.new(STDOUT)`.
8
- def logger= obj
9
- @logger = obj
10
- end
11
-
12
- # Sets the number of threads in the thread pool used for executing the tasks. Defaults to 1 thread.
13
- def threads= count
14
- @thread_count = count
15
- end
16
-
17
- # Gets the number of threads in the thread pool used for executing the tasks. Returns `nil` unless previously set or Iodine is running.
18
- def threads
19
- @thread_count
20
- end
21
-
22
- # Sets the number of processes that should be spawned in Server mode. Defaults to 1 (no processes spawned).
23
- #
24
- # * Forking (spwaning processes) might NOT work on all systems (forking is supported by Ruby on Unix systems).
25
- # * Please make sure your code is safe to fork into different processes. For instance, Websocket broadcasting and unicasting won't work across different processes unless synced using an external Pub/Sub service/database such as Redis.
26
- # * Forking might cause some tasks (such as time based tasks) to be performed twice (once for each process). This is a feature. To avoid duplicated task performance, use a task (delayed execution) to initialize any tasks you want to perform only once. While the initial time based tasks and the server are shared across processes, the initial task stack will only run on the main process.
27
- def processes= count
28
- @spawn_count = count
29
- end
30
-
31
- # Gets the number of processes that should be spawned in Server mode. Defaults to 1 (no processes spawned). See {Iodine#processes=}.
32
- def processes
33
- @spawn_count
34
- end
35
-
36
- # Sets Iodine's server port. Defaults to the command line `-p` argument, or the ENV['PORT'] or 3000 (in this order).
37
- def port= port
38
- @port = port
39
- end
40
- # Gets Iodine's server port. Defaults to the command line `-p` argument, or the ENV['PORT'] or 3000 (in this order).
41
- def port
42
- @port
43
- end
44
- # Sets the IP binding address. Defaults to the command line `-ip` argument, or the ENV['IP'] or 0.0.0.0 (in this order).
45
- def bind= address
46
- @bind = address
47
- end
48
- # Gets the IP binding address. Defaults to the command line `-ip` argument, or the ENV['IP'] or 0.0.0.0 (in this order).
49
- def bind
50
- @bind
51
- end
52
-
53
- # Sets the Protocol the Iodine Server will use. Should be a child of {Iodine::Protocol}. Defaults to nil (no server).
54
- #
55
- # If the protocol passed does NOT inherit from {Iodine::Protocol}, Iodine will cycle without initiating a server until stopped (TimedEvent mode).
56
- def protocol= protocol
57
- @stop = protocol ? false : true
58
- @protocol = protocol
59
- end
60
- # Returns the cutrently active Iodine protocol (if exists).
61
- def protocol
62
- @protocol
63
- end
64
-
65
- # Sets the SSL flag, so that Iodine will require that new connection be encrypted.
66
- # Defaults to false unless the `ssl` command line flag is present.
67
- def ssl= required
68
- @ssl = required && true
69
- end
70
- # Returns true if Iodine will require that new connection be encrypted.
71
- def ssl
72
- @ssl
73
- end
74
-
75
- # Sets the SSL Context to be used when using an encrypted connection. Defaults to a self signed certificate and no verification.
76
- #
77
- # Manually setting the context will automatically set the SSL flag,
78
- # so that Iodine will require encryption for new incoming connections.
79
- def ssl_context= context
80
- @ssl = true
81
- @ssl_context = context
82
- end
83
-
84
- # Gets the SSL Context to be used when using an encrypted connection.
85
- def ssl_context
86
- @ssl_context ||= init_ssl_context
87
- end
88
-
89
- # Sets the an SSL Protocol Hash (`'name' => Protocol`), allowing dynamic Protocol Negotiation.
90
- # At the moment only NPN is supported. ALPN support should be established in a future release.
91
- #
92
- # * please notice that using allowing dynamic Protocol Negotiation could cause unexpected protocol choices when attempting to implement Opportunistic Encryption with {Iodine::SSLConnector}.
93
- def ssl_protocols= protocol_hash
94
- raise TypeError, "Iodine.ssl_protocols should be a Hash with Strings for keys (protocol identifiers) and Classes as values (Protocol classes)." unless protocol_hash.is_a?(Hash)
95
- @ssl = true
96
- ssl_context.npn_protocols = protocol_hash.keys
97
- @ssl_protocols = protocol_hash
98
- end
99
-
100
- # Gets the SSL Protocol Hash used for
101
- def ssl_protocols
102
- @ssl_protocols
103
- end
104
-
105
-
106
- protected
107
-
108
- #initializes a default SSLContext
109
- def init_ssl_context
110
- ssl_context = OpenSSL::SSL::SSLContext.new
111
- ssl_context.set_params verify_mode: OpenSSL::SSL::VERIFY_NONE
112
- ssl_context.cert_store = OpenSSL::X509::Store.new
113
- ssl_context.cert_store.set_default_paths
114
- ssl_context.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL #SESSION_CACHE_OFF
115
- ssl_context.cert, ssl_context.key = create_cert
116
- ssl_context
117
- end
118
-
119
- #creates a self-signed certificate
120
- def create_cert bits=2048, cn=nil, comment='a self signed certificate for when we only need encryption and no more.'
121
- unless cn
122
- host_name = Socket::gethostbyname(Socket::gethostname)[0].split('.')
123
- cn = String.new
124
- host_name.each {|n| cn << "/DC=#{n}"}
125
- cn << "/CN=Iodine.#{host_name.join('.')}"
126
- end
127
- # cn ||= "CN=#{Socket::gethostbyname(Socket::gethostname)[0] rescue Socket::gethostname}"
128
-
129
- time = Time.now
130
- rsa = OpenSSL::PKey::RSA.new(bits)
131
- cert = OpenSSL::X509::Certificate.new
132
- cert.version = 2
133
- cert.serial = 1
134
- name = OpenSSL::X509::Name.parse(cn)
135
- cert.subject = name
136
- cert.issuer = name
137
- cert.not_before = time
138
- cert.not_after = time + (365*24*60*60)
139
- cert.public_key = rsa.public_key
140
-
141
- ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
142
- ef.issuer_certificate = cert
143
- cert.extensions = [
144
- ef.create_extension("basicConstraints","CA:FALSE"),
145
- ef.create_extension("keyUsage", "keyEncipherment"),
146
- ef.create_extension("subjectKeyIdentifier", "hash"),
147
- ef.create_extension("extendedKeyUsage", "serverAuth"),
148
- ef.create_extension("nsComment", comment),
149
- ]
150
- aki = ef.create_extension("authorityKeyIdentifier",
151
- "keyid:always,issuer:always")
152
- cert.add_extension(aki)
153
- cert.sign(rsa, OpenSSL::Digest::SHA1.new)
154
-
155
- return cert, rsa
156
- end
157
-
158
- end
@@ -1,48 +0,0 @@
1
- module Iodine
2
-
3
- # This is a mini-protocol used only to implement the SSL Handshake in a non-blocking manner,
4
- # allowing for a hardcoded timeout (which you can monkey patch) of 3 seconds.
5
- class SSLConnector < Protocol
6
- def initialize io, protocol, options = nil
7
- @protocol = protocol
8
- @options = options
9
- super(io)
10
- end
11
- TIMEOUT = 3 # hardcoded SSL/TLS handshake timeout
12
- def on_open
13
- set_timeout TIMEOUT
14
- @ssl_socket = ::OpenSSL::SSL::SSLSocket.new(@io, ::Iodine.ssl_context)
15
- @ssl_socket.sync_close = true
16
- end
17
-
18
- # atempt an SSL Handshale
19
- def call
20
- return if @locker.locked?
21
- return unless @locker.try_lock
22
- begin
23
- @ssl_socket.accept_nonblock
24
- rescue ::IO::WaitReadable, ::IO::WaitWritable
25
- return
26
- rescue ::OpenSSL::SSL::SSLError
27
- @e = ::OpenSSL::SSL::SSLError.new "Self-signed Certificate?".freeze
28
- close
29
- return
30
- rescue => e
31
- ::Iodine.warn "SSL Handshake failed with: #{e.message}".freeze
32
- @e = e
33
- close
34
- return
35
- ensure
36
- @locker.unlock
37
- end
38
- ( (@ssl_socket.npn_protocol && ::Iodine.ssl_protocols[@ssl_socket.npn_protocol]) || @protocol).new @ssl_socket, @options
39
- end
40
- def on_close
41
- # inform
42
- ::Iodine.warn "SSL Handshake #{@e ? "failed with: #{@e.message} (#{@e.class.name})" : 'timed-out.'}".freeze
43
- # the core @io is already closed, but let's make sure the SSL object is closed as well.
44
- @ssl_socket.close unless @ssl_socket.closed?
45
- end
46
- end
47
-
48
- end
data/lib/iodine/timers.rb DELETED
@@ -1,95 +0,0 @@
1
- module Iodine
2
-
3
- #######################
4
- ## Timers
5
-
6
-
7
- # Every timed event is a member of the TimedEvent class and responds to it's methods.
8
- class TimedEvent
9
-
10
- # Sets/gets how often a timed event repeats, in seconds.
11
- attr_accessor :interval
12
- # Sets/gets how many times a timed event repeats.
13
- # If set to false or -1, the timed event will repead until the application quits.
14
- attr_accessor :repeat_limit
15
- # Allows you to acess or change the timer's Proc object.
16
- attr_accessor :job
17
-
18
- # Initialize a timed event.
19
- def initialize reactor, interval, repeat_limit = -1, args=[], job=nil
20
- @reactor = reactor
21
- @interval = interval
22
- @repeat_limit = repeat_limit ? repeat_limit.to_i : -1
23
- @job = job || (Proc.new { stop! })
24
- @next = @reactor.time + interval
25
- args << self
26
- @args = args
27
- end
28
-
29
- # stops a timed event.
30
- # @return [Iodine::TimedEvent] returns the TimedEvent object.
31
- def stop!
32
- @repeat_limit = 0
33
- @next = @reactor.time
34
- self
35
- end
36
-
37
- # Returns true if the timer is finished.
38
- #
39
- # If the timed event is due, this method will also add the event to the queue.
40
- # @return [true, false]
41
- def done?
42
- return false unless @next <= @reactor.time
43
- return true if @repeat_limit == 0
44
- @repeat_limit -= 1 if @repeat_limit.to_i > 0
45
- @reactor.run(*@args, &@job)
46
- @next = @reactor.time + @interval
47
- @repeat_limit == 0
48
- end
49
- end
50
-
51
- public
52
-
53
- # pushes a timed event to the timers's stack
54
- #
55
- # accepts:
56
- # seconds:: the minimal amount of seconds to wait before calling the handler's `call` method.
57
- # *arg:: any arguments that will be passed to the handler's `call` method.
58
- # &block:: the block to execute.
59
- #
60
- # A block is required.
61
- #
62
- # On top of the arguments passed to the `run_after` method, the timer object will be passed as the last agrument to the receiving block.
63
- #
64
- # Timed event's time of execution is dependant on the workload and continuous uptime of the process (timed events AREN'T persistent).
65
- #
66
- # @return [Iodine::TimedEvent] returns the new TimedEvent object.
67
- def run_after seconds, *args, &block
68
- timed_job seconds, 1, args, block
69
- end
70
-
71
- # pushes a repeated timed event to the timers's stack
72
- #
73
- # accepts:
74
- # seconds:: the minimal amount of seconds to wait before calling the handler's `call` method.
75
- # *arg:: any arguments that will be passed to the handler's `call` method.
76
- # &block:: the block to execute.
77
- #
78
- # A block is required.
79
- #
80
- # On top of the arguments passed to the `run_after` method, the timer object will be passed as the last agrument to the receiving block.
81
- #
82
- # Timed event's time of execution is dependant on the workload and continuous uptime of the process (timed events AREN'T persistent unless you save and reload them yourself).
83
- #
84
- # @return [Iodine::TimedEvent] returns the new TimedEvent object.
85
- def run_every seconds, *args, &block
86
- timed_job seconds, -1, args, block
87
- end
88
-
89
- protected
90
-
91
- # Creates a TimedEvent object and adds it to the Timers stack.
92
- def timed_job seconds, limit = false, args = [], block = nil
93
- @timer_locker.synchronize {@timers << TimedEvent.new(self, seconds, limit, args, block); @timers.last}
94
- end
95
- end