Changeset 2743 for pjproject/trunk/pjlib/src/pj/sock_common.c
- Timestamp:
- Jun 4, 2009 3:11:25 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/src/pj/sock_common.c
r2656 r2743 20 20 #include <pj/sock.h> 21 21 #include <pj/assert.h> 22 #include <pj/ctype.h> 22 23 #include <pj/errno.h> 23 24 #include <pj/ip_helper.h> … … 455 456 } 456 457 458 /* 459 * Parse address 460 */ 461 PJ_DEF(pj_status_t) pj_sockaddr_parse( int af, unsigned options, 462 const pj_str_t *str, 463 pj_sockaddr *addr) 464 { 465 const char *end = str->ptr + str->slen; 466 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); 473 474 /* Deduce address family if it's not given */ 475 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 if (colon_cnt > 1) 490 af = PJ_AF_INET6; 491 else 492 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 } 498 499 if (af == PJ_AF_INET) { 500 /* Parse as IPv4. Supported formats: 501 * - "10.0.0.1:80" 502 * - "10.0.0.1" 503 * - "10.0.0.1:" 504 * - ":80" 505 * - ":" 506 */ 507 pj_str_t ip_part; 508 unsigned long port; 509 510 if (last_colon_pos == NULL) 511 last_colon_pos = pj_strchr(str, ':'); 512 513 ip_part.ptr = (char*)str->ptr; 514 515 if (last_colon_pos) { 516 pj_str_t port_part; 517 int i; 518 519 ip_part.slen = last_colon_pos - str->ptr; 520 521 port_part.ptr = (char*)last_colon_pos + 1; 522 port_part.slen = end - port_part.ptr; 523 524 /* Make sure port number is valid */ 525 for (i=0; i<port_part.slen; ++i) { 526 if (!pj_isdigit(port_part.ptr[i])) 527 return PJ_EINVAL; 528 } 529 port = pj_strtoul(&port_part); 530 if (port > 65535) 531 return PJ_EINVAL; 532 } else { 533 ip_part.slen = str->slen; 534 port = 0; 535 } 536 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 * - "fe::01:80" ==> note: port number is zero in this case, not 80! 543 * - "[fe::01]:80" 544 * - "fe::01" 545 * - "fe::01:" 546 * - "[fe::01]" 547 * - "[fe::01]:" 548 * - "[::]:80" 549 * - ":::80" 550 * - "[::]" 551 * - "[::]:" 552 * - ":::" 553 * - "::" 554 */ 555 pj_str_t ip_part, port_part; 556 557 if (*str->ptr == '[') { 558 char *end_bracket = pj_strchr(str, ']'); 559 int i; 560 unsigned long port; 561 562 if (end_bracket == NULL) 563 return PJ_EINVAL; 564 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; 578 579 if (last_colon_pos < end_bracket) { 580 port_part.ptr = NULL; 581 port_part.slen = 0; 582 } else { 583 port_part.ptr = (char*)last_colon_pos + 1; 584 port_part.slen = end - port_part.ptr; 585 } 586 587 /* Make sure port number is valid */ 588 for (i=0; i<port_part.slen; ++i) { 589 if (!pj_isdigit(port_part.ptr[i])) 590 return PJ_EINVAL; 591 } 592 port = pj_strtoul(&port_part); 593 if (port > 65535) 594 return PJ_EINVAL; 595 596 return pj_sockaddr_init(PJ_AF_INET6, addr, &ip_part, 597 (pj_uint16_t)port); 598 } 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); 635 } 636 } 637 #endif 638 else { 639 return PJ_EIPV6NOTSUP; 640 } 641 } 642 457 643 static pj_bool_t is_usable_ip(const pj_sockaddr *addr) 458 644 {
Note: See TracChangeset
for help on using the changeset viewer.