Module: Iodine
- Extended by:
- Iodine
- Included in:
- Iodine
- Defined in:
- lib/iodine.rb,
lib/iodine/io.rb,
lib/iodine/core.rb,
lib/iodine/http.rb,
lib/iodine/timers.rb,
lib/iodine/logging.rb,
lib/iodine/version.rb,
lib/iodine/protocol.rb,
lib/iodine/settings.rb,
lib/iodine/http/hpack.rb,
lib/iodine/http/http1.rb,
lib/iodine/http/http2.rb,
lib/iodine/http/request.rb,
lib/iodine/http/session.rb,
lib/iodine/http/response.rb,
lib/iodine/ssl_connector.rb,
lib/iodine/http/websockets.rb,
lib/iodine/http/rack_support.rb,
lib/iodine/http/websocket_client.rb,
lib/iodine/http/websocket_handler.rb
Overview
Iodine is an easy Object-Oriented library for writing network applications (servers) with your own network protocol.
Please read the README file for an introduction to Iodine.
Here’s a quick and easy echo server, notice how Iodine will automatically start running once you finish setting everything up:
require 'iodine'
class MyProtocol < Iodine::Protocol
# Iodine will call this whenever a new connection is opened.
def on_open
# Iodine includes logging as well as unique assigned instance ID's.
Iodine.info "New connection id: #{id}"
# Iodine includes timeout support with automatic pinging or connection termination.
set_timeout 5
end
def data
write("-- Closing connection, goodbye.\n") && close if data =~ /^(bye|close|exit)/i
write(">> #{data.chomp}\n")
end
# Iodine will call this whenever a new connection is closed.
def on_close
Iodine.info "Closing connection id: #{id}"
end
# Iodine will call this whenever a a timeout is reached.
def ping
# If `write` fails, it automatically closes the connection.
write("-- Are you still there?\n")
end
end
# setting up the server is as easy as plugging in your Protocol class:
Iodine.protocol = MyProtocol
# if you are excecuting this script from IRB, exit IRB to start Iodine.
exit
Defined Under Namespace
Modules: Base Classes: Http, Protocol, SSLConnector, TimedEvent
Constant Summary collapse
- VERSION =
"0.0.4"
Instance Method Summary collapse
-
#bind ⇒ Object
Gets the IP binding address.
-
#bind=(address) ⇒ Object
Sets the IP binding address.
-
#debug(data, &block) ⇒ String, ...
logs debug info.
-
#error(data, &block) ⇒ String, ...
logs errors.
-
#fatal(data, &block) ⇒ String, ...
logs a fatal error.
-
#force_start! ⇒ Object
forces Iodine to start prematurely and asyncronously.
-
#info(data, &block) ⇒ String, ...
logs info.
-
#log(raw_text) ⇒ String
logs a raw text.
-
#logger ⇒ Object
Gets the logging object and allows you to call logging methods (i.e. ‘Iodine.log.info “Running”`).
-
#logger=(obj) ⇒ Object
Sets the logging object, which needs to act like ‘Logger`.
-
#on_shutdown(*args, &block) ⇒ Iodine
Adds a shutdown tasks.
-
#port ⇒ Object
Gets Iodine’s server port.
-
#port=(port) ⇒ Object
Sets Iodine’s server port.
-
#processes=(count) ⇒ Object
Sets the number of processes that should be spawned in Server mode.
-
#protocol ⇒ Object
Returns the cutrently active Iodine protocol (if exists).
-
#protocol=(protocol) ⇒ Object
Sets the Protocol the Iodine Server will use.
-
#run(*args, &block) ⇒ Iodine
(also: #run_async)
Accepts a block and runs it asynchronously.
-
#run_after(seconds, *args, &block) ⇒ Iodine::TimedEvent
pushes a timed event to the timers’s stack.
-
#run_every(seconds, *args, &block) ⇒ Iodine::TimedEvent
pushes a repeated timed event to the timers’s stack.
-
#signal_exit ⇒ nil
Signals Iodine to exit if it was running on Server or Timer mode.
-
#ssl ⇒ Object
Returns true if Iodine will require that new connection be encrypted.
-
#ssl=(required) ⇒ Object
Sets the SSL flag, so that Iodine will require that new connection be encrypted.
-
#ssl_context ⇒ Object
Gets the SSL Context to be used when using an encrypted connection.
-
#ssl_context=(context) ⇒ Object
Sets the SSL Context to be used when using an encrypted connection.
-
#ssl_protocols ⇒ Object
Gets the SSL Protocol Hash used for.
-
#ssl_protocols=(protocol_hash) ⇒ Object
Sets the an SSL Protocol Hash (‘’name’ => Protocol`), allowing dynamic Protocol Negotiation.
-
#switch_protocol(*args) ⇒ Protocol
Replaces (or creates) an IO’s protocol object.
-
#threads=(count) ⇒ Object
Sets the number of threads in the thread pool used for executing the tasks.
-
#time ⇒ Time
Gets the last time at which the IO Reactor was last active (last “tick”).
-
#to_a ⇒ Array
Returns an Array with all the currently active connection’s Protocol instances.
-
#warn(data, &block) ⇒ String, ...
logs warning.
Instance Method Details
#bind ⇒ Object
Gets the IP binding address. Defaults to the command line ‘-ip` argument, or the ENV or 0.0.0.0 (in this order).
39 40 41 |
# File 'lib/iodine/settings.rb', line 39 def bind @bind end |
#bind=(address) ⇒ Object
Sets the IP binding address. Defaults to the command line ‘-ip` argument, or the ENV or 0.0.0.0 (in this order).
35 36 37 |
# File 'lib/iodine/settings.rb', line 35 def bind= address @bind = address end |
#debug(data, &block) ⇒ String, ...
logs debug info
17 18 19 20 |
# File 'lib/iodine/logging.rb', line 17 def debug data, &block @logger.debug data, &block if @logger data end |
#error(data, &block) ⇒ String, ...
logs errors
29 30 31 32 |
# File 'lib/iodine/logging.rb', line 29 def error data, &block @logger.error data, &block if @logger data end |
#fatal(data, &block) ⇒ String, ...
logs a fatal error
35 36 37 38 |
# File 'lib/iodine/logging.rb', line 35 def fatal data, &block @logger.fatal data, &block if @logger data end |
#force_start! ⇒ Object
forces Iodine to start prematurely and asyncronously. This might case Iodine to exit abruptly, depending how the hosting application behaves.
35 36 37 38 |
# File 'lib/iodine/core.rb', line 35 def force_start! thread = Thread.new { startup true } Kernel.at_exit {thread.raise("stop"); thread.join} end |
#info(data, &block) ⇒ String, ...
logs info
11 12 13 14 |
# File 'lib/iodine/logging.rb', line 11 def info data, &block @logger.info data, &block if @logger data end |
#log(raw_text) ⇒ String
logs a raw text
41 42 43 44 |
# File 'lib/iodine/logging.rb', line 41 def log raw_text @logger << raw_text if @logger raw_text end |
#logger ⇒ Object
Gets the logging object and allows you to call logging methods (i.e. ‘Iodine.log.info “Running”`).
5 6 7 |
# File 'lib/iodine/logging.rb', line 5 def logger @logger end |
#logger=(obj) ⇒ Object
Sets the logging object, which needs to act like ‘Logger`. The default logger is `Logger.new(STDOUT)`.
8 9 10 |
# File 'lib/iodine/settings.rb', line 8 def logger= obj @logger = obj end |
#on_shutdown(*args, &block) ⇒ Iodine
Returns Adds a shutdown tasks. These tasks should be executed in order of creation.
23 24 25 26 |
# File 'lib/iodine/core.rb', line 23 def on_shutdown *args, &block @shutdown_queue << [block, args] self end |
#port ⇒ Object
Gets Iodine’s server port. Defaults to the command line ‘-p` argument, or the ENV or 3000 (in this order).
31 32 33 |
# File 'lib/iodine/settings.rb', line 31 def port @port end |
#port=(port) ⇒ Object
Sets Iodine’s server port. Defaults to the command line ‘-p` argument, or the ENV or 3000 (in this order).
27 28 29 |
# File 'lib/iodine/settings.rb', line 27 def port= port @port = port end |
#processes=(count) ⇒ Object
Sets the number of processes that should be spawned in Server mode. Defaults to 1 (no processes spawned).
-
Forking (spwaning processes) might NOT work on all systems (forking is supported by Ruby on Unix systems).
-
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.
-
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.
22 23 24 |
# File 'lib/iodine/settings.rb', line 22 def processes= count @spawn_count = count end |
#protocol ⇒ Object
Returns the cutrently active Iodine protocol (if exists).
51 52 53 |
# File 'lib/iodine/settings.rb', line 51 def protocol @protocol end |
#protocol=(protocol) ⇒ Object
46 47 48 49 |
# File 'lib/iodine/settings.rb', line 46 def protocol= protocol @stop = protocol ? false : true @protocol = protocol end |
#run(*args, &block) ⇒ Iodine Also known as: run_async
Accepts a block and runs it asynchronously. This method runs asynchronously and returns immediately.
use:
Iodine.run(arg1, arg2, arg3 ...) { |arg1, arg2, arg3...| do_something }
the block will be run within the current context, allowing access to current methods and variables.
16 17 18 19 |
# File 'lib/iodine/core.rb', line 16 def run *args, &block @queue << [block, args] self end |
#run_after(seconds, *args, &block) ⇒ Iodine::TimedEvent
pushes a timed event to the timers’s stack
accepts:
- seconds
-
the minimal amount of seconds to wait before calling the handler’s ‘call` method.
- *arg
-
any arguments that will be passed to the handler’s ‘call` method.
- &block
-
the block to execute.
A block is required.
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.
Timed event’s time of execution is dependant on the workload and continuous uptime of the process (timed events AREN’T persistent).
65 66 67 |
# File 'lib/iodine/timers.rb', line 65 def run_after seconds, *args, &block timed_job seconds, 1, args, block end |
#run_every(seconds, *args, &block) ⇒ Iodine::TimedEvent
pushes a repeated timed event to the timers’s stack
accepts:
- seconds
-
the minimal amount of seconds to wait before calling the handler’s ‘call` method.
- *arg
-
any arguments that will be passed to the handler’s ‘call` method.
- &block
-
the block to execute.
A block is required.
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.
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 85 |
# File 'lib/iodine/timers.rb', line 83 def run_every seconds, *args, &block timed_job seconds, -1, args, block end |
#signal_exit ⇒ nil
Returns Signals Iodine to exit if it was running on Server or Timer mode. Tasks will rundown pending timeout.
29 30 31 32 |
# File 'lib/iodine/core.rb', line 29 def signal_exit Process.kill("INT", 0) unless @stop nil end |
#ssl ⇒ Object
Returns true if Iodine will require that new connection be encrypted.
61 62 63 |
# File 'lib/iodine/settings.rb', line 61 def ssl @ssl end |
#ssl=(required) ⇒ Object
Sets the SSL flag, so that Iodine will require that new connection be encrypted. Defaults to false unless the ‘ssl` command line flag is present.
57 58 59 |
# File 'lib/iodine/settings.rb', line 57 def ssl= required @ssl = required && true end |
#ssl_context ⇒ Object
Gets the SSL Context to be used when using an encrypted connection.
75 76 77 |
# File 'lib/iodine/settings.rb', line 75 def ssl_context @ssl_context ||= init_ssl_context end |
#ssl_context=(context) ⇒ Object
Sets the SSL Context to be used when using an encrypted connection. Defaults to a self signed certificate and no verification.
Manually setting the context will automatically set the SSL flag, so that Iodine will require encryption for new incoming connections.
69 70 71 72 |
# File 'lib/iodine/settings.rb', line 69 def ssl_context= context @ssl = true @ssl_context = context end |
#ssl_protocols ⇒ Object
Gets the SSL Protocol Hash used for
91 92 93 |
# File 'lib/iodine/settings.rb', line 91 def ssl_protocols @ssl_protocols end |
#ssl_protocols=(protocol_hash) ⇒ Object
Sets the an SSL Protocol Hash (‘’name’ => Protocol`), allowing dynamic Protocol Negotiation. At the moment only NPN is supported. ALPN support should be established in a future release.
-
please notice that using allowing dynamic Protocol Negotiation could cause unexpected protocol choices when attempting to implement Opportunistic Encryption with SSLConnector.
83 84 85 86 87 88 |
# File 'lib/iodine/settings.rb', line 83 def ssl_protocols= protocol_hash 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) @ssl = true ssl_context.npn_protocols = protocol_hash.keys @ssl_protocols = protocol_hash end |
#switch_protocol(*args) ⇒ Protocol
Replaces (or creates) an IO’s protocol object.
Accepts 2 arguments, in the following order:
- io
-
the raw IO object.
- protocol
-
a protocol instance - should be an instance of a class inheriting from Protocol. type will NOT be checked - but Iodine could break if there is a type mismatch.
16 17 18 19 |
# File 'lib/iodine/io.rb', line 16 def switch_protocol *args @io_in << args args[1] end |
#threads=(count) ⇒ Object
Sets the number of threads in the thread pool used for executing the tasks. Defaults to 1 thread.
13 14 15 |
# File 'lib/iodine/settings.rb', line 13 def threads= count @thread_count = count end |
#time ⇒ Time
Returns Gets the last time at which the IO Reactor was last active (last “tick”).
6 7 8 |
# File 'lib/iodine/io.rb', line 6 def time @time end |
#to_a ⇒ Array
Returns an Array with all the currently active connection’s Protocol instances.
22 23 24 |
# File 'lib/iodine/io.rb', line 22 def to_a @ios.values end |
#warn(data, &block) ⇒ String, ...
logs warning
23 24 25 26 |
# File 'lib/iodine/logging.rb', line 23 def warn data, &block @logger.warn data, &block if @logger data end |