diff --git a/repos/gems/src/server/tcp_terminal/README b/repos/gems/src/server/tcp_terminal/README
index d230f62e0..bede9524a 100644
--- a/repos/gems/src/server/tcp_terminal/README
+++ b/repos/gems/src/server/tcp_terminal/README
@@ -4,9 +4,13 @@ to be used for each client is defined in as session policy in the config node
of the TCP server:
!
-!
+!
!
!
+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
at 'gems/run/tcp_terminal.run'.
diff --git a/repos/gems/src/server/tcp_terminal/main.cc b/repos/gems/src/server/tcp_terminal/main.cc
index 1d1a55413..8f96c9f83 100644
--- a/repos/gems/src/server/tcp_terminal/main.cc
+++ b/repos/gems/src/server/tcp_terminal/main.cc
@@ -110,9 +110,37 @@ class Open_socket : public Genode::List::Element
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:
Open_socket(int tcp_port);
+ Open_socket(char const * ip_addr, int tcp_port);
~Open_socket();
@@ -131,11 +159,29 @@ class Open_socket : public Genode::List::Element
*/
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
* 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
@@ -162,7 +208,7 @@ class Open_socket : public Genode::List::Element
socklen_t len = sizeof(addr);
_sd = accept(_listen_sd, &addr, &len);
- if (_sd != -1)
+ if (connection_established())
Genode::log("connection established");
/*
@@ -173,14 +219,6 @@ class Open_socket : public Genode::List::Element
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
*/
@@ -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()
{
if (_sd != -1) close(_sd);
@@ -433,6 +480,13 @@ class Terminal::Session_component : public Genode::Rpc_object 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;
}