/* This Work is under GPL provided with this work. This work is based on the java implementation of the Kademlia protocol. Kademlia: Peer-to-peer routing based on the XOR metric Copyright (C) 2002 Petar Maymounkov [petar@post.harvard.edu] http://kademlia.scs.cs.nyu.edu and This work is bassed on translation from Barry Dunne to C++ Copyright (C)2003 Barry Dunne (http://www.emule-project.net) */ #include "cygwin.h" #include "cSearchManager.h" #include "sTag.h" #include "opcodes.h" #include "misc.h" extern time_t currentTime; SearchMap cSearchManager::m_searches; size_t cSearchManager::m_nextID = 0; void cSearchManager::stopSearch(size_t searchID) {{{ SearchMap::iterator it = m_searches.begin(); SearchMap::iterator end = m_searches.end(); while (it != end) { SearchMap::iterator next = it; next++; if (it->second->m_searchID == searchID) { delete it->second; m_searches.erase(it); end = m_searches.end(); } it = next; } }}} void cSearchManager::stopAllSearches(void) {{{ SearchMap::iterator it; for (it = m_searches.begin(); it != m_searches.end(); it++) delete it->second; m_searches.clear(); }}} void cSearchManager::jumpStart(void) {{{ SearchMap::iterator it = m_searches.begin(); SearchMap::iterator end = m_searches.end(); while (it != end) { SearchMap::iterator next = it; next++; if (it->second->m_created + 120 < currentTime) { delete it->second; m_searches.erase(it); end = m_searches.end(); } else it->second->jumpStart(); it = next; } }}} void cSearchManager::processResponse(const uint8_t *target, uint32_t fromIP, uint16_t fromPort, cPeerList *results) {{{ class cSearch *s = NULL; SearchMap::const_iterator it = m_searches.find(target); if (it != m_searches.end()) s = it->second; if (s == NULL) { cPeerList::const_iterator it2; for (it2 = results->begin(); it2 != results->end(); it2++) delete (*it2); // delete results; return; } s->processResponse(target, fromIP, fromPort, results); }}} bool cSearchManager::alreadySearchingFor(const uint8_t *id) {{{ cHash ID(id); return (m_searches.count(ID) > 0); }}} bool cSearchManager::isKeywordSearch (const uint8_t *id) {{{ cHash ID(id); SearchMap::const_iterator it = m_searches.find(ID); class cSearch *s = NULL; if (it != m_searches.end()) s = it->second; if (s != NULL) return (s->m_type == cSearch::KEYWORD); return false; }}} size_t cSearchManager::findFile(const uint8_t *id) {{{ if (alreadySearchingFor(id)) return 0; size_t searchID = 0; class cSearch *s = new cSearch; s->m_searchID = searchID = ++m_nextID; s->m_type = cSearch::FILE; memcpy(s->m_target, id, HASH_LEN); size_t len, LEN = len = 4096; unsigned char *buf = s->m_searchTerms = reinterpret_cast(MALLOC(LEN)); ADD_U1 (&buf, &len, OP_EDONKEYHEADER); ADD_U1 (&buf, &len, OVERNET_SEARCH_REQUEST); ADD_HASH (&buf, &len, s->m_target); ADD_U1 (&buf, &len, 0); ADD_U2 (&buf, &len, 0); ADD_U2 (&buf, &len, 100); s->m_lenSearchTerms = LEN - len; cHash ID(id); m_searches[ID] = s; s->go(); return searchID; }}} void cSearchManager::getWords(const char *str, cWordList *words) {{{ if (str == NULL) return; if (words == NULL) return; char *tmp = STRDUP (str); char *s = tmp; while (strlen(s) > 0) { size_t len = strcspn(s, " ()[]{}<>,._-!?"); if (len > 2) { char b = s[len]; s[len] = 0; char *word = STRDUP (s); s[len] = b; for (size_t i=0; ipush_back(word); } else if ((len == 0) && (s[0] == '-')) { len = strcspn(s, " "); if ( (!strncasecmp(s, "-image", len)) || (!strncasecmp(s, "-audio", len)) || (!strncasecmp(s, "-video", len)) || (!strncasecmp(s, "-doc" , len)) || (!strncasecmp(s, "-pro" , len))) { char b = s[len]; s[len] = 0; char *word = STRDUP (s); s[len] = b; for (size_t i=0; ipush_back(word); } else len = 0; } if (len < strlen(s)) len++; s += len; } }}} size_t cSearchManager::findKeywords(const char *text) {{{ size_t searchID = 0; cSearch *s = new cSearch; s->m_type = cSearch::KEYWORD; getWords(text, &s->m_words); size_t word_count = s->m_words.size(); if (word_count == 0) {{{ delete s; return 0; }}} char *k = s->m_words.front(); memcpy(s->m_target, md4(k, strlen(k)), HASH_LEN); printf("Keyword search %s\n", hash_bin2hex(s->m_target)); if (alreadySearchingFor(s->m_target)) {{{ delete s; return 0; }}} if (word_count == 1) {{{ size_t len3, LEN3 = len3 = s->m_lenSearchTerms = 23; unsigned char *buf3 = s->m_searchTerms = reinterpret_cast(MALLOC (LEN3)); ADD_U1 (&buf3, &len3, OP_EDONKEYHEADER); // 1 ADD_U1 (&buf3, &len3, OVERNET_SEARCH_REQUEST); // 1 ADD_HASH (&buf3, &len3, s->m_target); // HASH_LEN ADD_U1 (&buf3, &len3,0); // 1 ADD_U2 (&buf3, &len3 , 0); // 2 ADD_U2 (&buf3, &len3 ,100); // 2 ASSERT (len3 == 0); m_searches[s->m_target] = s; searchID = ++m_nextID; s->m_searchID = searchID; s->go(); return searchID; }}} // Build keyword message (skip first keyword) size_t count = s->m_words.size() - 1; size_t len2, LEN2 = len2 = 4096; unsigned char *buf2 = s->m_searchTerms = reinterpret_cast(MALLOC (4096)); ADD_U1 (&buf2, &len2, OP_EDONKEYHEADER); // 1 ADD_U1 (&buf2, &len2, OVERNET_SEARCH_REQUEST); // 1 ADD_HASH (&buf2, &len2, s->m_target); // HASH_LEN ADD_U1 (&buf2, &len2 ,1); // 1 if (count > 0) {{{ // count * 2 for (size_t i=0; i<(count - 1); i++) { ADD_U1 (&buf2, &len2 ,0); // BRACKET ADD_U1 (&buf2, &len2 ,0); // AND } }}} cWordList::const_iterator it = s->m_words.begin(); for (it++; it != s->m_words.end(); it++) {{{ printf("WORD %s\n", *it); if (0 == strcmp(*it, "-image")) { add_strTag(&buf2, &len2, SEEK_IMAGE, "\x03"); count++; } else if (0 == strcmp(*it, "-audio")) { add_strTag(&buf2, &len2, SEEK_AUDIO, "\x03"); count++; } else if (0 == strcmp(*it, "-video")) { add_strTag(&buf2, &len2, SEEK_VIDEO, "\x03"); count++; } else if (0 == strcmp(*it, "-doc" )) { add_strTag(&buf2, &len2, SEEK_DOC , "\x03"); count++; } else if (0 == strcmp(*it, "-prc" )) { add_strTag(&buf2, &len2, SEEK_PRO , "\x03"); count++; } else { add_strCmp(&buf2, &len2, *it ); count++; } }}} ADD_U2 (&buf2, &len2 , 0); // 2 ADD_U2 (&buf2, &len2 ,100); // 2 s->m_lenSearchTerms = LEN2 - len2; m_searches[s->m_target] = s; searchID = ++m_nextID; s->m_searchID = searchID; s->go(); return searchID; }}} void cSearchManager::findNode(const uint8_t *id) {{{ if (alreadySearchingFor(id)) return; class cSearch *s = new cSearch; s->m_type = cSearch::NODE; memcpy(s->m_target, id, HASH_LEN); s->m_searchTerms = NULL; s->m_lenSearchTerms = 0; s->m_searchID = 0; m_searches[s->m_target] = s; s->go(); }}}