2018-06-12 11:18:30 +02:00
|
|
|
/*
|
|
|
|
* \brief Utilities for handling the 'session_requests' ROM
|
|
|
|
* \author Emery Hemingway
|
|
|
|
* \date 2018-04-08
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2018 Genode Labs GmbH
|
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __SESSION_REQUESTS_H_
|
|
|
|
#define __SESSION_REQUESTS_H_
|
|
|
|
|
|
|
|
#include <base/attached_rom_dataspace.h>
|
|
|
|
#include <base/session_state.h>
|
|
|
|
#include <base/component.h>
|
|
|
|
|
|
|
|
namespace Genode {
|
|
|
|
struct Session_request_handler;
|
|
|
|
class Session_requests_rom;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct Genode::Session_request_handler : Interface
|
|
|
|
{
|
|
|
|
virtual void handle_session_create(Session_state::Name const &,
|
|
|
|
Parent::Server::Id,
|
|
|
|
Session_state::Args const &) = 0;
|
|
|
|
virtual void handle_session_upgrade(Parent::Server::Id,
|
|
|
|
Session_state::Args const &) { }
|
|
|
|
virtual void handle_session_close(Parent::Server::Id) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-07-12 17:49:56 +02:00
|
|
|
class Genode::Session_requests_rom : public Signal_handler<Session_requests_rom>
|
2018-06-12 11:18:30 +02:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
Parent &_parent;
|
|
|
|
Session_request_handler &_requests_handler;
|
|
|
|
|
|
|
|
Attached_rom_dataspace _parent_rom;
|
|
|
|
|
2018-07-12 17:49:56 +02:00
|
|
|
void _process()
|
2018-06-12 11:18:30 +02:00
|
|
|
{
|
|
|
|
_parent_rom.update();
|
|
|
|
Xml_node requests = _parent_rom.xml();
|
|
|
|
|
|
|
|
auto const create_fn = [&] (Xml_node request)
|
|
|
|
{
|
|
|
|
Parent::Server::Id const id {
|
|
|
|
request.attribute_value("id", ~0UL) };
|
|
|
|
|
|
|
|
typedef Session_state::Name Name;
|
|
|
|
typedef Session_state::Args Args;
|
2018-07-12 17:49:56 +02:00
|
|
|
|
|
|
|
Name name { };
|
|
|
|
Args args { };
|
|
|
|
|
|
|
|
try {
|
|
|
|
name = request.attribute_value("service", Name());
|
|
|
|
args = request.sub_node("args").decoded_content<Args>();
|
|
|
|
} catch (...) {
|
|
|
|
Genode::error("failed to parse request ", request);
|
|
|
|
return;
|
|
|
|
}
|
2018-06-12 11:18:30 +02:00
|
|
|
|
|
|
|
try { _requests_handler.handle_session_create(name, id, args); }
|
|
|
|
catch (Service_denied) {
|
|
|
|
_parent.session_response(id, Parent::SERVICE_DENIED); }
|
|
|
|
catch (Insufficient_ram_quota) {
|
|
|
|
_parent.session_response(id, Parent::INSUFFICIENT_RAM_QUOTA); }
|
|
|
|
catch (Insufficient_cap_quota) {
|
|
|
|
_parent.session_response(id, Parent::INSUFFICIENT_CAP_QUOTA); }
|
|
|
|
catch (...) {
|
|
|
|
error("unhandled exception while creating session");
|
|
|
|
_parent.session_response(id, Parent::SERVICE_DENIED);
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
auto const upgrade_fn = [&] (Xml_node request)
|
|
|
|
{
|
|
|
|
Parent::Server::Id const id {
|
|
|
|
request.attribute_value("id", ~0UL) };
|
|
|
|
|
|
|
|
typedef Session_state::Args Args;
|
2018-07-12 17:49:56 +02:00
|
|
|
Args args { };
|
|
|
|
try { args = request.sub_node("args").decoded_content<Args>(); }
|
|
|
|
catch (...) {
|
|
|
|
Genode::error("failed to parse request ", request);
|
|
|
|
return;
|
|
|
|
}
|
2018-06-12 11:18:30 +02:00
|
|
|
|
|
|
|
_requests_handler.handle_session_upgrade(id, args);
|
|
|
|
};
|
|
|
|
|
|
|
|
auto const close_fn = [&] (Xml_node request)
|
|
|
|
{
|
|
|
|
Parent::Server::Id const id {
|
|
|
|
request.attribute_value("id", ~0UL) };
|
|
|
|
_requests_handler.handle_session_close(id);
|
|
|
|
};
|
|
|
|
|
|
|
|
/* close sessions to free resources */
|
|
|
|
requests.for_each_sub_node("close", close_fn);
|
|
|
|
|
|
|
|
/* service existing sessions */
|
|
|
|
requests.for_each_sub_node("upgrade", upgrade_fn);
|
|
|
|
|
|
|
|
/* create new sessions */
|
|
|
|
requests.for_each_sub_node("create", create_fn);
|
|
|
|
}
|
2018-07-12 17:49:56 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Session_requests_rom(Genode::Env &env,
|
|
|
|
Session_request_handler &requests_handler)
|
|
|
|
: Signal_handler<Session_requests_rom>(env.ep(), *this, &Session_requests_rom::_process),
|
|
|
|
_parent(env.parent()),
|
|
|
|
_requests_handler(requests_handler),
|
|
|
|
_parent_rom(env, "session_requests")
|
|
|
|
{
|
|
|
|
_parent_rom.sigh(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Post a signal to this requests handler
|
|
|
|
*/
|
|
|
|
void schedule() {
|
|
|
|
Signal_transmitter(*this).submit(); }
|
2018-06-12 11:18:30 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|