class Roby::Interface::TCPServer

An object that publishes a Roby interface using a TCP server

Attributes

clients[R]

@return [Array<Client>] set of currently active clients

interface[R]

@return [Interface] the interface object we give access to

server[R]

@return [::TCPServer] the TCP server we are accepting from

Public Class Methods

new(app, host: nil, port: Roby::Interface::DEFAULT_PORT) click to toggle source

Creates a new interface server on the given port

@param [Integer] port

# File lib/roby/interface/tcp.rb, line 32
def initialize(app, host: nil, port: Roby::Interface::DEFAULT_PORT)
    @app = app
    @interface = Interface.new(app)
    @server =
        begin ::TCPServer.new(host, port)
        rescue TypeError
            raise Errno::EADDRINUSE, "#{port} already in use"
        end
    @clients = Array.new
    @abort_on_exception = true
    @accept_executor = Concurrent::CachedThreadPool.new
    @accept_future = queue_accept_future
    @propagation_handler_id = interface.execution_engine.
        add_propagation_handler(
            description: 'TCPServer#process_pending_requests',
            on_error: :ignore) do
                process_pending_requests
            end
    @warn_about_disconnection = false
end

Public Instance Methods

close() click to toggle source

Closes this server

# File lib/roby/interface/tcp.rb, line 122
def close
    clients.each do |c|
        unless c.closed?
            c.close
        end
    end
    clients.clear
    if server && !server.closed?
        server.close
    end
    @accept_executor.shutdown
    interface.execution_engine.
        remove_propagation_handler(@propagation_handler_id)
end
create_server(socket) click to toggle source

Creates a server object that will manage the replies on a particular TCP socket

@return [Server]

# File lib/roby/interface/tcp.rb, line 74
def create_server(socket)
    Server.new(DRobyChannel.new(socket, false), interface)
end
has_client?(client) click to toggle source

Whether the given client is handled by this server

# File lib/roby/interface/tcp.rb, line 138
def has_client?(client)
    @clients.include?(client)
end
ip_address() click to toggle source

@return [String] the address this interface is bound to

# File lib/roby/interface/tcp.rb, line 20
def ip_address
    server.local_address.ip_address
end
ip_port() click to toggle source

@return [Integer] the port on which this interface runs

# File lib/roby/interface/tcp.rb, line 25
def ip_port
    server.local_address.ip_port
end
port() click to toggle source

Returns the port this server is bound to

@return [Integer]

# File lib/roby/interface/tcp.rb, line 64
def port
    Roby.warn_deprecated "Interface::TCPServer#port is deprecated in favor "\
        "of #ip_port to match ruby's Addrinfo API"
    ip_port
end
process_pending_requests() click to toggle source

Process all incoming connection requests

The new clients are added into the Roby event loop

# File lib/roby/interface/tcp.rb, line 81
def process_pending_requests
    if @accept_future.rejected?
        raise @accept_future.reason
    elsif @accept_future.fulfilled?
        clients << create_server(@accept_future.value)
        @accept_future = queue_accept_future
    end

    exceptions = []
    clients.delete_if do |client|
        begin
            client.poll
        rescue Exception => e
            client.close

            if warn_about_disconnection?
                Roby::Interface.warn "disconnecting from #{client.client_id}"
            end

            next(true) if e.kind_of?(ComError)

            if abort_on_exception?
                exceptions << e
            else
                Roby.log_exception_with_backtrace(e, Roby::Interface, :warn)
            end
            true
        end
    end

    raise exceptions.first unless exceptions.empty?
rescue Exception => e
    if abort_on_exception?
        @app.execution_engine.
            add_framework_error(e, "Interface::TCPServer")
    else
        Roby.log_exception_with_backtrace(e, Roby, :warn)
    end
end
queue_accept_future() click to toggle source
# File lib/roby/interface/tcp.rb, line 53
def queue_accept_future
    Concurrent::Future.execute(executor: @accept_executor) do
        socket = @server.accept
        socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
        socket
    end
end