⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trut.cpp

📁 一个用于点对点传输加密的工具包源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2001 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *   the documentation and/or other materials provided with the *   distribution. * * 3. Neither the name of the Intel Corporation nor the names of its *    contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *//* * trut: Trusted Gnutella client. */#include <stdio.h>#include <string.h>#include <ptp/rand.h>#include <ptp/encode.h>#include <ptp/debug.h>#include "trut.h"#define STRLEN_CONST(x) (sizeof(x) - 1)#define STRNCMP_CONST(x, y) strncmp((const char*)(x), (y), sizeof(y) - 1)/* * Trut::SearchContext: Pending search information. */struct Trut::SearchContext:public PTP::List::Entry{	BYTE m_guid[Gnutella::GUID_SIZE];	SearchCallback m_callback;	void *m_context;	Group *m_group;};/* * Trut::TransferContext: Pending file transfer. */struct Trut::TransferContext{	TransferContext(FILE *f, PTP::Net::Connection *c = NULL)		:fp(f), conn(c), callback(NULL), size(0) {}	FILE *fp;	PTP::Net::Connection *conn;	Trut::GetCallback callback;	Trut::File *file;	void *context;	unsigned long size;};/* * Trut::GetContext: Pending file download. */struct Trut::GetContext:public PTP::List::Entry{	GetContext():m_conn(NULL), m_path(NULL) {}	~GetContext()	{		delete [] m_path;		delete m_conn;	}	Trut *m_trut;	PTP::Key *m_key;	const PTP::Identity *m_id;	PTP::Net::Connection *m_conn;	Trut::File *m_file;	char *m_path;	Trut::GetCallback m_callback;	void *m_context;	unsigned long m_size;	PTP::Thread m_thread;};/* * Trut::PutContext: Pending file upload. */struct Trut::PutContext{	Trut::Host *m_host;	BYTE *m_resp;	const PTP::Identity *m_id;};/* * Trut::Host::SendGnutella: Send a Gnutella packet. * @pkt: Gnutella packet. */voidTrut::Host::SendGnutella(const BYTE *pkt){        int size = 0;        if (STRNCMP_CONST((char*) pkt, "GNUTELLA") != 0)        {                Gnutella::Packet *p = (Gnutella::Packet *) pkt;                size = sizeof(*p) + Gnutella::Get32(p->size);        }        else                size = strlen((char*) pkt);        m_conn->WriteAll(pkt, size);}/* * Trut::Host::ReceiveGnutella: Receive a Gnutella packet. * Returns: Gnutella packet or NULL on error. */BYTE *Trut::Host::ReceiveGnutella(){        char buffer[512];        int readsize = m_conn->Read((BYTE*) buffer, sizeof(buffer) - 1);        if (readsize <= 0)                return NULL;        int size = 0;        if (STRNCMP_CONST(buffer, GNUTELLA_CONNECT_REQUEST) != 0            && STRNCMP_CONST(buffer, GNUTELLA_CONNECT_RESPONSE) != 0)        {                Gnutella::Packet *pkt = (Gnutella::Packet*) buffer;                size = sizeof(*pkt) + Gnutella::Get32(pkt->size);        }        else        {                buffer[readsize] = '\0';                size = readsize;        }	if (size < 0)		return NULL;	        BYTE *pkt = new BYTE[size];        memcpy(pkt, buffer, readsize);        if (size > readsize	    && m_conn->ReadAll(pkt + readsize, size - readsize) < 0)        {                delete [] pkt;                pkt = NULL;        }        return pkt;}/** * Trut::Trut: Class constructor. * @store: Certificate store. */Trut::Trut(PTP::Store *store)	:m_store(store), m_open(NULL), m_close(NULL){	m_ip = PTP::Net::Lookup("localhost");	m_port = PORT_DEFAULT;	m_local = m_store->Find(NULL, 1);	m_auth = new PTP::Authenticator(m_store);}/** * Trut::~Trut: Class destructor. */Trut::~Trut(){	delete m_auth;	SearchStop();	LeaveAllGroups();	RemoveAllShared();	RemoveAllPorts();	RemoveAllHosts();}/** * Trut::AddPort: Create a new server port. * @port: TCP port number. * Returns: Port connection or NULL on error. */Trut::Port *Trut::AddPort(PTP::Net::Port port){	Port *p = new Port;	p->m_trut = this;	p->m_conn = new PTP::Net::Connection(PTP::Net::Connection::RAW,					     port ? port:PORT_DEFAULT);	if (p->m_conn->Open())	{		delete p;		return NULL;	}	m_port = (PTP::Net::Port) p->GetPort();	m_ports.Insert(p);	p->m_thread.Start(PortThread, p);	return p;}/* * Trut::PortThread: Handle server connection. * @context: Port context. * Returns: NULL. */void *Trut::PortThread(void *context){	Port *port = (Port*) context;	for (;;)	{		PTP::Net::Connection *conn = port->m_conn->Accept(1);		if (!conn)			continue;		char url[256];		sprintf(url,			"%lu.%lu.%lu.%lu:%u",			(conn->GetIp() >> 24) & 0xff,			(conn->GetIp() >> 16) & 0xff,			(conn->GetIp() >> 8) & 0xff,			(conn->GetIp() & 0xff),			conn->GetPort());		Host *host = new Host;		host->m_trut = port->m_trut;		host->m_conn = conn;		host->m_url = strdup(url);				if (host->m_conn->GetType() == PTP::Net::Connection::HTTP)		{			PutContext ctx;			ctx.m_host = host;			ctx.m_resp = new BYTE[HEADER_SIZE];			ctx.m_id = NULL;			if (host->m_trut->PutAuth(conn,						  &ctx.m_id,						  ctx.m_resp) == 0)				host->m_thread.Start(PutThread, &ctx);			else			{				delete [] ctx.m_resp;				delete host;			}		}		else		{			host->m_trut->m_hosts.Insert(host);			if (host->m_trut->m_open)				(*host->m_trut->m_open)(host,							&host->m_context);			host->m_thread.Start(HostThread, host);		}	}	port->m_trut->m_ports.Remove(port);	delete port;	PTP::Thread::Exit(0);	return NULL;}/* * Trut::PutThread: Handle file transmit. * @context: Transmit context. * Returns: NULL. */void *Trut::PutThread(void *context){	PutContext *ctx = (PutContext*) context;	Host *host = ctx->m_host;	PTP::Collection::Entry *entry = NULL;	PTP::Key *key = NULL;	int size = 0;	char *hdr = new char[HEADER_SIZE];	if (!host->m_conn->ReadHttpHdr(hdr, HEADER_SIZE))	{		delete [] hdr;		delete [] ctx->m_resp;		delete host;		PTP::Thread::Exit(0);		return NULL;	}	if (STRNCMP_CONST(hdr, "GET /get/") == 0)	{		char *start = hdr + STRLEN_CONST("GET /get/");		unsigned long ref = strtoul(start, NULL, 10);		entry = host->m_trut->m_collect.Find(ref);	}	else if (STRNCMP_CONST(hdr, "GET /gets/") == 0)	{		char *start = hdr + STRLEN_CONST("GET /gets/");		char *end = strchr(start, '/');		*end = '\0';		Group *group = host->m_trut->FindGroup(start);		if (!group || !group->m_key)			goto fail;		key = group->m_key;		start = end + 1;		unsigned long ref = strtoul(start, NULL, 16);		entry = host->m_trut->m_collect.Find(ref);		start = (char*) entry->GetName();		end = strrchr(start, '/');		int iskey = (strncmp(start, "/secure/", 8) == 0			     && end			     && strcmp(end + 1, "key") == 0);		if (iskey)			key = NULL;		if (iskey		    && group->m_accept		    && ctx->m_id		    && (*group->m_accept)(group,					  ctx->m_id->GetName(),					  group->m_context) == 0)			goto fail;	}	else		goto fail;	if (!entry)		goto fail;	// get data size	size = entry->GetSize();	if (ctx->m_id)	{		size = PTP::Identity::CIPHERTEXT_SIZE;	}	else if (key)	{		if (entry->GetPath())		{			TransferContext ctx(fopen(entry->GetPath(), "rb"));			if (!ctx.fp)				goto fail;			size = key->Encrypt(PutRead, NULL, &ctx);			fclose(ctx.fp);		}		else		{			size = key->Encrypt(entry->GetData(),					    entry->GetSize(),					    NULL);		}	}	// send header	sprintf(hdr,		"HTTP 200\r\n"		"Content-type:application/binary\r\n"		"Content-length:%d\r\n"		"%s\r\n",		size,		ctx->m_resp);	host->m_conn->WriteAll((BYTE*) hdr, strlen(hdr));	// send data	if (entry->GetPath())	{		TransferContext ctx(fopen(entry->GetPath(), "rb"),				    host->m_conn);		if (!ctx.fp)			goto fail;		if (key)			key->Encrypt(PutRead, PutWrite, &ctx);		else			PTP::Key::Transfer(PutRead, PutWrite, &ctx);		fclose(ctx.fp);	}	else	{		if (ctx->m_id)		{			BYTE buffer[PTP::Identity::CIPHERTEXT_SIZE];			ctx->m_id->Encrypt(entry->GetData(),					   entry->GetSize(),					   buffer);			host->m_conn->WriteAll(buffer, sizeof(buffer));		}		else if (key)		{			BYTE *buffer = new BYTE[size];			key->Encrypt(entry->GetData(),				     entry->GetSize(),				     buffer);			host->m_conn->WriteAll(buffer, size);			delete [] buffer;		}		else		{			host->m_conn->WriteAll(entry->GetData(),					       entry->GetSize());		}	}	delete [] hdr;	delete [] ctx->m_resp;	delete host;	PTP::Thread::Exit(0);	return NULL; fail:	sprintf(hdr,		"HTTP 404\r\n"		"Content-type: text/html\r\n\r\n"		"<B>404 NOT FOUND</B>\n");	host->m_conn->WriteAll((BYTE*) hdr, strlen(hdr));	delete [] hdr;	delete [] ctx->m_resp;	delete host;	PTP::Thread::Exit(0);	return NULL;}/** * Trut::RemovePort: Destroy a server port. * @port: Port connection. */voidTrut::RemovePort(Port *port){	m_ports.Remove(port);	port->m_thread.Kill();	delete port;}/** * Trut::RemoveAllPorts: Destroy all server ports. */voidTrut::RemoveAllPorts(){	Port *port;	m_ports.Lock();	PTP_LIST_FOREACH(Port, port, &m_ports)        {		m_ports.Remove(port, 0);		port->m_thread.Kill();		delete port;	}	m_ports.Unlock();}/** * Trut::AddHost: Create a new Gnutella connection. * @url: Destination URL. * Returns: Client connection or NULL on error. */Trut::Host *Trut::AddHost(const char *url){	PTP::Net::Port port;	PTP::Net::Ip ip = PTP::Net::Lookup(url, &port, PORT_DEFAULT);	if (!ip)		return NULL;	Host *host = new Host;	host->m_trut = this;	host->m_url = strdup(url);	host->m_conn = new PTP::Net::Connection(PTP::Net::Connection::RAW,						ip,						port);	host->SendGnutella((BYTE*) GNUTELLA_CONNECT_REQUEST);	BYTE *pkt = host->ReceiveGnutella();	int ok = (pkt && STRNCMP_CONST((char*) pkt,				       GNUTELLA_CONNECT_RESPONSE) == 0);	delete [] pkt;	if (!ok)	{		delete host;		return NULL;	}	m_hosts.Insert(host);	if (m_open)		(*m_open)(host, &host->m_context);	host->m_thread.Start(HostThread, host);	return host;}/* * Trut::HostThread: Handle client connection. * @context: Client context. * Returns: NULL. */void *Trut::HostThread(void *context){	Host *host = (Host*) context;	for (;;)	{		Gnutella::Packet *pkt			= (Gnutella::Packet*) host->ReceiveGnutella();		if (!pkt)			break;				if (STRNCMP_CONST((char*) pkt, GNUTELLA_CONNECT_REQUEST) == 0)		{			host->SendGnutella((BYTE*) GNUTELLA_CONNECT_RESPONSE);		}		else		{			switch (pkt->type)			{			case Gnutella::SEARCH_RESPONSE:				host->m_trut->HandleSearchResponse(					host,					(Gnutella::SearchResp*) pkt);				break;			case Gnutella::SEARCH_REQUEST:				host->m_trut->HandleSearchRequest(					host,					(Gnutella::SearchRqst*) pkt);				break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -