1/*
2 * Copyright 2012-2013 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Paweł Dziepak, pdziepak@quarnos.org
7 */
8#ifndef RPCCALLBACKSERVER_H
9#define RPCCALLBACKSERVER_H
10
11
12#include <util/AutoLock.h>
13
14#include "Connection.h"
15
16
17namespace RPC {
18
19class Callback;
20class Server;
21
22struct ConnectionEntry {
23	Connection*			fConnection;
24	thread_id			fThread;
25
26	ConnectionEntry*	fNext;
27	ConnectionEntry*	fPrev;
28};
29
30union CallbackSlot {
31	Callback*	fCallback;
32	int32		fNext;
33};
34
35class CallbackServer {
36public:
37							CallbackServer(int networkFamily);
38							~CallbackServer();
39
40	static	CallbackServer*	Get(Server* server);
41	static	void			ShutdownAll();
42
43			status_t		RegisterCallback(Callback* callback);
44			status_t		UnregisterCallback(Callback* callback);
45
46	inline	PeerAddress		LocalID();
47
48protected:
49			status_t		StartServer();
50			status_t		StopServer();
51
52			status_t		NewConnection(Connection* connection);
53			status_t		ReleaseConnection(ConnectionEntry* entry);
54
55	static	status_t		ListenerThreadLauncher(void* object);
56			status_t		ListenerThread();
57
58	static	status_t		ConnectionThreadLauncher(void* object);
59			status_t		ConnectionThread(ConnectionEntry* entry);
60
61	inline	Callback*		GetCallback(int32 id);
62
63private:
64	static	mutex			fServerCreationLock;
65	static	CallbackServer*	fServers[2];
66
67			mutex			fConnectionLock;
68			ConnectionEntry*	fConnectionList;
69			ConnectionListener*	fListener;
70
71			mutex			fThreadLock;
72			thread_id		fThread;
73			bool			fThreadRunning;
74
75			rw_lock			fArrayLock;
76			CallbackSlot*	fCallbackArray;
77			uint32			fArraySize;
78			int32			fFreeSlot;
79
80			int				fNetworkFamily;
81};
82
83
84inline PeerAddress
85CallbackServer::LocalID()
86{
87	PeerAddress address;
88
89	ASSERT(fListener != NULL);
90
91	memset(&address, 0, sizeof(address));
92	fListener->GetLocalAddress(&address);
93	return address;
94}
95
96
97inline Callback*
98CallbackServer::GetCallback(int32 id)
99{
100	ReadLocker _(fArrayLock);
101	if (id >= 0 && static_cast<uint32>(id) < fArraySize)
102		return fCallbackArray[id].fCallback;
103	return NULL;
104}
105
106
107}		// namespace RPC
108
109#endif	// RPCCALLBACKSERVER_H
110
111