📄 miniupnpc.c
字号:
{ PRINT_SOCKET_ERROR("socket"); return NULL; } /* reception */ memset(&sockudp_r, 0, sizeof(struct sockaddr_in)); sockudp_r.sin_family = AF_INET;#ifdef TX_FROM_UPNP_PORT sockudp_r.sin_port = htons(PORT);#endif sockudp_r.sin_addr.s_addr = INADDR_ANY; /* emission */ memset(&sockudp_w, 0, sizeof(struct sockaddr_in)); sockudp_w.sin_family = AF_INET; sockudp_w.sin_port = htons(PORT); sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);#ifdef WIN32 if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)#else if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)#endif { PRINT_SOCKET_ERROR("setsockopt"); return NULL; } if(multicastif) { struct in_addr mc_if; mc_if.s_addr = inet_addr(multicastif); sockudp_r.sin_addr.s_addr = mc_if.s_addr; if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } } /* Avant d'envoyer le paquet on bind pour recevoir la reponse */ if (bind(sudp, (struct sockaddr *)&sockudp_r, sizeof(struct sockaddr_in)) != 0) { PRINT_SOCKET_ERROR("bind"); closesocket(sudp); return NULL; } /* receiving SSDP response packet */ for(n = 0;;) { if(n == 0) { /* sending the SSDP M-SEARCH packet */ n = snprintf(bufr, sizeof(bufr), MSearchMsgFmt, deviceList[deviceIndex++]); /*printf("Sending %s", bufr);*/ n = sendto(sudp, bufr, n, 0, (struct sockaddr *)&sockudp_w, sizeof(struct sockaddr_in)); if (n < 0) { PRINT_SOCKET_ERROR("sendto"); closesocket(sudp); return devlist; } } /* Waiting for SSDP REPLY packet to M-SEARCH */ n = ReceiveData(sudp, bufr, sizeof(bufr), delay); if (n < 0) { /* error */ closesocket(sudp); return devlist; } else if (n == 0) { /* no data or Time Out */ if (devlist || (deviceList[deviceIndex] == 0)) { /* no more device type to look for... */ closesocket(sudp); return devlist; } } else { const char * descURL=NULL; int urlsize=0; const char * st=NULL; int stsize=0; /*printf("%d byte(s) :\n%s\n", n, bufr);*/ /* affichage du message */ parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize); if(st&&descURL) { /*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n", stsize, st, urlsize, descURL); */ tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize); tmp->pNext = devlist; tmp->descURL = tmp->buffer; tmp->st = tmp->buffer + 1 + urlsize; memcpy(tmp->buffer, descURL, urlsize); tmp->buffer[urlsize] = '\0'; memcpy(tmp->buffer + urlsize + 1, st, stsize); tmp->buffer[urlsize+1+stsize] = '\0'; devlist = tmp; } } }}/* freeUPNPDevlist() should be used to * free the chained list returned by upnpDiscover() */void freeUPNPDevlist(struct UPNPDev * devlist){ struct UPNPDev * next; while(devlist) { next = devlist->pNext; free(devlist); devlist = next; }}static voidurl_cpy_or_cat(char * dst, const char * src, int n){ if( (src[0] == 'h') &&(src[1] == 't') &&(src[2] == 't') &&(src[3] == 'p') &&(src[4] == ':') &&(src[5] == '/') &&(src[6] == '/')) { strncpy(dst, src, n); } else { int l = strlen(dst); if(src[0] != '/') dst[l++] = '/'; if(l<=n) strncpy(dst + l, src, n - l); }}/* Prepare the Urls for usage... */void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, const char * descURL){ char * p; int n1, n2, n3; n1 = strlen(data->urlbase); if(n1==0) n1 = strlen(descURL); n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ n2 = n1; n3 = n1; n1 += strlen(data->scpdurl); n2 += strlen(data->controlurl); n3 += strlen(data->controlurl_CIF); urls->ipcondescURL = (char *)malloc(n1); urls->controlURL = (char *)malloc(n2); urls->controlURL_CIF = (char *)malloc(n3); /* maintenant on chope la desc du WANIPConnection */ if(data->urlbase[0] != '\0') strncpy(urls->ipcondescURL, data->urlbase, n1); else strncpy(urls->ipcondescURL, descURL, n1); p = strchr(urls->ipcondescURL+7, '/'); if(p) p[0] = '\0'; strncpy(urls->controlURL, urls->ipcondescURL, n2); strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3); url_cpy_or_cat(urls->ipcondescURL, data->scpdurl, n1); url_cpy_or_cat(urls->controlURL, data->controlurl, n2); url_cpy_or_cat(urls->controlURL_CIF, data->controlurl_CIF, n3);#ifdef DEBUG printf("urls->ipcondescURL='%s' %d n1=%d\n", urls->ipcondescURL, strlen(urls->ipcondescURL), n1); printf("urls->controlURL='%s' %d n2=%d\n", urls->controlURL, strlen(urls->controlURL), n2); printf("urls->controlURL_CIF='%s' %d n3=%d\n", urls->controlURL_CIF, strlen(urls->controlURL_CIF), n3);#endif}voidFreeUPNPUrls(struct UPNPUrls * urls){ if(!urls) return; free(urls->controlURL); urls->controlURL = 0; free(urls->ipcondescURL); urls->ipcondescURL = 0; free(urls->controlURL_CIF); urls->controlURL_CIF = 0;}int ReceiveData(int socket, char * data, int length, int timeout){ int n;#ifndef WIN32 struct pollfd fds[1]; /* for the poll */ fds[0].fd = socket; fds[0].events = POLLIN; n = poll(fds, 1, timeout); if(n < 0) { PRINT_SOCKET_ERROR("poll"); return -1; } else if(n == 0) { return 0; }#else fd_set socketSet; TIMEVAL timeval; FD_ZERO(&socketSet); FD_SET(socket, &socketSet); timeval.tv_sec = timeout / 1000; timeval.tv_usec = (timeout % 1000) * 1000; n = select(0, &socketSet, NULL, NULL, &timeval); if(n < 0) { PRINT_SOCKET_ERROR("select"); return -1; } else if(n == 0) { return 0; } #endif n = recv(socket, data, length, 0); if(n<0) { PRINT_SOCKET_ERROR("recv"); } return n;}intUPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data){ char status[64]; unsigned int uptime; status[0] = '\0'; UPNP_GetStatusInfo(urls->controlURL, data->servicetype, status, &uptime); if(0 == strcmp("Connected", status)) { return 1; } else return 0;}/* UPNP_GetValidIGD() : * return values : * 0 = NO IGD found * 1 = A valid connected IGD has been found * 2 = A valid IGD has been found but it reported as * not connected * 3 = an UPnP device has been found but was not recognized as an IGD * * In any non zero return case, the urls and data structures * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * free allocated memory. */intUPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen){ char * descXML; int descXMLsize = 0; struct UPNPDev * dev; int ndev = 0; int state; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ if(!devlist) {#ifdef DEBUG printf("Empty devlist\n");#endif return 0; } for(state = 1; state <= 3; state++) { for(dev = devlist; dev; dev = dev->pNext) { /* we should choose an internet gateway device. * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ if((state >= 3) || strstr(dev->st, "InternetGatewayDevice")) { descXML = miniwget_getaddr(dev->descURL, &descXMLsize, lanaddr, lanaddrlen); if(descXML) { ndev++; memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(descXML, descXMLsize, data); free(descXML); descXML = NULL; GetUPNPUrls(urls, data, dev->descURL);#ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, UPNPIGD_IsConnected(urls, data));#endif if((state >= 2) || UPNPIGD_IsConnected(urls, data)) return state; FreeUPNPUrls(urls); memset(data, 0, sizeof(struct IGDdatas)); }#ifdef DEBUG else { printf("error getting XML description %s\n", dev->descURL); }#endif } } } return 0;}/* UPNP_GetIGDFromUrl() * Used when skipping the discovery process. * return value : * 0 - Not ok * 1 - OK */intUPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen){ char * descXML; int descXMLsize = 0; descXML = miniwget_getaddr(rootdescurl, &descXMLsize, lanaddr, lanaddrlen); if(descXML) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(descXML, descXMLsize, data); free(descXML); descXML = NULL; GetUPNPUrls(urls, data, rootdescurl); return 1; } else { return 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -