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

📄 upnpnat.cpp

📁 这是一个嵌入式linux系统下的BT下载工具包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** *   Copyright (C) 2005-2006 Gao Xianchao                                  * *                 2007 Gao Xianchao gnap_an linux_lyb ahlongxp            * *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * *   This program is distributed in the hope that it will be useful,       * *   but WITHOUT ANY WARRANTY; without even the implied warranty of        * *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         * *   GNU General Public License for more details.                          * *                                                                         * *   You should have received a copy of the GNU General Public License     * *   along with this program; if not, write to the                         * *   Free Software Foundation, Inc.,                                       * *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             * ***************************************************************************/#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <glib.h>#include "UPnpNat.h"#include "log.h"#include "utils.h"/***************************************************************** General Defines                                             *****************************************************************/#define HTTP_OK "200 OK"#define DEFAULT_HTTP_PORT 80#define MAX_PORT_SIZE 6#define SIZEOF_HTTP 7         /* size of "http://" string */#define RECEIVE_TIMEOUT 10000#define CONSECUTIVE_RECEIVE_TIMEOUT 500#define DISCOVERY_TIMEOUT 1000/***************************************************************** Discovery/Description Defines                               *****************************************************************/#define NUM_UDP_ATTEMPTS 2/* Address and port of an SSDP request used for discovery */#define HTTPMU_HOST_ADDRESS "239.255.255.250"#define HTTPMU_HOST_PORT 1900#define SEARCH_REQUEST_DEVICE "urn:schemas-upnp-org:service:%s"#define SEARCH_REQUEST_STRING "M-SEARCH * HTTP/1.1\r\n"            \                              "HOST: 239.255.255.250:1900\r\n"     \                              "ST:upnp:rootdevice\r\n"          \                              "Man:\"ssdp:discover\"\r\n"  \                              "MX: 3\r\n"                          \                              "\r\n"#define MAX_DISCOVERY_RECEIVE_SIZE 400#define MAX_DESCRIPTION_RECEIVE_SIZE 7000#define MAX_DESCRIPTION_HTTP_HEADER_SIZE 100/******************************************************************** Action Defines                                                 ********************************************************************/#define HTTP_HEADER_ACTION "POST %s HTTP/1.1\r\n"                         \                           "HOST: %s\r\n"                                  \                           "SOAPACTION: "                                  \                           "\"urn:schemas-upnp-org:"                       \                           "service:%s#%s\"\r\n"                           \                           "CONTENT-TYPE: text/xml ; charset=\"utf-8\"\r\n"\                           "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n"#define SOAP_ACTION  "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"     \                     "<s:Envelope xmlns:s="                               \                     "\"http://schemas.xmlsoap.org/soap/envelope/\" "     \                     "s:encodingStyle="                                   \                     "\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n" \                     "<s:Body>\r\n"                                       \                     "<u:%s xmlns:u="                                     \                     "\"urn:schemas-upnp-org:service:%s\">\r\n%s"         \                     "</u:%s>\r\n"                                        \                     "</s:Body>\r\n"                                      \                     "</s:Envelope>\r\n"#define PORT_MAPPING_LEASE_TIME "0"#define PORT_MAPPING_DESCRIPTION "BitStorm"#define ADD_PORT_MAPPING_PARAMS "<NewRemoteHost></NewRemoteHost>\r\n"      \                                "<NewExternalPort>%i</NewExternalPort>\r\n"\                                "<NewProtocol>%s</NewProtocol>\r\n"        \                                "<NewInternalPort>%i</NewInternalPort>\r\n"\                                "<NewInternalClient>%s"                    \                                "</NewInternalClient>\r\n"                 \                                "<NewEnabled>1</NewEnabled>\r\n"           \                                "<NewPortMappingDescription>"              \                                PORT_MAPPING_DESCRIPTION                   \                                "</NewPortMappingDescription>\r\n"         \                                "<NewLeaseDuration>"                       \                                PORT_MAPPING_LEASE_TIME                    \                                "</NewLeaseDuration>\r\n"#define DELETE_PORT_MAPPING_PARAMS "<NewRemoteHost></NewRemoteHost>\r\n" \                                   "<NewExternalPort>%i"                 \                                   "</NewExternalPort>\r\n"              \                                   "<NewProtocol>%s</NewProtocol>\r\n"                                   #define wanIP  "WANIPConnection:1"#define wanPPP  "WANPPPConnection:1"                                   // class CUPnpNatExplorerCUPnpNatExplorer::CUPnpNatExplorer(): _reactor(NULL), _eventHandler(NULL), _discoverTimerID(0), _found(false){}CUPnpNatExplorer::~CUPnpNatExplorer(){}void CUPnpNatExplorer::setSocketReactor(ISocketReactor* reactor){	_reactor = reactor;}void CUPnpNatExplorer::setEventHandler(IUPnpNatExplorerEventHandler* handler){	_eventHandler = handler;}void CUPnpNatExplorer::start(){	LOG_DEBUG("CUPnpNatExplorer::start");		_found = false;		CSocket::setReactor(NULL);	CSocket::close();	CSocket::createUDPSocket();	CSocket::setReactor(_reactor);			discover();}void CUPnpNatExplorer::stop(){	CSocket::setReactor(NULL);	CSocket::close();	}void CUPnpNatExplorer::discover(){	struct sockaddr_in server;	memset(&server, 0, sizeof(server));	server.sin_family = AF_INET;	server.sin_addr.s_addr = inet_addr(HTTPMU_HOST_ADDRESS);	server.sin_port = htons(HTTPMU_HOST_PORT);		std::string sendBuffer = SEARCH_REQUEST_STRING;		CSocket::maskRead(true);	sendto(getHandle(), sendBuffer.data(), sendBuffer.size(), 0, (const struct sockaddr*)&server, sizeof(server));				if(_discoverTimerID != 0)	{		_reactor->removeTimer(_discoverTimerID);	}	_discoverTimerID = _reactor->addTimer(this, 5000, true);	 }void CUPnpNatExplorer::parseDiscoverReponse(char* buffer, int len){	LOG_DEBUG("CUPnpNatExplorer::parseDiscoverReponse");	LOG_DEBUG("response = "<<buffer);		gchar* buf = buffer;	gchar* startDescURL;	gchar* endDescURL;	gchar* descURL;		if(g_strstr_len(buf, strlen(buf), HTTP_OK) == NULL)	{		return;	}		if((startDescURL = g_strstr_len(buf, strlen(buf), "http://")) == NULL)	{		return;	}		endDescURL = g_strstr_len(startDescURL, strlen(startDescURL), "\r");	if(endDescURL == NULL)	{		endDescURL = g_strstr_len(startDescURL, strlen(startDescURL), "\n");		if(endDescURL == NULL)		{			return;		} else if(endDescURL == startDescURL)		{			return;	    }	} else if(endDescURL == startDescURL)	{		return;	}		descURL = g_strndup(startDescURL, endDescURL-startDescURL);	LOG_DEBUG("descURL="<<descURL);	_found = true;	if(_eventHandler != NULL)		{		_eventHandler->OnGetDescriptionUrl(descURL);	}	g_free(descURL);	}int CUPnpNatExplorer::handleRead(){	struct sockaddr_in from;	socklen_t length = sizeof(struct sockaddr_in);	char* buffer = new char[MAX_DISCOVERY_RECEIVE_SIZE];	int ret = 0;	for(;;)	{		ret = recvfrom(getHandle(), buffer, MAX_DISCOVERY_RECEIVE_SIZE, 0, (struct sockaddr*)&from, &length);		if(ret == -1			&& errno == EINTR)		{			continue;		}		break;	}		if(ret > 0)	{		buffer[ret] = 0;		parseDiscoverReponse(buffer, ret);		}		delete[] buffer;		return 0;}int CUPnpNatExplorer::handleWrite(){	return 0;}void CUPnpNatExplorer::handleClose(){	CSocket::setReactor(NULL);	CSocket::close();}void CUPnpNatExplorer::onTimer(unsigned int id){	if(id == _discoverTimerID)	{		if(!_found)		{			discover();		}	}}CUPnpNatDescriptionParser::CUPnpNatDescriptionParser(): _reactor(NULL), _eventHandler(NULL), _timeoutTimerID(0), _state(DPS_INIT){}CUPnpNatDescriptionParser::~CUPnpNatDescriptionParser(){}void CUPnpNatDescriptionParser::setSocketReactor(ISocketReactor* reactor){	_reactor = reactor;}void CUPnpNatDescriptionParser::setDescriptionUrl(const char* url){	_url = url;}void CUPnpNatDescriptionParser::setEventHandler(IUPnpNatDescriptionParserEventHandler* handler){	_eventHandler = handler;}void CUPnpNatDescriptionParser::start(){	_timeoutTimerID = _reactor->addTimer(this, 5000, true);	connect();	_state = DPS_WORKING;}void CUPnpNatDescriptionParser::stop(){	if(_timeoutTimerID != 0)	{		_reactor->removeTimer(_timeoutTimerID);		_timeoutTimerID = 0;	}		CSocket::setReactor(NULL);	CSocket::close();}int CUPnpNatDescriptionParser::handleRead(){	char buffer[1024];	for(;;)	{		int ret = recv(getHandle(), buffer, sizeof(buffer), 0);		LOG_DEBUG("recv return "<<ret);		if(ret == 0)		{			maskRead(false);			return -1;		}				if(ret == -1)		{			if(errno == EINTR)			{				continue;			}						if(errno != EAGAIN)			{				maskRead(false);				return -1;			}			break;		}				if(ret > 0)		{			_recvBuffer.append(buffer, ret);		}	}			return 0;}int CUPnpNatDescriptionParser::handleWrite(){	LOG_DEBUG("CUPnpNatDescriptionParser::handleWrite");		sendRequest();	maskWrite(false);		return 0;}void CUPnpNatDescriptionParser::handleClose(){	LOG_DEBUG("CUPnpNatDescriptionParser::handleClose");		bool parseResult = false;		if(_recvBuffer.size() > 0)	{		char str[1024];		std::string ip;		std::string path;		unsigned short port;		parseUrl(_url.c_str(), ip, &port, path);						sprintf(str, "http://%s:%d", ip.c_str(), port);				parseResult= parseResponse(_recvBuffer.c_str(), str, wanIP);		if(!parseResult)		{			parseResult = parseResponse(_recvBuffer.c_str(), str, wanPPP);		}	}		if(!parseResult)	{		_state = DPS_ERROR;	}	else	{		_state = DPS_OK;	}		CSocket::setReactor(NULL);	CSocket::close();}void CUPnpNatDescriptionParser::onTimer(unsigned int id){	if( id == _timeoutTimerID)	{		handleClose();		_timeoutTimerID = 0;			}}void CUPnpNatDescriptionParser::connect(){	std::string ip;	std::string path;	unsigned short port;	parseUrl(_url.c_str(), ip, &port, path);		LOG_DEBUG("ip="<<ip<<" port="<<port<<" path="<<path);		CSocket::createTCPSocket();	CSocket::setReactor(_reactor);	CSocket::connect(ip.c_str(), port);	CSocket::maskWrite(true);		}void CUPnpNatDescriptionParser::sendRequest(){	std::string ip;	std::string path;	unsigned short port;	parseUrl(_url.c_str(), ip, &port, path);		gchar* httpRequest = g_strdup_printf("GET %s HTTP/1.1\r\nHost: %s:%d\r\n\r\n",                    path.c_str(), ip.c_str(), port);   LOG_DEBUG("httpRequest="<<httpRequest);   send(getHandle(), httpRequest, strlen(httpRequest), 0);   g_free(httpRequest);   maskRead(true);	}bool CUPnpNatDescriptionParser::parseResponse(const char* response, const char* httpUrl, const char* serviceType){  gchar* httpResponse = (gchar*)response;  gchar* httpURL = (gchar*)httpUrl;  gchar* xmlRoot;  gchar* baseURL;  gchar* controlURL;  gchar* service;  xmlnode* xmlRootNode;  xmlnode* serviceTypeNode;  xmlnode* controlURLNode;  xmlnode* baseURLNode;  // LOG_DEBUG("response = \n"<<response);  /* make sure we have a valid http response */  if(g_strstr_len(httpResponse, strlen(httpResponse), HTTP_OK) == NULL)  {  	return false;  }  /* find the root of the xml document */  if((xmlRoot = g_strstr_len(httpResponse, strlen(httpResponse), "<root")) == NULL)  {  	return false;  }  /* create the xml root node */  if((xmlRootNode = xmlnode_from_str(xmlRoot, size_t(-1))) == NULL)  {  	return false;  }

⌨️ 快捷键说明

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