1 /* 2 * Copyright 2012 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 RPCSERVER_H 9 #define RPCSERVER_H 10 11 12 #include <condition_variable.h> 13 #include <lock.h> 14 15 #include "Connection.h" 16 #include "RPCCall.h" 17 #include "RPCCallback.h" 18 #include "RPCReply.h" 19 20 21 namespace RPC { 22 23 struct Request { 24 uint32 fXID; 25 ConditionVariable fEvent; 26 27 bool fDone; 28 Reply** fReply; 29 status_t fError; 30 31 Request* fNext; 32 }; 33 34 class RequestManager { 35 public: 36 RequestManager(); 37 ~RequestManager(); 38 39 void AddRequest(Request* request); 40 Request* FindRequest(uint32 xid); 41 42 private: 43 mutex fLock; 44 45 // Neither SinglyLinkedList nor DoublyLinkedList is what we want 46 // here. And DoublyLinkedQueue is not even a queue. 47 Request* fQueueHead; 48 Request* fQueueTail; 49 50 }; 51 52 class ProgramData { 53 public: 54 virtual status_t ProcessCallback(CallbackRequest* request, 55 Connection* connection) = 0; 56 57 virtual ~ProgramData() { } 58 }; 59 60 class Server { 61 public: 62 Server(Connection* connection, 63 PeerAddress* address); 64 virtual ~Server(); 65 66 status_t SendCallAsync(Call* call, Reply** reply, 67 Request** request); 68 status_t ResendCallAsync(Call* call, 69 Request* request); 70 71 inline status_t WaitCall(Request* request, 72 bigtime_t time); 73 inline status_t CancelCall(Request* request); 74 status_t WakeCall(Request* request); 75 76 status_t Repair(); 77 78 inline const PeerAddress& ID() const; 79 inline PeerAddress LocalID() const; 80 81 inline ProgramData* PrivateData(); 82 inline void SetPrivateData(ProgramData* privateData); 83 84 Callback* GetCallback(); 85 86 private: 87 inline uint32 _GetXID(); 88 89 status_t _StartListening(); 90 91 status_t _Listener(); 92 static status_t _ListenerThreadStart(void* object); 93 94 thread_id fThread; 95 bool fThreadCancel; 96 status_t fThreadError; 97 98 RequestManager fRequests; 99 Connection* fConnection; 100 const PeerAddress* fAddress; 101 102 ProgramData* fPrivateData; 103 104 mutex fCallbackLock; 105 Callback* fCallback; 106 107 uint32 fRepairCount; 108 mutex fRepairLock; 109 110 int32 fXID; 111 }; 112 113 114 inline status_t 115 Server::WaitCall(Request* request, bigtime_t time) 116 { 117 if (request->fDone) 118 return B_OK; 119 return request->fEvent.Wait(B_RELATIVE_TIMEOUT, time); 120 } 121 122 123 inline status_t 124 Server::CancelCall(Request* request) 125 { 126 fRequests.FindRequest(request->fXID); 127 return B_OK; 128 } 129 130 131 inline const PeerAddress& 132 Server::ID() const 133 { 134 return *fAddress; 135 } 136 137 138 inline PeerAddress 139 Server::LocalID() const 140 { 141 PeerAddress addr; 142 memset(&addr, 0, sizeof(addr)); 143 fConnection->GetLocalAddress(&addr); 144 return addr; 145 } 146 147 148 inline ProgramData* 149 Server::PrivateData() 150 { 151 return fPrivateData; 152 } 153 154 155 inline void 156 Server::SetPrivateData(ProgramData* privateData) 157 { 158 delete fPrivateData; 159 fPrivateData = privateData; 160 } 161 162 163 struct ServerNode { 164 PeerAddress fID; 165 Server* fServer; 166 int fRefCount; 167 168 ServerNode* fLeft; 169 ServerNode* fRight; 170 }; 171 172 class ServerManager { 173 public: 174 ServerManager(); 175 ~ServerManager(); 176 177 status_t Acquire(Server** _server, AddressResolver* resolver, 178 ProgramData* (*createPrivateData)(Server*)); 179 void Release(Server* server); 180 181 private: 182 status_t _Acquire(Server** _server, const PeerAddress& address, 183 ProgramData* (*createPrivateData)(Server*)); 184 185 ServerNode* _Find(const PeerAddress& address); 186 void _Delete(ServerNode* node); 187 ServerNode* _Insert(ServerNode* node); 188 189 ServerNode* fRoot; 190 mutex fLock; 191 }; 192 193 } // namespace RPC 194 195 196 #endif // RPCSERVER_H 197 198