Hello Alexander,
I'm writing a server application which acts as a communicator between it's clients. Each of my sessions needs to know about other active sessions, so what I'd like to know is if there is a way to access the session object pool directly, or should I maintain my own list of running sessions?
In cases like this, we use the maintain a separate data structure. From my experience, the lookup of other sessions is mostly concerned about a certain property of the session object - not the session object as a whole. So it often make sense to give this property a separate name in the form of a type. For an example, you may take a look at the new TCP terminal server that comes with the Genode version 11.11. You can find it at:
gems/src/server/tcp_terminal/main.cc
In this server, each session corresponds to a potentially open socket. For this particular property (a socket that is open), we defined a separate interface ('Open_socket'), which is inherited by the 'Session_component'. At session-creation time, the 'Open_socket'-property gets constructed. In the constructor, its adds itself to the global 'open_socket_pool', which can then be used to query open sockets.
Of course, we could have used a plain list of sessions but the way the TCP terminal is implemented makes it more obvious which part of the session (only the 'Open_socket interface') is exposed to others.
I hope not to confuse you with this example. In short, I recommend you to use a separate data structure.
Also, a question about "doing it the right way". I transfer data chunks (not more than several Kbytes) to/from clients using RPC calls (initiated by clients), and I use Signal_transmitter objects to notify clients about data & other stuff. Is that normal? ;)
Great that you are asking! There is no universal answer to this question though. It depends on the rate and expected throughput of communication and the desired simplicity of your implementation. To give some examples:
* At core, we want to keep things as simple as possible. Hence, the LOG service uses a plain synchronous RPC interface for transmitting LOG output ('Log_session::write').
* For use cases where we expect a lot of traffic, the overhead of chopping the payload in tiny messages is unfortunate. For this reason, the higher-level 'Terminal::Session' interface is designed to use a combination of a shared-memory buffer and signaling. Client and server share a dataspace that is allocated at the server-side when the session is created. The server does newer change the content of the dataspace except when explicitly asked by the client. If a client wants to output data, it writes its data to the dataspace and then informs the server to consume it via a synchronous RPC call. While the RPC call is in flight, the server copies-out the data and consumes it. Reading data works similar. The client explicitly asks the server to copy new data to the dataspace by issuing an RPC call. So the payload gets transferred via shared memory but client and server work synchronous.
I think, your example resembles this case, right?
* For bulk data, it is often desired to decouple client and server as much as possible. For example, a NIC driver may receive network packets at a high rate, or a music player wants to stream a bulk of audio samples to a audio mixer. In such cases, issuing an RPC call per data packet is a bad idea because each packet would involve multiple context switches. For this reason Genode's interfaces for networking (nic_session), block devices (block_session), audio output (audio_out_session) make use of the packet-stream API. This API is based on shared memory and a data-flow protocol that uses signaling only. In contrast to the terminal session mentioned above, both client and server access the dataspace at the same time, but different portions of it. The pointers to the packet-stream API are:
os/include/os/packet_stream.h - general API os/include/packet_stream_rx/ - for a server that receives data os/include/packet_stream_tx/ - for a server that transmits data
The NIC session is both, a receiver and transmitter. So it is a good example to take as reference of using this API:
os/include/nic_session/
Hopefully, this little overview is of help. Please do not hesitate to dig further. .-)
Cheers Norman