- Timestamp:
- Feb 2, 2008 9:12:13 AM (17 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/include/pjlib-util/pcap.h
r1765 r1769 61 61 62 62 /** 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 */ 66 typedef 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 /** 63 76 * 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 returned65 * 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. 66 79 */ 67 80 typedef struct pj_pcap_filter … … 143 156 144 157 /** 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. 146 160 * 147 161 * @param file PCAP file handle. … … 154 168 155 169 /** 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. 157 172 * 158 173 * @param file PCAP file handle. 174 * @param udp_hdr Optional buffer to receive UDP header. 159 175 * @param udp_payload Buffer to receive the UDP payload. 160 176 * @param udp_payload_size On input, specify the size of the buffer. … … 165 181 */ 166 182 PJ_DECL(pj_status_t) pj_pcap_read_udp(pj_pcap_file *file, 183 pj_pcap_udp_hdr *udp_hdr, 167 184 pj_uint8_t *udp_payload, 168 185 pj_size_t *udp_payload_size); -
pjproject/trunk/pjlib-util/src/pjlib-util/pcap.c
r1767 r1769 55 55 56 56 #if 0 57 /* gcc insisted on aligning this struct to 32bit on ARM */ 57 58 typedef struct pj_pcap_eth_hdr 58 59 { 59 60 pj_uint8_t dest[6]; 60 61 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]; 62 63 } pj_pcap_eth_hdr; 63 64 #else … … 78 79 pj_uint32_t ip_dst; 79 80 } pj_pcap_ip_hdr; 80 81 typedef struct pj_pcap_udp_hdr82 {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()90 81 91 82 /* Implementation of pcap file */ … … 211 202 /* Read UDP packet */ 212 203 PJ_DEF(pj_status_t) pj_pcap_read_udp(pj_pcap_file *file, 204 pj_pcap_udp_hdr *udp_hdr, 213 205 pj_uint8_t *udp_payload, 214 206 pj_size_t *udp_payload_size) … … 343 335 } 344 336 337 /* Copy UDP header if caller wants it */ 338 if (udp_hdr) { 339 pj_memcpy(udp_hdr, &tmp.udp, sizeof(*udp_hdr)); 340 } 341 345 342 /* Calculate payload size */ 346 343 sz = pj_ntohs(tmp.udp.len) - sizeof(tmp.udp); -
pjproject/trunk/pjsip-apps/src/samples/pcaputil.c
r1766 r1769 58 58 ; 59 59 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; 60 static 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; 66 73 67 74 static void err_exit(const char *title, pj_status_t status) … … 75 82 } 76 83 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); 83 107 pj_shutdown(); 84 108 … … 98 122 unsigned *payload_size) 99 123 { 100 pj_size_t sz = bufsize;101 124 pj_status_t status; 102 125 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 } 121 209 } 122 210 … … 132 220 } pkt0; 133 221 pjmedia_codec_mgr *cmgr; 134 pjmedia_codec_info *ci;222 const pjmedia_codec_info *ci; 135 223 pjmedia_codec_param param; 136 pjmedia_codec *codec;137 224 unsigned samples_per_frame; 138 225 pj_status_t status; … … 140 227 /* Initialize all codecs */ 141 228 #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) ); 143 230 #endif /* PJMEDIA_HAS_SPEEX_CODEC */ 144 231 145 232 #if PJMEDIA_HAS_ILBC_CODEC 146 T( pjmedia_codec_ilbc_init( mept, 30) );233 T( pjmedia_codec_ilbc_init(app.mept, 30) ); 147 234 #endif /* PJMEDIA_HAS_ILBC_CODEC */ 148 235 149 236 #if PJMEDIA_HAS_GSM_CODEC 150 T( pjmedia_codec_gsm_init( mept) );237 T( pjmedia_codec_gsm_init(app.mept) ); 151 238 #endif /* PJMEDIA_HAS_GSM_CODEC */ 152 239 153 240 #if PJMEDIA_HAS_G711_CODEC 154 T( pjmedia_codec_g711_init( mept) );241 T( pjmedia_codec_g711_init(app.mept) ); 155 242 #endif /* PJMEDIA_HAS_G711_CODEC */ 156 243 157 244 #if PJMEDIA_HAS_L16_CODEC 158 T( pjmedia_codec_l16_init( mept, 0) );245 T( pjmedia_codec_l16_init(app.mept, 0) ); 159 246 #endif /* PJMEDIA_HAS_L16_CODEC */ 160 247 … … 166 253 crypto.key = *srtp_key; 167 254 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) ); 170 257 } 171 258 … … 174 261 &pkt0.payload, &pkt0.payload_len); 175 262 176 cmgr = pjmedia_endpt_get_codec_mgr( mept);263 cmgr = pjmedia_endpt_get_codec_mgr(app.mept); 177 264 178 265 /* Get codec info and param for the specified payload type */ 266 app.pt = pkt0.rtp->pt; 179 267 T( pjmedia_codec_mgr_get_codec_info(cmgr, pkt0.rtp->pt, &ci) ); 180 268 T( pjmedia_codec_mgr_get_default_param(cmgr, ci, ¶m) ); 181 269 182 270 /* 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, ¶m) );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, ¶m) ); 186 274 187 275 /* Open WAV file */ 188 276 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, 190 278 ci->clock_rate, ci->channel_cnt, 191 279 samples_per_frame, 192 280 param.info.pcm_bits_per_sample, 0, 0, 193 & wav) );281 &app.wav) ); 194 282 195 283 /* Loop reading PCAP and writing WAV file */ … … 207 295 ts.u64 = 0; 208 296 frame_cnt = PJ_ARRAY_SIZE(frames); 209 T( codec->op->parse(codec, pkt0.payload, pkt0.payload_len, &ts,210 297 T( app.codec->op->parse(app.codec, pkt0.payload, pkt0.payload_len, 298 &ts, &frame_cnt, frames) ); 211 299 212 300 /* Decode and write to WAV file */ … … 218 306 pcm_frame.size = samples_per_frame * 2; 219 307 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) ); 222 311 samples_cnt += samples_per_frame; 223 312 } … … 235 324 pcm_frame.size = samples_per_frame * 2; 236 325 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) ); 239 329 } else { 240 330 pj_bzero(pcm_frame.buf, pcm_frame.size); 241 331 } 242 332 243 T( pjmedia_port_put_frame( wav, &pcm_frame) );333 T( pjmedia_port_put_frame(app.wav, &pcm_frame) ); 244 334 ts_gap -= samples_per_frame; 245 335 } … … 341 431 T( pj_init() ); 342 432 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); 345 435 346 436 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) ); 351 441 352 442 if (pj_stristr(&output, &wav)) { … … 356 446 } 357 447 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); 361 451 pj_shutdown(); 362 452 return 0;
Note: See TracChangeset
for help on using the changeset viewer.