← Back to team overview

rohc team mailing list archive

Enhance RTP detector from single packet to deep inspection of N packets

 

Hello!

The following RTP detector:

http://bazaar.launchpad.net/~didier-barvaux/rohc/main/view/head:/app/sniffer/sniffer.c#L1722

which try to decide if RTP by single packet can be enhanced to do deep packet inspection, by verifying that SSRC is stable for certain thershold period.

#NOTE: as Rtp_Arr[] is internal to the detector it access it directly instead via rtp_private.



The new source:

/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/



#define RTP_APPROVE_THOLD       (5)

#define MAX_RTP_CID             (8)



typedef struct rtp_entry

{

    uint8_t     Cnt2Rtp;    // if free == 0, count (RTP_APPROVE_THOLD)5,4,3,2,1(RTP Approved)

    uint8_t     TBD;        // PT?

    uint16_t    TBD16;      // ...?

    uint32_t    LastPktTm;  // Last-Packet-TimeStamp, in sec

    uint32_t    srcIp;      // Source-IP, Kept in BigEndian

    uint32_t    SSRC;       // SSRC, Kept in BigEndian

} rtp_ent_t;

rtp_ent_t   Rtp_Arr[ MAX_RTP_CID ];



/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/



/**

* @brief The detection callback which do detect RTP stream

*

* @param ip           The inner ip packet

* @param udp          The udp header of the packet

* @param payload      The payload of the packet

* @param payload_size The size of the payload (in bytes) == udp.udp_length-8(=udp_header_size)

* @return             1 if the packet is an RTP packet, 0 otherwise

*/

static bool rtp_detect_cb(const unsigned char *const ip,

                          const unsigned char *const udp,

                          const unsigned char *const payload,

                          const unsigned int payload_size,

                          void *const rtp_private)

{

    const uint16_t max_well_known_port = 1024;

    const uint16_t sip_port = 5060;

    uint32_t ssrc, src_ip;

    uint16_t udp_sport;

    uint16_t udp_dport;

    //uint16_t udp_len; //==payload_size+8

    uint8_t rtp_pt;

    uint32_t ts_now;

    int jj, freeNdx;

    bool is_rtp = false;



    //assert(ip != NULL);

    //assert(udp != NULL);

    //assert(payload != NULL);

    //assert(rtp_private == NULL);

    if( !ip || !udp || !payload)

    {

        //cprintf("%srtp_detector_cb called with NULL ptr%s\n", ATR_RED, ATR_OFF);

        goto not_rtp;

    }

    bins.Detect++;



    /* retrieve UDP source and destination ports and UDP length */

    udp_sport = htons(*(uint16_t *)&udp[0]);    //memcpy(&udp_sport, udp, sizeof(uint16_t));

    udp_dport = htons(*(uint16_t *)&udp[2]);    //memcpy(&udp_dport, udp + 2, sizeof(uint16_t));

    //udp_len = htons(*(uint16_t *)&udp[4]);    //memcpy(&udp_len, udp + 4, sizeof(uint16_t));//NO-NEED==payload_size+8



    /* RTP streams do not use well known ports */

    if((udp_sport <= max_well_known_port) ||

       (udp_dport <= max_well_known_port))

    {

        goto not_rtp;

    }



    /* SIP (UDP/5060) is not RTP */

    if((udp_sport == sip_port) && (udp_dport == sip_port))

    {

        goto not_rtp;

    }



    /* the UDP destination port of RTP packet is even (the RTCP destination

     * port are RTP destination port + 1, so it is odd) */

    if(((udp_sport % 2) != 0) || ((udp_dport % 2) != 0))

    {

        goto not_rtp;

    }



    /* UDP Length shall not be too large */

    if(payload_size > 192)
    {
        goto not_rtp;
    }

    /* UDP payload shall at least contain the smallest RTP header */
    if(payload_size < 12)
    {
        goto not_rtp;
    }

    /* RTP Version bits shall be 2, eXtension-bit4 should be 0 */
    if((payload[0] & 0xd0) != 0x80)
    {
        goto not_rtp;
    }//..is Ver==2 & X==0?

#define DEEP_PKT_INSPECT // Make sure it is RTP session by RTP_APPROVE_THOLD packets inspection
    /* RTP payload type shall be:
     * G.711/PCMU (0), GSM (0x03), ITU-T G.723 (0x04),
     * ITU-T G.729 (0x12), dynamic RTP type 97 (0x61),
     * telephony-event (0x65), Speex (0x72),
     * or dynamic RTP type 125 (0x7d) */
    rtp_pt = payload[1] & 0x7f;
#ifndef DEEP_PKT_INSPECT
    if ((rtp_pt != 0x00) &&
        (rtp_pt != 0x03) && (rtp_pt != 0x04) && (rtp_pt != 0x12) &&
        (rtp_pt != 0x61) && (rtp_pt != 0x65) && (rtp_pt != 0x72) &&
        (rtp_pt != 0x7d))
    {
        goto not_rtp;
    }
#endif /*!DEEP_PKT_INSPECT*/

    /* we think that the UDP packet is a RTP packet */
#ifdef DEEP_PKT_INSPECT
    ssrc   =  *((uint32_t *)&payload[ 8 ]); // Let's keep it in Big Endian format
    src_ip =  *((uint32_t *)&ip[ 12 ]);     // Let's keep it in Big Endian format

    freeNdx = -1;
    ts_now = time(0); // ts_now = tp_now >> 20; //Note: tp_now is time in usec since application start, means  >> 20 => 1.048576sec
    for (jj = 0; jj < MAX_RTP_CID; jj++)
    {
        register uint32_t   DiffTm;         // Delta T in seconds

        DiffTm = ts_now - Rtp_Arr[ jj ].LastPktTm;
        if (DiffTm >> 4)                    // Is Delta-T > 16sec
            Rtp_Arr[ jj ].Cnt2Rtp = 0;      // Mark free

        if ((freeNdx < 0) && (Rtp_Arr[ jj ].Cnt2Rtp == 0))
            freeNdx = jj;                   // Record tentative entry, if non-existing entry

        if ((Rtp_Arr[ jj ].SSRC == ssrc) && (Rtp_Arr[ jj ].srcIp == src_ip))
        {
            if (Rtp_Arr[ jj ].Cnt2Rtp > 1)
                Rtp_Arr[ jj ].Cnt2Rtp--;
            Rtp_Arr[ jj ].LastPktTm = ts_now;
            if (Rtp_Arr[ jj ].Cnt2Rtp == 1)
            {
                bins.isRtp++;
                is_rtp = true;
            }
            break;                          // Found => stop search
        }//..this rtp-session entry found
    }//..search for rtp-session entry

    if ((jj == MAX_RTP_CID) &&(freeNdx >= 0))
    {
            printf("rtp_detector_cb Set rtp entry:%d w/ Ip:0x%x-%x pt:x%x\n", freeNdx, src_ip, ssrc, rtp_pt);
            Rtp_Arr[ freeNdx ].Cnt2Rtp = RTP_APPROVE_THOLD;
            Rtp_Arr[ freeNdx ].LastPktTm = ts_now;
            Rtp_Arr[ freeNdx ].srcIp = src_ip;
            Rtp_Arr[ freeNdx ].SSRC = ssrc;
    }//..rtp-session entry not-found => assign "free" entry
#else /*DEEP_PKT_INSPECT?*/
    bins.isRtp++;
    is_rtp = true;
#endif /*!DEEP_PKT_INSPECT*/

not_rtp:
    return is_rtp;
}//..rtp_detect_cb()


Gil Beniamini
Gilat Satellite Networks - R&D
gilb@xxxxxxxxx<mailto:gilb@xxxxxxxxx>
Phone: (972)-3-9252427 Fax:(972)-3-9293040


IMPORTANT - This email and any attachments
is intended for the above named addressee(s), and may contain information which
is confidential or privileged. If you are not the intended recipient, please
inform the sender immediately and delete this email: you should not copy or use
this e-mail for any purpose nor disclose its contents to any person.