2013-10-09 17:49:30 +02:00
|
|
|
/*
|
|
|
|
* \brief Service providing the 'Terminal_session' interface for a file
|
|
|
|
* \author Josef Soentgen
|
|
|
|
* \date 2013-10-08
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-01-17 15:45:54 +01:00
|
|
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
2013-10-09 17:49:30 +02:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2013-10-09 17:49:30 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
|
|
|
#include <base/heap.h>
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
#include <base/log.h>
|
2017-01-30 11:35:12 +01:00
|
|
|
#include <base/attached_ram_dataspace.h>
|
2017-05-02 17:35:01 +02:00
|
|
|
#include <base/attached_rom_dataspace.h>
|
2013-10-09 17:49:30 +02:00
|
|
|
#include <os/session_policy.h>
|
2017-05-02 17:35:01 +02:00
|
|
|
#include <libc/component.h>
|
2013-10-09 17:49:30 +02:00
|
|
|
#include <root/component.h>
|
|
|
|
#include <terminal_session/terminal_session.h>
|
|
|
|
|
|
|
|
/* libc includes */
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/select.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
|
|
|
|
class Open_file
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* File descriptor for open file
|
|
|
|
*/
|
|
|
|
int _fd;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Signal handler to be informed about the established connection
|
|
|
|
*/
|
2019-01-14 20:04:40 +01:00
|
|
|
Genode::Signal_context_capability _connected_sigh { };
|
2013-10-09 17:49:30 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Signal handler to be informed about data available to read
|
|
|
|
*/
|
2019-01-14 20:04:40 +01:00
|
|
|
Genode::Signal_context_capability _read_avail_sigh { };
|
2013-10-09 17:49:30 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Buffer for incoming data
|
|
|
|
*
|
|
|
|
* This buffer is used for synchronizing the reception of data in the
|
|
|
|
* main thread ('watch_sockets_for_incoming_data') and the entrypoint
|
|
|
|
* thread ('read'). The main thread fills the buffer if its not already
|
|
|
|
* occupied and the entrypoint thread consumes the buffer. When the
|
|
|
|
* buffer becomes occupied, the corresponding socket gets removed from
|
|
|
|
* the 'rfds' set of 'select()' until a read request from the terminal
|
|
|
|
* client comes in.
|
|
|
|
*/
|
|
|
|
enum { READ_BUF_SIZE = 4096 };
|
|
|
|
char _read_buf[READ_BUF_SIZE];
|
2019-01-14 20:04:40 +01:00
|
|
|
Genode::size_t _read_buf_bytes_used { };
|
2013-10-09 17:49:30 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Open_file(const char *filename) : _fd(-1)
|
|
|
|
{
|
2017-09-07 17:18:27 +02:00
|
|
|
Libc::with_libc([&] () { _fd = ::open(filename, O_CREAT|O_RDWR); });
|
2013-10-09 17:49:30 +02:00
|
|
|
if (_fd == -1)
|
|
|
|
::perror("open");
|
|
|
|
}
|
|
|
|
|
|
|
|
~Open_file() { close(_fd); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return file descriptor of the open file
|
|
|
|
*/
|
|
|
|
int fd() const { return _fd; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register signal handler to be notified once we openend the file
|
|
|
|
*/
|
|
|
|
void connected_sigh(Genode::Signal_context_capability sigh)
|
|
|
|
{
|
|
|
|
_connected_sigh = sigh;
|
|
|
|
|
|
|
|
/* notify the client immediatly if we have already openend the file */
|
|
|
|
if (file_opened() && _connected_sigh.valid())
|
|
|
|
Genode::Signal_transmitter(_connected_sigh).submit();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register signal handler to be notified when data is available for
|
|
|
|
* reading
|
|
|
|
*/
|
|
|
|
void read_avail_sigh(Genode::Signal_context_capability sigh)
|
|
|
|
{
|
|
|
|
_read_avail_sigh = sigh;
|
|
|
|
|
|
|
|
/* if read data is available right now, deliver signal immediately */
|
|
|
|
if (!read_buffer_empty() && _read_avail_sigh.valid())
|
|
|
|
Genode::Signal_transmitter(_read_avail_sigh).submit();
|
|
|
|
}
|
|
|
|
|
2018-02-07 17:03:19 +01:00
|
|
|
/**
|
|
|
|
* Return true if the file was successfully openend
|
|
|
|
*/
|
2013-10-09 17:49:30 +02:00
|
|
|
bool file_opened() const { return _fd != -1; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetch data from socket into internal read buffer
|
|
|
|
*/
|
|
|
|
void fill_read_buffer_and_notify_client()
|
|
|
|
{
|
|
|
|
if (_read_buf_bytes_used) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::warning("read buffer already in use");
|
2013-10-09 17:49:30 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read from file */
|
|
|
|
_read_buf_bytes_used = ::read(_fd, _read_buf, sizeof(_read_buf));
|
|
|
|
|
|
|
|
/* notify client about bytes available for reading */
|
|
|
|
if (_read_avail_sigh.valid())
|
|
|
|
Genode::Signal_transmitter(_read_avail_sigh).submit();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Flush internal read buffer into destination buffer
|
|
|
|
*/
|
|
|
|
Genode::size_t flush_read_buffer(char *dst, Genode::size_t dst_len)
|
|
|
|
{
|
|
|
|
Genode::size_t num_bytes = Genode::min(dst_len, _read_buf_bytes_used);
|
|
|
|
Genode::memcpy(dst, _read_buf, num_bytes);
|
|
|
|
_read_buf_bytes_used = 0;
|
|
|
|
return num_bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return true if the internal read buffer is ready to receive data
|
|
|
|
*/
|
|
|
|
bool read_buffer_empty() const { return _read_buf_bytes_used == 0; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
namespace Terminal {
|
|
|
|
|
|
|
|
class Session_component : public Genode::Rpc_object<Session, Session_component>,
|
2019-01-14 20:04:40 +01:00
|
|
|
private Open_file
|
2013-10-09 17:49:30 +02:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
Genode::Attached_ram_dataspace _io_buffer;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2017-02-23 15:08:46 +01:00
|
|
|
Session_component(Genode::Env &env,
|
|
|
|
Genode::size_t io_buffer_size, const char *filename)
|
2013-10-09 17:49:30 +02:00
|
|
|
:
|
|
|
|
Open_file(filename),
|
2017-02-23 15:08:46 +01:00
|
|
|
_io_buffer(env.ram(), env.rm(), io_buffer_size)
|
2013-10-09 17:49:30 +02:00
|
|
|
{ }
|
|
|
|
|
|
|
|
/********************************
|
|
|
|
** Terminal session interface **
|
|
|
|
********************************/
|
|
|
|
|
2018-02-07 17:03:19 +01:00
|
|
|
Size size() override { return Size(0, 0); }
|
2013-10-09 17:49:30 +02:00
|
|
|
|
2018-02-07 17:03:19 +01:00
|
|
|
bool avail() override
|
2013-10-09 17:49:30 +02:00
|
|
|
{
|
|
|
|
return !read_buffer_empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
Genode::size_t _read(Genode::size_t dst_len)
|
|
|
|
{
|
|
|
|
Genode::size_t num_bytes =
|
|
|
|
flush_read_buffer(_io_buffer.local_addr<char>(),
|
|
|
|
Genode::min(_io_buffer.size(), dst_len));
|
|
|
|
|
|
|
|
return num_bytes;
|
|
|
|
}
|
|
|
|
|
2017-01-17 15:45:54 +01:00
|
|
|
Genode::size_t _write(Genode::size_t num_bytes)
|
2013-10-09 17:49:30 +02:00
|
|
|
{
|
|
|
|
/* sanitize argument */
|
|
|
|
num_bytes = Genode::min(num_bytes, _io_buffer.size());
|
|
|
|
|
2017-09-07 17:18:27 +02:00
|
|
|
ssize_t written_bytes = 0;
|
|
|
|
Libc::with_libc([&] () {
|
|
|
|
/* write data to descriptor */
|
|
|
|
written_bytes = ::write(fd(),
|
|
|
|
_io_buffer.local_addr<char>(),
|
|
|
|
num_bytes);
|
|
|
|
});
|
2017-01-17 15:45:54 +01:00
|
|
|
|
|
|
|
if (written_bytes < 0) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("write error, dropping data");
|
2017-01-17 15:45:54 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return written_bytes;
|
2013-10-09 17:49:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Genode::Dataspace_capability _dataspace()
|
|
|
|
{
|
|
|
|
return _io_buffer.cap();
|
|
|
|
}
|
|
|
|
|
2018-02-07 17:03:19 +01:00
|
|
|
void read_avail_sigh(Genode::Signal_context_capability sigh) override
|
2013-10-09 17:49:30 +02:00
|
|
|
{
|
|
|
|
Open_file::read_avail_sigh(sigh);
|
|
|
|
}
|
|
|
|
|
2018-02-07 17:03:19 +01:00
|
|
|
void connected_sigh(Genode::Signal_context_capability sigh) override
|
2013-10-09 17:49:30 +02:00
|
|
|
{
|
|
|
|
Open_file::connected_sigh(sigh);
|
|
|
|
}
|
|
|
|
|
2018-02-07 17:03:19 +01:00
|
|
|
void size_changed_sigh(Genode::Signal_context_capability) override { }
|
|
|
|
|
2019-01-14 20:04:40 +01:00
|
|
|
Genode::size_t read(void *, Genode::size_t) override { return 0; }
|
|
|
|
Genode::size_t write(void const *, Genode::size_t) override { return 0; }
|
2013-10-09 17:49:30 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Root_component : public Genode::Root_component<Session_component>
|
|
|
|
{
|
2017-02-23 15:08:46 +01:00
|
|
|
private:
|
|
|
|
|
2017-05-02 17:35:01 +02:00
|
|
|
Genode::Env &_env;
|
|
|
|
Genode::Xml_node _config;
|
2017-02-23 15:08:46 +01:00
|
|
|
|
2013-10-09 17:49:30 +02:00
|
|
|
protected:
|
|
|
|
|
|
|
|
Session_component *_create_session(const char *args)
|
|
|
|
{
|
|
|
|
Genode::size_t io_buffer_size = 4096;
|
|
|
|
|
|
|
|
try {
|
2016-01-12 14:11:58 +01:00
|
|
|
Genode::Session_label label = Genode::label_from_args(args);
|
2017-05-02 17:35:01 +02:00
|
|
|
Genode::Session_policy policy(label, _config);
|
2013-10-09 17:49:30 +02:00
|
|
|
|
|
|
|
char filename[256];
|
|
|
|
policy.attribute("filename").value(filename, sizeof(filename));
|
|
|
|
|
|
|
|
if (policy.has_attribute("io_buffer_size"))
|
|
|
|
policy.attribute("io_buffer_size").value(&io_buffer_size);
|
|
|
|
|
|
|
|
return new (md_alloc())
|
2017-02-23 15:08:46 +01:00
|
|
|
Session_component(_env, io_buffer_size, filename);
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
}
|
|
|
|
catch (Genode::Xml_node::Nonexistent_attribute) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("missing \"filename\" attribute in policy definition");
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
throw Genode::Service_denied();
|
|
|
|
}
|
|
|
|
catch (Genode::Session_policy::No_policy_defined) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("invalid session request, no matching policy");
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
throw Genode::Service_denied();
|
2013-10-09 17:49:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*/
|
2017-02-23 15:08:46 +01:00
|
|
|
Root_component(Genode::Env &env,
|
2017-05-02 17:35:01 +02:00
|
|
|
Genode::Xml_node config,
|
2017-02-23 15:08:46 +01:00
|
|
|
Genode::Allocator *md_alloc)
|
2013-10-09 17:49:30 +02:00
|
|
|
:
|
2017-02-23 15:08:46 +01:00
|
|
|
Genode::Root_component<Session_component>(&env.ep().rpc_ep(), md_alloc),
|
2017-05-02 17:35:01 +02:00
|
|
|
_env(env), _config(config)
|
2013-10-09 17:49:30 +02:00
|
|
|
{ }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-23 15:08:46 +01:00
|
|
|
struct Main
|
2013-10-09 17:49:30 +02:00
|
|
|
{
|
2017-02-23 15:08:46 +01:00
|
|
|
Genode::Env &_env;
|
2013-10-09 17:49:30 +02:00
|
|
|
|
2017-05-02 17:35:01 +02:00
|
|
|
Genode::Attached_rom_dataspace _config_rom { _env, "config" };
|
|
|
|
Genode::Xml_node _config { _config_rom.xml() };
|
|
|
|
|
2017-02-23 15:08:46 +01:00
|
|
|
Genode::Sliced_heap _sliced_heap { _env.ram(), _env.rm() };
|
2013-10-09 17:49:30 +02:00
|
|
|
|
2017-02-23 15:08:46 +01:00
|
|
|
/* create root interface for service */
|
2017-05-02 17:35:01 +02:00
|
|
|
Terminal::Root_component _root { _env, _config, &_sliced_heap };
|
2013-10-09 17:49:30 +02:00
|
|
|
|
2017-02-23 15:08:46 +01:00
|
|
|
Main(Genode::Env &env) : _env(env)
|
|
|
|
{
|
|
|
|
using namespace Genode;
|
2013-10-09 17:49:30 +02:00
|
|
|
|
2017-02-23 15:08:46 +01:00
|
|
|
/* announce service at our parent */
|
|
|
|
_env.parent().announce(env.ep().manage(_root));
|
|
|
|
}
|
|
|
|
};
|
2013-10-09 17:49:30 +02:00
|
|
|
|
|
|
|
|
2017-09-07 17:18:27 +02:00
|
|
|
void Libc::Component::construct(Libc::Env &env)
|
|
|
|
{
|
|
|
|
Libc::with_libc([&] () { static Main main(env); });
|
|
|
|
}
|