1 // ServerManager.cpp
2
3 #include "ServerManager.h"
4
5 #include <errno.h>
6 #include <unistd.h>
7
8 #ifdef HAIKU_TARGET_PLATFORM_BEOS
9 # include <socket.h>
10 #else
11 # include <netinet/in.h>
12 # include <sys/socket.h>
13 #endif
14
15 #include <AutoDeleter.h>
16 #include <AutoLocker.h>
17 #include <ByteOrder.h>
18 #include <HashMap.h>
19
20 #include "Compatibility.h"
21 #include "DebugSupport.h"
22 #include "ExtendedServerInfo.h"
23 #include "InsecureChannel.h"
24 #include "NetAddress.h"
25 #include "NetFSDefs.h"
26 #include "RequestChannel.h"
27 #include "Requests.h"
28 #include "TaskManager.h"
29 #include "Utils.h"
30
31 // server info states
32 enum {
33 STATE_ADDING,
34 STATE_REMOVING,
35 STATE_UPDATING,
36 STATE_READY,
37 STATE_OBSOLETE
38 };
39
40
41 // ServerInfoMap
42 struct ServerManager::ServerInfoMap : HashMap<NetAddress, ExtendedServerInfo*> {
43 };
44
45 // ServerInfoTask
46 class ServerManager::ServerInfoTask : public Task {
47 public:
ServerInfoTask(ServerManager * manager,ExtendedServerInfo * oldServerInfo,ExtendedServerInfo * serverInfo)48 ServerInfoTask(ServerManager* manager, ExtendedServerInfo* oldServerInfo,
49 ExtendedServerInfo* serverInfo)
50 : Task("server info task"),
51 fServerManager(manager),
52 fOldServerInfo(oldServerInfo),
53 fServerInfo(serverInfo),
54 fFD(-1),
55 fSuccess(false)
56 {
57 if (fServerInfo)
58 fServerInfo->AcquireReference();
59 }
60
~ServerInfoTask()61 virtual ~ServerInfoTask()
62 {
63 Stop();
64 if (!fSuccess) {
65 if (fOldServerInfo)
66 fServerManager->_UpdatingServerFailed(fServerInfo);
67 else
68 fServerManager->_AddingServerFailed(fServerInfo);
69 }
70 if (fServerInfo)
71 fServerInfo->ReleaseReference();
72 }
73
Init()74 status_t Init()
75 {
76 // create a socket
77 fFD = socket(AF_INET, SOCK_STREAM, 0);
78 if (fFD < 0) {
79 ERROR("ServerManager::ServerInfoTask: ERROR: Failed to create "
80 "socket: %s\n", strerror(errno));
81 return errno;
82 }
83 return B_OK;
84 }
85
Execute()86 virtual status_t Execute()
87 {
88 // connect to the server info port
89 sockaddr_in addr = fServerInfo->GetAddress().GetAddress();
90 addr.sin_port = htons(kDefaultServerInfoPort);
91 if (connect(fFD, (sockaddr*)&addr, sizeof(addr)) < 0) {
92 ERROR("ServerManager::ServerInfoTask: ERROR: Failed to connect "
93 "to server info port: %s\n", strerror(errno));
94 return errno;
95 }
96
97 // create a channel
98 InsecureChannel channel(fFD);
99
100 // receive a request
101 RequestChannel requestChannel(&channel);
102 Request* _request;
103 status_t error = requestChannel.ReceiveRequest(&_request);
104 if (error != B_OK) {
105 ERROR("ServerManager::ServerInfoTask: ERROR: Failed to receive "
106 "server info request: %s\n", strerror(errno));
107 return error;
108 }
109 ObjectDeleter<Request> requestDeleter(_request);
110 ServerInfoRequest* request = dynamic_cast<ServerInfoRequest*>(_request);
111 if (!request) {
112 ERROR("ServerManager::ServerInfoTask: ERROR: Received request "
113 "is not a server info request.\n");
114 return B_BAD_DATA;
115 }
116
117 // get the info
118 error = fServerInfo->SetTo(&request->serverInfo);
119 if (error != B_OK)
120 return error;
121
122 // notify the manager
123 if (fOldServerInfo)
124 fServerManager->_ServerUpdated(fServerInfo);
125 else
126 fServerManager->_ServerAdded(fServerInfo);
127
128 fSuccess = true;
129 return B_OK;
130 }
131
Stop()132 virtual void Stop()
133 {
134 safe_closesocket(fFD);
135 }
136
137 private:
138 ServerManager* fServerManager;
139 ExtendedServerInfo* fOldServerInfo;
140 ExtendedServerInfo* fServerInfo;
141 int32 fFD;
142 bool fUpdate;
143 bool fSuccess;
144 };
145
146
147 // #pragma mark -
148
149 // constructor
ServerManager(Listener * listener)150 ServerManager::ServerManager(Listener* listener)
151 : fLock("server manager"),
152 fBroadcastListener(-1),
153 fBroadcastListenerSocket(-1),
154 fListener(listener),
155 fTerminating(false)
156 {
157 }
158
159 // destructor
~ServerManager()160 ServerManager::~ServerManager()
161 {
162 Uninit();
163 }
164
165 // Init
166 status_t
Init()167 ServerManager::Init()
168 {
169 // create the server info map
170 fServerInfos = new(std::nothrow) ServerInfoMap();
171 if (!fServerInfos)
172 RETURN_ERROR(B_NO_MEMORY);
173 status_t error = fServerInfos->InitCheck();
174 if (error != B_OK)
175 RETURN_ERROR(error);
176
177 // init the broadcast listener
178 error = _InitBroadcastListener();
179 if (error != B_OK)
180 RETURN_ERROR(error);
181
182 return B_OK;
183 }
184
185 // Uninit
186 void
Uninit()187 ServerManager::Uninit()
188 {
189 // stop the broadcast listener
190 fTerminating = true;
191 _TerminateBroadcastListener();
192
193 // remove all server infos
194 AutoLocker<Locker> _(fLock);
195 for (ServerInfoMap::Iterator it = fServerInfos->GetIterator();
196 it.HasNext();) {
197 ExtendedServerInfo* serverInfo = it.Next().value;
198 serverInfo->ReleaseReference();
199 }
200 fServerInfos->Clear();
201 }
202
203 // Run
204 void
Run()205 ServerManager::Run()
206 {
207 // start the broadcast listener
208 resume_thread(fBroadcastListener);
209 }
210
211 // GetServerInfo
212 ExtendedServerInfo*
GetServerInfo(const NetAddress & address)213 ServerManager::GetServerInfo(const NetAddress& address)
214 {
215 AutoLocker<Locker> _(fLock);
216 ExtendedServerInfo* serverInfo = fServerInfos->Get(address);
217 if (!serverInfo
218 || (serverInfo->GetState() != STATE_READY
219 && serverInfo->GetState() != STATE_UPDATING)) {
220 return NULL;
221 }
222 serverInfo->AcquireReference();
223 return serverInfo;
224 }
225
226 // AddServer
227 status_t
AddServer(const NetAddress & address)228 ServerManager::AddServer(const NetAddress& address)
229 {
230 // check, if the server is already known
231 AutoLocker<Locker> locker(fLock);
232 ExtendedServerInfo* oldInfo = fServerInfos->Get(address);
233 if (oldInfo)
234 return B_OK;
235
236 // create a new server info and add it
237 ExtendedServerInfo* serverInfo
238 = new(std::nothrow) ExtendedServerInfo(address);
239 if (!serverInfo)
240 return B_NO_MEMORY;
241 serverInfo->SetState(STATE_ADDING);
242 BReference<ExtendedServerInfo> serverInfoReference(serverInfo, true);
243 status_t error = fServerInfos->Put(address, serverInfo);
244 if (error != B_OK)
245 return error;
246 serverInfo->AcquireReference();
247
248 // create and execute the task -- it will do what is necessary
249 ServerInfoTask task(this, NULL, serverInfo);
250 error = task.Init();
251 if (error != B_OK)
252 return error;
253
254 locker.Unlock();
255 return task.Execute();
256 }
257
258 // RemoveServer
259 void
RemoveServer(const NetAddress & address)260 ServerManager::RemoveServer(const NetAddress& address)
261 {
262 // check, if the server is known at all
263 AutoLocker<Locker> locker(fLock);
264 ExtendedServerInfo* serverInfo = fServerInfos->Get(address);
265 if (!serverInfo)
266 return;
267
268 // If its current state is not STATE_READY, then an info thread is currently
269 // trying to add/update it. We mark the info STATE_REMOVING, which will
270 // remove the info as soon as possible.
271 if (serverInfo->GetState() == STATE_READY) {
272 BReference<ExtendedServerInfo> _(serverInfo);
273 _RemoveServer(serverInfo);
274 locker.Unlock();
275 fListener->ServerRemoved(serverInfo);
276 } else
277 serverInfo->SetState(STATE_REMOVING);
278 }
279
280 // _BroadcastListenerEntry
281 int32
_BroadcastListenerEntry(void * data)282 ServerManager::_BroadcastListenerEntry(void* data)
283 {
284 return ((ServerManager*)data)->_BroadcastListener();
285 }
286
287 // _BroadcastListener
288 int32
_BroadcastListener()289 ServerManager::_BroadcastListener()
290 {
291 TaskManager taskManager;
292 while (!fTerminating) {
293 taskManager.RemoveDoneTasks();
294
295 // receive
296 sockaddr_in addr;
297 addr.sin_family = AF_INET;
298 addr.sin_port = htons(kDefaultBroadcastPort);
299 addr.sin_addr.s_addr = INADDR_ANY;
300 socklen_t addrSize = sizeof(addr);
301 BroadcastMessage message;
302 //PRINT(("ServerManager::_BroadcastListener(): recvfrom()...\n"));
303 ssize_t bytesRead = recvfrom(fBroadcastListenerSocket, &message,
304 sizeof(message), 0, (sockaddr*)&addr, &addrSize);
305 if (bytesRead < 0) {
306 PRINT("ServerManager::_BroadcastListener(): recvfrom() "
307 "failed: %s\n", strerror(errno));
308 continue;
309 }
310
311 // check message size, magic, and protocol version
312 if (bytesRead != sizeof(BroadcastMessage)) {
313 PRINT("ServerManager::_BroadcastListener(): received "
314 "%ld bytes, but it should be %lu\n", bytesRead,
315 sizeof(BroadcastMessage));
316 continue;
317 }
318 if (message.magic != B_HOST_TO_BENDIAN_INT32(BROADCAST_MESSAGE_MAGIC)) {
319 PRINT("ServerManager::_BroadcastListener(): message has"
320 " bad magic.\n");
321 continue;
322 }
323 if (message.protocolVersion
324 != (int32)B_HOST_TO_BENDIAN_INT32(NETFS_PROTOCOL_VERSION)) {
325 PRINT("ServerManager::_BroadcastListener(): protocol "
326 "version does not match: %" B_PRId32 " vs. %d.\n",
327 (int32)B_BENDIAN_TO_HOST_INT32(
328 message.protocolVersion),
329 NETFS_PROTOCOL_VERSION);
330 continue;
331 }
332
333 // check, if the server is local
334 NetAddress netAddress(addr);
335 #ifndef ADD_SERVER_LOCALHOST
336 if (netAddress.IsLocal())
337 continue;
338 #endif // ADD_SERVER_LOCALHOST
339
340 AutoLocker<Locker> locker(fLock);
341 ExtendedServerInfo* oldServerInfo = fServerInfos->Get(netAddress);
342
343 // examine the message
344 switch (B_BENDIAN_TO_HOST_INT32(message.message)) {
345 case BROADCAST_MESSAGE_SERVER_TICK:
346 // PRINT(("ServerManager::_BroadcastListener(): "
347 // "BROADCAST_MESSAGE_SERVER_TICK.\n"));
348 if (oldServerInfo)
349 continue;
350 break;
351 case BROADCAST_MESSAGE_SERVER_UPDATE:
352 // PRINT(("ServerManager::_BroadcastListener(): "
353 // "BROADCAST_MESSAGE_SERVER_UPDATE.\n"));
354 break;
355 case BROADCAST_MESSAGE_CLIENT_HELLO:
356 // PRINT(("ServerManager::_BroadcastListener(): "
357 // "BROADCAST_MESSAGE_CLIENT_HELLO. Ignoring.\n"));
358 continue;
359 break;
360 }
361
362 if (oldServerInfo && oldServerInfo->GetState() != STATE_READY)
363 continue;
364
365 // create a new server info and add it
366 ExtendedServerInfo* serverInfo
367 = new(std::nothrow) ExtendedServerInfo(netAddress);
368 if (!serverInfo)
369 return B_NO_MEMORY;
370 serverInfo->SetState(STATE_ADDING);
371 BReference<ExtendedServerInfo> serverInfoReference(serverInfo, true);
372 if (oldServerInfo) {
373 oldServerInfo->SetState(STATE_UPDATING);
374 } else {
375 status_t error = fServerInfos->Put(netAddress, serverInfo);
376 if (error != B_OK)
377 continue;
378 serverInfo->AcquireReference();
379 }
380
381 // create a task to add/update the server info
382 ServerInfoTask* task = new(std::nothrow) ServerInfoTask(this, oldServerInfo,
383 serverInfo);
384 if (!task) {
385 if (oldServerInfo) {
386 oldServerInfo->SetState(STATE_READY);
387 } else {
388 fServerInfos->Remove(serverInfo->GetAddress());
389 serverInfo->ReleaseReference();
390 }
391 continue;
392 }
393 // now the task has all info and will call the respective cleanup
394 // method when being deleted
395 if (task->Init() != B_OK) {
396 delete task;
397 continue;
398 }
399 status_t error = taskManager.RunTask(task);
400 if (error != B_OK) {
401 ERROR("ServerManager::_BroadcastListener(): Failed to start server "
402 "info task: %s\n", strerror(error));
403 continue;
404 }
405 }
406 return B_OK;
407 }
408
409 // _InitBroadcastListener
410 status_t
_InitBroadcastListener()411 ServerManager::_InitBroadcastListener()
412 {
413 // create a socket
414 fBroadcastListenerSocket = socket(AF_INET, SOCK_DGRAM, 0);
415 if (fBroadcastListenerSocket < 0)
416 return errno;
417 // bind it to the port
418 sockaddr_in addr;
419 addr.sin_family = AF_INET;
420 addr.sin_port = htons(kDefaultBroadcastPort);
421 addr.sin_addr.s_addr = INADDR_ANY;
422 if (bind(fBroadcastListenerSocket, (sockaddr*)&addr, sizeof(addr)) < 0) {
423 ERROR("ServerManager::_InitBroadcastListener(): ERROR: bind()ing the "
424 "broadcasting socket failed: %s\n", strerror(errno));
425 safe_closesocket(fBroadcastListenerSocket);
426 return errno;
427 }
428 // spawn the thread
429 #if USER
430 fBroadcastListener = spawn_thread(&_BroadcastListenerEntry,
431 "broadcast listener", B_NORMAL_PRIORITY, this);
432 #else
433 fBroadcastListener = spawn_kernel_thread(&_BroadcastListenerEntry,
434 "broadcast listener", B_NORMAL_PRIORITY, this);
435 #endif
436 if (fBroadcastListener < 0)
437 return fBroadcastListener;
438 return B_OK;
439 }
440
441 // _TerminateBroadcastListener
442 void
_TerminateBroadcastListener()443 ServerManager::_TerminateBroadcastListener()
444 {
445 safe_closesocket(fBroadcastListenerSocket);
446 if (fBroadcastListener >= 0) {
447 int32 result;
448 wait_for_thread(fBroadcastListener, &result);
449 }
450 }
451
452 // _ServerAdded
453 void
_ServerAdded(ExtendedServerInfo * serverInfo)454 ServerManager::_ServerAdded(ExtendedServerInfo* serverInfo)
455 {
456 AutoLocker<Locker> locker(fLock);
457 if (fServerInfos->Get(serverInfo->GetAddress()) == serverInfo) {
458 // check whether someone told us to remove the server in the meantime
459 if (serverInfo->GetState() == STATE_REMOVING) {
460 _RemoveServer(serverInfo);
461 if (fListener) {
462 locker.Unlock();
463 fListener->ServerRemoved(serverInfo);
464 }
465 return;
466 }
467
468 // no, everything is fine: go on...
469 serverInfo->SetState(STATE_READY);
470 if (fListener) {
471 locker.Unlock();
472 fListener->ServerAdded(serverInfo);
473 }
474 } else {
475 WARN("ServerManager::_ServerAdded(%p): WARNING: Unexpected server "
476 "info.\n", serverInfo);
477 }
478 }
479
480 // _ServerUpdated
481 void
_ServerUpdated(ExtendedServerInfo * serverInfo)482 ServerManager::_ServerUpdated(ExtendedServerInfo* serverInfo)
483 {
484 AutoLocker<Locker> locker(fLock);
485 ExtendedServerInfo* oldInfo = fServerInfos->Get(serverInfo->GetAddress());
486 if (serverInfo != oldInfo) {
487 // check whether someone told us to remove the server in the meantime
488 if (oldInfo->GetState() == STATE_REMOVING) {
489 oldInfo->AcquireReference();
490 _RemoveServer(oldInfo);
491 if (fListener) {
492 locker.Unlock();
493 fListener->ServerRemoved(oldInfo);
494 }
495 oldInfo->ReleaseReference();
496 return;
497 }
498
499 // no, everything is fine: go on...
500 fServerInfos->Put(serverInfo->GetAddress(), serverInfo);
501 serverInfo->AcquireReference();
502 serverInfo->SetState(STATE_READY);
503 oldInfo->SetState(STATE_OBSOLETE);
504 if (fListener) {
505 locker.Unlock();
506 fListener->ServerUpdated(oldInfo, serverInfo);
507 }
508 oldInfo->ReleaseReference();
509 } else {
510 WARN("ServerManager::_ServerUpdated(%p): WARNING: Unexpected server "
511 "info.\n", serverInfo);
512 }
513 }
514
515 // _AddingServerFailed
516 void
_AddingServerFailed(ExtendedServerInfo * serverInfo)517 ServerManager::_AddingServerFailed(ExtendedServerInfo* serverInfo)
518 {
519 AutoLocker<Locker> locker(fLock);
520 if (fServerInfos->Get(serverInfo->GetAddress()) == serverInfo) {
521 bool removing = (serverInfo->GetState() == STATE_REMOVING);
522 fServerInfos->Remove(serverInfo->GetAddress());
523 serverInfo->ReleaseReference();
524 serverInfo->SetState(STATE_OBSOLETE);
525
526 // notify the listener, if someone told us in the meantime to remove
527 // the server
528 if (removing) {
529 locker.Unlock();
530 fListener->ServerRemoved(serverInfo);
531 }
532 } else {
533 WARN("ServerManager::_AddingServerFailed(%p): WARNING: Unexpected "
534 "server info.\n", serverInfo);
535 }
536 }
537
538 // _UpdatingServerFailed
539 void
_UpdatingServerFailed(ExtendedServerInfo * serverInfo)540 ServerManager::_UpdatingServerFailed(ExtendedServerInfo* serverInfo)
541 {
542 AutoLocker<Locker> locker(fLock);
543 ExtendedServerInfo* oldInfo = fServerInfos->Get(serverInfo->GetAddress());
544 if (serverInfo != oldInfo) {
545 // check whether someone told us to remove the server in the meantime
546 if (oldInfo->GetState() == STATE_REMOVING) {
547 oldInfo->AcquireReference();
548 _RemoveServer(oldInfo);
549 if (fListener) {
550 locker.Unlock();
551 fListener->ServerRemoved(oldInfo);
552 }
553 oldInfo->ReleaseReference();
554 serverInfo->SetState(STATE_OBSOLETE);
555 return;
556 }
557
558 // no, everything is fine: go on...
559 serverInfo->SetState(STATE_OBSOLETE);
560 oldInfo->SetState(STATE_READY);
561 } else {
562 WARN("ServerManager::_UpdatingServerFailed(%p): WARNING: Unexpected "
563 "server info.\n", serverInfo);
564 }
565 }
566
567 // _RemoveServer
568 //
569 // fLock must be held.
570 void
_RemoveServer(ExtendedServerInfo * serverInfo)571 ServerManager::_RemoveServer(ExtendedServerInfo* serverInfo)
572 {
573 if (!serverInfo)
574 return;
575
576 ExtendedServerInfo* oldInfo = fServerInfos->Get(serverInfo->GetAddress());
577 if (oldInfo) {
578 fServerInfos->Remove(oldInfo->GetAddress());
579 oldInfo->SetState(STATE_OBSOLETE);
580 oldInfo->ReleaseReference();
581 }
582 }
583
584
585 // #pragma mark -
586
587 // destructor
~Listener()588 ServerManager::Listener::~Listener()
589 {
590 }
591
592