Переадресация портов UPnP с C ++ в Windows - PullRequest
3 голосов
/ 06 января 2012

Я пытаюсь использовать интерфейс C ++ IUPnPNAT для достижения автоматической переадресации портов в приложении P2P под Windows, и я не могу заставить его работать только потому, что он всегда возвращает объект NULL. Я не был уверен, что мой маршрутизатор поддерживает UPnP, потому что он не показывает никакой опции в веб-интерфейсе, но если я установлю eMule или Skype, они сразу же открывают порты и работают нормально, поэтому проблема должна быть в моем коде или в интерфейсе Microsoft. Как eMule и Skype делают это? Никто не может мне помочь?

Я вставляю свой код:

WORD abre_puerto() {
WORD puerto, i; 
wchar_t buf_port[12], puerto_s[6]; 
char nombre[256], ip[16]; 
wchar_t ipw[16], descripcion[100];
struct addrinfo *resultado = NULL; 
struct addrinfo *ptr = NULL; 
struct addrinfo hints; 
struct sockaddr_in *sockaddr_ipv4;
IUPnPNAT *nat; 
IStaticPortMappingCollection *coleccion; 
IStaticPortMapping *mapeado; 
BSTR protocolo, ipb;

swprintf(buf_port, sizeof(buf_port), L"%d", time(NULL));
swprintf(puerto_s, sizeof(puerto_s), L"151%c%c", buf_port[wcslen(buf_port) - 2], buf_port[wcslen(buf_port) - 1]);
puerto = _wtoi(puerto_s);

if(gethostname(nombre, sizeof(nombre)) == SOCKET_ERROR) {return 0;}
ZeroMemory(&hints, sizeof(hints)); 
hints.ai_family = AF_INET; 
hints.ai_socktype = SOCK_STREAM; 
hints.ai_protocol = IPPROTO_TCP;
if(getaddrinfo(nombre, NULL, &hints, &resultado) != 0) {return 0;}

sockaddr_ipv4 = (struct sockaddr_in *)resultado->ai_addr;
strcpy(ip, inet_ntoa(sockaddr_ipv4->sin_addr));
MultiByteToWideChar(CP_UTF8, 0, ip, -1, ipw, sizeof(ipw));
ipb = SysAllocString(ipw);

nat = NULL; coleccion = NULL; mapeado = NULL;

if(CoInitialize(NULL) != S_OK) {return 0;}

if(CoCreateInstance(__uuidof(UPnPNAT), NULL, CLSCTX_ALL, __uuidof(IUPnPNAT), (void **)&nat) != S_OK) {return 0;}
else if(nat == NULL) {return 0;}

if(nat->get_StaticPortMappingCollection(&coleccion) != S_OK) {return 0;}
else if(coleccion == NULL) {return 0;} //fails here: coleccion is allways NULL!

protocolo = SysAllocString(L"TCP");
wcscpy(descripcion, TEXT("PROOF"));

for(i = 0; i < 250; i++) {
if(coleccion->get_Item(puerto, protocolo, &mapeado) != S_OK || mapeado == NULL) {break;}
puerto++; mapeado->Release(); mapeado = NULL;
}
if(i == 250) {return 0;}
if(coleccion->Add(puerto, protocolo, puerto, ipb, TRUE, descripcion, &mapeado) != S_OK) {return 0;}
else if(mapeado == NULL) {return 0;}
nat->Release(); coleccion->Release(); mapeado->Release();
CoUninitialize();

return puerto;
}

Большое спасибо.

1 Ответ

1 голос
/ 06 января 2012

Извинения, но вы не указали явно расположение полученного указателя NULL.

Если CoCreateInstance возвращает ноль, то это означает, что рассматриваемый класс не зарегистрирован на соответствующем компьютере сOLE / COM - тот факт, что работа Skype / eMule не имеет значения, поскольку они, вероятно, используют библиотеку, встроенную в приложение, а не COM-объект.

вы должны убедиться, что COM-объект зарегистрирован насистема, которая его использует - найдите в реестре uuid UPnPNAT.

, если вы хотите, чтобы приложение работало на нескольких системах, вам следует рассмотреть возможность прямого подключения к .lib и не использовать COM для подключения кобъект, который может или не может быть зарегистрирован в системе во время его использования.

...