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: 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 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 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 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 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 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 160 ServerManager::~ServerManager() 161 { 162 Uninit(); 163 } 164 165 // Init 166 status_t 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 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 205 ServerManager::Run() 206 { 207 // start the broadcast listener 208 resume_thread(fBroadcastListener); 209 } 210 211 // GetServerInfo 212 ExtendedServerInfo* 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 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 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 282 ServerManager::_BroadcastListenerEntry(void* data) 283 { 284 return ((ServerManager*)data)->_BroadcastListener(); 285 } 286 287 // _BroadcastListener 288 int32 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 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 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 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 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 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 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 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 588 ServerManager::Listener::~Listener() 589 { 590 } 591 592