/* * Loads existing nodes from disk */ void KBucket::loadNodes(SimpleXML& xml) { xml.resetCurrentChild(); if(xml.findChild("Nodes")) { xml.stepIn(); while(xml.findChild("Node")) { CID cid = CID(xml.getChildAttrib("CID")); string i4 = xml.getChildAttrib("I4"); uint16_t u4 = static_cast<uint16_t>(xml.getIntChildAttrib("U4")); if(Utils::isGoodIPPort(i4, u4)) { UDPKey udpKey; string key = xml.getChildAttrib("key"); string keyIp = xml.getChildAttrib("keyIP"); if(!key.empty() && !keyIp.empty()) { udpKey.key = CID(key); udpKey.ip = keyIp; } //addUser(cid, i4, u4); BootstrapManager::getInstance()->addBootstrapNode(i4, u4, cid, udpKey); } } xml.stepOut(); } }
/* * Generates UDP key for specified IP address */ CID Utils::getUdpKey(const string& targetIp) { CID myUdpKey = CID(SETTING(DHT_KEY)); TigerTree th; th.update(myUdpKey.data(), sizeof(CID)); th.update(targetIp.c_str(), targetIp.size()); return CID(th.finalize()); }
CID CID::generate() { uint8_t data[CID::SIZE]; for(size_t i = 0; i < sizeof(data); ++i) { data[i] = (uint8_t)Util::rand(); } return CID(data); }
CID CID::FromString(const std::string &cid) { uuid_t uuid; int ret = uuid_parse(cid.data(), uuid); if (ret == -1) uuid_clear(uuid); return CID(uuid); }
static struct oio_url_s * _metacd_load_url (struct req_args_s *args) { const gchar *s; struct oio_url_s *url = oio_url_empty(); if (NULL != (s = NS())) oio_url_set (url, OIOURL_NS, s); if (NULL != (s = ACCOUNT())) oio_url_set (url, OIOURL_ACCOUNT, s); if (NULL != (s = REF())) oio_url_set (url, OIOURL_USER, s); if (NULL != (s = TYPE())) oio_url_set (url, OIOURL_TYPE, s); if (NULL != (s = PATH())) { oio_url_set (url, OIOURL_PATH, s); if (NULL != (s = VERSION())) oio_url_set (url, OIOURL_VERSION, s); } if (NULL != (s = CID())) oio_url_set (url, OIOURL_HEXID, s); if (NULL != (s = CONTENT())) oio_url_set (url, OIOURL_CONTENTID, s); return url; }
void QueuedUsers::slotContextMenu(){ QModelIndexList indexes = treeView_USERS->selectionModel()->selectedRows(0); if (indexes.isEmpty()) return; QMenu *m = new QMenu(this); m->addAction(tr("Grant slot")); if (m->exec(QCursor::pos())){ for (const auto &i : indexes){ QueuedUserItem *item = reinterpret_cast<QueuedUserItem*>(i.internalPointer()); if (!item) continue; QString id = item->cid; if (!id.isEmpty()){ UserPtr user = ClientManager::getInstance()->findUser(CID(id.toStdString())); if (user){ try { UploadManager::getInstance()->reserveSlot(HintedUser(user, _tq(item->hub))); } catch ( ... ) {} } } } } m->deleteLater(); }
void MessageManager::loadUsers() { try { SimpleXML xml; SettingsManager::loadSettingFile(xml, CONFIG_DIR, CONFIG_NAME); auto cm = ClientManager::getInstance(); if (xml.findChild("Ignored")) { xml.stepIn(); xml.resetCurrentChild(); if (xml.findChild("Users")) { xml.stepIn(); while (xml.findChild("User")) { UserPtr user = cm->getUser(CID(xml.getChildAttrib("CID"))); { WLock(cm->getCS()); cm->addOfflineUser(user, xml.getChildAttrib("Nick"), xml.getChildAttrib("Hub"), (uint32_t)xml.getIntChildAttrib("LastSeen")); } WLock l(Ignorecs); ignoredUsers.emplace(user); user->setFlag(User::IGNORED); } xml.stepOut(); } xml.stepOut(); } } catch (const Exception& e) { LogManager::getInstance()->message(STRING_F(LOAD_FAILED_X, CONFIG_NAME % e.getError()), LogManager::LOG_ERROR); } }
/* * Loads existing indexes from disk */ void IndexManager::loadIndexes(SimpleXML& xml) { xml.resetCurrentChild(); if(xml.findChild("Files")) { xml.stepIn(); while(xml.findChild("File")) { const TTHValue tth = TTHValue(xml.getChildAttrib("TTH")); SourceList sources; xml.stepIn(); while(xml.findChild("Source")) { Source source; source.setCID(CID(xml.getChildAttrib("CID"))); source.setIp(xml.getChildAttrib("I4")); source.setUdpPort(static_cast<uint16_t>(xml.getIntChildAttrib("U4"))); source.setSize(xml.getLongLongChildAttrib("SI")); source.setExpires(xml.getLongLongChildAttrib("EX")); source.setPartial(false); sources.push_back(source); } tthList.insert(std::make_pair(tth, sources)); xml.stepOut(); } xml.stepOut(); } }
CID Deserializer::deserializeCID(const string& aCID) { if (!Encoder::isBase32(aCID.c_str())) { throw std::invalid_argument("Invalid CID"); } return CID(aCID); }
void ConnectionManager::on(AdcCommand::INF, UserConnection* aSource, const AdcCommand& cmd) throw() { if(aSource->getState() != UserConnection::STATE_INF) { // Already got this once, ignore... aSource->send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_GENERIC, "Expecting INF")); dcdebug("CM::onINF %p sent INF twice\n", (void*)aSource); aSource->disconnect(); return; } string cid; if(!cmd.getParam("ID", 0, cid)) { aSource->send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_INF_MISSING, "ID missing").addParam("FL", "ID")); dcdebug("CM::onINF missing ID\n"); aSource->disconnect(); return; } aSource->setUser(ClientManager::getInstance()->findUser(CID(cid))); if(!aSource->getUser()) { dcdebug("CM::onINF: User not found"); aSource->send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_GENERIC, "User not found")); putConnection(aSource); return; } if(aSource->isSet(UserConnection::FLAG_INCOMING)) { aSource->setFlag(UserConnection::FLAG_DOWNLOAD); addDownloadConnection(aSource); } else { aSource->setFlag(UserConnection::FLAG_UPLOAD); addUploadConnection(aSource); } }
void AdcHub::on(Connected) throw() { dcassert(state == STATE_PROTOCOL); setMe(ClientManager::getInstance()->getUser(CID(SETTING(CLIENT_ID)), this, false)); lastInfoMap.clear(); send("HSUP +BAS0\n"); fire(ClientListener::Connected(), this); }
CID Node::getUdpKey() const { // if our external IP changed from the last time, we can't encrypt packet with this key if(DHT::getInstance()->getLastExternalIP() == key.ip) return key.key; else return CID(); }
void UserApi::on(ClientManagerListener::UserUpdated, const OnlineUser& aUser) noexcept { if (aUser.getUser()->getCID() == CID()) return; maybeSend("user_updated", [&] { return Serializer::serializeUser(aUser); }); }
CID ClientManager::makeCid(const string& aNick, const string& aHubUrl) const throw() { string n = Text::toLower(aNick); TigerHash th; th.update(n.c_str(), n.length()); th.update(Text::toLower(aHubUrl).c_str(), aHubUrl.length()); // Construct hybrid CID from the bits of the tiger hash - should be // fairly random, and hopefully low-collision return CID(th.finalize()); }
void UserApi::on(ClientManagerListener::UserDisconnected, const UserPtr& aUser, bool aWentOffline) noexcept { if (aUser->getCID() == CID()) return; maybeSend("user_disconnected", [&] { return json({ { "user", Serializer::serializeUser(aUser) }, { "went_offline", aWentOffline }, }); }); }
void UserApi::on(ClientManagerListener::UserConnected, const OnlineUser& aUser, bool aWasOffline) noexcept { if (aUser.getUser()->getCID() == CID()) return; maybeSend("user_connected", [&] { return json({ { "user", Serializer::serializeUser(aUser) }, { "was_offline", aWasOffline }, }); }); }
CID Utils::getDistance(const CID& cid1, const CID& cid2) { uint8_t distance[CID::SIZE]; for(int i = 0; i < CID::SIZE; i++) { distance[i] = cid1.data()[i] ^ cid2.data()[i]; } return CID(distance); }
void BootstrapManager::on(HttpConnectionListener::Complete, HttpConnection*, string const&, bool /*fromCoral*/) throw() { if(!nodesXML.empty()) { try { uLongf destLen = BUFSIZE; boost::scoped_array<uint8_t> destBuf; // decompress incoming packet int result; do { destLen *= 2; destBuf.reset(new uint8_t[destLen]); result = uncompress(&destBuf[0], &destLen, (Bytef*)nodesXML.data(), nodesXML.length()); } while (result == Z_BUF_ERROR); if(result != Z_OK) { // decompression error!!! throw Exception("Decompress error."); } SimpleXML remoteXml; remoteXml.fromXML(string((char*)&destBuf[0], destLen)); remoteXml.stepIn(); while(remoteXml.findChild("Node")) { CID cid = CID(remoteXml.getChildAttrib("CID")); string i4 = remoteXml.getChildAttrib("I4"); string u4 = remoteXml.getChildAttrib("U4"); addBootstrapNode(i4, static_cast<uint16_t>(Util::toInt(u4)), cid, UDPKey()); } remoteXml.stepOut(); } catch(Exception& e) { LogManager::getInstance()->message("DHT bootstrap error: " + e.getError()); } } }
Client::Client(const string& p_HubURL, char separator_, bool secure_) : m_cs(std::unique_ptr<webrtc::RWLockWrapper> (webrtc::RWLockWrapper::CreateRWLock())), m_reconnDelay(120), m_lastActivity(GET_TICK()), //registered(false), [-] IRainman fix. autoReconnect(false), m_encoding(Text::systemCharset), state(STATE_DISCONNECTED), m_client_sock(0), m_HubURL(p_HubURL), m_port(0), m_separator(separator_), m_secure(secure_), m_countType(COUNT_UNCOUNTED), m_availableBytes(0), m_exclChecks(false) // [+] IRainman fix. { dcassert(p_HubURL == Text::toLower(p_HubURL)); const auto l_my_user = new User(ClientManager::getMyCID()); const auto l_hub_user = new User(CID()); #ifdef PPA_INCLUDE_LASTIP_AND_USER_RATIO m_HubID = CFlylinkDBManager::getInstance()->get_dic_hub_id(m_HubURL); dcassert(m_HubID != 0); l_my_user->setHubID(m_HubID); // ƒл¤ сохранени¤ кол-ва мессаг по самому себе //l_hub_user->setHubID(m_HubID); // ƒл¤ бота-хаба не сохран¤ем пока #endif m_myOnlineUser = new OnlineUser(UserPtr(l_my_user), *this, 0); // [+] IRainman fix. m_hubOnlineUser = new OnlineUser(UserPtr(l_hub_user), *this, AdcCommand::HUB_SID); // [+] IRainman fix. // [-] IRainman. //m_hEventClientInitialized = CreateEvent(NULL, TRUE, FALSE, NULL);//[+]FlylinkDC string file, proto, query, fragment; Util::decodeUrl(getHubUrl(), proto, m_address, m_port, file, query, fragment); if (!query.empty()) { m_keyprint = Util::decodeQuery(query)["kp"]; #ifdef _DEBUG LogManager::getInstance()->message("keyprint = " + m_keyprint); #endif } #ifdef _DEBUG else { LogManager::getInstance()->message("hubURL = " + getHubUrl() + " query.empty()"); } #endif TimerManager::getInstance()->addListener(this); }
UserPtr DirectoryListing::getUserFromFilename(const string& fileName) { // General file list name format: [username].[CID].[xml|xml.bz2] string name = Util::getFileName(fileName); string ext = Text::toLower(Util::getFileExt(name)); if (ext == ".dcls" || ext == ".dclst") // [+] IRainman dclst support { auto l_user = std::make_shared<User>(CID(), name, 0); return l_user; } // Strip off any extensions if (ext == ".bz2") { name.erase(name.length() - 4); ext = Text::toLower(Util::getFileExt(name)); } if (ext == ".xml") { name.erase(name.length() - 4); } // Find CID string::size_type i = name.rfind('.'); if (i == string::npos) { return ClientManager::getUser(name, "Unknown Hub", 0); } size_t n = name.length() - (i + 1); // CID's always 39 chars long... if (n != 39) { return ClientManager::getUser(name, "Unknown Hub", 0); } const CID cid(name.substr(i + 1)); if (cid.isZero()) { return ClientManager::getUser(name, "Unknown Hub", 0); } UserPtr u = ClientManager::createUser(cid, name.substr(0, i), 0); return u; }
void ClientManager::loadUsers() { try { SimpleXML xml; xml.fromXML(File(getUsersFile(), File::READ, File::OPEN).read()); if(xml.findChild("Users")) { xml.stepIn(); { Lock l(cs); while(xml.findChild("User")) { nicks[CID(xml.getChildAttrib("CID"))] = std::make_pair(xml.getChildAttrib("Nick"), false); } } xml.stepOut(); } } catch(const Exception&) { } }
/* * Processes incoming request to publish file */ void IndexManager::processPublishSourceRequest(const string& ip, uint16_t port, const UDPKey& udpKey, const AdcCommand& cmd) { const CID cid = CID(cmd.getParam(0)); string tth; if(!cmd.getParam("TR", 1, tth)) return; // nothing to identify a file? string size; if(!cmd.getParam("SI", 1, size)) return; // no file size? string partial; cmd.getParam("PF", 1, partial); addSource(TTHValue(tth), cid, ip, port, Util::toInt64(size), partial == "1"); // send response AdcCommand res(AdcCommand::SEV_SUCCESS, AdcCommand::SUCCESS, "File published", AdcCommand::TYPE_UDP); res.addParam("FC", "PUB"); res.addParam("TR", tth); DHT::getInstance()->send(res, ip, port, cid, udpKey); }
CID CID::Generate() { return CID(CIDImpl::Generate()); }
void SettingsManager::load(string const& aFileName) { try { SimpleXML xml; xml.fromXML(File(aFileName, File::READ, File::OPEN).read()); xml.resetCurrentChild(); xml.stepIn(); if(xml.findChild("Settings")) { xml.stepIn(); int i; for(i=STR_FIRST; i<STR_LAST; i++) { const string& attr = settingTags[i]; dcassert(attr.find("SENTRY") == string::npos); if(xml.findChild(attr)) set(StrSetting(i), xml.getChildData()); xml.resetCurrentChild(); } for(i=INT_FIRST; i<INT_LAST; i++) { const string& attr = settingTags[i]; dcassert(attr.find("SENTRY") == string::npos); if(xml.findChild(attr)) set(IntSetting(i), Util::toInt(xml.getChildData())); xml.resetCurrentChild(); } for(i=INT64_FIRST; i<INT64_LAST; i++) { const string& attr = settingTags[i]; dcassert(attr.find("SENTRY") == string::npos); if(xml.findChild(attr)) set(Int64Setting(i), Util::toInt64(xml.getChildData())); xml.resetCurrentChild(); } xml.stepOut(); } if(SETTING(PRIVATE_ID).length() != 39 || CID(SETTING(PRIVATE_ID)).isZero()) { set(PRIVATE_ID, CID::generate().toBase32()); } double v = Util::toDouble(SETTING(CONFIG_VERSION)); // if(v < 0.x) { // Fix old settings here } if(v <= 0.674) { // Formats changed, might as well remove these... set(LOG_FORMAT_POST_DOWNLOAD, Util::emptyString); set(LOG_FORMAT_POST_UPLOAD, Util::emptyString); set(LOG_FORMAT_MAIN_CHAT, Util::emptyString); set(LOG_FORMAT_PRIVATE_CHAT, Util::emptyString); set(LOG_FORMAT_STATUS, Util::emptyString); set(LOG_FORMAT_SYSTEM, Util::emptyString); set(LOG_FILE_MAIN_CHAT, Util::emptyString); set(LOG_FILE_STATUS, Util::emptyString); set(LOG_FILE_PRIVATE_CHAT, Util::emptyString); set(LOG_FILE_UPLOAD, Util::emptyString); set(LOG_FILE_DOWNLOAD, Util::emptyString); set(LOG_FILE_SYSTEM, Util::emptyString); } if(SETTING(SET_MINISLOT_SIZE) < 64) set(SET_MINISLOT_SIZE, 64); if(SETTING(AUTODROP_INTERVAL) < 1) set(AUTODROP_INTERVAL, 1); if(SETTING(AUTODROP_ELAPSED) < 1) set(AUTODROP_ELAPSED, 1); if(SETTING(AUTO_SEARCH_LIMIT) > 5) set(AUTO_SEARCH_LIMIT, 5); else if(SETTING(AUTO_SEARCH_LIMIT) < 1) set(AUTO_SEARCH_LIMIT, 1); #ifdef _DEBUG set(PRIVATE_ID, CID::generate().toBase32()); #endif setDefault(UDP_PORT, SETTING(TCP_PORT)); File::ensureDirectory(SETTING(TLS_TRUSTED_CERTIFICATES_PATH)); fire(SettingsManagerListener::Load(), xml); xml.stepOut(); } catch(const Exception&) { if(CID(SETTING(PRIVATE_ID)).isZero()) set(PRIVATE_ID, CID::generate().toBase32()); } }
void UDPServer::handlePacket(uint8_t* aBuf, size_t aLen, const string& aRemoteIp) { string x((char*) aBuf, aLen); //check if this packet has been encrypted if (SETTING(ENABLE_SUDP) && aLen >= 32 && ((aLen & 15) == 0)) { SearchManager::getInstance()->decryptPacket(x, aLen, aBuf, BUFSIZE); } delete aBuf; if (x.empty()) return; COMMAND_DEBUG(x, DebugManager::TYPE_CLIENT_UDP, DebugManager::INCOMING, aRemoteIp); if(x.compare(0, 4, "$SR ") == 0) { SearchManager::getInstance()->onSR(x, aRemoteIp); } else if(x.compare(1, 4, "RES ") == 0 && x[x.length() - 1] == 0x0a) { AdcCommand c(x.substr(0, x.length()-1)); if(c.getParameters().empty()) return; string cid = c.getParam(0); if(cid.size() != 39) return; UserPtr user = ClientManager::getInstance()->findUser(CID(cid)); if(!user) return; // This should be handled by AdcCommand really... c.getParameters().erase(c.getParameters().begin()); SearchManager::getInstance()->onRES(c, user, aRemoteIp); } else if (x.compare(1, 4, "PSR ") == 0 && x[x.length() - 1] == 0x0a) { AdcCommand c(x.substr(0, x.length()-1)); if(c.getParameters().empty()) return; string cid = c.getParam(0); if(cid.size() != 39) return; UserPtr user = ClientManager::getInstance()->findUser(CID(cid)); // when user == NULL then it is probably NMDC user, check it later c.getParameters().erase(c.getParameters().begin()); SearchManager::getInstance()->onPSR(c, user, aRemoteIp); } else if (x.compare(1, 4, "PBD ") == 0 && x[x.length() - 1] == 0x0a) { if (!SETTING(USE_PARTIAL_SHARING)) { return; } //LogManager::getInstance()->message("GOT PBD UDP: " + x); AdcCommand c(x.substr(0, x.length()-1)); if(c.getParameters().empty()) return; string cid = c.getParam(0); if(cid.size() != 39) return; UserPtr user = ClientManager::getInstance()->findUser(CID(cid)); c.getParameters().erase(c.getParameters().begin()); if (user) SearchManager::getInstance()->onPBD(c, user); } else if ((x.compare(1, 4, "UBD ") == 0 || x.compare(1, 4, "UBN ") == 0) && x[x.length() - 1] == 0x0a) { AdcCommand c(x.substr(0, x.length()-1)); if(c.getParameters().empty()) return; c.getParameters().erase(c.getParameters().begin()); if (x.compare(1, 4, "UBN ") == 0) { //LogManager::getInstance()->message("GOT UBN UDP: " + x); UploadManager::getInstance()->onUBN(c); } else { //LogManager::getInstance()->message("GOT UBD UDP: " + x); UploadManager::getInstance()->onUBD(c); } } }
void SearchManager::onData(const string& x, const string& remoteIp) { if(x.compare(0, 4, "$SR ") == 0) { string::size_type i, j; // Directories: $SR <nick><0x20><directory><0x20><free slots>/<total slots><0x05><Hubname><0x20>(<Hubip:port>) // Files: $SR <nick><0x20><filename><0x05><filesize><0x20><free slots>/<total slots><0x05><Hubname><0x20>(<Hubip:port>) i = 4; if( (j = x.find(' ', i)) == string::npos) { return; } string nick = x.substr(i, j-i); i = j + 1; // A file has 2 0x05, a directory only one size_t cnt = count(x.begin() + j, x.end(), 0x05); SearchResult::Types type = SearchResult::TYPE_FILE; string file; int64_t size = 0; if(cnt == 1) { // We have a directory...find the first space beyond the first 0x05 from the back // (dirs might contain spaces as well...clever protocol, eh?) type = SearchResult::TYPE_DIRECTORY; // Get past the hubname that might contain spaces if((j = x.rfind(0x05)) == string::npos) { return; } // Find the end of the directory info if((j = x.rfind(' ', j-1)) == string::npos) { return; } if(j < i + 1) { return; } file = x.substr(i, j-i) + '\\'; } else if(cnt == 2) { if( (j = x.find((char)5, i)) == string::npos) { return; } file = x.substr(i, j-i); i = j + 1; if( (j = x.find(' ', i)) == string::npos) { return; } size = Util::toInt64(x.substr(i, j-i)); } i = j + 1; if( (j = x.find('/', i)) == string::npos) { return; } int freeSlots = Util::toInt(x.substr(i, j-i)); i = j + 1; if( (j = x.find((char)5, i)) == string::npos) { return; } int slots = Util::toInt(x.substr(i, j-i)); i = j + 1; if( (j = x.rfind(" (")) == string::npos) { return; } string hubName = x.substr(i, j-i); i = j + 2; if( (j = x.rfind(')')) == string::npos) { return; } HintedUser user; user.hint = ClientManager::getInstance()->findHub(x.substr(i, j - i)); if(user.hint.empty()) { // Could happen if hub has multiple URLs / IPs user = ClientManager::getInstance()->findLegacyUser(nick); if(!user) return; } string encoding = ClientManager::getInstance()->findHubEncoding(user.hint); nick = Text::toUtf8(nick, encoding); file = Text::toUtf8(file, encoding); hubName = Text::toUtf8(hubName, encoding); if(!user) { user.user = ClientManager::getInstance()->findUser(nick, user.hint); if(!user) return; } string tth; if(hubName.compare(0, 4, "TTH:") == 0) { tth = hubName.substr(4); StringList names = ClientManager::getInstance()->getHubNames(user); hubName = names.empty() ? _("Offline") : Util::toString(names); } if(tth.empty() && type == SearchResult::TYPE_FILE) { return; } fire(SearchManagerListener::SR(), SearchResultPtr(new SearchResult(user, type, slots, freeSlots, size, file, hubName, remoteIp, TTHValue(tth), Util::emptyString))); } else if(x.compare(1, 4, "RES ") == 0 && x[x.length() - 1] == 0x0a) { AdcCommand c(x.substr(0, x.length()-1)); if(c.getParameters().empty()) return; string cid = c.getParam(0); if(cid.size() != 39) return; UserPtr user = ClientManager::getInstance()->findUser(CID(cid)); if(!user) return; // This should be handled by AdcCommand really... c.getParameters().erase(c.getParameters().begin()); onRES(c, user, remoteIp); } /*else if(x.compare(1, 4, "SCH ") == 0 && x[x.length() - 1] == 0x0a) { try { respond(AdcCommand(x.substr(0, x.length()-1))); } catch(ParseException& ) { } }*/ // Needs further DoS investigation }
const CID& ClientManager::getMyPID() { if(pid.isZero()) pid = CID(SETTING(PRIVATE_ID)); return pid; }
CID ClientManager::getMyCID() { TigerHash tiger; tiger.update(getMyPID().data(), CID::SIZE); return CID(tiger.finalize()); }
CID CID::FromData(const uint8_t *data) { return CID(CIDImpl::FromData(data)); }
CID CID::FromString(const std::string &cid) { return CID(CIDImpl::FromString(cid)); }