Server Configuration File: server.rb
This Ruby file contains the custom application logic writen by the user along with programmable callbacks for OverSIP events. All those callbacks are executed within a new Ruby Fiber, allowing synchronous style coding by using em-synchrony libraries.
Example code in this page makes use of the oversip-mod-mysql MySQL driver with synchronous style coding (no callbacks for retrieving the SQL queries result).
The server.rb
file is divided in the following sections:
Custom Application Logic
The top of the file is reserved for custom code writen by the user. Typicaly the user loads here external required Gems or libraries (via require "gem-name"
) and adds modules, classes and methods for building a custom application logic on top of OverSIP.
If the user adds a module or class here it’s useful it to include/extend the OverSIP::Logger
module so the user can make use of the methods provided by OverSIP for logging into Syslog (log_debug
, log_info
, log_warn
, etc).
Example code
require "oversip-mod-mysql"
module MyApp
extend ::OverSIP::Logger
# Load valid WebSocket Origin values from DB.
def self.load_valid_websocket_origins
log_info "loading valid origins from DB..."
@valid_websocket_origins ||= []
valid_websocket_origins = []
db = OverSIP::Modules::Mysql.pool(:my_db)
result = db.query "SELECT origin FROM websocket_origins"
result.each do |row|
valid_websocket_origins << row["origin"]
end
@valid_websocket_origins = valid_websocket_origins
end
# Get the Array with the loaded valid WebSocket Origins.
def self.valid_websocket_origins
@valid_websocket_origins
end
[...]
end
When the user’s custom code is too long it can be split into different files. For example, the user could create a directory /etc/oversip/my_app/
containing custom files and load them at the top of server.rb
as follows:
require "/etc/oversip/my_app/file1.rb"
require "/etc/oversip/my_app/file2.rb"
require "/etc/oversip/my_app/file3.rb"
[...]
System Events
This section includes programmable callbacks for system events:
OverSIP::SystemEvents.on_initialize
This method is called by OverSIP when main configuration files have been loaded. This method is NOT executed again when OverSIP is reloaded (HUP
signal or /etc/init.d/oversip reload
).
This is the place for setting i.e. dabatase connections (by using existing OverSIP 3rd party modules such us oversip-mod-mysql, oversip-mod-postgresql or EventMachine libraries such as couchbase-ruby-client-em, EventMachine built-in Memcache client, or some others via em-synchrony).
NOTE: If you need to use Ruby threads within your application logic (via the EventMachine.defer()
method) then this method is a good place to set the EventMachine.threadpool_size
parameter.
Example code
def (OverSIP::SystemEvents).on_initialize
log_info "setting my DB connection..."
OverSIP::Modules::Mysql.add_pool({
:pool_name => :my_db,
:pool_size => 5,
:host => "localhost",
:username => "oversip",
:password => "xxxxxx",
:database => "oversip"
})
end
OverSIP::SystemEvents.on_started
This method is called by OverSIP once the core reactor has been started. Place here code to retrieve information from i.e. a database and fill some custom variable that will be later inspected in runtime.
Example code
def (OverSIP::SystemEvents).on_started
MyApp.load_valid_websocket_origins()
end
OverSIP::SystemEvents.on_user_reload
This method is called by OverSIP when a USR1
signal is received by the OverSIP main process (or /etc/init.d/oversip user-reload
is executed) and allows the user to set custom code to be executed or reloaded.
For example, this method could be used to reload a Ruby object (i.e. a Hash
) with data retrieved from a database when such an information has been modified in the database.
Example code
def (OverSIP::SystemEvents).on_user_reload
MyApp.load_valid_websocket_origins()
end
OverSIP::SystemEvents.on_terminated
(error)
This method is called after OverSIP has been terminated.
Parameters
error
true
in case OverSIP has died in an unexpected way.
Example code
def (OverSIP::SystemEvents).on_terminated(error)
if error
log_notice "exiting with error: #{error.inspect}"
else
log_info "properly exiting"
end
end
SIP Events
This section includes programmable callbacks for SIP events:
OverSIP::SipEvents.on_request
(request)
This method is called when a SIP request is received.
Parameters
request
- The
OverSIP::SIP::Request
instance.
Example code
For a full example code check the OverSIP::SipEvents.on_request
section in the default server.rb
file.
OverSIP::SipEvents.on_client_tls_handshake
(connection, pems)
This method is called when a SIP client initiates a TLS handshake with OverSIP. It is not called if the SIP callback_on_client_tls_handshake
parameter is not set.
Take a look to the TLS API for using the data provided by this method.
NOTE: When the SIP parameter use_tls_tunnel
is enabled, incoming SIP TLS connections are handled by Stud processes and thus this method is not called.
Parameters
connection
- The
OverSIP::SIP::Connection
instance. pems
- An
Array
with the chain of X509 certificates in PEM format (String
) presented by the client during the TLS handshake. The first element is the most-resolved certificate, followed by the successive intermediate certificates and the root (or CA) certificate at the end. It could be empty if the client does not present a TLS certificate.
OverSIP::SipEvents.on_server_tls_handshake
(connection, pems)
This method is called when OverSIP initiates a TLS handshake with a SIP server. It is not called if the callback_on_server_tls_handshake
is not set for the “Proxy” instance being used for routing the SIP request.
In case the connection is not desired (after TLS certificate validation) it can be closed (and thus the SIP request not sent) by calling the close()
method in the given OverSIP::SIP::Connection
instance. It would generate an internal 500
“TLS Validation Failed” SIP response.
Take a look to the TLS API for using the data provided by this method.
Parameters
connection
- The
OverSIP::SIP::Connection
instance. pems
- An
Array
with the chain of X509 certificates in PEM format (String
) presented by the server during the TLS handshake. The first element is the most-resolved certificate, followed by the successive intermediate certificates and the root (or CA) certificate at the end.
WebSocket Events
This section includes programmable callbacks for WebSocket events:
OverSIP::WebSocketEvents.on_connection
(connection, http_request)
This method is called when a client attempts to establish a WebSocket connection and once OverSIP has validated that the HTTP GET request is a valid WebSocket handshake request but before OverSIP replies the HTTP 101 “Switching Protocols”.
Based on the HTTP request parameters and local policy the user can decide here whether to allow or reject the WebSocket connection attempt. This can be done by inspecting specific fields of the request (i.e. Origin header, Cookie header, request URI value and parameters, etc) and data from the connection (source address, plain or secure WebSocket connection, etc). The user can reject the WebSocket connection by calling connection.http_reject
(so the HTTP 101 response required for completing the WebSocket handshake wont take place).
Parameters
connection
- The associated
OverSIP::WebSocket::Connection
instance. request
- The WebSocket handshake
OverSIP::WebSocket::HttpRequest
instance.
Example code
def (OverSIP::WebSocketEvents).on_connection(connection, http_request)
# Check the Origin header against my allowed list of domains.
if MyApp.valid_websocket_origins.include? http_request.hdr_origin
log_info "allowed WebSocket connection"
else
log_warn "WebSocket connection rejected, invalid Origin: #{http_request.hdr_origin}"
connection.http_reject 403, "Origin not allowed"
end
end
OverSIP::WebSocketEvents.on_disconnection
(connection, client_closed)
This method is called when a WebSocket connection is closed.
Parameters
connection
- The associated
OverSIP::WebSocket::Connection
instance. client_closed
true
if the client caused the disconnection,false
otherwise (OverSIP closed it).
Example code
def (OverSIP::WebSocketEvents).on_disconnection(connection, client_closed)
if client_closed
log_info "WebSocket connection closed by the client"
else
log_info "WebSocket connection closed by OverSIP"
end
end
OverSIP::WebSocketEvents.on_client_tls_handshake
(connection, pems)
This method is called when a WebSocket client initiates a TLS handshake with OverSIP. It is not called if the WebSocket callback_on_client_tls_handshake
parameter is not set.
Take a look to the TLS API for using the data provided by this method.
NOTE: When the WebSocket parameter use_tls_tunnel
is enabled, incoming WebSocket TLS connections are handled by Stud processes and thus this method is not called.
Parameters
connection
- The
OverSIP::WebSocket::Connection
instance. pems
- An
Array
with the chain of X509 certificates in PEM format (String
) presented by the client during the TLS handshake. The first element is the most-resolved certificate, followed by the successive intermediate certificates and the root (or CA) certificate at the end. It could be empty if the client does not present a TLS certificate.