📄 trut.cpp
字号:
GetContext *get; m_gets.Lock(); PTP_LIST_FOREACH(GetContext, get, &m_gets) { if (get->m_file == file) { get->m_thread.Kill(); m_gets.Remove(get, 0); delete get; break; } } m_gets.Unlock();}/** * Trut::JoinGroup: Join a secure group. * @name: Group name. * @wait: Time (in seconds) to wait for a group reply. * @join: Group join callback. * @accept: Group accept callback. * @context: Callback context. */voidTrut::JoinGroup(const char *name, int wait, JoinCallback join, AcceptCallback accept, void *context){ JoinStatus status = JOIN_ERROR; char *keyname = NULL; Group *group = FindGroup(name); if (!group || group->m_key) { if (!group) { group = new Group; group->m_trut = this; group->m_name = strdup(name); m_groups.Insert(group); } group->m_join = join; group->m_accept = accept; group->m_context = context; group->m_responses = 0; keyname = new char[(strlen(group->GetName()) + 32)]; sprintf(keyname, "/secure/%s/key", group->GetName()); Search(keyname, FindKey, group, NULL); PTP::Thread::Sleep(wait); if (group->m_key || group->m_responses > 0) { delete [] keyname; return; } SearchStop(group); group->m_key = new PTP::Key; { BYTE keydata[PTP::Key::KEY_SIZE]; group->m_key->Export(keydata); PTP::Collection::Entry *entry = new PTP::Collection::Entry(keyname, keydata, sizeof(keydata)); m_collect.Add(entry); status = JOIN_CREATED; } } else status = JOIN_OK; delete [] keyname; if (group->m_join) { (*group->m_join)(group, status, group->m_context); }}/* * Trut::FindKey: Group search response callback. * @file: Key file. * @context: Callback context. */voidTrut::FindKey(File *file, void *context){ Group *group = (Group*) context; if (!group || !group->m_trut) return; if (!group->m_key && strcmp("key", file->GetName()) == 0) { group->m_responses++; file->m_group = group; group->m_trut->Get(file, NULL, FetchKey, group); } delete file;}/* * Trut::FetchKey: Group key get callback. * @file: Key file. * @status: Get status. * @data: Key data. * @size: Data size. * @context: Callback context. */voidTrut::FetchKey(File *file, GetStatus status, BYTE *data, unsigned long size, void *context){ Group *group = (Group*) context; Trut *trut = group->m_trut; switch (status) { case GET_OK: return; case GET_DONE: { group->m_key = new PTP::Key(data); char *keyname = new char[ (strlen(group->GetName()) + STRLEN_CONST("/secure/" "/key") + 1)]; sprintf(keyname, "/secure/%s/key", group->GetName()); PTP::Collection::Entry *entry = new PTP::Collection::Entry(keyname, data, size); trut->m_collect.Add(entry); delete [] keyname; if (group->m_join) { (*group->m_join)(group, JOIN_OK, group->m_context); } } break; default: if (group->m_join) (*group->m_join)(group, JOIN_ERROR, group->m_context); break; }}/** * Trut::FindGroup: Locate group by name. * @name: Group name. * Returns: Group. */Trut::Group *Trut::FindGroup(const char *name){ if (!name) return NULL; Group *group; m_groups.Lock(); PTP_LIST_FOREACH(Group, group, &m_groups) { if (strcmp(group->GetName(), name) == 0) break; } m_groups.Unlock(); return group;}/** * Trut::LeaveGroup: Leave secure group. * @group: Group. */voidTrut::LeaveGroup(Group *group){ if (!group) return; m_groups.Remove(group); delete group;}/** * Trut::LeaveAllGroups: Leave all secure groups. */voidTrut::LeaveAllGroups(){ Group *group; m_groups.Lock(); PTP_LIST_FOREACH(Group, group, &m_groups) { m_groups.Remove(group, 0); delete group; } m_groups.Unlock();}/** * Trut::AddShared: Share directory files with a group. * @path: Directory pathname. * @ext: File extension list. * @group: Group. * Returns: Shared directory information. */Trut::Shared *Trut::AddShared(const char *path, const char *ext, Group *group){ Shared *shared = new Shared; shared->m_path = strdup(path); shared->m_ext = ext ? strdup(ext):NULL; shared->m_group = group; m_shared.Insert(shared); m_collect.Add(shared->GetPath(), shared->GetExt(), group); RescanAllShared(); return shared;}/** * Trut::RemoveShared: Remove directory from shared list. * @shared: Shared directory information. */voidTrut::RemoveShared(Shared *shared){ m_shared.Remove(shared); m_collect.Remove(shared->GetPath()); RescanAllShared(); delete shared;}/** * Trut::UpdateShared: Update shared directory information. * @shared: Shared directory information. * @ext: File extension list. * @group: Group. */voidTrut::UpdateShared(Shared *shared, const char *ext, Group *group){ m_collect.Remove(shared->GetPath()); delete [] shared->m_ext; shared->m_ext = ext ? strdup(ext):NULL; shared->m_group = group; m_collect.Add(shared->GetPath(), shared->GetExt(), group); RescanAllShared();}/** * Trut::RescanAllShared: Scan shared directories for matching files. */voidTrut::RescanAllShared(){ m_collect.Rescan();}/** * Trut::RemoveAllShared: Remove all directories from shared list. */voidTrut::RemoveAllShared(){ Shared *shared; m_shared.Lock(); PTP_LIST_FOREACH(Shared, shared, &m_shared) { m_collect.Remove(shared->GetPath()); m_shared.Remove(shared, 0); delete shared; } m_shared.Unlock();}/* * Trut::HandleSearchResponse: Handle a search response. * @host: Source of response. * @resp: Response packet. * Returns: 0 on success or -1 on invalid search response. */intTrut::HandleSearchResponse(Host *host, Gnutella::SearchResp *resp){ SearchContext *search; m_searches.Lock(); PTP_LIST_FOREACH(SearchContext, search, &m_searches) { if (memcmp(search->m_guid, resp->guid, sizeof(search->m_guid)) == 0) break; } m_searches.Unlock(); if (!search) return -1; if (search->m_group) { BYTE *data = (BYTE*) resp + sizeof(Gnutella::Packet); int size = Gnutella::Get32(resp->size); size = search->m_group->m_key->Decrypt(data, size, data); if (size <= 0) return -1; Gnutella::Set32(resp->size, size); } if (!search->m_callback) return 0; Gnutella::SearchEntry *entry = (Gnutella::SearchEntry*)(resp + 1); for (int i = 0; i < resp->count; i++) { File *file = new File; file->m_trut = this; file->m_name = strdup(entry->name); file->m_size = Gnutella::Get32(entry->size); file->m_ref = Gnutella::Get32(entry->ref); file->m_ip = ntohl(Gnutella::Get32(resp->ip)); file->m_port = Gnutella::Get16(resp->port); file->m_speed = Gnutella::Get32(resp->speed); file->m_group = search->m_group; (*search->m_callback)(file, search->m_context); entry = entry->GetNext(); } return 0;}/** * Trut::HandleSearchRequest: Handle a search request. * @host: Request source. * @rqst: Search request. * Returns: 0 on success or -1 on error. */intTrut::HandleSearchRequest(Host *host, Gnutella::SearchRqst *rqst){ char *str = rqst->search; BYTE *plain = NULL; Group *group = NULL; int key = 0; if (STRNCMP_CONST(str, "/secure/") == 0) { char *start = str + STRLEN_CONST("/secure/"); char *end = strchr(start, '/'); if (!end) return -1; *end = '\0'; group = FindGroup(start); *end = '/'; start = end + 1; key = (strcmp(start, "key") == 0); if (key) group = NULL; if (group) { int ciphersize = strlen(start); int plainsize = group->m_key->Decrypt( NULL, ciphersize >> 1, NULL); plain = new BYTE[ciphersize + 4]; ciphersize = PTP::Encoding::DecodeBase64( start, ciphersize, plain); plainsize = group->m_key->Decrypt(plain, ciphersize, plain); if (plainsize < 0) { delete [] plain; return 0; } plain[plainsize] = '\0'; str = (char*) plain; } } PTP::Collection::Entry *entry = NULL; int size = ((sizeof(Gnutella::SearchResp) + sizeof(Gnutella::SearchTrailer))); int count = 0; for (;;) { entry = m_collect.Find(str, entry); if (!entry) break; if (entry->GetContext() == (void*) group) { const char *name = key ? "key":entry->GetName(); size += (sizeof(Gnutella::SearchEntry) + strlen(name)); count++; } } if (!count) { delete [] plain; return 0; } int osize = size; if (group) { size -= sizeof(Gnutella::Packet); size = group->m_key->Encrypt(NULL, size, NULL); size += sizeof(Gnutella::Packet); } Gnutella::SearchResp *resp = (Gnutella::SearchResp*) new BYTE[size]; memset(resp, 0, size); memcpy(resp->guid, rqst->guid, sizeof(resp->guid)); resp->type = Gnutella::SEARCH_RESPONSE; resp->ttl = Gnutella::DEFAULT_TTL; resp->hops = 0; Gnutella::Set32(resp->size, size - sizeof(Gnutella::Packet)); resp->count = count; Gnutella::Set16(resp->port, m_port); Gnutella::Set32(resp->ip, htonl(m_ip)); Gnutella::Set32(resp->speed, 0); Gnutella::SearchEntry *srch = (Gnutella::SearchEntry*)(resp + 1); entry = NULL; for (;;) { entry = m_collect.Find(str, entry); if (!entry) break; if (entry->GetContext() == (void*) group) { const char *name = key ? "key":entry->GetName(); Gnutella::Set32(srch->ref, entry->GetId()); Gnutella::Set32(srch->size, entry->GetSize()); strcpy(srch->name, name); srch = srch->GetNext(); } } delete [] plain; Gnutella::SearchTrailer *trailer = (Gnutella::SearchTrailer*) srch; PTP::Random::Fill(trailer->guid, sizeof(trailer->guid)); if (group) { BYTE *data = (BYTE*) resp + sizeof(Gnutella::Packet); int size = osize - sizeof(Gnutella::Packet); size = group->m_key->Encrypt(data, size, data); } host->SendGnutella((const BYTE*) resp); delete [] ((BYTE*) resp); return 0;}/** * Trut::GetRead: Read data from network. * @buffer: [!OUT] Data buffer. * @size: Data size. * @context: Transfer context. * Returns: Read size. */intTrut::GetRead(BYTE *buffer, int size, void *context){ TransferContext *ctx = (TransferContext*) context; int s = ctx->conn->Read(buffer, size); return s;}/** * Trut::GetWrite: Write data to a file. * @buffer: Data buffer. * @size: Data size. * @context: Transfer context. * Returns: Write size. */intTrut::GetWrite(const BYTE *buffer, int size, void *context){ TransferContext *ctx = (TransferContext*) context; int s = fwrite(buffer, 1, size, ctx->fp); if (s >= 0) { ctx->size += s; if (ctx->callback) { (*ctx->callback)(ctx->file, Trut::GET_OK, NULL, ctx->size, ctx->context); } } return s;}/** * Trut::PutRead: Read data from a file. * @buffer: [!OUT] Data buffer. * @size: Data size. * @context: Transfer context. * Returns: Read size. */intTrut::PutRead(BYTE *buffer, int size, void *context){ TransferContext *ctx = (TransferContext*) context; return fread(buffer, 1, size, ctx->fp);}/** * Trut::PutWrite: Write data to the network. * @buffer: Data buffer. * @size: Data size. * @context: Transfer context. * Returns: Write size. */intTrut::PutWrite(const BYTE *buffer, int size, void *context){ TransferContext *ctx = (TransferContext*) context; return ctx->conn->WriteAll(buffer, size);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -