// vi:set ft=cpp: -*- Mode: C++ -*- /** * \file * \brief IPC server loop */ /* * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>, * Alexander Warg <warg@os.inf.tu-dresden.de>, * Torsten Frenzel <frenzel@os.inf.tu-dresden.de> * economic rights: Technische Universität Dresden (Germany) * * This file is part of TUD:OS and distributed under the terms of the * GNU General Public License 2. * Please see the COPYING-GPL-2 file for details. * * As a special exception, you may use this file as part of a free software * library without restriction. Specifically, if other files instantiate * templates or use macros or inline functions from this file, or you compile * this file and link it with other files to produce an executable, this * file does not by itself cause the resulting executable to be covered by * the GNU General Public License. This exception does not however * invalidate any other reasons why the executable file might be covered by * the GNU General Public License. */ #pragma once #include <l4/sys/capability> #include <l4/sys/typeinfo_svr> #include <l4/sys/err.h> #include <l4/cxx/ipc_stream> #include <l4/sys/cxx/ipc_epiface> #include <l4/sys/cxx/ipc_server_loop> #include <l4/cxx/type_traits> #include <l4/cxx/exceptions> namespace L4 { /** * \ingroup cxx_ipc_server * \brief Abstract server object to be used with L4::Server and * L4::Basic_registry. * \note Usually L4::Server_object_t is used as a base class when writing * server objects. * * This server object provides an abstract interface that is used by the * L4::Registry_dispatcher model. You can derive subclasses from this * interface and implement application specific server objects. */ class Server_object : public Epiface { public: /** * \brief The abstract handler for client requests to the object. * \param rights The rights bits in the invoked capability. * \param ios The Ipc::Iostream for reading the request and writing the reply. * \retval -L4_ENOREPLY Instructs the server loop to not send a reply. * \retval <0 Error, reply with error code. * \retval >=0 Success, reply with return value. * * This function must be implemented by application specific server * objects. The implementation must unmarshall data from the stream (`ios`) * and create a reply by marshalling to the stream (`ios`). For details * about the IPC stream see [IPC stream operators](\ref ipc_stream). * * \note You need to extract the complete message from the \a ios stream * before inserting any reply data or before doing any function call * that may use the UTCB. Otherwise, the incoming message may get lost. */ virtual int dispatch(unsigned long rights, Ipc::Iostream &ios) = 0; l4_msgtag_t dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb) { L4::Ipc::Iostream ios(utcb); ios.tag() = tag; int r = dispatch(rights, ios); return ios.prepare_ipc(r); } Cap<Kobject> obj_cap() const { return cap_cast<Kobject>(Epiface::obj_cap()); } }; /** * \ingroup cxx_ipc_server * Base class (template) for server implementing server objects. * \tparam IFACE The IPC interface class that defines the interface that shall * be implemented. * \tparam BASE The server object base class (usually L4::Server_object). */ template<typename IFACE, typename BASE = L4::Server_object> struct Server_object_t : BASE { /// Data type of the IPC interface definition typedef IFACE Interface; /// \return the server-side buffer demand based in \a IFACE. typename BASE::Demand get_buffer_demand() const { return typename L4::Kobject_typeid<IFACE>::Demand(); } /** * Implementation of the meta protocol based on \a IFACE. * \param ios The IO stream used for receiving the message. * * This function can be used to handle incoming #L4_PROTO_META protcol * requests. The implementation uses the L4::Type_info of \a IFACE * to handle the requests. Call this function in the implementation of * Server_object::dispatch() when the received message tag has protocol * #L4_PROTO_META (L4::Meta::Protocol). */ int dispatch_meta_request(L4::Ipc::Iostream &ios) { return L4::Util::handle_meta_request<IFACE>(ios); } /** * Implementation of protocol-based dispatch for this server object. * \param self The this pointer for the object (inherits from * Server_object_t). * \param rights The rights from the received IPC (forwarded to p_dispatch()). * \param ios The message stream for the incoming and the reply message. * * Server objects may call this function from their dispatch() function. * This function reads the protocol ID from the message tag and uses the * p_dispatch code to dispatch to overloaded p_dispatch functions of self. */ template<typename THIS> static int proto_dispatch(THIS *self, l4_umword_t rights, L4::Ipc::Iostream &ios) { l4_msgtag_t t; ios >> t; return Kobject_typeid<IFACE>::proto_dispatch(self, t.label(), rights, ios); } }; /** * \ingroup cxx_ipc_server * Helper class to implement p_dispatch based server objects. * \tparam Derived The data type of your server object class. * \tparam IFACE The data type providing the interface definition * for the object. * \tparam BASE Optional data-type of the base server object (usually * L4::Server_object) * \implements L4::Server_object * * This class implements the standard dispatch() function of L4::Server_object * and forwards incoming messages to a set of overloaded p_dispatch() functions. * There must be a p_dispatch() function in Derived for each interface provided * by IFACE with the signature * \code int p_dispatch(Iface *, unsigned rights, L4::Ipc::Iostream &) \endcode * that is called for messages with protocol == Iface::Protocol. * * Example signature for L4Re::Dataspace is: * \code int p_dispatch(L4Re::Dataspace *, unsigned, L4::Ipc::Iostream &) \endcode */ template<typename Derived, typename IFACE, typename BASE = L4::Server_object> struct Server_object_x : Server_object_t<IFACE, BASE> { /// Implementation forwarding to p_dispatch(). int dispatch(l4_umword_t r, L4::Ipc::Iostream &ios) { return Server_object_t<IFACE, BASE>::proto_dispatch(static_cast<Derived *>(this), r, ios); } }; /** * \ingroup cxx_ipc_server * Server object base class for handling IRQ messages. * * This server object base class implements the empty interface * (L4::Kobject). The implementation of Server_object::dispatch() must * return -#L4_ENOREPLY, because IRQ messages do not handle replies. */ struct Irq_handler_object : Server_object_t<Kobject> {}; }