switch_rtp_pcap.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. /*
  2. * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
  3. * Copyright (C) 2005-2021, Anthony Minessale II <anthm@freeswitch.org>
  4. *
  5. * Version: MPL 1.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License Version
  8. * 1.1 (the "License"); you may not use this file except in compliance with
  9. * the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14. * for the specific language governing rights and limitations under the
  15. * License.
  16. *
  17. * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
  18. *
  19. * The Initial Developer of the Original Code is
  20. * Anthony Minessale II <anthm@freeswitch.org>
  21. * Portions created by the Initial Developer are Copyright (C)
  22. * the Initial Developer. All Rights Reserved.
  23. *
  24. * Contributor(s):
  25. * Dragos Oancea <dragos@signalwire.com>
  26. *
  27. * switch_rtp_pcap.c -- tests RTP stack using PCAP.
  28. */
  29. #include <switch.h>
  30. #include <test/switch_test.h>
  31. /* before adding a pcap file: tcprewrite --dstipmap=X.X.X.X/32:192.168.0.1/32 --srcipmap=X.X.X.X/32:192.168.0.2/32 -i in.pcap -o out.pcap */
  32. #include <pcap.h>
  33. #ifndef MSG_CONFIRM
  34. #define MSG_CONFIRM 0
  35. #endif
  36. static const char *rx_host = "127.0.0.1";
  37. static const char *tx_host = "127.0.0.1";
  38. static switch_rtp_t *rtp_session = NULL;
  39. const char *err = NULL;
  40. switch_rtp_packet_t rtp_packet;
  41. switch_frame_flag_t *frame_flags;
  42. switch_io_flag_t io_flags;
  43. switch_payload_t read_pt;
  44. static switch_port_t audio_rx_port = 1234;
  45. static int got_media_timeout = 0;
  46. //#define USE_RTCP_PCAP
  47. #define NTP_TIME_OFFSET 2208988800UL
  48. /* https://www.tcpdump.org/pcap.html */
  49. /* IP header */
  50. struct sniff_ip {
  51. u_char ip_vhl; /* version << 4 | header length >> 2 */
  52. u_char ip_tos; /* type of service */
  53. u_short ip_len; /* total length */
  54. u_short ip_id; /* identification */
  55. u_short ip_off; /* fragment offset field */
  56. #define IP_RF 0x8000 /* reserved fragment flag */
  57. #define IP_DF 0x4000 /* dont fragment flag */
  58. #define IP_MF 0x2000 /* more fragments flag */
  59. #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
  60. u_char ip_ttl; /* time to live */
  61. u_char ip_p; /* protocol */
  62. u_short ip_sum; /* checksum */
  63. struct in_addr ip_src,ip_dst; /* source and dest address */
  64. };
  65. #define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
  66. /* switch_rtp.c - calc_local_lsr_now() */
  67. #if 0
  68. static inline uint32_t test_calc_local_lsr_now(switch_time_t now, uint32_t past /*milliseconds*/)
  69. {
  70. // switch_time_t now;
  71. uint32_t ntp_sec, ntp_usec, lsr_now, sec;
  72. // now = switch_micro_time_now() - (past * 1000);
  73. now = now - (past * 1000);
  74. sec = (uint32_t)(now/1000000); /* convert to seconds */
  75. ntp_sec = sec+NTP_TIME_OFFSET; /* convert to NTP seconds */
  76. ntp_usec = (uint32_t)(now - ((switch_time_t) sec*1000000)); /* remove seconds to keep only the microseconds */
  77. lsr_now = (uint32_t)(ntp_usec*0.065536) | (ntp_sec&0x0000ffff)<<16; /* 0.065536 is used for convertion from useconds to fraction of 65536 (x65536/1000000) */
  78. return lsr_now;
  79. }
  80. static void test_prepare_rtcp(void *rtcp_packet, float est_last, uint32_t rtt, uint8_t loss)
  81. {
  82. /* taken from switch_rtp.c, rtcp_generate_sender_info() */
  83. /* === */
  84. char *rtcp_sr_trigger = rtcp_packet;
  85. switch_time_t now;
  86. uint32_t sec, ntp_sec, ntp_usec;
  87. uint32_t ntp_msw;
  88. uint32_t ntp_lsw;
  89. uint32_t *ptr_msw;
  90. uint32_t *ptr_lsw;
  91. uint32_t lsr;
  92. uint32_t *ptr_lsr;
  93. uint32_t dlsr = 0;
  94. uint32_t *ptr_dlsr;
  95. uint8_t *ptr_loss;
  96. now = switch_micro_time_now();
  97. sec = (uint32_t)(now/1000000); /* convert to seconds */
  98. ntp_sec = sec+NTP_TIME_OFFSET; /* convert to NTP seconds */
  99. ntp_msw = htonl(ntp_sec); /* store result in "most significant word" */
  100. ntp_usec = (uint32_t)(now - (sec*1000000)); /* remove seconds to keep only the microseconds */
  101. ntp_lsw = htonl((u_long)(ntp_usec*(double)(((uint64_t)1)<<32)*1.0e-6));
  102. /* === */
  103. /*patch the RTCP payload to set the RTT we want */
  104. ptr_msw = (uint32_t *)rtcp_sr_trigger + 2;
  105. *ptr_msw = ntp_msw;
  106. ptr_lsw = (uint32_t *)rtcp_sr_trigger + 3;
  107. *ptr_lsw = ntp_lsw;
  108. lsr = test_calc_local_lsr_now(now, est_last * 1000 + rtt /*ms*/);
  109. ptr_lsr = (uint32_t *)rtcp_sr_trigger + 11;
  110. *ptr_lsr = htonl(lsr);
  111. ptr_dlsr = (uint32_t *)rtcp_sr_trigger + 12;
  112. *ptr_dlsr = htonl(dlsr);
  113. ptr_loss = (uint8_t *)rtcp_sr_trigger + 32;
  114. *ptr_loss = loss;
  115. }
  116. #endif
  117. static switch_status_t rtp_test_start_call(switch_core_session_t **psession)
  118. {
  119. char *r_sdp;
  120. uint8_t match = 0, p = 0;
  121. switch_core_session_t *session;
  122. switch_channel_t *channel = NULL;
  123. switch_status_t status;
  124. switch_media_handle_t *media_handle;
  125. switch_core_media_params_t *mparams;
  126. switch_stream_handle_t stream = { 0 };
  127. switch_call_cause_t cause;
  128. /*tone stream extension*/
  129. status = switch_ivr_originate(NULL, psession, &cause, "null/+1234", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
  130. session = *psession;
  131. if (!(session)) {
  132. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "no session\n");
  133. return SWITCH_STATUS_FALSE;
  134. }
  135. if (status != SWITCH_STATUS_SUCCESS) {
  136. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_ivr_originate() failed\n");
  137. return SWITCH_STATUS_FALSE;
  138. }
  139. channel = switch_core_session_get_channel(session);
  140. if (!channel) {
  141. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_core_session_get_channel() failed\n");
  142. return SWITCH_STATUS_FALSE;
  143. }
  144. mparams = switch_core_session_alloc(session, sizeof(switch_core_media_params_t));
  145. mparams->inbound_codec_string = switch_core_session_strdup(session, "PCMU");
  146. mparams->outbound_codec_string = switch_core_session_strdup(session, "PCMU");
  147. mparams->rtpip = switch_core_session_strdup(session, (char *)rx_host);
  148. status = switch_media_handle_create(&media_handle, session, mparams);
  149. if (status != SWITCH_STATUS_SUCCESS) {
  150. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_media_handle_create() failed\n");
  151. return SWITCH_STATUS_FALSE;
  152. }
  153. switch_channel_set_variable(channel, "absolute_codec_string", "PCMU");
  154. switch_channel_set_variable(channel, "send_silence_when_idle", "-1");
  155. switch_channel_set_variable(channel, "rtp_timer_name", "soft");
  156. switch_channel_set_variable(channel, "media_timeout", "1000");
  157. switch_channel_set_variable(channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, rx_host);
  158. switch_channel_set_variable_printf(channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, "%d", audio_rx_port);
  159. r_sdp = switch_core_session_sprintf(session,
  160. "v=0\n"
  161. "o=FreeSWITCH 1632033305 1632033306 IN IP4 %s\n"
  162. "s=-\n"
  163. "c=IN IP4 %s\n"
  164. "t=0 0\n"
  165. "m=audio 11114 RTP/AVP 0 101\n"
  166. "a=rtpmap:0 PCMU/8000\n"
  167. "a=rtpmap:101 telephone-event/8000\n"
  168. "a=rtcp-mux\n",
  169. tx_host, tx_host);
  170. status = switch_core_media_prepare_codecs(session, SWITCH_FALSE);
  171. if (status != SWITCH_STATUS_SUCCESS) {
  172. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_core_media_prepare_codecs() failed\n");
  173. return SWITCH_STATUS_FALSE;
  174. }
  175. match = switch_core_media_negotiate_sdp(session, r_sdp, &p, SDP_OFFER);
  176. if (match != 1) {
  177. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_core_media_negotiate_sdp() failed\n");
  178. return SWITCH_STATUS_FALSE;
  179. }
  180. status = switch_core_media_choose_ports(session, SWITCH_TRUE, SWITCH_FALSE);
  181. if (status != SWITCH_STATUS_SUCCESS) {
  182. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_core_media_choose_ports() failed\n");
  183. return SWITCH_STATUS_FALSE;
  184. }
  185. status = switch_core_media_activate_rtp(session);
  186. if (status != SWITCH_STATUS_SUCCESS) {
  187. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_core_media_activate_rtp() failed\n");
  188. return SWITCH_STATUS_FALSE;
  189. }
  190. switch_core_media_set_rtp_flag(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_RTP_FLAG_DEBUG_RTP_READ);
  191. switch_core_media_set_rtp_flag(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_RTP_FLAG_DEBUG_RTP_WRITE);
  192. SWITCH_STANDARD_STREAM(stream);
  193. switch_api_execute("fsctl", "debug_level 10", session, &stream);
  194. switch_safe_free(stream.data);
  195. return SWITCH_STATUS_SUCCESS;
  196. }
  197. static switch_status_t rtp_test_end_call(switch_core_session_t **psession)
  198. {
  199. switch_channel_t *channel = NULL;
  200. switch_core_session_t *session = *psession;
  201. channel = switch_core_session_get_channel(session);
  202. if (!channel) {
  203. return SWITCH_STATUS_FALSE;
  204. }
  205. switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
  206. switch_media_handle_destroy(session);
  207. switch_core_session_rwunlock(session);
  208. return SWITCH_STATUS_SUCCESS;
  209. }
  210. static void rtp_test_init_frame(switch_frame_t **pwrite_frame, switch_core_session_t **psession)
  211. {
  212. const unsigned char hdr_packet[]="\x80\x00\xcd\x15\xfd\x86\x00\x00\x61\x5a\xe1\x37";
  213. switch_frame_alloc(pwrite_frame, SWITCH_RECOMMENDED_BUFFER_SIZE);
  214. (*pwrite_frame)->codec = switch_core_session_get_write_codec(*psession);
  215. (*pwrite_frame)->datalen = SWITCH_RTP_HEADER_LEN; /*init with dummy RTP header*/
  216. memcpy((*pwrite_frame)->data, &hdr_packet, SWITCH_RTP_HEADER_LEN);
  217. }
  218. static void show_event(switch_event_t *event) {
  219. char *str;
  220. /*print the event*/
  221. switch_event_serialize_json(event, &str);
  222. if (str) {
  223. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", str);
  224. switch_safe_free(str);
  225. }
  226. }
  227. static void event_handler(switch_event_t *event)
  228. {
  229. const char *new_ev = switch_event_get_header(event, "Event-Name");
  230. if (new_ev && !strcmp(new_ev, "CHANNEL_HANGUP")) {
  231. if (!strcmp(switch_event_get_header(event, "Hangup-Cause"), "MEDIA_TIMEOUT")) {
  232. got_media_timeout = 1;
  233. }
  234. }
  235. show_event(event);
  236. }
  237. FST_CORE_DB_BEGIN("./conf_rtp")
  238. {
  239. FST_SUITE_BEGIN(switch_rtp_pcap)
  240. {
  241. FST_SETUP_BEGIN()
  242. {
  243. fst_requires_module("mod_loopback");
  244. }
  245. FST_SETUP_END()
  246. FST_TEARDOWN_BEGIN()
  247. {
  248. }
  249. FST_TEARDOWN_END()
  250. #if 0
  251. FST_TEST_BEGIN(test_rtp_stall_with_rtcp_muxed_with_timer)
  252. {
  253. switch_core_session_t *session = NULL;
  254. switch_status_t status;
  255. uint32_t plen = SWITCH_RTP_HEADER_LEN;
  256. char rpacket[SWITCH_RECOMMENDED_BUFFER_SIZE];
  257. switch_payload_t pt = { 0 };
  258. switch_frame_flag_t frameflags = { 0 };
  259. int x = 0;
  260. switch_frame_t *write_frame;
  261. pcap_t *pcap;
  262. const unsigned char *packet;
  263. char errbuf[PCAP_ERRBUF_SIZE];
  264. struct pcap_pkthdr pcap_header;
  265. char rtcp_sr_trigger[] = "\x81\xc8\x00\x0c\x78\x9d\xac\x45\xe2\x67\xa5\x74\x30\x60\x56\x81\x00\x19"
  266. "\xaa\x00\x00\x00\x06\xd7\x00\x01\x2c\x03\x5e\xbd\x2f\x0b\x00"
  267. "\x00\x00\x00\x00\x00\x57\xc4\x00\x00\x00\x39\xa5\x73\xfe\x90\x00\x00\x2c\x87"
  268. "\x81\xca\x00\x0c\x78\x9d\xac\x45\x01\x18\x73\x69\x70\x3a\x64\x72\x40\x31\x39\x32\x2e"
  269. "\x31\x36\x38\x2e\x30\x2e\x31\x33\x3a\x37\x30\x36\x30\x06\x0e\x4c\x69\x6e\x70\x68\x6f"
  270. "\x6e\x65\x2d\x33\x2e\x36\x2e\x31\x00\x00";
  271. const struct sniff_ip *ip; /* The IP header */
  272. int size_ip, jump_over;
  273. struct timeval prev_ts = { 0 };
  274. switch_time_t time_nowpacket = 0, time_prevpacket = 0;
  275. switch_socket_t *sock_rtp = NULL;
  276. switch_sockaddr_t *sock_addr = NULL;
  277. const char *str_err;
  278. switch_size_t rough_add = 0;
  279. status = rtp_test_start_call(&session);
  280. fst_requires(status == SWITCH_STATUS_SUCCESS);
  281. fst_requires(session);
  282. pcap = pcap_open_offline_with_tstamp_precision("pcap/milliwatt.long.pcmu.rtp.pcap", PCAP_TSTAMP_PRECISION_MICRO, errbuf);
  283. fst_requires(pcap);
  284. switch_core_media_set_rtp_flag(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_RTP_FLAG_ENABLE_RTCP);
  285. rtp_session = switch_core_media_get_rtp_session(session, SWITCH_MEDIA_TYPE_AUDIO);
  286. rtp_test_init_frame(&write_frame, &session);
  287. switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_PAUSE);
  288. if (switch_socket_create(&sock_rtp, AF_INET, SOCK_DGRAM, 0, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
  289. fst_requires(0); /*exit*/
  290. }
  291. switch_sockaddr_new(&sock_addr, rx_host, audio_rx_port, switch_core_session_get_pool(session));
  292. fst_requires(sock_addr);
  293. switch_rtp_set_remote_address(rtp_session, tx_host, switch_sockaddr_get_port(sock_addr), 0, SWITCH_FALSE, &str_err);
  294. switch_rtp_reset(rtp_session);
  295. while ((packet = pcap_next(pcap, &pcap_header))) {
  296. /*assume only UDP/RTP packets in the pcap*/
  297. uint32_t rcvd_datalen = pcap_header.caplen;
  298. size_t len;
  299. switch_size_t tmp_len;
  300. int diff_us = (pcap_header.ts.tv_sec-prev_ts.tv_sec)*1000000+(pcap_header.ts.tv_usec-prev_ts.tv_usec);
  301. if (diff_us > 0) {
  302. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SENT pkt diff: %d us\n", diff_us);
  303. usleep(diff_us);
  304. }
  305. prev_ts = pcap_header.ts;
  306. len = pcap_header.caplen;
  307. if (len <= 42) {
  308. continue;
  309. }
  310. ip = (struct sniff_ip*)(packet + 14);
  311. size_ip = IP_HL(ip) * 4;
  312. jump_over = 14 /*SIZE_ETHERNET*/ + size_ip /*IP HDR size*/ + 8 /* UDP HDR SIZE */; /* jump 42 bytes over network layers/headers */
  313. packet += jump_over;
  314. x++;
  315. if (!(x%10)) { /* send a RTCP SR packet every 10th RTP packet */
  316. int add_rtt = 200;
  317. test_prepare_rtcp(&rtcp_sr_trigger, 2, add_rtt, 0xa0);
  318. tmp_len = sizeof(rtcp_sr_trigger);
  319. /*RTCP muxed*/
  320. if (switch_socket_sendto(sock_rtp, sock_addr, MSG_CONFIRM, (const char*)rtcp_sr_trigger, &tmp_len) != SWITCH_STATUS_SUCCESS) {
  321. fst_requires(0);
  322. }
  323. plen = sizeof(rtcp_sr_trigger);
  324. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Sent RTCP. Packet size = [%u]\n", plen);
  325. status = switch_rtp_read(rtp_session, (void *)rpacket, &rcvd_datalen, &pt, &frameflags, io_flags);
  326. if (pt == SWITCH_RTP_CNG_PAYLOAD /*timeout*/) {
  327. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "read CNG/RTCP, skip\n");
  328. while (1) {
  329. status = switch_rtp_read(rtp_session, (void *)&rpacket, &rcvd_datalen, &pt, &frameflags, io_flags);
  330. if (frameflags || SFF_RTCP) break;
  331. }
  332. }
  333. fst_requires(status == SWITCH_STATUS_SUCCESS);
  334. }
  335. if (packet[0] == 0x80 && packet[1] == 0 /*PCMU*/) {
  336. int16_t *seq = (int16_t *)packet + 1;
  337. plen = len - jump_over;
  338. tmp_len = plen;
  339. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sent RTP. Packet size = [%u] seq = [%d]\n", plen, htons(*seq));
  340. if (switch_socket_sendto(sock_rtp, sock_addr, MSG_CONFIRM, (const char*)packet, &tmp_len) != SWITCH_STATUS_SUCCESS) {
  341. fst_requires(0);
  342. }
  343. }
  344. status = switch_rtp_read(rtp_session, (void *)&rpacket, &rcvd_datalen, &pt, &frameflags, io_flags);
  345. if (pt == SWITCH_RTP_CNG_PAYLOAD /*timeout*/) {
  346. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "read CNG, skip\n");
  347. continue;
  348. }
  349. time_prevpacket = time_nowpacket;
  350. time_nowpacket = switch_time_now();
  351. if (time_prevpacket) { // skip init.
  352. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "RECV pkt diff: %ld us\n", time_nowpacket - time_prevpacket);
  353. fst_requires((time_nowpacket - time_prevpacket) < 80000);
  354. rough_add += time_nowpacket - time_prevpacket; /* just add to var for visual comparison */
  355. }
  356. fst_requires(status == SWITCH_STATUS_SUCCESS);
  357. if (pt == SWITCH_RTP_CNG_PAYLOAD /*timeout*/) continue;
  358. fst_requires(rcvd_datalen == plen - SWITCH_RTP_HEADER_LEN);
  359. }
  360. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "RECV total delay: %lu\n", rough_add); /*around 17092408 us*/
  361. switch_yield(1000 * 1000);
  362. if (write_frame) switch_frame_free(&write_frame);
  363. switch_rtp_destroy(&rtp_session);
  364. rtp_test_end_call(&session);
  365. switch_socket_close(sock_rtp);
  366. pcap_close(pcap);
  367. switch_yield(1000 * 1000);
  368. }
  369. FST_TEST_END()
  370. #endif
  371. FST_TEST_BEGIN(test_rtp_media_timeout)
  372. {
  373. switch_core_session_t *session = NULL;
  374. switch_status_t status;
  375. uint32_t plen = SWITCH_RTP_HEADER_LEN;
  376. char rpacket[SWITCH_RECOMMENDED_BUFFER_SIZE];
  377. switch_payload_t pt = { 0 };
  378. switch_frame_flag_t frameflags = { 0 };
  379. int x = 0;
  380. switch_frame_t *write_frame;
  381. pcap_t *pcap;
  382. const unsigned char *packet;
  383. char errbuf[PCAP_ERRBUF_SIZE];
  384. struct pcap_pkthdr pcap_header;
  385. const struct sniff_ip *ip; /* The IP header */
  386. int size_ip, jump_over;
  387. struct timeval prev_ts = { 0 };
  388. switch_socket_t *sock_rtp = NULL;
  389. switch_sockaddr_t *sock_addr = NULL;
  390. const char *str_err;
  391. status = rtp_test_start_call(&session);
  392. fst_requires(status == SWITCH_STATUS_SUCCESS);
  393. fst_requires(session);
  394. switch_event_bind("", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL);
  395. pcap = pcap_open_offline_with_tstamp_precision("pcap/milliwatt.pcmu.rtp.pcap", PCAP_TSTAMP_PRECISION_MICRO, errbuf);
  396. fst_requires(pcap);
  397. switch_core_media_set_rtp_flag(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_RTP_FLAG_ENABLE_RTCP);
  398. rtp_session = switch_core_media_get_rtp_session(session, SWITCH_MEDIA_TYPE_AUDIO);
  399. fst_requires(rtp_session);
  400. rtp_test_init_frame(&write_frame, &session);
  401. switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_PAUSE);
  402. if (switch_socket_create(&sock_rtp, AF_INET, SOCK_DGRAM, 0, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
  403. fst_requires(0); /*exit*/
  404. }
  405. switch_sockaddr_new(&sock_addr, rx_host, audio_rx_port, switch_core_session_get_pool(session));
  406. fst_requires(sock_addr);
  407. switch_rtp_set_remote_address(rtp_session, tx_host, switch_sockaddr_get_port(sock_addr), 0, SWITCH_FALSE, &str_err);
  408. switch_rtp_reset(rtp_session);
  409. /* send 3 packets then wait and expect RTP timeout */
  410. while ((packet = pcap_next(pcap, &pcap_header)) && x < 3) {
  411. /*assume only UDP/RTP packets in the pcap*/
  412. uint32_t rcvd_datalen = pcap_header.caplen;
  413. size_t len;
  414. switch_size_t tmp_len;
  415. int diff_us = (pcap_header.ts.tv_sec-prev_ts.tv_sec)*1000000+(pcap_header.ts.tv_usec-prev_ts.tv_usec);
  416. if (diff_us > 0) {
  417. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SENT pkt diff: %d us\n", diff_us);
  418. usleep(diff_us);
  419. }
  420. x++;
  421. prev_ts = pcap_header.ts;
  422. len = pcap_header.caplen;
  423. if (len <= 42) {
  424. continue;
  425. }
  426. ip = (struct sniff_ip*)(packet + 14);
  427. size_ip = IP_HL(ip) * 4;
  428. jump_over = 14 /*SIZE_ETHERNET*/ + size_ip /*IP HDR size*/ + 8 /* UDP HDR SIZE */; /* jump 42 bytes over network layers/headers */
  429. packet += jump_over;
  430. if (packet[0] == 0x80 && packet[1] == 0 /*PCMU*/) {
  431. int16_t *seq = (int16_t *)packet + 1;
  432. plen = len - jump_over;
  433. tmp_len = plen;
  434. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sent RTP. Packet size = [%u] seq = [%d]\n", plen, htons(*seq));
  435. if (switch_socket_sendto(sock_rtp, sock_addr, MSG_CONFIRM, (const char*)packet, &tmp_len) != SWITCH_STATUS_SUCCESS) {
  436. fst_requires(0);
  437. }
  438. }
  439. status = switch_rtp_read(rtp_session, (void *)&rpacket, &rcvd_datalen, &pt, &frameflags, io_flags);
  440. if (pt == SWITCH_RTP_CNG_PAYLOAD /*timeout*/) {
  441. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "read CNG, skip\n");
  442. continue;
  443. }
  444. fst_requires(status == SWITCH_STATUS_SUCCESS);
  445. fst_requires(rcvd_datalen == plen - SWITCH_RTP_HEADER_LEN);
  446. }
  447. x = 150; /* 3 seconds max */
  448. while (x || !got_media_timeout) {
  449. uint32_t rcvd_datalen;
  450. status = switch_rtp_read(rtp_session, (void *)&rpacket, &rcvd_datalen, &pt, &frameflags, io_flags);
  451. if (pt == SWITCH_RTP_CNG_PAYLOAD /*timeout*/) {
  452. switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "read CNG, skip\n");
  453. }
  454. switch_yield(20 * 1000);
  455. fst_requires(status == SWITCH_STATUS_SUCCESS);
  456. x--;
  457. }
  458. if (write_frame) switch_frame_free(&write_frame);
  459. switch_rtp_destroy(&rtp_session);
  460. rtp_test_end_call(&session);
  461. switch_socket_close(sock_rtp);
  462. pcap_close(pcap);
  463. fst_check(got_media_timeout);
  464. }
  465. FST_TEST_END()
  466. }
  467. FST_SUITE_END()
  468. }
  469. FST_CORE_END()