class Roby::Interface::Server

The server-side object allowing to access an interface (e.g. a Roby app) through any communication channel

Attributes

client_id[R]

@return [String] a string that allows the user to identify the client

interface[R]

@return [Interface] the interface object we are giving access to

io[R]

@return [DRobyChannel] the IO to the client

Public Class Methods

new(io, interface, main_thread: Thread.current) click to toggle source

@param [DRobyChannel] io a channel to the server @param [Interface] interface the interface object we give remote

access to
# File lib/roby/interface/server.rb, line 19
def initialize(io, interface, main_thread: Thread.current)
    @notifications_enabled = true
    @io = io
    @interface = interface
    @main_thread = main_thread
    @pending_notifications = Queue.new

    interface.on_cycle_end do
        write_packet(
            [
                :cycle_end,
                interface.execution_engine.cycle_index,
                interface.execution_engine.cycle_start
            ], defer_exceptions: true)
    end
    interface.on_notification do |*args|
        if notifications_enabled?
            @pending_notifications << args
        end
        if Thread.current == @main_thread
            flush_pending_notifications
        end
    end
    interface.on_ui_event do |*args|
        write_packet([:ui_event, *args], defer_exceptions: true)
    end
    interface.on_job_notification do |*args|
        write_packet([:job_progress, *args], defer_exceptions: true)
    end
    interface.on_exception do |*args|
        write_packet([:exception, *args], defer_exceptions: true)
    end
end

Public Instance Methods

close() click to toggle source
# File lib/roby/interface/server.rb, line 85
def close
    io.close
end
closed?() click to toggle source
# File lib/roby/interface/server.rb, line 81
def closed?
    io.closed?
end
disable_notifications() click to toggle source
# File lib/roby/interface/server.rb, line 77
def disable_notifications
    self.notifications_enabled = false
end
enable_notifications() click to toggle source
# File lib/roby/interface/server.rb, line 73
def enable_notifications
    self.notifications_enabled = true
end
flush_pending_notifications() click to toggle source
# File lib/roby/interface/server.rb, line 53
def flush_pending_notifications
    notifications = []
    until @pending_notifications.empty?
        notifications << @pending_notifications.pop
    end
    notifications.each do |args|
        write_packet([:notification, *args], defer_exceptions: true)
    end
end
handshake(id) click to toggle source
# File lib/roby/interface/server.rb, line 67
def handshake(id)
    @client_id = id
    Roby::Interface.info "new interface client: #{id}"
    [interface.actions, interface.commands]
end
has_deferred_exception?() click to toggle source
# File lib/roby/interface/server.rb, line 106
def has_deferred_exception?
    @deferred_exception
end
poll() click to toggle source

Process one command from the client, and send the reply

# File lib/roby/interface/server.rb, line 123
def poll
    raise @deferred_exception if has_deferred_exception?

    path, m, *args = io.read_packet
    return unless m

    begin
        reply =
            if m == :process_batch
                process_batch(path, args.first)
            else
                process_call(path, m, *args)
            end

        true
    rescue Exception => e
        write_packet([:bad_call, e])
        return
    end

    begin
        write_packet([:reply, reply])
    rescue ComError
        raise
    rescue Exception => e
        write_packet([:protocol_error, e])
        raise
    end
end
process_batch(path, calls) click to toggle source
# File lib/roby/interface/server.rb, line 89
def process_batch(path, calls)
    calls.map do |p, m, *a|
        process_call(path + p, m, *a)
    end
end
process_call(path, name, *args) click to toggle source
# File lib/roby/interface/server.rb, line 95
def process_call(path, name, *args)
    if path.empty? && respond_to?(name)
        send(name, *args)
    else
        receiver = path.inject(interface) do |obj, subcommand|
            obj.send(subcommand)
        end
        receiver.send(name, *args)
    end
end
to_io() click to toggle source
# File lib/roby/interface/server.rb, line 63
def to_io
    io.to_io
end
write_packet(call, defer_exceptions: false) click to toggle source
# File lib/roby/interface/server.rb, line 110
def write_packet(call, defer_exceptions: false)
    return if has_deferred_exception?

    flush_pending_notifications
    io.write_packet(call)
rescue Exception => e
    if defer_exceptions
        @deferred_exception = e
    else raise
    end
end