Ejemplo n.º 1
0
static bool getUPnPURLs(char* szUrl, size_t sizeUrl)
{
	char* szData = (char*)mir_alloc(8192);

	gatewayFound = httpTransact(szUrl, szData, 8192, NULL, DeviceGetReq) == 200;
	if (gatewayFound)
	{
		char szTemp[256], *rpth;
		size_t ctlLen;

		txtParseParam(szData, NULL, "<URLBase>", "</URLBase>", szTemp, sizeof(szTemp));
		strncpy(szCtlUrl, szTemp[0] ? szTemp : szUrl, sizeof(szCtlUrl));
		szCtlUrl[sizeof(szCtlUrl)-1] = 0;

		mir_snprintf(szTemp, sizeof(szTemp), search_device, szDev);
		txtParseParam(szData, szTemp, "<controlURL>", "</controlURL>", szUrl, sizeUrl);

		// URL combining per RFC 2396
		if ( szUrl[0] != 0 )
		{
			if (strstr(szUrl, "://") != NULL)                     // absolute URI
				rpth = szCtlUrl;
			else if (strncmp(szUrl, "//", 2) == 0)                // relative URI net_path
			{
				rpth = strstr(szCtlUrl, "//");
				if (rpth == NULL) rpth = szCtlUrl;
			}
			else if (szUrl[0] == '/')                             // relative URI abs_path
			{
				rpth = strstr(szCtlUrl, "//");
				rpth = rpth ? rpth + 2 : szCtlUrl;

				rpth = strchr(rpth, '/');
				if (rpth == NULL) rpth = szCtlUrl + strlen(szCtlUrl);
			}
			else
			{                                                      // relative URI rel_path
				size_t ctlCLen = strlen(szCtlUrl);
				rpth = szCtlUrl + ctlCLen;
				if (ctlCLen != 0 && *(rpth-1) != '/')
					strncpy(rpth++, "/", sizeof(szCtlUrl) - ctlCLen);
			}

			ctlLen = sizeof(szCtlUrl) - (rpth - szCtlUrl);
			strncpy(rpth, szUrl, ctlLen);
			szCtlUrl[sizeof(szCtlUrl)-1] = 0;
		}
		else
		{
			szCtlUrl[0] = 0;
			gatewayFound = false;
		}
	}
	mir_free(szData);

	return gatewayFound;
}
Ejemplo n.º 2
0
static unsigned getExtIP(void)
{
	char szExtIP[30];
	char* szData = (char*)mir_alloc(4096); szData[0] = 0;

	unsigned extip = 0;
	int res = httpTransact(szCtlUrl, szData, 4096, "GetExternalIPAddress", ControlAction);
	if (res == 200 && txtParseParam(szData, "<NewExternalIPAddress", ">", "<", szExtIP, sizeof(szExtIP)))
		extip = ntohl(inet_addr(szExtIP));

	mir_free(szData);
	return extip;
}
Ejemplo n.º 3
0
bool NetlibUPnPAddPortMapping(WORD intport, char *proto, WORD *extport, DWORD *extip, bool search)
{
	int res = 0, i = 5;

	if (findUPnPGateway())
	{
		char* szData = (char*)mir_alloc(4096);
		char szExtIP[30];

		*extport = intport - 1;
		*extip = ntohl(locIP.sin_addr.S_un.S_addr);

		WaitForSingleObject(portListMutex, INFINITE);

		do
		{
			++*extport;
			mir_snprintf(szData, 4096, add_port_mapping,
				*extport, proto, intport, inet_ntoa(locIP.sin_addr));
			res = httpTransact(szCtlUrl, szData, 4096, "AddPortMapping", ControlAction);
			txtParseParam(szData, NULL, "<errorCode>", "</errorCode>", szExtIP, sizeof(szExtIP));

		}
		while (search && res == 500 && atol(szExtIP) == 718 && --i);

		mir_free(szData);

		if (res == 200)
		{
			unsigned ip = getExtIP();
			if (ip) *extip = ip; 

			if (numports >= numportsAlloc)
				mir_realloc(portList, sizeof(WORD)*(numportsAlloc += 10));
			portList[numports++] = *extport;
		}

		ReleaseMutex(portListMutex);
	}

	return res == 200;
}
Ejemplo n.º 4
0
void NetlibUPnPCleanup(void*)
{
	// upnp is disabled globally, no need for a cleanup
	if (db_get_b(NULL, "Netlib", "NLEnableUPnP", 1) == 0)
		return;

	{
		int incoming = 0;
		mir_cslock lck(csNetlibUser);
		for (int i = 0; i < netlibUser.getCount(); i++)
			if (netlibUser[i]->user.flags & NUF_INCOMING) {
				incoming = 1;
				break;
			}

		if (!incoming)
			return;
	}

	if (findUPnPGateway()) {
		char *szData = (char*)alloca(4096);
		char buf[50], lip[50];
		unsigned j = 0, k, num = 100;

		strncpy_s(lip, inet_ntoa(locIP.sin_addr), _TRUNCATE);

		WaitForSingleObject(portListMutex, INFINITE);

		if (httpTransact(szCtlUrl, szData, 4096, "PortMappingNumberOfEntries", ControlQuery) == 200 &&
			txtParseParam(szData, "QueryStateVariableResponse", "<return>", "<", buf, sizeof(buf)))
			num = atol(buf);

		WORD ports[30];
		for (unsigned i = 0; i < num && !Miranda_Terminated(); i++) {
			mir_snprintf(szData, 4096, get_port_mapping, i);

			ReleaseMutex(portListMutex);
			WaitForSingleObject(portListMutex, INFINITE);

			if (httpTransact(szCtlUrl, szData, 4096, "GetGenericPortMappingEntry", ControlAction) != 200)
				break;

			if (!txtParseParam(szData, "<NewPortMappingDescription", ">", "<", buf, sizeof(buf)) || mir_strcmp(buf, "Miranda") != 0)
				continue;

			if (!txtParseParam(szData, "<NewInternalClient", ">", "<", buf, sizeof(buf)) || mir_strcmp(buf, lip) != 0)
				continue;

			if (txtParseParam(szData, "<NewExternalPort", ">", "<", buf, sizeof(buf))) {
				WORD mport = (WORD)atol(buf);

				if (j >= _countof(ports))
					break;

				for (k = 0; k < numports; ++k)
					if (portList[k] == mport)
						break;

				if (k >= numports)
					ports[j++] = mport;
			}
		}

		ReleaseMutex(portListMutex);

		for (unsigned i = 0; i < j && !Miranda_Terminated(); i++)
			NetlibUPnPDeletePortMapping(ports[i], "TCP");
	}
}
Ejemplo n.º 5
0
static void discoverUPnP(void)
{
	char* buf;
	int buflen;
	unsigned i, j, nip = 0;
	unsigned* ips = NULL;

	static const unsigned any = INADDR_ANY;
	static const TIMEVAL tv = { 1, 600000 };

	char szUrl[256] = "";
	char hostname[256];
	PHOSTENT he;
	fd_set readfd;

	SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

	SOCKADDR_IN enetaddr;
	enetaddr.sin_family = AF_INET;
	enetaddr.sin_port = htons(1900);
	enetaddr.sin_addr.s_addr = inet_addr("239.255.255.250");

	gethostname(hostname, sizeof(hostname));
	he = gethostbyname(hostname);

	if (he) {
		while (he->h_addr_list[nip]) ++nip;

		ips = (unsigned*)mir_alloc(nip * sizeof(unsigned));

		for (j = 0; j < nip; j++)
			ips[j] = *(unsigned*)he->h_addr_list[j];
	}

	buf = (char*)mir_alloc(1500);

	for (i = 3; --i && szUrl[0] == 0;) {
		for (j = 0; j < nip; j++) {
			if (ips)
				setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (char *)&ips[j], sizeof(unsigned));

			buflen = mir_snprintf(buf, 1500, search_request_msg, "WANIPConnection:1");
			sendto(sock, buf, buflen, 0, (SOCKADDR*)&enetaddr, sizeof(enetaddr));
			LongLog(buf);

			buflen = mir_snprintf(buf, 1500, search_request_msg, "WANPPPConnection:1");
			sendto(sock, buf, buflen, 0, (SOCKADDR*)&enetaddr, sizeof(enetaddr));
			LongLog(buf);
		}

		if (Miranda_Terminated()) break;

		FD_ZERO(&readfd);
		FD_SET(sock, &readfd);

		while (select(1, &readfd, NULL, NULL, &tv) >= 1) {
			buflen = recv(sock, buf, 1500, 0);
			if (buflen != SOCKET_ERROR) {
				buf[buflen] = 0;
				LongLog(buf);

				if (txtParseParam(buf, NULL, "LOCATION:", "\n", szUrl, sizeof(szUrl)) ||
					txtParseParam(buf, NULL, "Location:", "\n", szUrl, sizeof(szUrl))) {
					char age[30];
					char szHostNew[256], szHostExist[256];

					lrtrim(szUrl);

					parseURL(szUrl, szHostNew, NULL, NULL);
					parseURL(szCtlUrl, szHostExist, NULL, NULL);
					if (mir_strcmp(szHostNew, szHostExist) == 0) {
						gatewayFound = true;
						break;
					}

					txtParseParam(buf, NULL, "ST:", "\n", szDev, sizeof(szDev));
					txtParseParam(buf, "max-age", " = ", "\n", age, sizeof(age));
					expireTime = atoi(lrtrimp(age));
					lrtrim(szDev);

					if (getUPnPURLs(szUrl, sizeof(szUrl))) {
						gatewayFound = getExtIP() != 0;
						if (gatewayFound) break;
					}
				}
			}
			FD_ZERO(&readfd);
			FD_SET(sock, &readfd);
		}
	}

	mir_free(buf);
	mir_free(ips);
	setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (char *)&any, sizeof(unsigned));
	closesocket(sock);
}
Ejemplo n.º 6
0
static int httpTransact(char* szUrl, char* szResult, int resSize, char* szActionName, ReqType reqtype)
{
	// Parse URL
	char szHost[256], szPath[256], szRes[16];
	int sz = 0, res = 0;
	unsigned short sPort;
	bool needClose = false;

	const char* szPostHdr = soap_post_hdr;
	char* szData = (char*)mir_alloc(4096);
	char* szReq = NULL;

	parseURL(szUrl, szHost, &sPort, szPath);

	if (sPort != sConnPort || _stricmp(szHost, szConnHost))
		closeRouterConnection();
	else
		validateSocket();

	while (true) {
		retryCount = 0;
		switch (reqtype) {
		case DeviceGetReq:
			sz = mir_snprintf(szData, 4096, xml_get_hdr, szPath, szHost, sPort);
			break;

		case ControlAction:
		{
			char szData1[1024];

			szReq = mir_strdup(szResult);
			sz = mir_snprintf(szData1, _countof(szData1),
				soap_action, szActionName, szDev, szReq, szActionName);

			sz = mir_snprintf(szData, 4096,
				szPostHdr, szPath, szHost, sPort,
				sz, szDev, szActionName, szData1);
		}
		break;

		case ControlQuery:
		{
			char szData1[1024];

			sz = mir_snprintf(szData1, _countof(szData1),
				soap_query, szActionName);

			sz = mir_snprintf(szData, 4096,
				szPostHdr, szPath, szHost, sPort,
				sz, "urn:schemas-upnp-org:control-1-0", "QueryStateVariable", szData1);
		}
		break;
		}
		szResult[0] = 0;
		{
			static const TIMEVAL tv = { 6, 0 };
			static unsigned ttl = 4;
			static u_long mode = 1;
			fd_set rfd, wfd, efd;
			SOCKADDR_IN enetaddr;

retrycon:
			if (sock == INVALID_SOCKET) {
				sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

				enetaddr.sin_family = AF_INET;
				enetaddr.sin_port = htons(sPort);
				enetaddr.sin_addr.s_addr = inet_addr(szHost);

				// Resolve host name if needed
				if (enetaddr.sin_addr.s_addr == INADDR_NONE) {
					PHOSTENT he = gethostbyname(szHost);
					if (he)
						enetaddr.sin_addr.s_addr = *(unsigned*)he->h_addr_list[0];
				}

				NetlibLogf(NULL, "UPnP HTTP connection Host: %s Port: %u", szHost, sPort);

				FD_ZERO(&rfd); FD_ZERO(&wfd); FD_ZERO(&efd);
				FD_SET(sock, &rfd); FD_SET(sock, &wfd); FD_SET(sock, &efd);

				// Limit the scope of the connection (does not work for
				setsockopt(sock, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(unsigned));

				// Put socket into non-blocking mode for timeout on connect
				ioctlsocket(sock, FIONBIO, &mode);

				// Connect to the remote host
				if (connect(sock, (SOCKADDR*)&enetaddr, sizeof(enetaddr)) == SOCKET_ERROR) {
					int err = WSAGetLastError();

					// Socket connection failed
					if (err != WSAEWOULDBLOCK) {
						closeRouterConnection();
						NetlibLogf(NULL, "UPnP connect failed %d", err);
						break;
					}
					// Wait for socket to connect
					else if (select(1, &rfd, &wfd, &efd, &tv) != 1) {
						closeRouterConnection();
						NetlibLogf(NULL, "UPnP connect timeout");
						break;
					}
					else if (!FD_ISSET(sock, &wfd)) {
						closeRouterConnection();
						NetlibLogf(NULL, "UPnP connect failed");
						break;
					}
				}
				strncpy_s(szConnHost, szHost, _TRUNCATE);
				sConnPort = sPort;
			}

			if (send(sock, szData, sz, 0) != SOCKET_ERROR) {
				char *hdrend = NULL;
				int acksz = 0, pktsz = 0;

				if (szActionName == NULL) {
					int len = sizeof(locIP);
					getsockname(sock, (SOCKADDR*)&locIP, &len);
					if (locIP.sin_addr.S_un.S_addr == 0x0100007f) {
						struct hostent *he;

						gethostname(szPath, sizeof(szPath));
						he = gethostbyname(szPath);
						if (he != NULL)
							locIP.sin_addr.S_un.S_addr = *(PDWORD)he->h_addr_list[0];
					}
				}

				LongLog(szData);
				sz = 0;
				while (true) {
					int bytesRecv;

					FD_ZERO(&rfd);
					FD_SET(sock, &rfd);

					// Wait for the next packet
					if (select(1, &rfd, NULL, NULL, &tv) != 1) {
						closeRouterConnection();
						NetlibLogf(NULL, "UPnP recieve timeout");
						break;
					}

					//
					bytesRecv = recv(sock, &szResult[sz], resSize - sz, 0);

					// Connection closed or aborted, all data received
					if (bytesRecv == 0 || bytesRecv == SOCKET_ERROR) {
						closeRouterConnection();
						if ((bytesRecv == SOCKET_ERROR || sz == 0) && retryCount < 2) {
							++retryCount;
							goto retrycon;
						}
						break;
					}

					sz += bytesRecv;

					// Insert null terminator to use string functions
					if (sz >= (resSize - 1)) {
						szResult[resSize - 1] = 0;
						break;
					}
					else
						szResult[sz] = 0;

					// HTTP header found?
					if (hdrend == NULL) {
						// Find HTTP header end
						hdrend = strstr(szResult, "\r\n\r\n");
						if (hdrend == NULL) {
							hdrend = strstr(szResult, "\n\n");
							if (hdrend) hdrend += 2;
						}

						else
							hdrend += 4;

						if (hdrend != NULL) {
							// Get packet size if provided
							if (txtParseParam(szResult, NULL, "Content-Length:", "\n", szRes, sizeof(szRes)) ||
								txtParseParam(szResult, NULL, "CONTENT-LENGTH:", "\n", szRes, sizeof(szRes))) {
								// Add size of HTTP header to the packet size to compute full transmission size
								pktsz = atol(ltrimp(szRes)) + (hdrend - szResult);
							}
							// Get encoding type if provided
							else if (txtParseParam(szResult, NULL, "Transfer-Encoding:", "\n", szRes, sizeof(szRes))) {
								if (_stricmp(lrtrimp(szRes), "Chunked") == 0)
									acksz = hdrend - szResult;
							}
							if (txtParseParam(szResult, NULL, "Connection:", "\n", szRes, sizeof(szRes))) {
								needClose = (_stricmp(lrtrimp(szRes), "close") == 0);
							}
						}
					}

					// Content-Length bytes reached, all data received
					if (sz >= pktsz && pktsz != 0) {
						szResult[pktsz] = 0;
						break;
					}

					// Chunked encoding processing
					if (sz > acksz && acksz != 0) {
retry:
						// Parse out chunk size
						char* data = szResult + acksz;
						char* peol1 = data == hdrend ? data - 1 : strchr(data, '\n');
						if (peol1 != NULL) {
							char *peol2 = strchr(++peol1, '\n');
							if (peol2 != NULL) {
								// Get chunk size
								int chunkBytes = strtol(peol1, NULL, 16);
								acksz += chunkBytes;
								peol2++;

								memmove(data, peol2, mir_strlen(peol2) + 1);
								sz -= peol2 - data;

								// Last chunk, all data received
								if (chunkBytes == 0) break;
								if (sz > acksz) goto retry;
							}
						}
					}
				}
				LongLog(szResult);
			}
			else {
				if (retryCount < 2) {
					closeRouterConnection();
					++retryCount;
					goto retrycon;
				}
				else
					NetlibLogf(NULL, "UPnP send failed %d", WSAGetLastError());
			}
		}
		txtParseParam(szResult, "HTTP", " ", " ", szRes, sizeof(szRes));
		res = atol(szRes);
		if (szActionName != NULL && res == 405 && szPostHdr == soap_post_hdr)
			szPostHdr = soap_post_hdr_m;
		else
			break;
	}

	if (needClose)
		closeRouterConnection();

	mir_free(szData);
	mir_free(szReq);
	return res;
}
Ejemplo n.º 7
0
void CMsnProto::getOIMs(ezxml_t xmli)
{
	ezxml_t toki = ezxml_child(xmli, "M");
	if (toki == NULL) return;

	char* getReqHdr;
	ezxml_t reqmsg;
	ezxml_t xmlreq = oimRecvHdr("GetMessage", reqmsg, getReqHdr);

	ezxml_t reqmid = ezxml_add_child(reqmsg, "messageId", 0);
	ezxml_t reqmrk = ezxml_add_child(reqmsg, "alsoMarkAsRead", 0);
	ezxml_set_txt(reqmrk, "false");

	char* delReqHdr;
	ezxml_t delmsg;
	ezxml_t xmldel = oimRecvHdr("DeleteMessages", delmsg, delReqHdr);
	ezxml_t delmids = ezxml_add_child(delmsg, "messageIds", 0);

	while (toki != NULL) {
		const char* szId = ezxml_txt(ezxml_child(toki, "I"));
		const char* szEmail = ezxml_txt(ezxml_child(toki, "E"));

		ezxml_set_txt(reqmid, szId);
		char* szData = ezxml_toxml(xmlreq, true);

		unsigned status;
		char* url = (char*)mir_strdup(oimRecvUrl);

		char* tResult = getSslResult(&url, szData, getReqHdr, status);

		free(szData);
		mir_free(url);

		if (tResult != NULL && status == 200) {
			ezxml_t xmlm = ezxml_parse_str(tResult, mir_strlen(tResult));
			ezxml_t body = getSoapResponse(xmlm, "GetMessage");

			MimeHeaders mailInfo;
			const char* mailbody = mailInfo.readFromBuffer((char*)ezxml_txt(body));

			time_t evtm = time(NULL);
			const char* arrTime = mailInfo["X-OriginalArrivalTime"];
			if (arrTime != NULL) {
				char szTime[32], *p;
				txtParseParam(arrTime, "FILETIME", "[", "]", szTime, sizeof(szTime));

				unsigned filetimeLo = strtoul(szTime, &p, 16);
				if (*p == ':') {
					unsigned __int64 filetime = strtoul(p + 1, &p, 16);
					filetime <<= 32;
					filetime |= filetimeLo;
					filetime /= 10000000;
#ifndef __GNUC__
					filetime -= 11644473600ui64;
#else
					filetime -= 11644473600ull;
#endif
					evtm = (time_t)filetime;
				}
			}

			PROTORECVEVENT pre = { 0 };
			pre.szMessage = mailInfo.decodeMailBody((char*)mailbody);
			pre.timestamp = evtm;
			ProtoChainRecvMsg(MSN_HContactFromEmail(szEmail), &pre);
			mir_free(pre.szMessage);

			ezxml_t delmid = ezxml_add_child(delmids, "messageId", 0);
			ezxml_set_txt(delmid, szId);

			ezxml_free(xmlm);
		}
		mir_free(tResult);
		toki = ezxml_next(toki);
	}
	ezxml_free(xmlreq);
	mir_free(getReqHdr);

	if (ezxml_child(delmids, "messageId") != NULL) {
		char* szData = ezxml_toxml(xmldel, true);

		unsigned status;
		char* url = (char*)mir_strdup(oimRecvUrl);

		char* tResult = getSslResult(&url, szData, delReqHdr, status);

		mir_free(url);
		mir_free(tResult);
		free(szData);
	}
	ezxml_free(xmldel);
	mir_free(delReqHdr);
}