📄 trut.cpp
字号:
default: break; } } delete [] ((BYTE*) pkt); } host->m_trut->m_hosts.Remove(host); if (host->m_trut->m_close) (*host->m_trut->m_close)(host, host->m_context); delete host; PTP::Thread::Exit(0); return NULL;}/** * Trut::RemoveHost: Destroy a client connection. * @host: Client connection. */voidTrut::RemoveHost(Host *host){ m_hosts.Remove(host); host->m_thread.Kill(); if (m_close) (*m_close)(host, host->m_context); delete host;}/** * Trut::RemoveAllHosts: Destroy all client connections. */voidTrut::RemoveAllHosts(){ Host *host; m_hosts.Lock(); PTP_LIST_FOREACH(Host, host, &m_hosts) { m_hosts.Remove(host, 0); host->m_thread.Kill(); if (m_close) (*m_close)(host, host->m_context); delete host; } m_hosts.Unlock();}/** * Trut::GetHosts: Enumerate clients connections. * @callback: Connection callback. */voidTrut::GetHosts(void (*callback)(Host *host)){ if (!callback) return; Host *host; m_hosts.Lock(); PTP_LIST_FOREACH(Host, host, &m_hosts) { (*callback)(host); } m_hosts.Unlock();}/** * Trut::Search: Send a search request. * @str: Search string. * @callback: Search response callback. * @context: Callback context. * @group: Search group. */voidTrut::Search(const char *str, SearchCallback callback, void *context, Group *group){ if (!str || !callback) return; SearchContext *entry = new SearchContext; memset(entry, 0, sizeof(*entry)); PTP::Random::Fill(entry->m_guid, sizeof(entry->m_guid)); entry->m_callback = callback; entry->m_context = context; entry->m_group = group; m_searches.Insert(entry); BYTE *cipher = NULL; if (entry->m_group && entry->m_group->m_key) { int hdrsize = (STRLEN_CONST("/secure/") + strlen(entry->m_group->GetName()) + 1); int encsize = entry->m_group->m_key->Encrypt( NULL, strlen(str), NULL); cipher = new BYTE[hdrsize + (encsize * 2) + 4]; sprintf((char*) cipher, "/secure/%s/", entry->m_group->GetName()); entry->m_group->m_key->Encrypt( (const BYTE*) str, strlen(str), cipher + hdrsize); PTP::Encoding::EncodeBase64( cipher + hdrsize, encsize, (char*)(cipher + hdrsize), encsize); str = (const char*) cipher; } int size = sizeof(Gnutella::SearchRqst) + strlen(str) + 1; BYTE *buffer = new BYTE[size]; memset(buffer, 0, size); Gnutella::SearchRqst *rqst = (Gnutella::SearchRqst*) buffer; memcpy(rqst->guid, entry->m_guid, sizeof(rqst->guid)); rqst->type = Gnutella::SEARCH_REQUEST; rqst->ttl = Gnutella::DEFAULT_TTL; rqst->hops = 0; Gnutella::Set32(rqst->size, size - sizeof(Gnutella::Packet)); Gnutella::Set16(rqst->speed, 0); strcpy(rqst->search, str); delete [] cipher; Host *host; m_hosts.Lock(); PTP_LIST_FOREACH(Host, host, &m_hosts) { host->SendGnutella(buffer); } m_hosts.Unlock(); delete [] buffer;}/** * Trut::SearchStop: Terminate a search request. * @context: Search callback context. */voidTrut::SearchStop(void *context){ SearchContext *search; m_searches.Lock(); PTP_LIST_FOREACH(SearchContext, search, &m_searches) { if (context && search->m_context != context) continue; m_searches.Remove(search, 0); delete search; } m_searches.Unlock();}/* * Trut::GetAuth: Handle client-side authentication. * @conn: Client connection. * @rqst: HTTP request. * Returns: 0 on success or -1 on failed authentication. */intTrut::GetAuth(PTP::Net::Connection *conn, const BYTE *rqst){ int secure = (STRNCMP_CONST(rqst, "GET /gets/") == 0); char *hdr = new char[HEADER_SIZE]; strcpy(hdr, (char*) rqst); BYTE key[PTP::Identity::KEY_SIZE]; m_local->GetKey(key); if (secure) AppendAuthValue(hdr, "Identity", key, sizeof(key)); strcat(hdr, "\r\n"); conn->WriteAll((BYTE*) hdr, strlen(hdr)); if (!conn->ReadHttpHdr(hdr, HEADER_SIZE)) { delete [] hdr; return -1; } if (!secure) { conn->Unget((BYTE*) hdr, strlen(hdr)); delete [] hdr; return 0; } conn->Close(); BYTE rkey[PTP::Identity::KEY_SIZE]; BYTE rchal[PTP::Authenticator::CHALLENGE_SIZE]; if (GetAuthValue(hdr, "Identity", rkey, sizeof(rkey)) || GetAuthValue(hdr, "Challenge", rchal, sizeof(rchal))) { delete [] hdr; return -1; } const PTP::Identity *rid = m_store->Find(NULL, 0, rkey); if (!rid) { delete [] hdr; return -1; } strcpy(hdr, (char*) rqst); BYTE chal[PTP::Authenticator::CHALLENGE_SIZE]; m_auth->Challenge(rid, CHALLENGE_TIME, (void*) rid, chal); AppendAuthValue(hdr, "Challenge", chal, sizeof(chal)); BYTE resp[PTP::Authenticator::RESPONSE_SIZE]; m_auth->Respond(rchal, resp); AppendAuthValue(hdr, "Response", resp, sizeof(resp)); strcat(hdr, "\r\n"); conn->WriteAll((BYTE*) hdr, strlen(hdr)); if (!conn->ReadHttpHdr(hdr, HEADER_SIZE)) { delete [] hdr; return -1; } BYTE rresp[PTP::Authenticator::RESPONSE_SIZE]; if (GetAuthValue(hdr, "Response", rresp, sizeof(rresp)) || m_auth->Verify(rresp) == NULL) { delete [] hdr; return -1; } conn->Unget((BYTE*) hdr, strlen(hdr)); delete [] hdr; return 0;}/* * Trut::PutAuth: Handle server-side authentication. * @conn: Client connection. * @id: [!OUT] Client identity. * @rsp: [!OUT] Authentication response. * Returns: 0 on success or -1 on failed or partial authentication. */intTrut::PutAuth(PTP::Net::Connection *conn, const PTP::Identity **id, BYTE *rsp){ const char *rqst = "HTTP/1.1 401 Unauthorized\r\n" "Connection: Keep-Alive\r\n"; rsp[0] = '\0'; char *hdr = new char[HEADER_SIZE]; if (!conn->ReadHttpHdr(hdr, HEADER_SIZE)) { delete [] hdr; return -1; } int secure = (STRNCMP_CONST(hdr, "GET /gets/") == 0); if (!secure) { conn->Unget((BYTE*) hdr, strlen(hdr)); delete [] hdr; return 0; } BYTE rkey[PTP::Identity::KEY_SIZE]; if (GetAuthValue(hdr, "Identity", rkey, sizeof(rkey)) == 0) { const PTP::Identity *rid = m_store->Find(NULL, 0, rkey); if (!rid) { delete [] hdr; return -1; } strcpy(hdr, rqst); BYTE key[PTP::Identity::KEY_SIZE]; m_local->GetKey(key); AppendAuthValue(hdr, "Identity", key, sizeof(key)); BYTE chal[PTP::Authenticator::CHALLENGE_SIZE]; m_auth->Challenge(rid, CHALLENGE_TIME, (void*) rid, chal); AppendAuthValue(hdr, "Challenge", chal, sizeof(chal)); strcat(hdr, "\r\n"); conn->WriteAll((BYTE*) hdr, strlen(hdr)); delete [] hdr; return -1; } BYTE rresp[PTP::Authenticator::RESPONSE_SIZE]; BYTE rchal[PTP::Authenticator::CHALLENGE_SIZE]; if (GetAuthValue(hdr, "Response", rresp, sizeof(rresp)) || GetAuthValue(hdr, "Challenge", rchal, sizeof(rchal))) { delete [] hdr; return -1; } const PTP::Identity *rid = (const PTP::Identity*) m_auth->Verify(rresp); if (!rid) { delete [] hdr; return -1; } conn->Unget((BYTE*) hdr, strlen(hdr)); strcpy(hdr, rqst); BYTE resp[PTP::Authenticator::RESPONSE_SIZE]; m_auth->Respond(rchal, resp); AppendAuthValue((char*) rsp, "Response", resp, sizeof(resp)); *id = rid; delete [] hdr; return 0;}/* * Trut::GetAuthValue: Retrieve HTTP header value. * @hdr: HTTP header. * @name: Value name. * @value: [!OUT] Value data. * @size: Expected value size. * Returns: 0 on sucess or -1 on error. */intTrut::GetAuthValue(const char *hdr, const char *name, BYTE *value, int size){ int namesize = strlen(name); char *start = (char*) hdr; for (;;) { start = strstr(start, name); if (!start) return -1; start += namesize; if (*start == ':') break; } start++; start += strspn(start, " \t"); char *end = start + strspn(start, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"); int valuesize = end - start; valuesize = PTP::Encoding::DecodeBase64(start, valuesize, value); return 0;}/* * Trut::AppendAuthValue: Add HTTP header value. * @hdr: [!OUT] HTTP header. * @name: Value name. * @value: Value data. * @size: Value size. */voidTrut::AppendAuthValue(char *hdr, const char *name, const BYTE *value, int size){ strcat(hdr, name); strcat(hdr, ": "); hdr += strlen(hdr); PTP::Encoding::EncodeBase64(value, size, hdr, size); strcat(hdr, "\r\n");}/** * Trut::Get: Retrieve file. * @file: File. * @path: Destination file name. * @callback: Get callback. * @context: Callback context. */voidTrut::Get(File *file, const char *path, GetCallback callback, void *context){ GetContext *get = new GetContext; get->m_trut = this; get->m_file = file; get->m_path = path ? strdup(path):NULL; get->m_callback = callback; get->m_context = context; get->m_conn = new PTP::Net::Connection( PTP::Net::Connection::HTTP, file->GetIp(), file->GetPort()); const Group *group = file->GetGroup(); get->m_key = group ? group->m_key:NULL; get->m_id = NULL; char *hdr = new char[HEADER_SIZE]; if (group) { if (strcmp(file->GetName(), "key") == 0) get->m_id = m_local; sprintf(hdr, "GET /gets/%s/%04lx HTTP/1.0\r\n" "Connection: Keep-Alive\r\n", group->GetName(), file->m_ref); } else { sprintf(hdr, "GET /get/%lu/%s HTTP/1.0\r\n" "Connection: Keep-Alive\r\n", file->m_ref, file->GetName()); } int status = 0; int size = 0; if (GetAuth(get->m_conn, (BYTE*) hdr) || !get->m_conn->ReadHttpHdr(hdr, HEADER_SIZE, &status, &size) || status != PTP::Net::HTTP_OK || size <= 0) { if (get->m_callback) { (*get->m_callback)(get->m_file, GET_ERROR, NULL, 0, get->m_context); } delete [] hdr; delete get; return; } get->m_size = size; delete [] hdr; m_gets.Insert(get); get->m_thread.Start(GetThread, get);}/** * Trut::GetThread: Handle file receive. * @context: Receive context. * Returns: NULL. */void *Trut::GetThread(void *context){ GetContext *get = (GetContext*) context; int size = 0; BYTE *buffer = NULL; GetStatus status = GET_ERROR; if (get->m_path) { TransferContext ctx(fopen(get->m_path, "wb"), get->m_conn); ctx.callback = get->m_callback; ctx.file = get->m_file; ctx.context = get->m_context; ctx.size = 0; if (ctx.fp) { if (get->m_key) { size = get->m_key->Decrypt(GetRead, GetWrite, &ctx); } else { size = PTP::Key::Transfer(GetRead, GetWrite, &ctx); } fclose(ctx.fp); status = GET_DONE; } } else { buffer = new BYTE[get->m_size]; size = get->m_conn->ReadAll(buffer, get->m_size); if (get->m_id) size = get->m_id->Decrypt(buffer, buffer); else if (get->m_key) size = get->m_key->Decrypt(buffer, size, buffer); status = GET_DONE; } if (size < 0) status = GET_ERROR; if (get->m_callback) { (*get->m_callback)(get->m_file, status, buffer, size, get->m_context); } delete [] buffer; get->m_trut->m_gets.Remove(get); delete get; PTP::Thread::Exit(0); return NULL;}/** * Trut::GetWait: Wait for get request to complete. * @file: File. */voidTrut::GetWait(File *file){ GetContext *get; m_gets.Lock(); PTP_LIST_FOREACH(GetContext, get, &m_gets) { if (get->m_file == file) break; } m_gets.Unlock(); if (get) get->m_thread.Wait();}/** * Trut::GetStop: Terminate get request. * @file: File. */voidTrut::GetStop(File *file){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -