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

📄 upnp.cpp

📁 非常难得的eMule(电骡) V0.45b 源码下载 值得研究
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"

#include "upnp.h"

#define UPNPPORTMAP0   _T("WANIPConnection")
#define UPNPPORTMAP1   _T("WANPPPConnection")
#define UPNPGETEXTERNALIP _T("GetExternalIPAddress"),_T("NewExternalIPAddress")
#define UPNPADDPORTMAP _T("AddPortMapping")
#define UPNPDELPORTMAP _T("DeletePortMapping")

static const ulong	UPNPADDR = 0xFAFFFFEF;
static const int	UPNPPORT = 1900;
static const CString	URNPREFIX = _T("urn:schemas-upnp-org:");

const CString getString(int i)
{
	CString s;

	s.Format(_T("%d"), i);

	return s;
}

const CString GetArgString(const CString& name, const CString& value)
{
	return _T("<") + name + _T(">") + value + _T("</") + name + _T(">");
}

const CString GetArgString(const CString& name, int value)
{
	return _T("<") + name + _T(">") + getString(value) + _T("</") + name + _T(">");
}

bool SOAP_action(CString addr, uint16 port, const CString request, CString &response)
{
	char buffer[10240];

	const CStringA sa(request);
	int length = sa.GetLength();
	strcpy(buffer, (const char*)sa);

	uint32 ip = inet_addr(CStringA(addr));
	struct sockaddr_in sockaddr;
	memset(&sockaddr, 0, sizeof(sockaddr));
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons(port);
	sockaddr.sin_addr.S_un.S_addr = ip;
	int s = socket(AF_INET, SOCK_STREAM, 0);
	u_long lv = 1;
	ioctlsocket(s, FIONBIO, &lv);
	connect(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
	Sleep(20);
	int n = send(s, buffer, length, 0);
	Sleep(100);
	int rlen = recv(s, buffer, sizeof(buffer), 0);
	closesocket(s);
	if (rlen == SOCKET_ERROR) return false;
	if (!rlen) return false;

	response = CString(CStringA(buffer, rlen));

	return true;
}

int SSDP_sendRequest(int s, uint32 ip, uint16 port, const CString& request)
{
	char buffer[10240];

	const CStringA sa(request);
	int length = sa.GetLength();
	strcpy(buffer, (const char*)sa);

	struct sockaddr_in sockaddr;
	memset(&sockaddr, 0, sizeof(sockaddr));
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons(port);
	sockaddr.sin_addr.S_un.S_addr = ip;

	return sendto(s, buffer, length, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
}

bool parseHTTPResponse(const CString& response, CString& result)
{
	int pos = 0;

	CString status = response.Tokenize(_T("\r\n"), pos);

	result = response;
	result.Delete(0, pos);

	pos = 0;
	status.Tokenize(_T(" "), pos);
	status = status.Tokenize(_T(" "), pos);
	if (status.IsEmpty() || status[0]!='2') return false;
	return true;
}

const CString getProperty(const CString& all, const CString& name)
{
	CString startTag = '<' + name + '>';
	CString endTag = _T("</") + name + '>';
	CString property;

	int posStart = all.Find(startTag);
	if (posStart<0) return CString();

	int posEnd = all.Find(endTag, posStart);
	if (posStart>=posEnd) return CString();

	return all.Mid(posStart + startTag.GetLength(), posEnd - posStart - startTag.GetLength());
}

MyUPnP::MyUPnP()
: m_version(1)
{
	m_uLocalIP = 0;
	isSearched = false;
}

MyUPnP::~MyUPnP()
{
	UPNPNAT_MAPPING search;
	POSITION pos = m_Mappings.GetHeadPosition();
	while(pos){
		search = m_Mappings.GetNext(pos);
		RemoveNATPortMapping(search, false);
	}

	m_Mappings.RemoveAll();
}


bool MyUPnP::InternalSearch(int version)
{
	if(version<=0)version = 1;
	m_version = version;

#define NUMBEROFDEVICES	2
	CString devices[][2] = {
		{UPNPPORTMAP1, _T("service")},
		{UPNPPORTMAP0, _T("service")},
		{_T("InternetGatewayDevice"), _T("device")},
	};

	int s = socket(AF_INET, SOCK_DGRAM, 0);
	u_long lv = 1;
	ioctlsocket(s, FIONBIO, &lv);

	int rlen = 0;
	for (int i=0; rlen<=0 && i<500; i++) {
		if (!(i%100)) {
			for (int i=0; i<NUMBEROFDEVICES; i++) {
				m_name.Format(_T("%s%s:%s:%d"), URNPREFIX, devices[i][1], devices[i][0], version);
				CString request;
				request.Format(_T("M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: %d\r\nST: %s\r\n\r\n"),
					6, m_name);
				SSDP_sendRequest(s, UPNPADDR, UPNPPORT, request);
			}
		}

		Sleep(10);

		char buffer[10240];
		rlen = recv(s, buffer, sizeof(buffer), 0);
		if (rlen <= 0) continue;
		closesocket(s);

		CString response = CString(CStringA(buffer, rlen));
		CString result;
		if (!parseHTTPResponse(response, result)) return false;

		for (int d=0; d<NUMBEROFDEVICES; d++) {
			m_name.Format(_T("%s%s:%s:%d"), URNPREFIX, devices[d][1], devices[d][0], version);
			if (result.Find(m_name) >= 0) {
				for (int pos = 0;;) {
					CString line = result.Tokenize(_T("\r\n"), pos);
					if (line.IsEmpty()) return false;
					CString name = line.Mid(0, 9);
					name.MakeUpper();
					if (name == _T("LOCATION:")) {
						line.Delete(0, 9);
						m_description = line;
						m_description.Trim();
						return GetDescription();
					}
				}
			}
		}
	}
	closesocket(s);

	return false;
}

bool MyUPnP::Search(int version)
{
	if (isSearched) return isComplete();

	isSearched = true;

	return InternalSearch(version);
}

static CString NGetAddressFromUrl(const CString& str, CString& post, CString& host, int& port)
{
	CString s = str;

	post = _T("");
	host = post;
	port = 0;
	int pos = s.Find(_T("://"));
	if (!pos) return CString();
	s.Delete(0, pos + 3);

	pos = s.Find('/');
	if (!pos) {
		host = s;
		s = _T("");
	} else {
		host = s.Mid(0, pos);
		s.Delete(0, pos);
	}

	if (s.IsEmpty()) {
		post = _T("");
	} else {
		post = s;
	}

	pos = 0;
	CString addr = host.Tokenize(_T(":"), pos);
	s = host.Tokenize(_T(":"), pos);
	if (s.IsEmpty()) {
		port = 80;
	} else {
		port = _tstoi(s);
	}

	return addr;
}

bool MyUPnP::GetDescription()
{
	if(!Valid())return false;
	CString post, host, addr;
	int port = 0;
	addr = NGetAddressFromUrl(m_description, post, host, port);
	if(addr.IsEmpty())return false;
	CString request = CString(_T("GET ")) + post + _T(" HTTP/1.1\r\nHOST: ") + host + _T("\r\nACCEPT-LANGUAGE: en\r\n\r\n");
	CString response;
	if (!SOAP_action(addr, port, request, response)) return false;
	CString result;
	if (!parseHTTPResponse(response, result)) return false;

	m_friendlyname = getProperty(result, _T("friendlyName"));
	m_modelname = getProperty(result, _T("modelName"));
	m_baseurl = getProperty(result, _T("URLBase"));
	if(m_baseurl.IsEmpty())m_baseurl = CString(_T("http://")) + host + _T("/");
	if(m_baseurl[m_baseurl.GetLength() - 1]!='/')m_baseurl += _T("/");
	
	CString serviceType = _T("<serviceType>") + m_name + _T("</serviceType>");
	int pos = result.Find(serviceType);
	if (pos >= 0) {
		result.Delete(0, pos + serviceType.GetLength());
		pos = result.Find(_T("</service>"));
		if (pos >= 0) {
			result = result.Mid(0, pos);
			m_controlurl = getProperty(result, _T("controlURL"));
			if (!m_controlurl.IsEmpty() && m_controlurl[0] == '/') {
				m_controlurl = m_baseurl + m_controlurl.Mid(1);
			}
		}
	}

	return isComplete();
}

CString MyUPnP::GetProperty(const CString& name, CString& response)
{
	if (!isComplete())return CString();
	CString post, host, addr;
	int port = 0;
	addr = NGetAddressFromUrl(m_controlurl, post, host, port);
	if(addr.IsEmpty())return CString();
	CString cnt;
	CString psr;
	cnt.Append(_T("<s:Envelope\r\n    xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\r\n    "));
	cnt.Append(_T("s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n  <s:Body>\r\n    <u:"));
	cnt.Append(name);
	cnt.Append(_T(" xmlns:u=\""));
	cnt.Append(m_name);
	cnt.Append(_T("\">\r\n    </u:"));
	cnt.Append(name);
	cnt.Append(_T(">\r\n  </s:Body>\r\n</s:Envelope>\r\n\r\n"));
	psr.Append(_T("POST "));
	psr.Append(post);
	psr.Append(_T(" HTTP/1.1\r\nHOST: "));
	psr.Append(host);
	psr.Append(_T("\r\nContent-Length: "));
	psr.Append(getString(CStringA(cnt).GetLength()));
	psr.Append(_T("\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nSOAPAction: \""));
	psr.Append(m_name);
	psr.Append(_T("#"));
	psr.Append(name);
	psr.Append(_T("\"\r\n\r\n"));
	psr.Append(cnt);

	CString request = psr;
	if (!SOAP_action(addr, port, request, response)) return CString();
	CString result;
	if (!parseHTTPResponse(response, result)) return CString();

	return getProperty(result, response);
}

bool MyUPnP::InvokeCommand(const CString& name, const CString& args)
{

⌨️ 快捷键说明

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