Ignore:
Timestamp:
Feb 27, 2012 2:41:21 PM (8 years ago)
Author:
nanang
Message:

Fix #1440: Send and parse RTCP compound packet, containing report (RR/SR/XR), SDES, and BYE.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/1.x/pjmedia/src/pjmedia/rtcp.c

    r3907 r3960  
    3030#define RTCP_SR   200 
    3131#define RTCP_RR   201 
     32#define RTCP_SDES 202 
     33#define RTCP_BYE  203 
    3234#define RTCP_XR   207 
     35 
     36enum { 
     37    RTCP_SDES_NULL  = 0, 
     38    RTCP_SDES_CNAME = 1, 
     39    RTCP_SDES_NAME  = 2, 
     40    RTCP_SDES_EMAIL = 3, 
     41    RTCP_SDES_PHONE = 4, 
     42    RTCP_SDES_LOC   = 5, 
     43    RTCP_SDES_TOOL  = 6, 
     44    RTCP_SDES_NOTE  = 7 
     45}; 
    3346 
    3447#if PJ_HAS_HIGH_RES_TIMER==0 
     
    474487 
    475488 
    476 PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *sess, 
    477                                    const void *pkt, 
    478                                    pj_size_t size) 
     489static void parse_rtcp_report( pjmedia_rtcp_session *sess, 
     490                               const void *pkt, 
     491                               pj_size_t size) 
    479492{ 
    480493    pjmedia_rtcp_common *common = (pjmedia_rtcp_common*) pkt; 
     
    653666 
    654667 
     668static void parse_rtcp_sdes(pjmedia_rtcp_session *sess, 
     669                            const void *pkt, 
     670                            pj_size_t size) 
     671{ 
     672    pjmedia_rtcp_sdes *sdes = &sess->stat.peer_sdes; 
     673    char *p, *p_end; 
     674    char *b, *b_end; 
     675 
     676    p = (char*)pkt + 8; 
     677    p_end = (char*)pkt + size; 
     678 
     679    pj_bzero(sdes, sizeof(*sdes)); 
     680    b = sess->stat.peer_sdes_buf_; 
     681    b_end = b + sizeof(sess->stat.peer_sdes_buf_); 
     682 
     683    while (p < p_end) { 
     684        pj_uint8_t sdes_type, sdes_len; 
     685        pj_str_t sdes_value = {NULL, 0}; 
     686 
     687        sdes_type = *p++; 
     688 
     689        /* Check for end of SDES item list */ 
     690        if (sdes_type == RTCP_SDES_NULL || p == p_end) 
     691            break; 
     692 
     693        sdes_len = *p++; 
     694 
     695        /* Check for corrupted SDES packet */ 
     696        if (p + sdes_len > p_end) 
     697            break; 
     698 
     699        /* Get SDES item */ 
     700        if (b + sdes_len < b_end) { 
     701            pj_memcpy(b, p, sdes_len); 
     702            sdes_value.ptr = b; 
     703            sdes_value.slen = sdes_len; 
     704            b += sdes_len; 
     705        } else { 
     706            /* Insufficient SDES buffer */ 
     707            PJ_LOG(5, (sess->name, 
     708                    "Unsufficient buffer to save RTCP SDES type %d:%.*s", 
     709                    sdes_type, sdes_len, p)); 
     710            p += sdes_len; 
     711            continue; 
     712        } 
     713 
     714        switch (sdes_type) { 
     715        case RTCP_SDES_CNAME: 
     716            sdes->cname = sdes_value; 
     717            break; 
     718        case RTCP_SDES_NAME: 
     719            sdes->name = sdes_value; 
     720            break; 
     721        case RTCP_SDES_EMAIL: 
     722            sdes->email = sdes_value; 
     723            break; 
     724        case RTCP_SDES_PHONE: 
     725            sdes->phone = sdes_value; 
     726            break; 
     727        case RTCP_SDES_LOC: 
     728            sdes->loc = sdes_value; 
     729            break; 
     730        case RTCP_SDES_TOOL: 
     731            sdes->tool = sdes_value; 
     732            break; 
     733        case RTCP_SDES_NOTE: 
     734            sdes->note = sdes_value; 
     735            break; 
     736        default: 
     737            TRACE_((sess->name, "Received unknown RTCP SDES type %d:%.*s", 
     738                    sdes_type, sdes_value.slen, sdes_value.ptr)); 
     739            break; 
     740        } 
     741 
     742        p += sdes_len; 
     743    } 
     744} 
     745 
     746 
     747static void parse_rtcp_bye(pjmedia_rtcp_session *sess, 
     748                           const void *pkt, 
     749                           pj_size_t size) 
     750{ 
     751    pj_str_t reason = {"-", 1}; 
     752 
     753    /* Check and get BYE reason */ 
     754    if (size > 8) { 
     755        reason.slen = *((pj_uint8_t*)pkt+8); 
     756        pj_memcpy(sess->stat.peer_sdes_buf_, ((pj_uint8_t*)pkt+9), 
     757                  reason.slen); 
     758        reason.ptr = sess->stat.peer_sdes_buf_; 
     759    } 
     760 
     761    /* Just print RTCP BYE log */ 
     762    PJ_LOG(5, (sess->name, "Received RTCP BYE, reason: %.*s", 
     763               reason.slen, reason.ptr)); 
     764} 
     765 
     766 
     767PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *sess, 
     768                                   const void *pkt, 
     769                                   pj_size_t size) 
     770{ 
     771    pj_uint8_t *p, *p_end; 
     772 
     773    p = (pj_uint8_t*)pkt; 
     774    p_end = p + size; 
     775    while (p < p_end) { 
     776        pjmedia_rtcp_common *common = (pjmedia_rtcp_common*)p; 
     777        unsigned len; 
     778 
     779        len = (pj_ntohs((pj_uint16_t)common->length)+1) * 4; 
     780        switch(common->pt) { 
     781        case RTCP_SR: 
     782        case RTCP_RR: 
     783        case RTCP_XR: 
     784            parse_rtcp_report(sess, p, len); 
     785            break; 
     786        case RTCP_SDES: 
     787            parse_rtcp_sdes(sess, p, len); 
     788            break; 
     789        case RTCP_BYE: 
     790            parse_rtcp_bye(sess, p, len); 
     791            break; 
     792        default: 
     793            /* Ignore unknown RTCP */ 
     794            TRACE_((sess->name, "Received unknown RTCP packet type=%d", 
     795                    common->pt)); 
     796            break; 
     797        } 
     798 
     799        p += len; 
     800    } 
     801} 
     802 
     803 
    655804PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess,  
    656805                                     void **ret_p_pkt, int *len) 
     
    805954} 
    806955 
     956 
     957PJ_DEF(pj_status_t) pjmedia_rtcp_build_rtcp_sdes( 
     958                                            pjmedia_rtcp_session *session,  
     959                                            void *buf, 
     960                                            pj_size_t *length, 
     961                                            const pjmedia_rtcp_sdes *sdes) 
     962{ 
     963    pjmedia_rtcp_common *hdr; 
     964    pj_uint8_t *p; 
     965    unsigned len; 
     966 
     967    PJ_ASSERT_RETURN(session && buf && length && sdes, PJ_EINVAL); 
     968 
     969    /* Verify SDES item length */ 
     970    if (sdes->cname.slen > 255 || sdes->name.slen  > 255 || 
     971        sdes->email.slen > 255 || sdes->phone.slen > 255 || 
     972        sdes->loc.slen   > 255 || sdes->tool.slen  > 255 || 
     973        sdes->note.slen  > 255) 
     974    { 
     975        return PJ_EINVAL; 
     976    } 
     977 
     978    /* Verify buffer length */ 
     979    len = sizeof(*hdr); 
     980    if (sdes->cname.slen) len += sdes->cname.slen + 2; 
     981    if (sdes->name.slen)  len += sdes->name.slen  + 2; 
     982    if (sdes->email.slen) len += sdes->email.slen + 2; 
     983    if (sdes->phone.slen) len += sdes->phone.slen + 2; 
     984    if (sdes->loc.slen)   len += sdes->loc.slen   + 2; 
     985    if (sdes->tool.slen)  len += sdes->tool.slen  + 2; 
     986    if (sdes->note.slen)  len += sdes->note.slen  + 2; 
     987    len++; /* null termination */ 
     988    len = ((len+3)/4) * 4; 
     989    if (len > *length) 
     990        return PJ_ETOOSMALL; 
     991 
     992    /* Build RTCP SDES header */ 
     993    hdr = (pjmedia_rtcp_common*)buf; 
     994    pj_memcpy(hdr, &session->rtcp_sr_pkt.common,  sizeof(*hdr)); 
     995    hdr->pt = RTCP_SDES; 
     996    hdr->length = pj_htons((pj_uint16_t)(len/4 - 1)); 
     997 
     998    /* Build RTCP SDES items */ 
     999    p = (pj_uint8_t*)hdr + sizeof(*hdr); 
     1000#define BUILD_SDES_ITEM(SDES_NAME, SDES_TYPE) \ 
     1001    if (sdes->SDES_NAME.slen) { \ 
     1002        *p++ = SDES_TYPE; \ 
     1003        *p++ = (pj_uint8_t)sdes->SDES_NAME.slen; \ 
     1004        pj_memcpy(p, sdes->SDES_NAME.ptr, sdes->SDES_NAME.slen); \ 
     1005        p += sdes->SDES_NAME.slen; \ 
     1006    } 
     1007    BUILD_SDES_ITEM(cname, RTCP_SDES_CNAME); 
     1008    BUILD_SDES_ITEM(name,  RTCP_SDES_NAME); 
     1009    BUILD_SDES_ITEM(email, RTCP_SDES_EMAIL); 
     1010    BUILD_SDES_ITEM(phone, RTCP_SDES_PHONE); 
     1011    BUILD_SDES_ITEM(loc,   RTCP_SDES_LOC); 
     1012    BUILD_SDES_ITEM(tool,  RTCP_SDES_TOOL); 
     1013    BUILD_SDES_ITEM(note,  RTCP_SDES_NOTE); 
     1014#undef BUILD_SDES_ITEM 
     1015 
     1016    /* Null termination */ 
     1017    *p++ = 0; 
     1018 
     1019    /* Pad to 32bit */ 
     1020    while ((p-(pj_uint8_t*)buf) % 4) 
     1021        *p++ = 0; 
     1022 
     1023    /* Finally */ 
     1024    pj_assert((int)len == p-(pj_uint8_t*)buf); 
     1025    *length = len; 
     1026 
     1027    return PJ_SUCCESS; 
     1028} 
     1029 
     1030 
     1031PJ_DEF(pj_status_t) pjmedia_rtcp_build_rtcp_bye(pjmedia_rtcp_session *session, 
     1032                                                void *buf, 
     1033                                                pj_size_t *length, 
     1034                                                const pj_str_t *reason) 
     1035{ 
     1036    pjmedia_rtcp_common *hdr; 
     1037    pj_uint8_t *p; 
     1038    unsigned len; 
     1039 
     1040    PJ_ASSERT_RETURN(session && buf && length, PJ_EINVAL); 
     1041 
     1042    /* Verify BYE reason length */ 
     1043    if (reason && reason->slen > 255) 
     1044        return PJ_EINVAL; 
     1045 
     1046    /* Verify buffer length */ 
     1047    len = sizeof(*hdr); 
     1048    if (reason && reason->slen) len += reason->slen + 1; 
     1049    len = ((len+3)/4) * 4; 
     1050    if (len > *length) 
     1051        return PJ_ETOOSMALL; 
     1052 
     1053    /* Build RTCP BYE header */ 
     1054    hdr = (pjmedia_rtcp_common*)buf; 
     1055    pj_memcpy(hdr, &session->rtcp_sr_pkt.common,  sizeof(*hdr)); 
     1056    hdr->pt = RTCP_BYE; 
     1057    hdr->length = pj_htons((pj_uint16_t)(len/4 - 1)); 
     1058 
     1059    /* Write RTCP BYE reason */ 
     1060    p = (pj_uint8_t*)hdr + sizeof(*hdr); 
     1061    if (reason && reason->slen) { 
     1062        *p++ = (pj_uint8_t)reason->slen; 
     1063        pj_memcpy(p, reason->ptr, reason->slen); 
     1064        p += reason->slen; 
     1065    } 
     1066 
     1067    /* Pad to 32bit */ 
     1068    while ((p-(pj_uint8_t*)buf) % 4) 
     1069        *p++ = 0; 
     1070 
     1071    pj_assert((int)len == p-(pj_uint8_t*)buf); 
     1072    *length = len; 
     1073 
     1074    return PJ_SUCCESS; 
     1075} 
     1076 
     1077 
    8071078PJ_DEF(pj_status_t) pjmedia_rtcp_enable_xr( pjmedia_rtcp_session *sess,  
    8081079                                            pj_bool_t enable) 
Note: See TracChangeset for help on using the changeset viewer.