1b35311f1SPawel Dziepak/*
2b35311f1SPawel Dziepak * Copyright 2012 Haiku, Inc. All rights reserved.
3b35311f1SPawel Dziepak * Distributed under the terms of the MIT License.
4b35311f1SPawel Dziepak *
5b35311f1SPawel Dziepak * Authors:
6b35311f1SPawel Dziepak *		Pawe�� Dziepak, pdziepak@quarnos.org
7b35311f1SPawel Dziepak */
8b35311f1SPawel Dziepak#ifndef RPCSERVER_H
9b35311f1SPawel Dziepak#define RPCSERVER_H
10b35311f1SPawel Dziepak
11b35311f1SPawel Dziepak
12b35311f1SPawel Dziepak#include <condition_variable.h>
13b35311f1SPawel Dziepak#include <lock.h>
14b35311f1SPawel Dziepak
15b35311f1SPawel Dziepak#include "Connection.h"
16b35311f1SPawel Dziepak#include "RPCCall.h"
1794c47dc6SPawel Dziepak#include "RPCCallback.h"
18b35311f1SPawel Dziepak#include "RPCReply.h"
19b35311f1SPawel Dziepak
20b35311f1SPawel Dziepak
21b35311f1SPawel Dziepaknamespace RPC {
22b35311f1SPawel Dziepak
23b35311f1SPawel Dziepakstruct Request {
24b35311f1SPawel Dziepak	uint32				fXID;
25b35311f1SPawel Dziepak	ConditionVariable	fEvent;
26be4c74eaSPawel Dziepak
270792abe0SPawel Dziepak	bool				fDone;
28b35311f1SPawel Dziepak	Reply**				fReply;
29be4c74eaSPawel Dziepak	status_t			fError;
30b35311f1SPawel Dziepak
31b35311f1SPawel Dziepak	Request*			fNext;
32b35311f1SPawel Dziepak};
33b35311f1SPawel Dziepak
34b35311f1SPawel Dziepakclass RequestManager {
35b35311f1SPawel Dziepakpublic:
36b35311f1SPawel Dziepak						RequestManager();
37b35311f1SPawel Dziepak						~RequestManager();
38b35311f1SPawel Dziepak
39367b07d5SPawel Dziepak			void		AddRequest(Request* request);
40b35311f1SPawel Dziepak			Request*	FindRequest(uint32 xid);
41b35311f1SPawel Dziepak
42b35311f1SPawel Dziepakprivate:
43b35311f1SPawel Dziepak			mutex		fLock;
44a4caa431SPawel Dziepak
45a4caa431SPawel Dziepak			// Neither SinglyLinkedList nor DoublyLinkedList is what we want
46a4caa431SPawel Dziepak			// here. And DoublyLinkedQueue is not even a queue.
47b35311f1SPawel Dziepak			Request*	fQueueHead;
48b35311f1SPawel Dziepak			Request*	fQueueTail;
49b35311f1SPawel Dziepak
50b35311f1SPawel Dziepak};
51b35311f1SPawel Dziepak
526ee3ed0fSPawel Dziepakclass ProgramData {
536ee3ed0fSPawel Dziepakpublic:
544a153753SPawel Dziepak	virtual	status_t	ProcessCallback(CallbackRequest* request,
554a153753SPawel Dziepak							Connection* connection) = 0;
564a153753SPawel Dziepak
576ee3ed0fSPawel Dziepak	virtual				~ProgramData() { }
586ee3ed0fSPawel Dziepak};
596ee3ed0fSPawel Dziepak
60b35311f1SPawel Dziepakclass Server {
61b35311f1SPawel Dziepakpublic:
62367b07d5SPawel Dziepak									Server(Connection* connection,
63a37a2288SPawel Dziepak										PeerAddress* address);
645cdf02dbSPawel Dziepak	virtual							~Server();
65b35311f1SPawel Dziepak
663ce57b34SPawel Dziepak			status_t				SendCallAsync(Call* call, Reply** reply,
673ce57b34SPawel Dziepak										Request** request);
68367b07d5SPawel Dziepak			status_t				ResendCallAsync(Call* call,
69367b07d5SPawel Dziepak										Request* request);
70367b07d5SPawel Dziepak
713ce57b34SPawel Dziepak	inline	status_t				WaitCall(Request* request,
72ad1a84afSPawel Dziepak										bigtime_t time);
733ce57b34SPawel Dziepak	inline	status_t				CancelCall(Request* request);
74be4c74eaSPawel Dziepak			status_t				WakeCall(Request* request);
753ce57b34SPawel Dziepak
765cdf02dbSPawel Dziepak			status_t				Repair();
775cdf02dbSPawel Dziepak
78a4caa431SPawel Dziepak	inline	const PeerAddress&		ID() const;
79a4caa431SPawel Dziepak	inline	PeerAddress				LocalID() const;
80b35311f1SPawel Dziepak
816ee3ed0fSPawel Dziepak	inline	ProgramData*			PrivateData();
82367b07d5SPawel Dziepak	inline	void					SetPrivateData(ProgramData* privateData);
836ee3ed0fSPawel Dziepak
8494c47dc6SPawel Dziepak			Callback*				GetCallback();
8594c47dc6SPawel Dziepak
86b35311f1SPawel Dziepakprivate:
875cdf02dbSPawel Dziepak	inline	uint32					_GetXID();
885cdf02dbSPawel Dziepak
895cdf02dbSPawel Dziepak			status_t				_StartListening();
905cdf02dbSPawel Dziepak
915cdf02dbSPawel Dziepak			status_t				_Listener();
92367b07d5SPawel Dziepak	static	status_t				_ListenerThreadStart(void* object);
93b35311f1SPawel Dziepak
945cdf02dbSPawel Dziepak			thread_id				fThread;
955cdf02dbSPawel Dziepak			bool					fThreadCancel;
965cdf02dbSPawel Dziepak			status_t				fThreadError;
97b35311f1SPawel Dziepak
985cdf02dbSPawel Dziepak			RequestManager			fRequests;
995cdf02dbSPawel Dziepak			Connection*				fConnection;
100a4caa431SPawel Dziepak			const PeerAddress*		fAddress;
101b35311f1SPawel Dziepak
1026ee3ed0fSPawel Dziepak			ProgramData*			fPrivateData;
1036ee3ed0fSPawel Dziepak
10494c47dc6SPawel Dziepak			mutex					fCallbackLock;
10594c47dc6SPawel Dziepak			Callback*				fCallback;
10694c47dc6SPawel Dziepak
10747e68f1cSPawel Dziepak			uint32					fRepairCount;
10847e68f1cSPawel Dziepak			mutex					fRepairLock;
10947e68f1cSPawel Dziepak
11073ad2473SPawel Dziepak			int32					fXID;
111b35311f1SPawel Dziepak};
112b35311f1SPawel Dziepak
1133ce57b34SPawel Dziepak
1143ce57b34SPawel Dziepakinline status_t
1153ce57b34SPawel DziepakServer::WaitCall(Request* request, bigtime_t time)
1163ce57b34SPawel Dziepak{
1170792abe0SPawel Dziepak	if (request->fDone)
1180792abe0SPawel Dziepak		return B_OK;
1193ce57b34SPawel Dziepak	return request->fEvent.Wait(B_RELATIVE_TIMEOUT, time);
1203ce57b34SPawel Dziepak}
1213ce57b34SPawel Dziepak
1223ce57b34SPawel Dziepak
1233ce57b34SPawel Dziepakinline status_t
1243ce57b34SPawel DziepakServer::CancelCall(Request* request)
1253ce57b34SPawel Dziepak{
1263ce57b34SPawel Dziepak	fRequests.FindRequest(request->fXID);
1273ce57b34SPawel Dziepak	return B_OK;
1283ce57b34SPawel Dziepak}
1293ce57b34SPawel Dziepak
1303ce57b34SPawel Dziepak
131a37a2288SPawel Dziepakinline const PeerAddress&
1325cdf02dbSPawel DziepakServer::ID() const
1335cdf02dbSPawel Dziepak{
1345cdf02dbSPawel Dziepak	return *fAddress;
1355cdf02dbSPawel Dziepak}
1365cdf02dbSPawel Dziepak
1372a292557SPawel Dziepak
138a37a2288SPawel Dziepakinline PeerAddress
1392a292557SPawel DziepakServer::LocalID() const
1402a292557SPawel Dziepak{
141a37a2288SPawel Dziepak	PeerAddress addr;
1422a292557SPawel Dziepak	memset(&addr, 0, sizeof(addr));
143367b07d5SPawel Dziepak	fConnection->GetLocalAddress(&addr);
1442a292557SPawel Dziepak	return addr;
1452a292557SPawel Dziepak}
1462a292557SPawel Dziepak
1472a292557SPawel Dziepak
1486ee3ed0fSPawel Dziepakinline ProgramData*
1496ee3ed0fSPawel DziepakServer::PrivateData()
1506ee3ed0fSPawel Dziepak{
1516ee3ed0fSPawel Dziepak	return fPrivateData;
1526ee3ed0fSPawel Dziepak}
1536ee3ed0fSPawel Dziepak
1546ee3ed0fSPawel Dziepak
1556ee3ed0fSPawel Dziepakinline void
156367b07d5SPawel DziepakServer::SetPrivateData(ProgramData* privateData)
1576ee3ed0fSPawel Dziepak{
1586ee3ed0fSPawel Dziepak	delete fPrivateData;
159367b07d5SPawel Dziepak	fPrivateData = privateData;
1606ee3ed0fSPawel Dziepak}
1616ee3ed0fSPawel Dziepak
1626ee3ed0fSPawel Dziepak
163b35311f1SPawel Dziepakstruct ServerNode {
164a37a2288SPawel Dziepak	PeerAddress	fID;
1655cdf02dbSPawel Dziepak	Server*			fServer;
1665cdf02dbSPawel Dziepak	int				fRefCount;
167b35311f1SPawel Dziepak
1685cdf02dbSPawel Dziepak	ServerNode*		fLeft;
1695cdf02dbSPawel Dziepak	ServerNode* 	fRight;
170b35311f1SPawel Dziepak};
171b35311f1SPawel Dziepak
172b35311f1SPawel Dziepakclass ServerManager {
173b35311f1SPawel Dziepakpublic:
174b35311f1SPawel Dziepak						ServerManager();
175b35311f1SPawel Dziepak						~ServerManager();
176b35311f1SPawel Dziepak
177a0d5a922SPawel Dziepak			status_t	Acquire(Server** _server, AddressResolver* resolver,
178367b07d5SPawel Dziepak								ProgramData* (*createPrivateData)(Server*));
179367b07d5SPawel Dziepak			void		Release(Server* server);
180b35311f1SPawel Dziepak
181b35311f1SPawel Dziepakprivate:
182a0d5a922SPawel Dziepak			status_t	_Acquire(Server** _server, const PeerAddress& address,
183a0d5a922SPawel Dziepak								ProgramData* (*createPrivateData)(Server*));
184b35311f1SPawel Dziepak
185a37a2288SPawel Dziepak			ServerNode*	_Find(const PeerAddress& address);
186b35311f1SPawel Dziepak			void		_Delete(ServerNode* node);
187b35311f1SPawel Dziepak			ServerNode*	_Insert(ServerNode* node);
188b35311f1SPawel Dziepak
189b35311f1SPawel Dziepak			ServerNode*	fRoot;
190b35311f1SPawel Dziepak			mutex		fLock;
191b35311f1SPawel Dziepak};
192b35311f1SPawel Dziepak
193b35311f1SPawel Dziepak}		// namespace RPC
194b35311f1SPawel Dziepak
195b35311f1SPawel Dziepak
196b35311f1SPawel Dziepak#endif	// RPCSERVER_H
197b35311f1SPawel Dziepak
198