class ADAM6050::Session
The session object is used by the server to keep track of authenticated clients. Once a client is registered with the session it will be reported as valid for a period of time, after which it is again marked as invalid and needs to register again. Any activity before the timeout will reset the countdown.
Usage¶ ↑
The following example creates a session with a 10 second timeout and registers a sender. `#validate!` is then called at a later point in time to verify that the sender is still valid.
session = Session.new timeout: 10.0 session.register sender # The following call will raise an exception if more # than 10 seconds has passed. session.validate! sender
Constants
- DEFAULT_CLEANUP_INTERVALL
@return [Numeric] the default number of seconds to wait after one cleanup
before perfoming the next.
- DEFAULT_TIMEOUT
@return [Numeric] the default number of seconds a sender is valid with no
interaction.
Public Class Methods
@param timeout [Numeric] the number of seconds a sender is valid with no
interaction.
@param cleanup_interval [Numeric] the number of seconds to wait after one
cleanup before perfoming the next.
# File lib/adam6050/session.rb, line 49 def initialize(timeout: DEFAULT_TIMEOUT, cleanup_interval: DEFAULT_CLEANUP_INTERVALL) @session = {} @timeout = timeout @cleanup_interval = cleanup_interval @next_cleanup = 0.0 end
Public Instance Methods
Removes invalid senders from the session.
@param time [Numeric] the current time. The current time will be used if
not specified.
@return [Numeric] the next time before which no cleanup will be performed.
# File lib/adam6050/session.rb, line 112 def cleanup!(time: monotonic_timestamp) return if time < @next_cleanup delete_expired! time, @timeout @next_cleanup = time + @cleanup_interval end
Register a new sender as valid in the current session.
@param sender [Socket::UDPSource] the udp client. @param time [Numeric] the current time. The current time will be used if
not specified.
@return [nil]
# File lib/adam6050/session.rb, line 70 def register(sender, time: monotonic_timestamp) @session[session_key sender] = time nil end
@return [Integer] the number of senders currently known by the session.
Note that this may include invalid senders that have not yet been cleaned up.
# File lib/adam6050/session.rb, line 60 def size @session.size end
A sender is valid as long as it is registered and has not expired within the current session.
@param sender [Socket::UDPSource] the udp client. @param time [Numeric] the current time. The current time will be used if
not specified.
@return [true] if the sender has authenticated and has been active within
the configured timeout.
@return [false] otherwise.
# File lib/adam6050/session.rb, line 84 def valid?(sender, time: monotonic_timestamp) !expired? @session.fetch(session_key(sender), 0.0), time, @timeout end
Renews the given sender if it is still valid within the session and raises an exception otherwise.
@raise [UnknownSender] if the given sender is not registered. @raise [InvalidSender] if the given sender is not valid.
@param sender [Socket::UDPSource] the udp client. @param time [Numeric] the current time. The current time will be used if
not specified.
@return [nil]
# File lib/adam6050/session.rb, line 98 def validate!(sender, time: monotonic_timestamp) key = session_key sender last_observed = @session.fetch(key) { raise UnknownSender, sender } raise InvalidSender, sender if expired? last_observed, time, @timeout @session[key] = time nil end
Private Instance Methods
@param time [Numeric] the current time. @param timeout [Numeric] the time after which expired clients should be
deleted.
@return [Hash] the session hash with expired clients deleted.
# File lib/adam6050/session.rb, line 151 def delete_expired!(time, timeout) @session.delete_if { |_, t| expired? t, time, timeout } end
@param last_seen [Numeric] the time when the client was last seen. @param time [Numeric] the current time. @param timeout [Numeric] the time after which expired clients should be
deleted.
@return [false] if the time last seen is within the timeout. @return [true] otherwise.
# File lib/adam6050/session.rb, line 142 def expired?(last_seen, time, timeout) threshold = time - timeout last_seen < threshold end
This is slightly faster than calling Time.now since no new object needs to be allocated.
@return [Numeric] the current monotonic process time.
# File lib/adam6050/session.rb, line 132 def monotonic_timestamp Process.clock_gettime Process::CLOCK_MONOTONIC end
@param sender [Socket::UDPSource] the UDP client. @return [#hash] a unique identifier for the sender.
# File lib/adam6050/session.rb, line 124 def session_key(sender) sender.remote_address.ip_address end