Changeset 3299 for pjproject/trunk/pjlib/src/pj/ioqueue_select.c
- Timestamp:
- Aug 27, 2010 6:46:29 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/src/pj/ioqueue_select.c
r2554 r3299 38 38 #include <pj/compat/socket.h> 39 39 #include <pj/sock_select.h> 40 #include <pj/sock_qos.h> 40 41 #include <pj/errno.h> 41 42 … … 123 124 #endif 124 125 }; 126 127 /* Proto */ 128 static pj_status_t replace_udp_sock(pj_ioqueue_key_t *h); 125 129 126 130 /* Include implementation for common abstraction after we declare … … 621 625 #endif 622 626 627 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 628 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 629 static pj_status_t replace_udp_sock(pj_ioqueue_key_t *h) 630 { 631 enum flags { 632 HAS_PEER_ADDR = 1, 633 HAS_QOS = 2 634 }; 635 pj_sock_t old_sock, new_sock = PJ_INVALID_SOCKET; 636 pj_sockaddr local_addr, rem_addr; 637 int val, addr_len; 638 pj_fd_set_t *fds[3]; 639 unsigned i, fds_cnt, flags=0; 640 pj_qos_params qos_params; 641 unsigned msec; 642 pj_status_t status; 643 644 pj_lock_acquire(h->ioqueue->lock); 645 646 old_sock = h->fd; 647 648 /* Can only replace UDP socket */ 649 pj_assert(h->fd_type == pj_SOCK_DGRAM()); 650 651 PJ_LOG(4,(THIS_FILE, "Attempting to replace UDP socket %d", old_sock)); 652 653 /* Investigate the old socket */ 654 addr_len = sizeof(local_addr); 655 status = pj_sock_getsockname(old_sock, &local_addr, &addr_len); 656 if (status != PJ_SUCCESS) 657 goto on_error; 658 659 addr_len = sizeof(rem_addr); 660 status = pj_sock_getpeername(old_sock, &rem_addr, &addr_len); 661 if (status == PJ_SUCCESS) 662 flags |= HAS_PEER_ADDR; 663 664 status = pj_sock_get_qos_params(old_sock, &qos_params); 665 if (status == PJ_SUCCESS) 666 flags |= HAS_QOS; 667 668 /* We're done with the old socket, close it otherwise we'll get 669 * error in bind() 670 */ 671 pj_sock_close(old_sock); 672 673 /* Prepare the new socket */ 674 status = pj_sock_socket(local_addr.addr.sa_family, PJ_SOCK_DGRAM, 0, 675 &new_sock); 676 if (status != PJ_SUCCESS) 677 goto on_error; 678 679 /* Even after the socket is closed, we'll still get "Address in use" 680 * errors, so force it with SO_REUSEADDR 681 */ 682 val = 1; 683 status = pj_sock_setsockopt(new_sock, SOL_SOCKET, SO_REUSEADDR, 684 &val, sizeof(val)); 685 if (status != PJ_SUCCESS) 686 goto on_error; 687 688 /* The loop is silly, but what else can we do? */ 689 addr_len = pj_sockaddr_get_len(&local_addr); 690 for (msec=20; ; msec<1000? msec=msec*2 : 1000) { 691 status = pj_sock_bind(new_sock, &local_addr, addr_len); 692 if (status != PJ_STATUS_FROM_OS(EADDRINUSE)) 693 break; 694 PJ_LOG(4,(THIS_FILE, "Address is still in use, retrying..")); 695 pj_thread_sleep(msec); 696 } 697 698 if (status != PJ_SUCCESS) 699 goto on_error; 700 701 if (flags & HAS_QOS) { 702 status = pj_sock_set_qos_params(new_sock, &qos_params); 703 if (status != PJ_SUCCESS) 704 goto on_error; 705 } 706 707 if (flags & HAS_PEER_ADDR) { 708 status = pj_sock_connect(new_sock, &rem_addr, addr_len); 709 if (status != PJ_SUCCESS) 710 goto on_error; 711 } 712 713 /* Set socket to nonblocking. */ 714 val = 1; 715 #if defined(PJ_WIN32) && PJ_WIN32!=0 || \ 716 defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0 717 if (ioctlsocket(new_sock, FIONBIO, &val)) { 718 #else 719 if (ioctl(new_sock, FIONBIO, &val)) { 720 #endif 721 status = pj_get_netos_error(); 722 goto on_error; 723 } 724 725 /* Replace the occurrence of old socket with new socket in the 726 * fd sets. 727 */ 728 fds_cnt = 0; 729 fds[fds_cnt++] = &h->ioqueue->rfdset; 730 fds[fds_cnt++] = &h->ioqueue->wfdset; 731 #if PJ_HAS_TCP 732 fds[fds_cnt++] = &h->ioqueue->xfdset; 733 #endif 734 735 for (i=0; i<fds_cnt; ++i) { 736 if (PJ_FD_ISSET(old_sock, fds[i])) { 737 PJ_FD_CLR(old_sock, fds[i]); 738 PJ_FD_SET(new_sock, fds[i]); 739 } 740 } 741 742 /* And finally replace the fd in the key */ 743 h->fd = new_sock; 744 745 PJ_LOG(4,(THIS_FILE, "UDP has been replaced successfully!")); 746 747 pj_lock_release(h->ioqueue->lock); 748 749 return PJ_SUCCESS; 750 751 on_error: 752 if (new_sock != PJ_INVALID_SOCKET) 753 pj_sock_close(new_sock); 754 PJ_PERROR(1,(THIS_FILE, status, "Error replacing socket")); 755 pj_lock_release(h->ioqueue->lock); 756 return status; 757 } 758 #endif 759 623 760 624 761 /*
Note: See TracChangeset
for help on using the changeset viewer.