Method: Iodine.listen
- Defined in:
- ext/iodine/iodine.c
.listen(args) ⇒ Object
listen can be used to listen to any incoming connections, including HTTP and raw (tcp/ip and unix sockets) connections.
Iodine.listen(settings)
Supported Settigs:
:url |
URL indicating service type, host name and port. Path will be parsed as a Unix socket. |
:handler |
(deprecated: :app) see details below. |
:address |
an IP address or a unix socket address. Only relevant if :url is missing. |
:log |
(HTTP only) request logging. For global verbosity see verbosity |
:max_body |
(HTTP only) maximum upload size allowed per request before disconnection (in Mb). |
:max_headers |
(HTTP only) maximum total header length allowed per request (in Kb). |
:max_msg |
(WebSockets only) maximum message size pre message (in Kb). |
:ping |
(:raw clients and WebSockets only) ping interval (in seconds). Up to 255 seconds. |
:port |
port number to listen to either a String or Number) |
:public |
(HTTP server only) public folder for static file service. |
:service |
(:raw / :tls / :ws / :wss / :http / :https ) a supported service this socket will listen to. |
:timeout |
(HTTP only) keep-alive timeout in seconds. Up to 255 seconds. |
:tls |
an TLS context object for encrypted connections. |
Some connection settings are only valid when listening to HTTP / WebSocket connections.
If :url is provided, it will overwrite the :address and :port settings (if provided).
For HTTP connections, the :handler must be a valid Rack application object (answers .call(env)).
Here's an example for an HTTP hello world application:
require 'iodine'
# a handler can be a block
Iodine.listen(service: :http, port: "3000") {|env| [200, {"Content-Length" => "12"}, ["Hello World!"]] }
# start the service
Iodine.threads = 1
Iodine.start
Here's another example, using a Unix Socket instead of a TCP/IP socket for an HTTP hello world application.
This example shows how the :url option can be used, but the :address settings could have been used for the same effect (with port: 0).
require 'iodine'
# note that unix sockets in URL form use an absolute path.
Iodine.listen(url: "http://:0/tmp/sock.sock") {|env| [200, {"Content-Length" => "12"}, ["Hello World!"]] }
# start the service
Iodine.threads = 1
Iodine.start
For raw connections, the :handler object should be an object that answer .call and returns a valid callback object that supports the following callbacks (see also Connection):
on_open(client) |
called after a connection was established |
on_message(client,data) |
called when incoming data is available. Data may be fragmented. |
on_drained(client) |
called after pending client.write events have been processed (see Iodine::Connection#pending). |
ping(client) |
called whenever a timeout has occured (see Iodine::Connection#timeout=). |
on_shutdown(client) |
called if the server is shutting down. This is called before the connection is closed. |
on_close(client) |
called when the connection with the client was closed. |
The client argument passed to the :handler callbacks is an Connection instance that represents the connection / the client.
Here's an example for a telnet based chat-room example:
require 'iodine'
# define the protocol for our service
module ChatHandler
def self.on_open(client)
# Set a connection timeout
client.timeout = 10
# subscribe to the chat channel.
client.subscribe :chat
# Write a welcome message
client.publish :chat, "new member entered the chat\r\n"
end
# this is called for incoming data - note data might be fragmented.
def self.(client, data)
# publish the data we received
client.publish :chat, data
# close the connection when the time comes
client.close if data =~ /^bye[\n\r]/
end
# called whenever timeout occurs.
def self.ping(client)
client.write "System: quite, isn't it...?\r\n"
end
# called if the connection is still open and the server is shutting down.
def self.on_shutdown(client)
# write the data we received
client.write "Chat server going away. Try again later.\r\n"
end
# returns the callback object (self).
def self.call
self
end
end
# we use can both the `handler` keyword or a block, anything that answers #call.
Iodine.listen(service: :raw, port: "3000", handler: ChatHandler)
# we can listen to more than a single socket at a time.
Iodine.listen(url: "raw://:3030", handler: ChatHandler)
# start the service
Iodine.threads = 1
Iodine.start
Returns the handler object used.
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 |
# File 'ext/iodine/iodine.c', line 1122
static VALUE iodine_listen(VALUE self, VALUE args) {
// clang-format on
iodine_connection_args_s s = iodine_connect_args(args, 1);
intptr_t uuid = -1;
switch (s.service) {
case IODINE_SERVICE_RAW:
uuid = iodine_tcp_listen(s);
break;
case IODINE_SERVICE_HTTP: /* overflow */
case IODINE_SERVICE_WS:
uuid = iodine_http_listen(s);
break;
}
iodine_connect_args_cleanup(&s);
if (uuid == -1)
rb_raise(rb_eRuntimeError, "Couldn't open listening socket.");
return s.handler;
(void)self;
}
|