Changeset 1769


Ignore:
Timestamp:
Feb 2, 2008 9:12:13 AM (16 years ago)
Author:
bennylp
Message:

More ticket #465: option to return UDP header in pj_pcap_read_udp(), and better RTP packet handling in pcaputil sample

Location:
pjproject/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/include/pjlib-util/pcap.h

    r1765 r1769  
    6161 
    6262/** 
     63 * This describes UDP header, which may optionally be returned in 
     64 * #pj_pcap_read_udp() function. All fields are in network byte order. 
     65 */ 
     66typedef struct pj_pcap_udp_hdr 
     67{ 
     68    pj_uint16_t src_port;   /**< Source port.       */ 
     69    pj_uint16_t dst_port;   /**< Destination port   */ 
     70    pj_uint16_t len;        /**< Length.            */ 
     71    pj_uint16_t csum;       /**< Checksum.          */ 
     72} pj_pcap_udp_hdr; 
     73 
     74 
     75/** 
    6376 * This structure describes the filter to be used when reading packets from 
    64  * a PCAP file. The filter is used to select what packets can be returned 
    65  * to a read operation. 
     77 * a PCAP file. When a filter is configured, only packets matching all the 
     78 * filter specifications will be read from PCAP file. 
    6679 */ 
    6780typedef struct pj_pcap_filter 
     
    143156 
    144157/** 
    145  * Configure filter for reading the file. 
     158 * Configure filter for reading the file. When filter is configured, 
     159 * only packets matching all the filter settings will be returned. 
    146160 * 
    147161 * @param file      PCAP file handle. 
     
    154168 
    155169/** 
    156  * Read UDP payload from the next packet in the PCAP file. 
     170 * Read UDP payload from the next packet in the PCAP file. Optionally it 
     171 * can return the UDP header, if caller supplies it. 
    157172 * 
    158173 * @param file              PCAP file handle. 
     174 * @param udp_hdr           Optional buffer to receive UDP header. 
    159175 * @param udp_payload       Buffer to receive the UDP payload. 
    160176 * @param udp_payload_size  On input, specify the size of the buffer. 
     
    165181 */ 
    166182PJ_DECL(pj_status_t) pj_pcap_read_udp(pj_pcap_file *file, 
     183                                      pj_pcap_udp_hdr *udp_hdr, 
    167184                                      pj_uint8_t *udp_payload, 
    168185                                      pj_size_t *udp_payload_size); 
  • pjproject/trunk/pjlib-util/src/pjlib-util/pcap.c

    r1767 r1769  
    5555 
    5656#if 0 
     57/* gcc insisted on aligning this struct to 32bit on ARM */ 
    5758typedef struct pj_pcap_eth_hdr  
    5859{ 
    5960    pj_uint8_t  dest[6]; 
    6061    pj_uint8_t  src[6]; 
    61     pj_uint8_t  len[2]; /* problem with struct size if pj_uint16_t */ 
     62    pj_uint8_t  len[2]; 
    6263} pj_pcap_eth_hdr; 
    6364#else 
     
    7879    pj_uint32_t ip_dst; 
    7980} pj_pcap_ip_hdr; 
    80  
    81 typedef struct pj_pcap_udp_hdr 
    82 { 
    83     pj_uint16_t src_port; 
    84     pj_uint16_t dst_port; 
    85     pj_uint16_t len; 
    86     pj_uint16_t csum; 
    87 } pj_pcap_udp_hdr; 
    88  
    89 #pragma pack() 
    9081 
    9182/* Implementation of pcap file */ 
     
    211202/* Read UDP packet */ 
    212203PJ_DEF(pj_status_t) pj_pcap_read_udp(pj_pcap_file *file, 
     204                                     pj_pcap_udp_hdr *udp_hdr, 
    213205                                     pj_uint8_t *udp_payload, 
    214206                                     pj_size_t *udp_payload_size) 
     
    343335            } 
    344336 
     337            /* Copy UDP header if caller wants it */ 
     338            if (udp_hdr) { 
     339                pj_memcpy(udp_hdr, &tmp.udp, sizeof(*udp_hdr)); 
     340            } 
     341 
    345342            /* Calculate payload size */ 
    346343            sz = pj_ntohs(tmp.udp.len) - sizeof(tmp.udp); 
  • pjproject/trunk/pjsip-apps/src/samples/pcaputil.c

    r1766 r1769  
    5858; 
    5959 
    60 static pj_caching_pool cp; 
    61 static pj_pool_t *pool; 
    62 static pjmedia_endpt *mept; 
    63 static pj_pcap_file *pcap; 
    64 static pjmedia_port *wav; 
    65 static pjmedia_transport *srtp; 
     60static struct app 
     61{ 
     62    pj_caching_pool      cp; 
     63    pj_pool_t           *pool; 
     64    pjmedia_endpt       *mept; 
     65    pj_pcap_file        *pcap; 
     66    pjmedia_port        *wav; 
     67    pjmedia_codec       *codec; 
     68    unsigned             pt; 
     69    pjmedia_transport   *srtp; 
     70    pjmedia_rtp_session  rtp_sess; 
     71    pj_bool_t            rtp_sess_init; 
     72} app; 
    6673 
    6774static void err_exit(const char *title, pj_status_t status) 
     
    7582    } 
    7683 
    77     if (srtp) pjmedia_transport_close(srtp); 
    78     if (wav) pjmedia_port_destroy(wav); 
    79     if (pcap) pj_pcap_close(pcap); 
    80     if (mept) pjmedia_endpt_destroy(mept); 
    81     if (pool) pj_pool_release(pool); 
    82     pj_caching_pool_destroy(&cp); 
     84    if (app.srtp) pjmedia_transport_close(app.srtp); 
     85    if (app.wav) { 
     86        pj_ssize_t pos = pjmedia_wav_writer_port_get_pos(app.wav); 
     87        if (pos >= 0) { 
     88            unsigned msec; 
     89            msec = pos / 2 * 1000 / app.wav->info.clock_rate; 
     90            printf("Written: %dm:%02ds.%03d\n", 
     91                    msec / 1000 / 60, 
     92                    (msec / 1000) % 60, 
     93                    msec % 1000); 
     94        } 
     95        pjmedia_port_destroy(app.wav); 
     96    } 
     97    if (app.pcap) pj_pcap_close(app.pcap); 
     98    if (app.codec) { 
     99        pjmedia_codec_mgr *cmgr; 
     100        app.codec->op->close(app.codec); 
     101        cmgr = pjmedia_endpt_get_codec_mgr(app.mept); 
     102        pjmedia_codec_mgr_dealloc_codec(cmgr, app.codec); 
     103    } 
     104    if (app.mept) pjmedia_endpt_destroy(app.mept); 
     105    if (app.pool) pj_pool_release(app.pool); 
     106    pj_caching_pool_destroy(&app.cp); 
    83107    pj_shutdown(); 
    84108 
     
    98122                     unsigned *payload_size) 
    99123{ 
    100     pj_size_t sz = bufsize; 
    101124    pj_status_t status; 
    102125 
    103     status = pj_pcap_read_udp(pcap, buf, &sz); 
    104     if (status != PJ_SUCCESS) 
    105         err_exit("Error reading PCAP file", status); 
    106  
    107     if (sz < sizeof(pjmedia_rtp_hdr) + 10) { 
    108         err_exit("Invalid RTP packet", PJ_SUCCESS); 
    109     } 
    110  
    111     /* Decrypt SRTP */ 
    112     if (srtp) { 
    113         int len = sz; 
    114         T(pjmedia_transport_srtp_decrypt_pkt(srtp, PJ_TRUE, buf, &len)); 
    115         sz = len; 
    116     } 
    117  
    118     *rtp = (pjmedia_rtp_hdr*)buf; 
    119     *payload = (pj_uint8_t*) (buf + sizeof(pjmedia_rtp_hdr)); 
    120     *payload_size = sz - sizeof(pjmedia_rtp_hdr); 
     126    /* Init RTP session */ 
     127    if (!app.rtp_sess_init) { 
     128        T(pjmedia_rtp_session_init(&app.rtp_sess, 0, 0)); 
     129        app.rtp_sess_init = PJ_TRUE; 
     130    } 
     131 
     132    /* Loop reading until we have a good RTP packet */ 
     133    for (;;) { 
     134        pj_size_t sz = bufsize; 
     135        const pjmedia_rtp_hdr *r; 
     136        const void *p; 
     137        pjmedia_rtp_status seq_st; 
     138 
     139        status = pj_pcap_read_udp(app.pcap, NULL, buf, &sz); 
     140        if (status != PJ_SUCCESS) 
     141            err_exit("Error reading PCAP file", status); 
     142 
     143        /* Decode RTP packet to make sure that this is an RTP packet. 
     144         * We will decode it again to get the payload after we do 
     145         * SRTP decoding 
     146         */ 
     147        status = pjmedia_rtp_decode_rtp(&app.rtp_sess, buf, sz, &r,  
     148                                        &p, payload_size); 
     149        if (status != PJ_SUCCESS) { 
     150            char errmsg[PJ_ERR_MSG_SIZE]; 
     151            pj_strerror(status, errmsg, sizeof(errmsg)); 
     152            printf("Not RTP packet, skipping packet: %s\n", errmsg); 
     153            continue; 
     154        } 
     155 
     156        /* Decrypt SRTP */ 
     157        if (app.srtp) { 
     158            int len = sz; 
     159            status = pjmedia_transport_srtp_decrypt_pkt(app.srtp, PJ_TRUE,  
     160                                                        buf, &len); 
     161            if (status != PJ_SUCCESS) { 
     162                char errmsg[PJ_ERR_MSG_SIZE]; 
     163                pj_strerror(status, errmsg, sizeof(errmsg)); 
     164                printf("SRTP packet decryption failed, skipping packet: %s\n",  
     165                        errmsg); 
     166                continue; 
     167            } 
     168            sz = len; 
     169 
     170            /* Decode RTP packet again */ 
     171            status = pjmedia_rtp_decode_rtp(&app.rtp_sess, buf, sz, &r, 
     172                                            &p, payload_size); 
     173            if (status != PJ_SUCCESS) { 
     174                char errmsg[PJ_ERR_MSG_SIZE]; 
     175                pj_strerror(status, errmsg, sizeof(errmsg)); 
     176                printf("Not RTP packet, skipping packet: %s\n", errmsg); 
     177                continue; 
     178            } 
     179        } 
     180 
     181        /* Update RTP session */ 
     182        pjmedia_rtp_session_update(&app.rtp_sess, r, &seq_st); 
     183 
     184        /* Skip out-of-order packet */ 
     185        if (seq_st.diff == 0) { 
     186            printf("Skipping out of order packet\n"); 
     187            continue; 
     188        } 
     189 
     190        /* Skip if payload type is different */ 
     191        if (r->pt != app.pt) { 
     192            printf("Skipping RTP packet with bad payload type\n"); 
     193            continue; 
     194        } 
     195 
     196        /* Skip bad packet */ 
     197        if (seq_st.status.flag.bad) { 
     198            printf("Skipping bad RTP\n"); 
     199            continue; 
     200        } 
     201 
     202 
     203        *rtp = (pjmedia_rtp_hdr*)r; 
     204        *payload = (pj_uint8_t*)p; 
     205 
     206        /* We have good packet */ 
     207        break; 
     208    } 
    121209} 
    122210 
     
    132220    } pkt0; 
    133221    pjmedia_codec_mgr *cmgr; 
    134     pjmedia_codec_info *ci; 
     222    const pjmedia_codec_info *ci; 
    135223    pjmedia_codec_param param; 
    136     pjmedia_codec *codec; 
    137224    unsigned samples_per_frame; 
    138225    pj_status_t status; 
     
    140227    /* Initialize all codecs */ 
    141228#if PJMEDIA_HAS_SPEEX_CODEC 
    142     T( pjmedia_codec_speex_init(mept, 0, 10, 10) ); 
     229    T( pjmedia_codec_speex_init(app.mept, 0, 10, 10) ); 
    143230#endif /* PJMEDIA_HAS_SPEEX_CODEC */ 
    144231 
    145232#if PJMEDIA_HAS_ILBC_CODEC 
    146     T( pjmedia_codec_ilbc_init(mept, 30) ); 
     233    T( pjmedia_codec_ilbc_init(app.mept, 30) ); 
    147234#endif /* PJMEDIA_HAS_ILBC_CODEC */ 
    148235 
    149236#if PJMEDIA_HAS_GSM_CODEC 
    150     T( pjmedia_codec_gsm_init(mept) ); 
     237    T( pjmedia_codec_gsm_init(app.mept) ); 
    151238#endif /* PJMEDIA_HAS_GSM_CODEC */ 
    152239 
    153240#if PJMEDIA_HAS_G711_CODEC 
    154     T( pjmedia_codec_g711_init(mept) ); 
     241    T( pjmedia_codec_g711_init(app.mept) ); 
    155242#endif  /* PJMEDIA_HAS_G711_CODEC */ 
    156243 
    157244#if PJMEDIA_HAS_L16_CODEC 
    158     T( pjmedia_codec_l16_init(mept, 0) ); 
     245    T( pjmedia_codec_l16_init(app.mept, 0) ); 
    159246#endif  /* PJMEDIA_HAS_L16_CODEC */ 
    160247 
     
    166253        crypto.key = *srtp_key; 
    167254        crypto.name = *srtp_crypto; 
    168         T( pjmedia_transport_srtp_create(mept, NULL, NULL, &srtp) ); 
    169         T( pjmedia_transport_srtp_start(srtp, &crypto, &crypto) ); 
     255        T( pjmedia_transport_srtp_create(app.mept, NULL, NULL, &app.srtp) ); 
     256        T( pjmedia_transport_srtp_start(app.srtp, &crypto, &crypto) ); 
    170257    } 
    171258 
     
    174261             &pkt0.payload, &pkt0.payload_len); 
    175262 
    176     cmgr = pjmedia_endpt_get_codec_mgr(mept); 
     263    cmgr = pjmedia_endpt_get_codec_mgr(app.mept); 
    177264 
    178265    /* Get codec info and param for the specified payload type */ 
     266    app.pt = pkt0.rtp->pt; 
    179267    T( pjmedia_codec_mgr_get_codec_info(cmgr, pkt0.rtp->pt, &ci) ); 
    180268    T( pjmedia_codec_mgr_get_default_param(cmgr, ci, &param) ); 
    181269 
    182270    /* Alloc and init codec */ 
    183     T( pjmedia_codec_mgr_alloc_codec(cmgr, ci, &codec) ); 
    184     T( codec->op->init(codec, pool) ); 
    185     T( codec->op->open(codec, &param) ); 
     271    T( pjmedia_codec_mgr_alloc_codec(cmgr, ci, &app.codec) ); 
     272    T( app.codec->op->init(app.codec, app.pool) ); 
     273    T( app.codec->op->open(app.codec, &param) ); 
    186274 
    187275    /* Open WAV file */ 
    188276    samples_per_frame = ci->clock_rate * param.info.frm_ptime / 1000; 
    189     T( pjmedia_wav_writer_port_create(pool, wav_filename, 
     277    T( pjmedia_wav_writer_port_create(app.pool, wav_filename, 
    190278                                      ci->clock_rate, ci->channel_cnt, 
    191279                                      samples_per_frame, 
    192280                                      param.info.pcm_bits_per_sample, 0, 0, 
    193                                       &wav) ); 
     281                                      &app.wav) ); 
    194282 
    195283    /* Loop reading PCAP and writing WAV file */ 
     
    207295        ts.u64 = 0; 
    208296        frame_cnt = PJ_ARRAY_SIZE(frames); 
    209         T( codec->op->parse(codec, pkt0.payload, pkt0.payload_len, &ts,  
    210                             &frame_cnt, frames) ); 
     297        T( app.codec->op->parse(app.codec, pkt0.payload, pkt0.payload_len,  
     298                                &ts, &frame_cnt, frames) ); 
    211299 
    212300        /* Decode and write to WAV file */ 
     
    218306            pcm_frame.size = samples_per_frame * 2; 
    219307 
    220             T( codec->op->decode(codec, &frames[i], pcm_frame.size, &pcm_frame) ); 
    221             T( pjmedia_port_put_frame(wav, &pcm_frame) ); 
     308            T( app.codec->op->decode(app.codec, &frames[i], pcm_frame.size,  
     309                                     &pcm_frame) ); 
     310            T( pjmedia_port_put_frame(app.wav, &pcm_frame) ); 
    222311            samples_cnt += samples_per_frame; 
    223312        } 
     
    235324            pcm_frame.size = samples_per_frame * 2; 
    236325 
    237             if (codec->op->recover) { 
    238                 T( codec->op->recover(codec, pcm_frame.size, &pcm_frame) ); 
     326            if (app.codec->op->recover) { 
     327                T( app.codec->op->recover(app.codec, pcm_frame.size,  
     328                                          &pcm_frame) ); 
    239329            } else { 
    240330                pj_bzero(pcm_frame.buf, pcm_frame.size); 
    241331            } 
    242332 
    243             T( pjmedia_port_put_frame(wav, &pcm_frame) ); 
     333            T( pjmedia_port_put_frame(app.wav, &pcm_frame) ); 
    244334            ts_gap -= samples_per_frame; 
    245335        } 
     
    341431    T( pj_init() ); 
    342432 
    343     pj_caching_pool_init(&cp, NULL, 0); 
    344     pool = pj_pool_create(&cp.factory, "pcaputil", 1000, 1000, NULL); 
     433    pj_caching_pool_init(&app.cp, NULL, 0); 
     434    app.pool = pj_pool_create(&app.cp.factory, "pcaputil", 1000, 1000, NULL); 
    345435 
    346436    T( pjlib_util_init() ); 
    347     T( pjmedia_endpt_create(&cp.factory, NULL, 0, &mept) ); 
    348  
    349     T( pj_pcap_open(pool, input.ptr, &pcap) ); 
    350     T( pj_pcap_set_filter(pcap, &filter) ); 
     437    T( pjmedia_endpt_create(&app.cp.factory, NULL, 0, &app.mept) ); 
     438 
     439    T( pj_pcap_open(app.pool, input.ptr, &app.pcap) ); 
     440    T( pj_pcap_set_filter(app.pcap, &filter) ); 
    351441 
    352442    if (pj_stristr(&output, &wav)) { 
     
    356446    } 
    357447 
    358     pjmedia_endpt_destroy(mept); 
    359     pj_pool_release(pool); 
    360     pj_caching_pool_destroy(&cp); 
     448    pjmedia_endpt_destroy(app.mept); 
     449    pj_pool_release(app.pool); 
     450    pj_caching_pool_destroy(&app.cp); 
    361451    pj_shutdown(); 
    362452    return 0; 
Note: See TracChangeset for help on using the changeset viewer.