Changeset 5737
- Timestamp:
- Feb 15, 2018 1:57:11 PM (7 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c
r5692 r5737 344 344 "Send error for socket %d, retrying", 345 345 h->fd)); 346 replace_udp_sock(h);346 send_rc = replace_udp_sock(h); 347 347 continue; 348 348 } … … 579 579 h->fd_type==pj_SOCK_DGRAM()) 580 580 { 581 replace_udp_sock(h); 581 rc = replace_udp_sock(h); 582 if (rc != PJ_SUCCESS) { 583 bytes_read = -rc; 584 } 582 585 } 583 586 #endif -
pjproject/trunk/pjlib/src/pj/ioqueue_select.c
r5680 r5737 728 728 PJ_LOG(4,(THIS_FILE, "Attempting to replace UDP socket %d", old_sock)); 729 729 730 /* Investigate the old socket */ 731 addr_len = sizeof(local_addr); 732 status = pj_sock_getsockname(old_sock, &local_addr, &addr_len); 730 for (msec=20; (msec<1000 && status != PJ_SUCCESS) ; 731 msec<1000? msec=msec*2 : 1000) 732 { 733 if (msec > 20) { 734 PJ_LOG(4,(THIS_FILE, "Retry to replace UDP socket %d", old_sock)); 735 pj_thread_sleep(msec); 736 } 737 738 /* Investigate the old socket */ 739 addr_len = sizeof(local_addr); 740 status = pj_sock_getsockname(old_sock, &local_addr, &addr_len); 741 if (status != PJ_SUCCESS) { 742 PJ_LOG(5,(THIS_FILE, "Error get socket name %d", status)); 743 continue; 744 } 745 746 addr_len = sizeof(rem_addr); 747 status = pj_sock_getpeername(old_sock, &rem_addr, &addr_len); 748 if (status != PJ_SUCCESS) { 749 PJ_LOG(5,(THIS_FILE, "Error get peer name %d", status)); 750 } else { 751 flags |= HAS_PEER_ADDR; 752 } 753 754 status = pj_sock_get_qos_params(old_sock, &qos_params); 755 if (status == PJ_STATUS_FROM_OS(EBADF) || 756 status == PJ_STATUS_FROM_OS(EINVAL)) 757 { 758 PJ_LOG(5,(THIS_FILE, "Error get qos param %d", status)); 759 continue; 760 } 761 762 if (status != PJ_SUCCESS) { 763 PJ_LOG(5,(THIS_FILE, "Error get qos param %d", status)); 764 } else { 765 flags |= HAS_QOS; 766 } 767 768 /* We're done with the old socket, close it otherwise we'll get 769 * error in bind() 770 */ 771 status = pj_sock_close(old_sock); 772 if (status != PJ_SUCCESS) { 773 PJ_LOG(5,(THIS_FILE, "Error closing socket %d", status)); 774 } 775 776 /* Prepare the new socket */ 777 status = pj_sock_socket(local_addr.addr.sa_family, PJ_SOCK_DGRAM, 0, 778 &new_sock); 779 if (status != PJ_SUCCESS) { 780 PJ_LOG(5,(THIS_FILE, "Error create socket %d", status)); 781 continue; 782 } 783 784 /* Even after the socket is closed, we'll still get "Address in use" 785 * errors, so force it with SO_REUSEADDR 786 */ 787 val = 1; 788 status = pj_sock_setsockopt(new_sock, SOL_SOCKET, SO_REUSEADDR, 789 &val, sizeof(val)); 790 if (status == PJ_STATUS_FROM_OS(EBADF) || 791 status == PJ_STATUS_FROM_OS(EINVAL)) 792 { 793 PJ_LOG(5,(THIS_FILE, "Error set socket option %d", 794 status)); 795 continue; 796 } 797 798 /* The loop is silly, but what else can we do? */ 799 addr_len = pj_sockaddr_get_len(&local_addr); 800 for (msec=20; msec<1000 ; msec<1000? msec=msec*2 : 1000) { 801 status = pj_sock_bind(new_sock, &local_addr, addr_len); 802 if (status != PJ_STATUS_FROM_OS(EADDRINUSE)) 803 break; 804 PJ_LOG(4,(THIS_FILE, "Address is still in use, retrying..")); 805 pj_thread_sleep(msec); 806 } 807 808 if (status != PJ_SUCCESS) 809 continue; 810 811 if (flags & HAS_QOS) { 812 status = pj_sock_set_qos_params(new_sock, &qos_params); 813 if (status == PJ_STATUS_FROM_OS(EINVAL)) { 814 PJ_LOG(5,(THIS_FILE, "Error set qos param %d", status)); 815 continue; 816 } 817 } 818 819 if (flags & HAS_PEER_ADDR) { 820 status = pj_sock_connect(new_sock, &rem_addr, addr_len); 821 if (status != PJ_SUCCESS) { 822 PJ_LOG(5,(THIS_FILE, "Error connect socket %d", status)); 823 continue; 824 } 825 } 826 } 827 733 828 if (status != PJ_SUCCESS) 734 829 goto on_error; 735 830 736 addr_len = sizeof(rem_addr);737 status = pj_sock_getpeername(old_sock, &rem_addr, &addr_len);738 if (status == PJ_SUCCESS)739 flags |= HAS_PEER_ADDR;740 741 status = pj_sock_get_qos_params(old_sock, &qos_params);742 if (status == PJ_SUCCESS)743 flags |= HAS_QOS;744 745 /* We're done with the old socket, close it otherwise we'll get746 * error in bind()747 */748 pj_sock_close(old_sock);749 750 /* Prepare the new socket */751 status = pj_sock_socket(local_addr.addr.sa_family, PJ_SOCK_DGRAM, 0,752 &new_sock);753 if (status != PJ_SUCCESS)754 goto on_error;755 756 /* Even after the socket is closed, we'll still get "Address in use"757 * errors, so force it with SO_REUSEADDR758 */759 val = 1;760 status = pj_sock_setsockopt(new_sock, SOL_SOCKET, SO_REUSEADDR,761 &val, sizeof(val));762 if (status != PJ_SUCCESS)763 goto on_error;764 765 /* The loop is silly, but what else can we do? */766 addr_len = pj_sockaddr_get_len(&local_addr);767 for (msec=20; ; msec<1000? msec=msec*2 : 1000) {768 status = pj_sock_bind(new_sock, &local_addr, addr_len);769 if (status != PJ_STATUS_FROM_OS(EADDRINUSE))770 break;771 PJ_LOG(4,(THIS_FILE, "Address is still in use, retrying.."));772 pj_thread_sleep(msec);773 }774 775 if (status != PJ_SUCCESS)776 goto on_error;777 778 if (flags & HAS_QOS) {779 status = pj_sock_set_qos_params(new_sock, &qos_params);780 if (status != PJ_SUCCESS)781 goto on_error;782 }783 784 if (flags & HAS_PEER_ADDR) {785 status = pj_sock_connect(new_sock, &rem_addr, addr_len);786 if (status != PJ_SUCCESS)787 goto on_error;788 }789 790 831 /* Set socket to nonblocking. */ 791 832 val = 1; … … 830 871 if (new_sock != PJ_INVALID_SOCKET) 831 872 pj_sock_close(new_sock); 832 PJ_PERROR(1,(THIS_FILE, status, "Error replacing socket "));873 PJ_PERROR(1,(THIS_FILE, status, "Error replacing socket [%d]", status)); 833 874 pj_lock_release(h->ioqueue->lock); 834 return status;875 return PJ_ESOCKETSTOP; 835 876 } 836 877 #endif -
pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c
r5654 r5737 70 70 unsigned tx_drop_pct; /**< Percent of tx pkts to drop. */ 71 71 unsigned rx_drop_pct; /**< Percent of rx pkts to drop. */ 72 pj_ioqueue_t *ioqueue; /**< Ioqueue instance. */ 72 73 73 74 pj_sock_t rtp_sock; /**< RTP socket */ … … 152 153 static pj_status_t transport_destroy (pjmedia_transport *tp); 153 154 155 static pj_status_t transport_restart (pj_bool_t is_rtp, 156 struct transport_udp *udp); 157 154 158 155 159 static pjmedia_transport_op transport_udp_op = … … 387 391 goto on_error; 388 392 393 tp->ioqueue = ioqueue; 389 394 390 395 /* Done */ … … 441 446 442 447 /* Notification from ioqueue about incoming RTP packet */ 443 static void on_rx_rtp( pj_ioqueue_key_t *key,444 pj_ioqueue_op_key_t *op_key, 445 448 static void on_rx_rtp(pj_ioqueue_key_t *key, 449 pj_ioqueue_op_key_t *op_key, 450 pj_ssize_t bytes_read) 446 451 { 447 452 struct transport_udp *udp; … … 451 456 452 457 udp = (struct transport_udp*) pj_ioqueue_get_user_data(key); 458 459 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 460 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 461 if (-bytes_read == PJ_ESOCKETSTOP) { 462 /* Try to recover by restarting the transport. */ 463 PJ_LOG(4, (udp->base.name, "Restarting RTP transport")); 464 status = transport_restart(PJ_TRUE, udp); 465 if (status == PJ_SUCCESS) { 466 PJ_LOG(4, (udp->base.name, "Success restarting RTP transport")); 467 } else { 468 PJ_PERROR(1, (udp->base.name, status, 469 "Error restarting RTP transport")); 470 } 471 return; 472 } 473 #endif 453 474 454 475 do { … … 565 586 566 587 udp = (struct transport_udp*) pj_ioqueue_get_user_data(key); 588 589 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 590 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 591 if (-bytes_read == PJ_ESOCKETSTOP) { 592 /* Try to recover by restarting the transport. */ 593 PJ_LOG(4, (udp->base.name, "Restarting RTCP transport")); 594 status = transport_restart(PJ_FALSE, udp); 595 if (status == PJ_SUCCESS) { 596 PJ_LOG(4, (udp->base.name, "Success restarting RTCP transport")); 597 } else { 598 PJ_PERROR(1, (udp->base.name, status, 599 "Error restarting RTCP transport")); 600 } 601 return; 602 } 603 #endif 567 604 568 605 do { … … 996 1033 } 997 1034 1035 static pj_status_t transport_restart(pj_bool_t is_rtp, 1036 struct transport_udp *udp) 1037 { 1038 pj_ioqueue_key_t *key = (is_rtp ? udp->rtp_key : udp->rtcp_key); 1039 pj_sock_t *sock = (is_rtp ? &udp->rtp_sock : &udp->rtcp_sock); 1040 pj_status_t status; 1041 int af; 1042 pj_sockaddr *addr; 1043 pj_ioqueue_callback cb; 1044 pj_ssize_t size; 1045 1046 /* Destroy existing socket, if any. */ 1047 if (key) { 1048 /* This will block the execution if callback is still 1049 * being called. 1050 */ 1051 pj_ioqueue_unregister(key); 1052 if (is_rtp) { 1053 udp->rtp_key = NULL; 1054 } else { 1055 udp->rtcp_key = NULL; 1056 } 1057 } else if (*sock != PJ_INVALID_SOCKET) { 1058 pj_sock_close(*sock); 1059 } 1060 *sock = PJ_INVALID_SOCKET; 1061 1062 /* Create socket */ 1063 af = udp->rtp_addr_name.addr.sa_family; 1064 status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, sock); 1065 1066 if (status != PJ_SUCCESS) 1067 goto on_error; 1068 1069 addr = (is_rtp) ? &udp->rtp_addr_name : &udp->rtcp_addr_name; 1070 status = pj_sock_bind(*sock, addr, pj_sockaddr_get_len(addr)); 1071 if (status != PJ_SUCCESS) 1072 goto on_error; 1073 1074 /* Set buffer size for RTP socket */ 1075 #if PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE 1076 { 1077 unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE; 1078 1079 status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_RCVBUF(), 1080 PJ_TRUE, &sobuf_size); 1081 if (status != PJ_SUCCESS) { 1082 pj_perror(3, udp->base.name, status, "Failed setting SO_RCVBUF"); 1083 } else { 1084 if (sobuf_size < PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE) { 1085 PJ_LOG(4, (udp->base.name, 1086 "Warning! Cannot set SO_RCVBUF as configured, " 1087 "now=%d, configured=%d", 1088 sobuf_size, PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE)); 1089 } else { 1090 PJ_LOG(5, (udp->base.name, "SO_RCVBUF set to %d", sobuf_size)); 1091 } 1092 } 1093 } 1094 #endif 1095 #if PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE 1096 { 1097 unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE; 1098 1099 status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_SNDBUF(), 1100 PJ_TRUE, &sobuf_size); 1101 if (status != PJ_SUCCESS) { 1102 pj_perror(3, udp->base.name, status, "Failed setting SO_SNDBUF"); 1103 } else { 1104 if (sobuf_size < PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE) { 1105 PJ_LOG(4, (udp->base.name, 1106 "Warning! Cannot set SO_SNDBUF as configured, " 1107 "now=%d, configured=%d", 1108 sobuf_size, PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE)); 1109 } else { 1110 PJ_LOG(5, (udp->base.name, "SO_SNDBUF set to %d", sobuf_size)); 1111 } 1112 } 1113 } 1114 #endif 1115 pj_bzero(&cb, sizeof(cb)); 1116 if (is_rtp) 1117 cb.on_read_complete = &on_rx_rtp; 1118 else 1119 cb.on_read_complete = &on_rx_rtcp; 1120 1121 if (is_rtp) { 1122 status = pj_ioqueue_register_sock(udp->pool, udp->ioqueue, *sock, udp, 1123 &cb, &udp->rtp_key); 1124 } else { 1125 status = pj_ioqueue_register_sock(udp->pool, udp->ioqueue, *sock, udp, 1126 &cb, &udp->rtcp_key); 1127 } 1128 1129 if (status != PJ_SUCCESS) 1130 goto on_error; 1131 1132 if (is_rtp) { 1133 size = sizeof(udp->rtp_pkt); 1134 status = pj_ioqueue_recvfrom(udp->rtp_key, &udp->rtp_read_op, 1135 udp->rtp_pkt, &size, 1136 PJ_IOQUEUE_ALWAYS_ASYNC, 1137 &udp->rtp_src_addr, &udp->rtp_addrlen); 1138 } else { 1139 size = sizeof(udp->rtcp_pkt); 1140 status = pj_ioqueue_recvfrom(udp->rtcp_key, &udp->rtcp_read_op, 1141 udp->rtcp_pkt, &size, 1142 PJ_IOQUEUE_ALWAYS_ASYNC, 1143 &udp->rtcp_src_addr, &udp->rtcp_addr_len); 1144 } 1145 if (status != PJ_EPENDING) 1146 goto on_error; 1147 1148 1149 return PJ_SUCCESS; 1150 on_error: 1151 if (*sock != PJ_INVALID_SOCKET) { 1152 pj_sock_close(*sock); 1153 *sock = PJ_INVALID_SOCKET; 1154 } 1155 return status; 1156 } -
pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c
r5649 r5737 143 143 goto on_return; 144 144 145 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 146 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 147 if (-bytes_read == PJ_ESOCKETSTOP) { 148 --tp->read_loop_spin; 149 /* Try to recover by restarting the transport. */ 150 PJ_LOG(4,(tp->base.obj_name, "Restarting SIP UDP transport")); 151 status = pjsip_udp_transport_restart2( 152 &tp->base, 153 PJSIP_UDP_TRANSPORT_DESTROY_SOCKET, 154 PJ_INVALID_SOCKET, 155 &tp->base.local_addr, 156 &tp->base.local_name); 157 158 if (status != PJ_SUCCESS) { 159 PJ_PERROR(1,(THIS_FILE, status, 160 "Error restarting SIP UDP transport")); 161 } 162 return; 163 } 164 #endif 165 145 166 /* 146 167 * The idea of the loop is to process immediate data received by … … 262 283 status != PJ_STATUS_FROM_OS(OSERR_ECONNRESET)) 263 284 { 264 265 285 PJSIP_ENDPT_LOG_ERROR((rdata->tp_info.transport->endpt, 266 286 rdata->tp_info.transport->obj_name, … … 305 325 tdata_op_key->tdata = NULL; 306 326 327 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 328 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 329 if (-bytes_sent == PJ_ESOCKETSTOP) { 330 pj_status_t status; 331 /* Try to recover by restarting the transport. */ 332 PJ_LOG(4,(tp->base.obj_name, "Restarting SIP UDP transport")); 333 status = pjsip_udp_transport_restart2( 334 &tp->base, 335 PJSIP_UDP_TRANSPORT_DESTROY_SOCKET, 336 PJ_INVALID_SOCKET, 337 &tp->base.local_addr, 338 &tp->base.local_name); 339 340 if (status != PJ_SUCCESS) { 341 PJ_PERROR(1,(THIS_FILE, status, 342 "Error restarting SIP UDP transport")); 343 } 344 return; 345 } 346 #endif 347 307 348 if (tdata_op_key->callback) { 308 349 tdata_op_key->callback(&tp->base, tdata_op_key->token, bytes_sent); … … 562 603 563 604 pj_assert(a_name->host.slen != 0); 605 606 if (pj_strcmp(&tp->base.local_name.host, &a_name->host) == 0 && 607 tp->base.local_name.port == a_name->port) 608 { 609 return; 610 } 611 564 612 pj_strdup_with_null(tp->base.pool, &tp->base.local_name.host, 565 613 &a_name->host); … … 1133 1181 /* Create the socket if it's not specified */ 1134 1182 if (sock == PJ_INVALID_SOCKET) { 1135 status = create_socket(local->addr.sa_family, local, 1136 pj_sockaddr_get_len(local), &sock); 1183 status = create_socket(local?local->addr.sa_family:pj_AF_UNSPEC(), 1184 local, local?pj_sockaddr_get_len(local):0, 1185 &sock); 1137 1186 if (status != PJ_SUCCESS) 1138 1187 return status;
Note: See TracChangeset
for help on using the changeset viewer.