Ignore:
Timestamp:
May 26, 2019 1:18:02 PM (3 years ago)
Author:
riza
Message:

Close #2202: Limit the number of ignored error when receiving RTP/RTCP.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c

    r5907 r6005  
    1919 */ 
    2020#include <pjmedia/transport_udp.h> 
     21#include <pj/compat/socket.h> 
    2122#include <pj/addr_resolv.h> 
    2223#include <pj/assert.h> 
     
    2728#include <pj/rand.h> 
    2829#include <pj/string.h> 
    29  
    3030 
    3131/* Maximum size of incoming RTP packet */ 
     
    155155                                       unsigned pct_lost); 
    156156static pj_status_t transport_destroy  (pjmedia_transport *tp); 
    157  
    158 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 
    159             PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 
    160157static pj_status_t transport_restart  (pj_bool_t is_rtp,  
    161158                                       struct transport_udp *udp); 
    162 #endif 
    163159 
    164160static pjmedia_transport_op transport_udp_op =  
     
    454450} 
    455451 
     452/* Call RTP cb. */ 
     453static void call_rtp_cb(struct transport_udp *udp, pj_ssize_t bytes_read,  
     454                        pj_bool_t *rem_switch) 
     455{ 
     456    void (*cb)(void*,void*,pj_ssize_t); 
     457    void (*cb2)(pjmedia_tp_cb_param*); 
     458    void *user_data; 
     459 
     460    cb = udp->rtp_cb; 
     461    cb2 = udp->rtp_cb2; 
     462    user_data = udp->user_data; 
     463 
     464    if (cb2) { 
     465        pjmedia_tp_cb_param param; 
     466 
     467        param.user_data = user_data; 
     468        param.pkt = udp->rtp_pkt; 
     469        param.size = bytes_read; 
     470        param.src_addr = &udp->rtp_src_addr; 
     471        param.rem_switch = PJ_FALSE; 
     472        (*cb2)(&param); 
     473        if (rem_switch) 
     474            *rem_switch = param.rem_switch; 
     475    } else if (cb) { 
     476        (*cb)(user_data, udp->rtp_pkt, bytes_read); 
     477    } 
     478} 
     479 
     480/* Call RTCP cb. */ 
     481static void call_rtcp_cb(struct transport_udp *udp, pj_ssize_t bytes_read) 
     482{ 
     483    void(*cb)(void*, void*, pj_ssize_t); 
     484    void *user_data; 
     485 
     486    cb = udp->rtcp_cb; 
     487    user_data = udp->user_data; 
     488 
     489    if (cb) 
     490        (*cb)(user_data, udp->rtcp_pkt, bytes_read); 
     491} 
    456492 
    457493/* Notification from ioqueue about incoming RTP packet */ 
     
    463499    pj_status_t status; 
    464500    pj_bool_t rem_switch = PJ_FALSE; 
     501    pj_bool_t transport_restarted = PJ_FALSE; 
     502    unsigned num_err = 0; 
     503    pj_status_t last_err = PJ_SUCCESS; 
    465504 
    466505    PJ_UNUSED_ARG(op_key); 
     
    470509    udp = (struct transport_udp*) pj_ioqueue_get_user_data(key); 
    471510 
    472 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 
    473             PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 
    474511    if (-bytes_read == PJ_ESOCKETSTOP) { 
    475512        /* Try to recover by restarting the transport. */ 
    476         PJ_LOG(4, (udp->base.name, "Restarting RTP transport")); 
    477513        status = transport_restart(PJ_TRUE, udp); 
    478         if (status == PJ_SUCCESS) { 
    479             PJ_LOG(4, (udp->base.name, "Success restarting RTP transport")); 
    480         } else { 
    481             PJ_PERROR(1, (udp->base.name, status,  
    482                           "Error restarting RTP transport")); 
     514        if (status != PJ_SUCCESS) { 
     515            bytes_read = -PJ_ESOCKETSTOP; 
     516            call_rtp_cb(udp, bytes_read, NULL); 
    483517        } 
    484518        return; 
    485519    } 
    486 #endif 
    487520 
    488521    do { 
    489         void (*cb)(void*,void*,pj_ssize_t); 
    490         void (*cb2)(pjmedia_tp_cb_param*); 
    491         void *user_data; 
    492522        pj_bool_t discard = PJ_FALSE; 
    493  
    494         cb = udp->rtp_cb; 
    495         cb2 = udp->rtp_cb2; 
    496         user_data = udp->user_data; 
    497523 
    498524        /* Simulate packet lost on RX direction */ 
     
    507533 
    508534        //if (!discard && udp->attached && cb) 
    509         if (!discard) { 
    510             if (cb2) { 
    511                 pjmedia_tp_cb_param param; 
    512  
    513                 param.user_data = user_data; 
    514                 param.pkt = udp->rtp_pkt; 
    515                 param.size = bytes_read; 
    516                 param.src_addr = &udp->rtp_src_addr; 
    517                 param.rem_switch = PJ_FALSE; 
    518                 (*cb2)(&param); 
    519                 rem_switch = param.rem_switch; 
    520             } else if (cb) { 
    521                 (*cb)(user_data, udp->rtp_pkt, bytes_read); 
    522             } 
     535        if (!discard &&  
     536            (-bytes_read != PJ_STATUS_FROM_OS(PJ_BLOCKING_ERROR_VAL)))  
     537        { 
     538            call_rtp_cb(udp, bytes_read, &rem_switch); 
    523539        } 
    524540 
     
    566582        udp->rtp_addrlen = sizeof(udp->rtp_src_addr); 
    567583        status = pj_ioqueue_recvfrom(udp->rtp_key, &udp->rtp_read_op, 
    568                                      udp->rtp_pkt, &bytes_read, 0, 
    569                                      &udp->rtp_src_addr,  
    570                                      &udp->rtp_addrlen); 
    571  
    572         if (status != PJ_EPENDING && status != PJ_SUCCESS) 
     584                                        udp->rtp_pkt, &bytes_read, 0, 
     585                                        &udp->rtp_src_addr, 
     586                                        &udp->rtp_addrlen); 
     587 
     588        if (status != PJ_EPENDING && status != PJ_SUCCESS) {         
     589            if (transport_restarted && last_err == status) { 
     590                /* Still the same error after restart */ 
     591                bytes_read = -PJ_ESOCKETSTOP; 
     592                call_rtp_cb(udp, bytes_read, NULL); 
     593                break; 
     594            } else if (PJMEDIA_IGNORE_RECV_ERR_CNT) { 
     595                if (last_err == status) { 
     596                    ++num_err; 
     597                } else { 
     598                    num_err = 1; 
     599                    last_err = status; 
     600                } 
     601 
     602                if (status == PJ_ESOCKETSTOP || 
     603                    num_err > PJMEDIA_IGNORE_RECV_ERR_CNT) 
     604                { 
     605                    status = transport_restart(PJ_TRUE, udp);                
     606                    if (status != PJ_SUCCESS) { 
     607                        bytes_read = -PJ_ESOCKETSTOP; 
     608                        call_rtp_cb(udp, bytes_read, NULL); 
     609                        break; 
     610                    } 
     611                    transport_restarted = PJ_TRUE; 
     612                    num_err = 0; 
     613                } 
     614            } 
    573615            bytes_read = -status; 
    574  
     616        } 
    575617    } while (status != PJ_EPENDING && status != PJ_ECANCELLED && 
    576618             udp->started); 
     
    585627    struct transport_udp *udp; 
    586628    pj_status_t status = PJ_SUCCESS; 
     629    pj_bool_t transport_restarted = PJ_FALSE; 
     630    unsigned num_err = 0; 
     631    pj_status_t last_err = PJ_SUCCESS; 
    587632 
    588633    PJ_UNUSED_ARG(op_key); 
     
    592637    udp = (struct transport_udp*) pj_ioqueue_get_user_data(key); 
    593638 
    594 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 
    595             PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 
    596639    if (-bytes_read == PJ_ESOCKETSTOP) { 
    597640        /* Try to recover by restarting the transport. */ 
    598         PJ_LOG(4, (udp->base.name, "Restarting RTCP transport")); 
    599641        status = transport_restart(PJ_FALSE, udp); 
    600         if (status == PJ_SUCCESS) { 
    601             PJ_LOG(4, (udp->base.name, "Success restarting RTCP transport")); 
    602         } else { 
    603             PJ_PERROR(1, (udp->base.name, status,  
    604                           "Error restarting RTCP transport")); 
     642        if (status != PJ_SUCCESS) { 
     643            bytes_read = -PJ_ESOCKETSTOP; 
     644            call_rtcp_cb(udp, bytes_read); 
    605645        } 
    606646        return; 
    607647    } 
    608 #endif 
    609648 
    610649    do { 
    611         void (*cb)(void*,void*,pj_ssize_t); 
    612         void *user_data; 
    613  
    614         cb = udp->rtcp_cb; 
    615         user_data = udp->user_data; 
    616  
    617         //if (udp->attached && cb) 
    618         if (cb) 
    619             (*cb)(user_data, udp->rtcp_pkt, bytes_read); 
     650        call_rtcp_cb(udp, bytes_read); 
    620651 
    621652#if defined(PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR) && \ 
     
    656687                                     &udp->rtcp_src_addr,  
    657688                                     &udp->rtcp_addr_len); 
    658         if (status != PJ_EPENDING && status != PJ_SUCCESS) 
     689 
     690        if (status != PJ_EPENDING && status != PJ_SUCCESS) { 
     691            if (transport_restarted && last_err == status) { 
     692                /* Still the same error after restart */ 
     693                bytes_read = -PJ_ESOCKETSTOP; 
     694                call_rtcp_cb(udp, bytes_read); 
     695                break; 
     696            } else if (PJMEDIA_IGNORE_RECV_ERR_CNT) { 
     697                if (last_err == status) { 
     698                    ++num_err; 
     699                } else { 
     700                    num_err = 1; 
     701                    last_err = status; 
     702                } 
     703 
     704                if (status == PJ_ESOCKETSTOP || 
     705                    num_err > PJMEDIA_IGNORE_RECV_ERR_CNT) 
     706                { 
     707                    status = transport_restart(PJ_FALSE, udp);               
     708                    if (status != PJ_SUCCESS) { 
     709                        bytes_read = -PJ_ESOCKETSTOP; 
     710                        call_rtcp_cb(udp, bytes_read); 
     711                        break; 
     712                    } 
     713                    transport_restarted = PJ_TRUE; 
     714                    num_err = 0; 
     715                } 
     716            } 
    659717            bytes_read = -status; 
    660  
     718        }        
    661719    } while (status != PJ_EPENDING && status != PJ_ECANCELLED && 
    662720             udp->started); 
     
    928986    PJ_ASSERT_RETURN(size <= PJMEDIA_MAX_MTU, PJ_ETOOBIG); 
    929987 
     988    if (!udp->started) { 
     989        return PJ_SUCCESS; 
     990    } 
     991 
    930992    /* Simulate packet lost on TX direction */ 
    931993    if (udp->tx_drop_pct) { 
     
    9851047 
    9861048    //PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP); 
     1049 
     1050    if (!udp->started) { 
     1051        return PJ_SUCCESS; 
     1052    } 
    9871053 
    9881054    if (addr == NULL) { 
     
    11811247} 
    11821248 
    1183 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 
    1184             PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 
    1185 static pj_status_t transport_restart(pj_bool_t is_rtp, 
     1249static pj_status_t transport_restart(pj_bool_t is_rtp,  
    11861250                                     struct transport_udp *udp) 
    11871251{ 
     
    11941258    pj_ssize_t size; 
    11951259 
     1260    PJ_LOG(4, (udp->base.name, "Restarting %s transport",  
     1261              (is_rtp)?"RTP":"RTCP")); 
     1262 
     1263    udp->started = PJ_FALSE; 
    11961264    /* Destroy existing socket, if any. */     
    11971265    if (key) { 
     
    12081276        pj_sock_close(*sock); 
    12091277    } 
    1210     *sock = PJ_INVALID_SOCKET; 
     1278    *sock = PJ_INVALID_SOCKET;    
    12111279 
    12121280    /* Create socket */ 
     
    12241292    /* Set buffer size for RTP socket */ 
    12251293#if PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE 
    1226     { 
     1294    if (is_rtp) { 
    12271295        unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE; 
    12281296 
    1229         status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_RCVBUF(), 
    1230                                           PJ_TRUE, &sobuf_size); 
    1231         if (status != PJ_SUCCESS) { 
    1232             pj_perror(3, udp->base.name, status, "Failed setting SO_RCVBUF"); 
    1233         } else { 
    1234             if (sobuf_size < PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE) { 
    1235                 PJ_LOG(4, (udp->base.name, 
    1236                            "Warning! Cannot set SO_RCVBUF as configured, " 
    1237                            "now=%d, configured=%d", 
    1238                            sobuf_size, PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE)); 
    1239             } else { 
    1240                 PJ_LOG(5, (udp->base.name, "SO_RCVBUF set to %d", sobuf_size)); 
    1241             } 
    1242         } 
     1297        pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_RCVBUF(),  
     1298                                 PJ_TRUE, &sobuf_size); 
    12431299    } 
    12441300#endif 
    12451301#if PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE 
    1246     { 
     1302    if (is_rtp) { 
    12471303        unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE; 
    12481304 
    1249         status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_SNDBUF(), 
    1250                                           PJ_TRUE, &sobuf_size); 
    1251         if (status != PJ_SUCCESS) { 
    1252             pj_perror(3, udp->base.name, status, "Failed setting SO_SNDBUF"); 
    1253         } else { 
    1254             if (sobuf_size < PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE) { 
    1255                 PJ_LOG(4, (udp->base.name, 
    1256                            "Warning! Cannot set SO_SNDBUF as configured, " 
    1257                            "now=%d, configured=%d", 
    1258                            sobuf_size, PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE)); 
    1259             } else { 
    1260                 PJ_LOG(5, (udp->base.name, "SO_SNDBUF set to %d", sobuf_size)); 
    1261             } 
    1262         } 
     1305        pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_SNDBUF(),  
     1306                                 PJ_TRUE, &sobuf_size); 
    12631307    } 
    12641308#endif 
     
    12961340        goto on_error; 
    12971341 
    1298  
     1342    udp->started = PJ_TRUE; 
     1343    PJ_LOG(4, (udp->base.name, "Success restarting %s transport",  
     1344              (is_rtp)?"RTP":"RTCP")); 
    12991345    return PJ_SUCCESS; 
    13001346on_error: 
     
    13031349        *sock = PJ_INVALID_SOCKET; 
    13041350    } 
     1351    PJ_PERROR(1, (udp->base.name, status,  
     1352                 "Error restarting %s transport", (is_rtp)?"RTP":"RTCP")); 
    13051353    return status; 
    13061354} 
    1307 #endif 
Note: See TracChangeset for help on using the changeset viewer.