- Timestamp:
- Aug 12, 2009 10:56:06 AM (15 years ago)
- Location:
- pjproject/trunk/pjlib
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/include/pj/sock.h
r2743 r2863 980 980 * @param af Optionally specify the address family to be used. If the 981 981 * address family is to be deducted from the input, specify 982 * pj_AF_UNSPEC() here. 982 * pj_AF_UNSPEC() here. Other supported values are 983 * #pj_AF_INET() and #pj_AF_INET6() 983 984 * @param options Additional options to assist the parsing, must be zero 984 985 * for now. … … 987 988 * 988 989 * @return PJ_SUCCESS if the parsing is successful. 990 * 991 * @see pj_sockaddr_parse2() 989 992 */ 990 993 PJ_DECL(pj_status_t) pj_sockaddr_parse(int af, unsigned options, 991 994 const pj_str_t *str, 992 995 pj_sockaddr *addr); 996 997 /** 998 * This function is similar to #pj_sockaddr_parse(), except that it will not 999 * convert the hostpart into IP address (thus possibly resolving the hostname 1000 * into a #pj_sockaddr. 1001 * 1002 * Unlike #pj_sockaddr_parse(), this function has a limitation that if port 1003 * number is specified in an IPv6 input string, the IP part of the IPv6 socket 1004 * address MUST be enclosed in square brackets, otherwise the port number will 1005 * be considered as part of the IPv6 IP address. 1006 * 1007 * @param af Optionally specify the address family to be used. If the 1008 * address family is to be deducted from the input, specify 1009 * #pj_AF_UNSPEC() here. Other supported values are 1010 * #pj_AF_INET() and #pj_AF_INET6() 1011 * @param options Additional options to assist the parsing, must be zero 1012 * for now. 1013 * @param str The input string to be parsed. 1014 * @param hostpart Optional pointer to store the host part of the socket 1015 * address, with any brackets removed. 1016 * @param port Optional pointer to store the port number. If port number 1017 * is not found, this will be set to zero upon return. 1018 * @param raf Optional pointer to store the detected address family of 1019 * the input address. 1020 * 1021 * @return PJ_SUCCESS if the parsing is successful. 1022 * 1023 * @see pj_sockaddr_parse() 1024 */ 1025 PJ_DECL(pj_status_t) pj_sockaddr_parse2(int af, unsigned options, 1026 const pj_str_t *str, 1027 pj_str_t *hostpart, 1028 pj_uint16_t *port, 1029 int *raf); 993 1030 994 1031 /***************************************************************************** -
pjproject/trunk/pjlib/src/pj/sock_common.c
r2743 r2863 459 459 * Parse address 460 460 */ 461 PJ_DEF(pj_status_t) pj_sockaddr_parse (int af, unsigned options,461 PJ_DEF(pj_status_t) pj_sockaddr_parse2(int af, unsigned options, 462 462 const pj_str_t *str, 463 pj_sockaddr *addr) 463 pj_str_t *p_hostpart, 464 pj_uint16_t *p_port, 465 int *raf) 464 466 { 465 467 const char *end = str->ptr + str->slen; 466 468 const char *last_colon_pos = NULL; 467 468 PJ_ASSERT_RETURN(addr, PJ_EINVAL); 469 PJ_ASSERT_RETURN(af==PJ_AF_UNSPEC || 470 af==PJ_AF_INET || 471 af==PJ_AF_INET6, PJ_EINVAL); 472 PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); 469 unsigned colon_cnt = 0; 470 const char *p; 471 472 PJ_ASSERT_RETURN((af==PJ_AF_INET || af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) && 473 options==0 && 474 str!=NULL, PJ_EINVAL); 475 476 /* Special handling for empty input */ 477 if (str->slen==0 || str->ptr==NULL) { 478 if (p_hostpart) 479 p_hostpart->slen = 0; 480 if (p_port) 481 *p_port = 0; 482 if (*raf) 483 *raf = PJ_AF_INET; 484 return PJ_SUCCESS; 485 } 486 487 /* Count the colon and get the last colon */ 488 for (p=str->ptr; p!=end; ++p) { 489 if (*p == ':') { 490 ++colon_cnt; 491 last_colon_pos = p; 492 } 493 } 473 494 474 495 /* Deduce address family if it's not given */ 475 496 if (af == PJ_AF_UNSPEC) { 476 unsigned colon_cnt = 0;477 const char *p;478 479 /* Can't accept NULL or empty input if address family is unknown */480 PJ_ASSERT_RETURN(str && str->slen, PJ_EINVAL);481 482 for (p=str->ptr; p!=end; ++p) {483 if (*p == ':') {484 ++colon_cnt;485 last_colon_pos = p;486 }487 }488 489 497 if (colon_cnt > 1) 490 498 af = PJ_AF_INET6; 491 499 else 492 500 af = PJ_AF_INET; 493 } else {494 /* Input may be NULL or empty as long as address family is given */495 if (str == NULL || str->slen == 0) 496 return pj_sockaddr_init(af, addr, NULL, 0); 497 } 501 } else if (af == PJ_AF_INET && colon_cnt > 1) 502 return PJ_EINVAL; 503 504 if (raf) 505 *raf = af; 498 506 499 507 if (af == PJ_AF_INET) { … … 505 513 * - ":" 506 514 */ 507 pj_str_t ip_part;515 pj_str_t hostpart; 508 516 unsigned long port; 509 517 510 if (last_colon_pos == NULL) 511 last_colon_pos = pj_strchr(str, ':'); 512 513 ip_part.ptr = (char*)str->ptr; 518 hostpart.ptr = (char*)str->ptr; 514 519 515 520 if (last_colon_pos) { … … 517 522 int i; 518 523 519 ip_part.slen = last_colon_pos - str->ptr;524 hostpart.slen = last_colon_pos - str->ptr; 520 525 521 526 port_part.ptr = (char*)last_colon_pos + 1; … … 531 536 return PJ_EINVAL; 532 537 } else { 533 ip_part.slen = str->slen;538 hostpart.slen = str->slen; 534 539 port = 0; 535 540 } 536 541 537 return pj_sockaddr_in_init(&addr->ipv4, &ip_part, (pj_uint16_t)port); 538 } 539 #if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6 540 else if (af == PJ_AF_INET6) { 541 /* Parse as IPv4. Supported formats: 542 if (p_hostpart) 543 *p_hostpart = hostpart; 544 if (p_port) 545 *p_port = (pj_uint16_t)port; 546 547 return PJ_SUCCESS; 548 549 } else if (af == PJ_AF_INET6) { 550 551 /* Parse as IPv6. Supported formats: 542 552 * - "fe::01:80" ==> note: port number is zero in this case, not 80! 543 553 * - "[fe::01]:80" … … 553 563 * - "::" 554 564 */ 555 pj_str_t ip_part, port_part;565 pj_str_t hostpart, port_part; 556 566 557 567 if (*str->ptr == '[') { 558 char *end_bracket = pj_strchr(str, ']');568 char *end_bracket; 559 569 int i; 560 570 unsigned long port; 561 571 572 if (last_colon_pos == NULL) 573 return PJ_EINVAL; 574 575 end_bracket = pj_strchr(str, ']'); 562 576 if (end_bracket == NULL) 563 577 return PJ_EINVAL; 564 578 565 ip_part.ptr = (char*)str->ptr + 1; 566 ip_part.slen = end_bracket - ip_part.ptr; 567 568 if (last_colon_pos == NULL) { 569 const char *p; 570 for (p=str->ptr; p!=end; ++p) { 571 if (*p == ':') 572 last_colon_pos = p; 573 } 574 } 575 576 if (last_colon_pos == NULL) 577 return PJ_EINVAL; 579 hostpart.ptr = (char*)str->ptr + 1; 580 hostpart.slen = end_bracket - hostpart.ptr; 578 581 579 582 if (last_colon_pos < end_bracket) { … … 594 597 return PJ_EINVAL; 595 598 596 return pj_sockaddr_init(PJ_AF_INET6, addr, &ip_part, 597 (pj_uint16_t)port); 599 if (p_hostpart) 600 *p_hostpart = hostpart; 601 if (p_port) 602 *p_port = (pj_uint16_t)port; 603 604 return PJ_SUCCESS; 605 598 606 } else { 599 int i; 600 unsigned long port; 601 602 /* First lets try to parse everything as IPv6 address */ 603 if (pj_sockaddr_init(PJ_AF_INET6, addr, str, 0)==PJ_SUCCESS) 604 return PJ_SUCCESS; 605 606 /* Parse as IPv6:port */ 607 if (last_colon_pos == NULL) { 608 const char *p; 609 for (p=str->ptr; p!=end; ++p) { 610 if (*p == ':') 611 last_colon_pos = p; 612 } 613 } 614 615 if (last_colon_pos == NULL) 616 return PJ_EINVAL; 617 618 ip_part.ptr = (char*)str->ptr; 619 ip_part.slen = last_colon_pos - str->ptr; 620 621 port_part.ptr = (char*)last_colon_pos + 1; 622 port_part.slen = end - port_part.ptr; 623 624 /* Make sure port number is valid */ 625 for (i=0; i<port_part.slen; ++i) { 626 if (!pj_isdigit(port_part.ptr[i])) 627 return PJ_EINVAL; 628 } 629 port = pj_strtoul(&port_part); 630 if (port > 65535) 631 return PJ_EINVAL; 632 633 return pj_sockaddr_init(PJ_AF_INET6, addr, &ip_part, 634 (pj_uint16_t)port); 607 /* Treat everything as part of the IPv6 IP address */ 608 if (p_hostpart) 609 *p_hostpart = *str; 610 if (p_port) 611 *p_port = 0; 612 613 return PJ_SUCCESS; 635 614 } 615 616 } else { 617 return PJ_EAFNOTSUP; 618 } 619 620 } 621 622 /* 623 * Parse address 624 */ 625 PJ_DEF(pj_status_t) pj_sockaddr_parse( int af, unsigned options, 626 const pj_str_t *str, 627 pj_sockaddr *addr) 628 { 629 pj_str_t hostpart; 630 pj_uint16_t port; 631 pj_status_t status; 632 633 PJ_ASSERT_RETURN(addr, PJ_EINVAL); 634 PJ_ASSERT_RETURN(af==PJ_AF_UNSPEC || 635 af==PJ_AF_INET || 636 af==PJ_AF_INET6, PJ_EINVAL); 637 PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); 638 639 status = pj_sockaddr_parse2(af, options, str, &hostpart, &port, &af); 640 if (status != PJ_SUCCESS) 641 return status; 642 643 status = pj_sockaddr_init(af, addr, &hostpart, port); 644 #if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6 645 if (status != PJ_SUCCESS && af == PJ_AF_INET6) { 646 /* Parsing does not yield valid address. Try to treat the last 647 * portion after the colon as port number. 648 */ 649 const char *last_colon_pos=NULL, *p; 650 const char *end = str->ptr + str->slen; 651 unsigned long long_port; 652 pj_str_t port_part; 653 int i; 654 655 /* Parse as IPv6:port */ 656 for (p=str->ptr; p!=end; ++p) { 657 if (*p == ':') 658 last_colon_pos = p; 659 } 660 661 if (last_colon_pos == NULL) 662 return status; 663 664 hostpart.ptr = (char*)str->ptr; 665 hostpart.slen = last_colon_pos - str->ptr; 666 667 port_part.ptr = (char*)last_colon_pos + 1; 668 port_part.slen = end - port_part.ptr; 669 670 /* Make sure port number is valid */ 671 for (i=0; i<port_part.slen; ++i) { 672 if (!pj_isdigit(port_part.ptr[i])) 673 return status; 674 } 675 long_port = pj_strtoul(&port_part); 676 if (long_port > 65535) 677 return status; 678 679 port = (pj_uint16_t)long_port; 680 681 status = pj_sockaddr_init(PJ_AF_INET6, addr, &hostpart, port); 636 682 } 637 683 #endif 638 else { 639 return PJ_EIPV6NOTSUP; 640 } 684 685 return status; 641 686 } 642 687 -
pjproject/trunk/pjlib/src/pjlib-test/sock.c
r2770 r2863 220 220 { "10.0.0.1:123456", IPv4}, /* port too big */ 221 221 { "1.2.3.4.5:80", IPv4}, /* invalid IP */ 222 { "10:0:80", IPv4}, /* hostname has colon */ 222 223 223 224 #if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
Note: See TracChangeset
for help on using the changeset viewer.