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; }
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"); } }