// _ServerInfoConnectionListener int32 NetFSServer::_ServerInfoConnectionListener() { if (fServerInfoConnectionListenerSocket < 0) return B_BAD_VALUE; TaskManager taskManager; // accept a incoming connection while (!fTerminating) { int fd = -1; do { taskManager.RemoveDoneTasks(); fd = accept(fServerInfoConnectionListenerSocket, NULL, 0); if (fd < 0) { status_t error = errno; if (error != B_INTERRUPTED) return error; if (fTerminating) return B_OK; } } while (fd < 0); // get a fresh server info ServerInfo info; status_t error = _GetServerInfo(info); if (error != B_OK) { closesocket(fd); return error; } // create a server info sender thread ServerInfoSender* sender = new(std::nothrow) ServerInfoSender(fd, info); if (!sender || sender->Init() != B_OK) { closesocket(fd); delete sender; } taskManager.RunTask(sender); } return B_OK; }
// _BroadcastListener int32 ServerManager::_BroadcastListener() { TaskManager taskManager; while (!fTerminating) { taskManager.RemoveDoneTasks(); // receive sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(kDefaultBroadcastPort); addr.sin_addr.s_addr = INADDR_ANY; socklen_t addrSize = sizeof(addr); BroadcastMessage message; //PRINT(("ServerManager::_BroadcastListener(): recvfrom()...\n")); ssize_t bytesRead = recvfrom(fBroadcastListenerSocket, &message, sizeof(message), 0, (sockaddr*)&addr, &addrSize); if (bytesRead < 0) { PRINT("ServerManager::_BroadcastListener(): recvfrom() " "failed: %s\n", strerror(errno)); continue; } // check message size, magic, and protocol version if (bytesRead != sizeof(BroadcastMessage)) { PRINT("ServerManager::_BroadcastListener(): received " "%ld bytes, but it should be %lu\n", bytesRead, sizeof(BroadcastMessage)); continue; } if (message.magic != B_HOST_TO_BENDIAN_INT32(BROADCAST_MESSAGE_MAGIC)) { PRINT("ServerManager::_BroadcastListener(): message has" " bad magic.\n"); continue; } if (message.protocolVersion != (int32)B_HOST_TO_BENDIAN_INT32(NETFS_PROTOCOL_VERSION)) { PRINT("ServerManager::_BroadcastListener(): protocol " "version does not match: %" B_PRId32 " vs. %d.\n", (int32)B_BENDIAN_TO_HOST_INT32( message.protocolVersion), NETFS_PROTOCOL_VERSION); continue; } // check, if the server is local NetAddress netAddress(addr); #ifndef ADD_SERVER_LOCALHOST if (netAddress.IsLocal()) continue; #endif // ADD_SERVER_LOCALHOST AutoLocker<Locker> locker(fLock); ExtendedServerInfo* oldServerInfo = fServerInfos->Get(netAddress); // examine the message switch (B_BENDIAN_TO_HOST_INT32(message.message)) { case BROADCAST_MESSAGE_SERVER_TICK: // PRINT(("ServerManager::_BroadcastListener(): " // "BROADCAST_MESSAGE_SERVER_TICK.\n")); if (oldServerInfo) continue; break; case BROADCAST_MESSAGE_SERVER_UPDATE: // PRINT(("ServerManager::_BroadcastListener(): " // "BROADCAST_MESSAGE_SERVER_UPDATE.\n")); break; case BROADCAST_MESSAGE_CLIENT_HELLO: // PRINT(("ServerManager::_BroadcastListener(): " // "BROADCAST_MESSAGE_CLIENT_HELLO. Ignoring.\n")); continue; break; } if (oldServerInfo && oldServerInfo->GetState() != STATE_READY) continue; // create a new server info and add it ExtendedServerInfo* serverInfo = new(std::nothrow) ExtendedServerInfo(netAddress); if (!serverInfo) return B_NO_MEMORY; serverInfo->SetState(STATE_ADDING); BReference<ExtendedServerInfo> serverInfoReference(serverInfo, true); if (oldServerInfo) { oldServerInfo->SetState(STATE_UPDATING); } else { status_t error = fServerInfos->Put(netAddress, serverInfo); if (error != B_OK) continue; serverInfo->AcquireReference(); } // create a task to add/update the server info ServerInfoTask* task = new(std::nothrow) ServerInfoTask(this, oldServerInfo, serverInfo); if (!task) { if (oldServerInfo) { oldServerInfo->SetState(STATE_READY); } else { fServerInfos->Remove(serverInfo->GetAddress()); serverInfo->ReleaseReference(); } continue; } // now the task has all info and will call the respective cleanup // method when being deleted if (task->Init() != B_OK) { delete task; continue; } status_t error = taskManager.RunTask(task); if (error != B_OK) { ERROR("ServerManager::_BroadcastListener(): Failed to start server " "info task: %s\n", strerror(error)); continue; } } return B_OK; }