Changeset 10578 for branches/1.9x/third-party/miniupnp/miniupnpc.c
- Timestamp:
- May 1, 2010, 4:21:41 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/1.9x/third-party/miniupnp/miniupnpc.c
r10285 r10578 1 /* $Id: miniupnpc.c,v 1. 74 2010/01/09 23:54:40nanard Exp $ */1 /* $Id: miniupnpc.c,v 1.80 2010/04/12 20:39:41 nanard Exp $ */ 2 2 /* Project : miniupnp 3 3 * Author : Thomas BERNARD … … 15 15 #define __BSD_VISIBLE 1 16 16 #endif 17 #endif18 19 #ifdef __APPLE__20 #define _DARWIN_C_SOURCE21 17 #endif 22 18 … … 51 47 #include <netinet/in.h> 52 48 #include <arpa/inet.h> 49 #include <netdb.h> 53 50 #if !defined(__amigaos__) && !defined(__amigaos4__) 54 51 #include <poll.h> 55 52 #endif 56 #include <netdb.h>57 53 #include <strings.h> 58 54 #include <errno.h> … … 74 70 #include "minixml.h" 75 71 #include "upnpcommands.h" 72 #include "connecthostport.h" 76 73 77 74 #ifdef WIN32 … … 172 169 } 173 170 174 /* simpleUPnPcommand :171 /* simpleUPnPcommand2 : 175 172 * not so simple ! 176 173 * return values : 177 174 * 0 - OK 178 175 * -1 - error */ 179 int simpleUPnPcommand(int s, const char * url, const char * service, 180 const char * action, struct UPNParg * args, 181 char * buffer, int * bufsize) 182 { 183 struct sockaddr_in dest; 176 static int simpleUPnPcommand2(int s, const char * url, const char * service, 177 const char * action, struct UPNParg * args, 178 char * buffer, int * bufsize, const char * httpversion) 179 { 184 180 char hostname[MAXHOSTNAMELEN+1]; 185 181 unsigned short port = 0; … … 191 187 int n; 192 188 int contentlen, headerlen; /* for the response */ 193 #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT 194 struct timeval timeout; 195 #endif 189 196 190 snprintf(soapact, sizeof(soapact), "%s#%s", service, action); 197 191 if(args==NULL) … … 262 256 if(s<0) 263 257 { 264 s = socket(PF_INET, SOCK_STREAM, 0);265 if(s <0)258 s = connecthostport(hostname, port); 259 if(s < 0) 266 260 { 267 PRINT_SOCKET_ERROR("socket");268 261 *bufsize = 0; 269 262 return -1; 270 263 } 271 #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT 272 /* setting a 3 seconds timeout for the connect() call */ 273 timeout.tv_sec = 3; 274 timeout.tv_usec = 0; 275 if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) 276 { 277 PRINT_SOCKET_ERROR("setsockopt"); 278 } 279 timeout.tv_sec = 3; 280 timeout.tv_usec = 0; 281 if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) 282 { 283 PRINT_SOCKET_ERROR("setsockopt"); 284 } 285 #endif 286 dest.sin_family = AF_INET; 287 dest.sin_port = htons(port); 288 dest.sin_addr.s_addr = inet_addr(hostname); 289 n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr)); 290 #ifdef MINIUPNPC_IGNORE_EINTR 291 while(n < 0 && errno == EINTR) 292 { 293 socklen_t len; 294 fd_set wset; 295 int err; 296 FD_ZERO(&wset); 297 FD_SET(s, &wset); 298 if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) 299 continue; 300 /*len = 0;*/ 301 /*n = getpeername(s, NULL, &len);*/ 302 len = sizeof(err); 303 if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { 304 PRINT_SOCKET_ERROR("getsockopt"); 305 closesocket(s); 306 return -1; 307 } 308 if(err != 0) { 309 errno = err; 310 n = -1; 311 } else { 312 n = 0; 313 } 314 } 315 #endif 316 if(n < 0) 317 { 318 PRINT_SOCKET_ERROR("connect"); 319 closesocket(s); 320 *bufsize = 0; 321 return -1; 322 } 323 } 324 325 n = soapPostSubmit(s, path, hostname, port, soapact, soapbody); 264 } 265 266 n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion); 326 267 if(n<=0) { 327 268 #ifdef DEBUG … … 354 295 closesocket(s); 355 296 return 0; 297 } 298 299 /* simpleUPnPcommand : 300 * not so simple ! 301 * return values : 302 * 0 - OK 303 * -1 - error */ 304 int simpleUPnPcommand(int s, const char * url, const char * service, 305 const char * action, struct UPNParg * args, 306 char * buffer, int * bufsize) 307 { 308 int result; 309 int origbufsize = *bufsize; 310 311 result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.0"); 312 if (result < 0 || *bufsize == 0) 313 { 314 #ifdef DEBUG 315 printf("Error or no result from SOAP request; retrying with HTTP/1.1\n"); 316 #endif 317 *bufsize = origbufsize; 318 result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.1"); 319 } 320 return result; 356 321 } 357 322 … … 451 416 int sudp; 452 417 int n; 453 struct sockaddr _in sockudp_r, sockudp_w;418 struct sockaddr sockudp_r; 454 419 unsigned int mx; 420 int rv; 421 struct addrinfo hints, *servinfo, *p; 455 422 #ifdef WIN32 456 423 /*MIB_IPFORWARDROW ip_forward;*/ … … 482 449 return NULL; 483 450 } 484 /* reception */ 485 memset(&sockudp_r, 0, sizeof(struct sockaddr_in)); 486 sockudp_r.sin_family = AF_INET; 487 if(sameport) 488 sockudp_r.sin_port = htons(PORT); 489 sockudp_r.sin_addr.s_addr = INADDR_ANY; 490 /* emission */ 491 memset(&sockudp_w, 0, sizeof(struct sockaddr_in)); 492 sockudp_w.sin_family = AF_INET; 493 sockudp_w.sin_port = htons(PORT); 494 sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); 451 /* reception */ 452 memset(&sockudp_r, 0, sizeof(struct sockaddr)); 453 if(0/*ipv6*/) { 454 struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r; 455 p->sin6_family = AF_INET6; 456 if(sameport) 457 p->sin6_port = htons(PORT); 458 p->sin6_addr = in6addr_any;//IN6ADDR_ANY_INIT;/*INADDR_ANY;*/ 459 } else { 460 struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r; 461 p->sin_family = AF_INET; 462 if(sameport) 463 p->sin_port = htons(PORT); 464 p->sin_addr.s_addr = INADDR_ANY; 465 } 466 #if 0 467 /* emission */ 468 memset(&sockudp_w, 0, sizeof(struct sockaddr_in)); 469 sockudp_w.sin_family = AF_INET; 470 sockudp_w.sin_port = htons(PORT); 471 sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); 472 #endif 495 473 #ifdef WIN32 496 474 /* This code could help us to use the right Network interface for … … 547 525 struct in_addr mc_if; 548 526 mc_if.s_addr = inet_addr(multicastif); 549 sockudp_r.sin_addr.s_addr = mc_if.s_addr; 527 if(0/*ipv6*/) { 528 } else { 529 ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; 530 } 550 531 if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) 551 532 { … … 555 536 556 537 /* Avant d'envoyer le paquet on bind pour recevoir la reponse */ 557 if (bind(sudp, (struct sockaddr *)&sockudp_r,sizeof(struct sockaddr_in)) != 0)538 if (bind(sudp, &sockudp_r, 0/*ipv6*/?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)) != 0) 558 539 { 559 540 PRINT_SOCKET_ERROR("bind"); … … 573 554 MSearchMsgFmt, deviceList[deviceIndex++], mx); 574 555 /*printf("Sending %s", bufr);*/ 556 #if 0 575 557 n = sendto(sudp, bufr, n, 0, 576 558 (struct sockaddr *)&sockudp_w, sizeof(struct sockaddr_in)); 577 559 if (n < 0) { 578 560 PRINT_SOCKET_ERROR("sendto"); 561 closesocket(sudp); 562 return devlist; 563 } 564 #endif 565 memset(&hints, 0, sizeof(hints)); 566 hints.ai_family = AF_UNSPEC; // AF_INET6 or AF_INET 567 hints.ai_socktype = SOCK_DGRAM; 568 /*hints.ai_flags = */ 569 if ((rv = getaddrinfo(UPNP_MCAST_ADDR, XSTR(PORT), &hints, &servinfo)) != 0) { 570 #ifdef WIN32 571 fprintf(stderr, "getaddrinfo() failed: %d\n", rv); 572 #else 573 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 574 #endif 575 return devlist; 576 } 577 for(p = servinfo; p; p = p->ai_next) { 578 n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); 579 if (n < 0) { 580 PRINT_SOCKET_ERROR("sendto"); 581 continue; 582 } 583 } 584 freeaddrinfo(servinfo); 585 if(n < 0) { 579 586 closesocket(sudp); 580 587 return devlist; … … 603 610 if(st&&descURL) 604 611 { 605 /*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n", 606 stsize, st, urlsize, descURL); */ 612 #ifdef DEBUG 613 printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n", 614 stsize, st, urlsize, descURL); 615 #endif 616 for(tmp=devlist; tmp; tmp = tmp->pNext) { 617 if(memcmp(tmp->descURL, descURL, urlsize) == 0 && 618 tmp->descURL[urlsize] == '\0' && 619 memcmp(tmp->st, st, stsize) == 0 && 620 tmp->st[stsize] == '\0') 621 break; 622 } 623 /* at the exit of the loop above, tmp is null if 624 * no duplicate device was found */ 625 if(tmp) 626 continue; 607 627 tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize); 608 628 tmp->pNext = devlist; … … 667 687 n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ 668 688 n2 = n1; n3 = n1; 669 n1 += strlen(data-> scpdurl);670 n2 += strlen(data-> controlurl);671 n3 += strlen(data-> controlurl_CIF);689 n1 += strlen(data->first.scpdurl); 690 n2 += strlen(data->first.controlurl); 691 n3 += strlen(data->CIF.controlurl); 672 692 673 693 urls->ipcondescURL = (char *)malloc(n1); … … 684 704 strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3); 685 705 686 url_cpy_or_cat(urls->ipcondescURL, data-> scpdurl, n1);687 688 url_cpy_or_cat(urls->controlURL, data-> controlurl, n2);689 690 url_cpy_or_cat(urls->controlURL_CIF, data-> controlurl_CIF, n3);691 692 #ifdef DEBUG 693 printf("urls->ipcondescURL='%s' % dn1=%d\n", urls->ipcondescURL,694 strlen(urls->ipcondescURL), n1);695 printf("urls->controlURL='%s' % dn2=%d\n", urls->controlURL,696 strlen(urls->controlURL), n2);697 printf("urls->controlURL_CIF='%s' % dn3=%d\n", urls->controlURL_CIF,698 strlen(urls->controlURL_CIF), n3);706 url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1); 707 708 url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2); 709 710 url_cpy_or_cat(urls->controlURL_CIF, data->CIF.controlurl, n3); 711 712 #ifdef DEBUG 713 printf("urls->ipcondescURL='%s' %u n1=%d\n", urls->ipcondescURL, 714 (unsigned)strlen(urls->ipcondescURL), n1); 715 printf("urls->controlURL='%s' %u n2=%d\n", urls->controlURL, 716 (unsigned)strlen(urls->controlURL), n2); 717 printf("urls->controlURL_CIF='%s' %u n3=%d\n", urls->controlURL_CIF, 718 (unsigned)strlen(urls->controlURL_CIF), n3); 699 719 #endif 700 720 } … … 769 789 unsigned int uptime; 770 790 status[0] = '\0'; 771 UPNP_GetStatusInfo(urls->controlURL, data-> servicetype,791 UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, 772 792 status, &uptime, NULL); 773 793 if(0 == strcmp("Connected", status)) … … 826 846 free(descXML); 827 847 descXML = NULL; 828 if(0==strcmp(data-> servicetype_CIF,848 if(0==strcmp(data->CIF.servicetype, 829 849 "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1") 830 850 || state >= 3 ) … … 840 860 return state; 841 861 FreeUPNPUrls(urls); 862 if(data->second.servicetype[0] != '\0') { 863 #ifdef DEBUG 864 printf("We tried %s, now we try %s !\n", 865 data->first.servicetype, data->second.servicetype); 866 #endif 867 /* swaping WANPPPConnection and WANIPConnection ! */ 868 memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); 869 memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); 870 memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); 871 GetUPNPUrls(urls, data, dev->descURL); 872 #ifdef DEBUG 873 printf("UPNPIGD_IsConnected(%s) = %d\n", 874 urls->controlURL, 875 UPNPIGD_IsConnected(urls, data)); 876 #endif 877 if((state >= 2) || UPNPIGD_IsConnected(urls, data)) 878 return state; 879 FreeUPNPUrls(urls); 880 } 842 881 } 843 882 memset(data, 0, sizeof(struct IGDdatas));
Note: See TracChangeset
for help on using the changeset viewer.