gems: add connect facility to tcp_terminal
Instead of listening for new TCP/IP connections only, the TCP terminal connects to a server when an IP address is configured in the policy for a terminal client. Fix #3619
This commit is contained in:
parent
56ef7ca9e7
commit
79dff674fd
|
@ -4,9 +4,13 @@ to be used for each client is defined in as session policy in the config node
|
||||||
of the TCP server:
|
of the TCP server:
|
||||||
|
|
||||||
! <config>
|
! <config>
|
||||||
! <policy label_prefix="client" port="8181"/>
|
! <policy label_prefix="client" ip="10.0.0.5" port="8181"/>
|
||||||
! <policy label_prefix="another_client" port="8282"/>
|
! <policy label_prefix="another_client" port="8282"/>
|
||||||
! </config>
|
! </config>
|
||||||
|
|
||||||
|
If only a port is described in the policy the TCP terminal will listen on
|
||||||
|
that port for incomming connections. If an IP address is provided additionally,
|
||||||
|
it connects to the IP address using the given port.
|
||||||
|
|
||||||
For an example of how to use the TCP terminal, please refer to the run script
|
For an example of how to use the TCP terminal, please refer to the run script
|
||||||
at 'gems/run/tcp_terminal.run'.
|
at 'gems/run/tcp_terminal.run'.
|
||||||
|
|
|
@ -110,9 +110,37 @@ class Open_socket : public Genode::List<Open_socket>::Element
|
||||||
return listen_sd;
|
return listen_sd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Establish remote connection
|
||||||
|
*
|
||||||
|
* \return socket descriptor used for the remote TCP connection
|
||||||
|
*/
|
||||||
|
static int _remote_connect(char const * ip, int tcp_port)
|
||||||
|
{
|
||||||
|
int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (sd == -1) {
|
||||||
|
Genode::error("socket creation failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_in sockaddr;
|
||||||
|
sockaddr.sin_family = PF_INET;
|
||||||
|
sockaddr.sin_port = htons (tcp_port);
|
||||||
|
sockaddr.sin_addr.s_addr = inet_addr(ip);
|
||||||
|
|
||||||
|
if (connect(sd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
|
||||||
|
Genode::error("connect to ", ip, ":", tcp_port, " failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Genode::log("connected to ", ip, ":", tcp_port, "...");
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Open_socket(int tcp_port);
|
Open_socket(int tcp_port);
|
||||||
|
Open_socket(char const * ip_addr, int tcp_port);
|
||||||
|
|
||||||
~Open_socket();
|
~Open_socket();
|
||||||
|
|
||||||
|
@ -131,11 +159,29 @@ class Open_socket : public Genode::List<Open_socket>::Element
|
||||||
*/
|
*/
|
||||||
int sd() const { return _sd; }
|
int sd() const { return _sd; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if TCP connection is established
|
||||||
|
*
|
||||||
|
* If the return value is false, we are still in listening more
|
||||||
|
* and have not yet called 'accept()'.
|
||||||
|
*/
|
||||||
|
bool connection_established() const { return _sd != -1; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register signal handler to be notified once we accepted the TCP
|
* Register signal handler to be notified once we accepted the TCP
|
||||||
* connection
|
* connection
|
||||||
*/
|
*/
|
||||||
void connected_sigh(Genode::Signal_context_capability sigh) { _connected_sigh = sigh; }
|
void connected_sigh(Genode::Signal_context_capability sigh)
|
||||||
|
{
|
||||||
|
_connected_sigh = sigh;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inform client about the finished initialization of the terminal
|
||||||
|
* session
|
||||||
|
*/
|
||||||
|
if (_connected_sigh.valid() && connection_established())
|
||||||
|
Genode::Signal_transmitter(_connected_sigh).submit();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register signal handler to be notified when data is available for
|
* Register signal handler to be notified when data is available for
|
||||||
|
@ -162,7 +208,7 @@ class Open_socket : public Genode::List<Open_socket>::Element
|
||||||
socklen_t len = sizeof(addr);
|
socklen_t len = sizeof(addr);
|
||||||
_sd = accept(_listen_sd, &addr, &len);
|
_sd = accept(_listen_sd, &addr, &len);
|
||||||
|
|
||||||
if (_sd != -1)
|
if (connection_established())
|
||||||
Genode::log("connection established");
|
Genode::log("connection established");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -173,14 +219,6 @@ class Open_socket : public Genode::List<Open_socket>::Element
|
||||||
Genode::Signal_transmitter(_connected_sigh).submit();
|
Genode::Signal_transmitter(_connected_sigh).submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if TCP connection is established
|
|
||||||
*
|
|
||||||
* If the return value is false, we are still in listening more
|
|
||||||
* and have not yet called 'accept()'.
|
|
||||||
*/
|
|
||||||
bool connection_established() const { return _sd != -1; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch data from socket into internal read buffer
|
* Fetch data from socket into internal read buffer
|
||||||
*/
|
*/
|
||||||
|
@ -406,6 +444,15 @@ Open_socket::Open_socket(int tcp_port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Open_socket::Open_socket(char const * ip_addr, int tcp_port)
|
||||||
|
:
|
||||||
|
_listen_sd(_remote_connect(ip_addr, tcp_port)), _sd(_listen_sd),
|
||||||
|
_read_buf_bytes_used(0), _read_buf_bytes_read(0)
|
||||||
|
{
|
||||||
|
open_socket_pool()->insert(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Open_socket::~Open_socket()
|
Open_socket::~Open_socket()
|
||||||
{
|
{
|
||||||
if (_sd != -1) close(_sd);
|
if (_sd != -1) close(_sd);
|
||||||
|
@ -433,6 +480,13 @@ class Terminal::Session_component : public Genode::Rpc_object<Session, Session_c
|
||||||
_io_buffer(env.ram(), env.rm(), io_buffer_size)
|
_io_buffer(env.ram(), env.rm(), io_buffer_size)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
Session_component(Genode::Env &env, Genode::size_t io_buffer_size,
|
||||||
|
char const * ip_addr, int tcp_port)
|
||||||
|
:
|
||||||
|
Open_socket(ip_addr, tcp_port),
|
||||||
|
_io_buffer(env.ram(), env.rm(), io_buffer_size)
|
||||||
|
{ }
|
||||||
|
|
||||||
/********************************
|
/********************************
|
||||||
** Terminal session interface **
|
** Terminal session interface **
|
||||||
********************************/
|
********************************/
|
||||||
|
@ -536,10 +590,18 @@ class Terminal::Root_component : public Genode::Root_component<Session_component
|
||||||
unsigned const tcp_port = policy.attribute_value("port", 0U);
|
unsigned const tcp_port = policy.attribute_value("port", 0U);
|
||||||
|
|
||||||
Session_component *session = nullptr;
|
Session_component *session = nullptr;
|
||||||
Libc::with_libc([&] () {
|
|
||||||
session = new (md_alloc())
|
|
||||||
Session_component(_env, io_buffer_size, tcp_port); });
|
|
||||||
|
|
||||||
|
if (policy.has_attribute("ip")) {
|
||||||
|
typedef Genode::String<16> Ip;
|
||||||
|
Ip ip_addr = policy.attribute_value("ip", Ip());
|
||||||
|
Libc::with_libc([&] () {
|
||||||
|
session = new (md_alloc())
|
||||||
|
Session_component(_env, io_buffer_size, ip_addr.string(), tcp_port); });
|
||||||
|
} else {
|
||||||
|
Libc::with_libc([&] () {
|
||||||
|
session = new (md_alloc())
|
||||||
|
Session_component(_env, io_buffer_size, tcp_port); });
|
||||||
|
}
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue