rtpsession.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. #include "precompile.h"
  2. #include "rtpsession.h"
  3. #include "memutil.h"
  4. #include <winpr/winsock.h>
  5. #define MAX_RTCP_BUF 1500
  6. struct rtp_session_t
  7. {
  8. int rtp_fd;
  9. int rtcp_fd;
  10. struct sockaddr_in local_rtp_addr;
  11. struct sockaddr_in local_rtcp_addr;
  12. struct sockaddr_in remote_rtp_addr;
  13. struct sockaddr_in remote_rtcp_addr;
  14. unsigned flags;
  15. rtp_state *rtpstat;
  16. };
  17. static __inline int bind_udp_socket_port(int sock,
  18. unsigned long local_ip,
  19. unsigned short port)
  20. {
  21. struct sockaddr_in addr = {0};
  22. addr.sin_family = AF_INET;
  23. addr.sin_port = port;
  24. addr.sin_addr.s_addr = local_ip;
  25. return bind(sock, (struct sockaddr*)&addr, sizeof(addr));
  26. }
  27. static __inline int bind_rtp_socket_pair(int rtp_sock,
  28. int rtcp_sock,
  29. unsigned long local_ip,
  30. unsigned short rtp_port,
  31. unsigned short rtcp_port)
  32. {
  33. if (bind_udp_socket_port(rtp_sock, local_ip, rtp_port) == 0 &&
  34. bind_udp_socket_port(rtcp_sock, local_ip, rtcp_port) == 0)
  35. return 0;
  36. return -1;
  37. }
  38. static __inline int is_addr_equal(const struct sockaddr_in *addr1, const struct sockaddr_in *addr2)
  39. {
  40. return addr1->sin_addr.s_addr == addr2->sin_addr.s_addr &&
  41. addr1->sin_port == addr2->sin_port;
  42. }
  43. #ifndef SIO_UDP_CONNRESET
  44. #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
  45. #endif
  46. static __inline int enable_udp_connreset(int sock, BOOL bOn)
  47. {
  48. DWORD dwBytesReturned = 0;
  49. BOOL bNewBehavior = bOn;
  50. return WSAIoctl(sock, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
  51. NULL, 0, &dwBytesReturned, NULL, NULL);
  52. }
  53. static int udp_block_send(int sock,
  54. const struct sockaddr*addr,
  55. int addrlen,
  56. const char *buf,
  57. int n)
  58. {
  59. int ret;
  60. WSABUF wsabuf[1];
  61. DWORD BytesSent;
  62. wsabuf[0].buf = (char*)buf;
  63. wsabuf[0].len = n;
  64. ret = WSASendTo(sock, &wsabuf[0], 1, &BytesSent, 0, addr, addrlen, NULL, NULL);
  65. if (ret == 0) {
  66. return 0;
  67. } else {
  68. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  69. fd_set fs;
  70. FD_ZERO(&fs);
  71. FD_SET(sock, &fs);
  72. return select(1, NULL, &fs, NULL, NULL);
  73. }
  74. }
  75. return -1;
  76. }
  77. static int udp_block_send2(int sock,
  78. const struct sockaddr*addr,
  79. int addrlen,
  80. const char *buf0,
  81. int n0,
  82. const char *buf1,
  83. int n1)
  84. {
  85. int ret;
  86. WSABUF wsabuf[2];
  87. DWORD BytesSent;
  88. wsabuf[0].buf = (char*)(buf0);
  89. wsabuf[0].len = n0;
  90. wsabuf[1].buf = (char*)(buf1);
  91. wsabuf[1].len = n1;
  92. ret = WSASendTo(sock, &wsabuf[0], 2, &BytesSent, 0, addr, addrlen, NULL, NULL);
  93. if (ret == 0) {
  94. return 0;
  95. } else {
  96. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  97. fd_set fs;
  98. FD_ZERO(&fs);
  99. FD_SET(sock, &fs);
  100. return select(1, NULL, &fs, NULL, NULL);
  101. }
  102. }
  103. return -1;
  104. }
  105. static int udp_poll_recv(int sock,
  106. struct sockaddr*addr,
  107. int *addrlen,
  108. char *buf,
  109. int n)
  110. {
  111. int ret;
  112. WSABUF wsabuf[1];
  113. DWORD dwBytesRecv;
  114. DWORD dwFlags = 0;
  115. wsabuf[0].buf = buf;
  116. wsabuf[0].len = n;
  117. ret = WSARecvFrom(sock, &wsabuf[0], 1, &dwBytesRecv, &dwFlags, addr, addrlen, NULL, NULL);
  118. return ret == 0 ? (int)dwBytesRecv : -1;
  119. }
  120. static int udp_poll_recv2(int sock,
  121. struct sockaddr*addr,
  122. int *addrlen,
  123. char *buf0,
  124. int n0,
  125. char *buf1,
  126. int n1)
  127. {
  128. int ret;
  129. WSABUF wsabuf[2];
  130. DWORD dwBytesRecv;
  131. DWORD dwFlags = 0;
  132. wsabuf[0].buf = buf0;
  133. wsabuf[0].len = n0;
  134. wsabuf[1].buf = buf1;
  135. wsabuf[1].len = n1;
  136. ret = WSARecvFrom(sock, &wsabuf[0], 2, &dwBytesRecv, &dwFlags, addr, addrlen, NULL, NULL);
  137. return ret == 0 ? (int)dwBytesRecv : -1;
  138. }
  139. static int rtp_session_send_rtcp_fb_tmmbn(rtp_session_t *sess, unsigned int ssrc) {
  140. if (sess && !(sess->flags & RTP_SESSION_FLAG_NO_RTCP)) {
  141. char tmp[MAX_RTCP_BUF];
  142. int n;
  143. n = rtp_state_rtcp_make_rtcp_fb_tmmbn(sess->rtpstat, tmp, sizeof(tmp), ssrc);
  144. if (n > 0) {
  145. udp_block_send(sess->rtcp_fd, (struct sockaddr*)&sess->remote_rtcp_addr,
  146. sizeof(struct sockaddr_in), tmp, n);
  147. }
  148. } else {
  149. return -1;
  150. }
  151. return 0;
  152. }
  153. //notice£¬this function must be called after rtp_state_on_recv_rtcp£¬
  154. //because rtp_state_on_recv_rtcp will update tmmbr_info.received before we send tmmbn.
  155. static void handle_rtcp_feedback_packet(rtp_session_t *sess, const char *buf, unsigned *flags) {
  156. rtcp_fb_header_t *fbh;
  157. rtcp_common_t *ch = (rtcp_common_t *)&buf[0];
  158. //we send tmmbn
  159. switch ((rtcp_rtpfb_type_t)ch->count) {
  160. case RTCP_RTPFB_TMMBR:
  161. fbh = (rtcp_fb_header_t *)(buf + sizeof(rtcp_common_t));
  162. rtp_session_send_rtcp_fb_tmmbn(sess, ntohl(fbh->packet_sender_ssrc));
  163. *flags |= RTP_SESSION_HAS_RTPFB_TMMBR;
  164. break;
  165. default:
  166. break;
  167. }
  168. }
  169. static void handle_rtcp_sr_packet(rtp_session_t *sess, const char *buf) {
  170. //RTP_SESSION_FLAG_RECVONLY, we send RR
  171. if (!(sess->flags & RTP_SESSION_FLAG_SENDONLY)) {
  172. char tmp[MAX_RTCP_BUF];
  173. int length = rtp_state_rtcp_make_rr(sess->rtpstat, tmp, sizeof(tmp));
  174. if (length > 0) {
  175. udp_block_send(sess->rtcp_fd, (struct sockaddr*)&sess->remote_rtcp_addr,
  176. sizeof(struct sockaddr_in), tmp, length);
  177. }
  178. }
  179. }
  180. static void handle_rtcp_packet(rtp_session_t *sess, const char *buf, int len) {
  181. int n = 0;
  182. while( n < len) {
  183. const rtcp_common_t *common = (rtcp_common_t *)((const char*)buf + n);
  184. if (common->version != 2)
  185. return ;
  186. n += sizeof(rtcp_common_t);
  187. switch (common->pt) {
  188. case RTCP_SR:
  189. handle_rtcp_sr_packet(sess, (char *)common);
  190. break;
  191. default:
  192. break;
  193. }
  194. n += ntohs(common->length) * 4;
  195. }
  196. }
  197. static int recv_rtcp_raw(rtp_session_t *sess, char *buf, int n)
  198. {
  199. int rc;
  200. struct sockaddr_in addr;
  201. int addrlen = sizeof(addr);
  202. if (!sess || !buf || n <= 0)
  203. return -1;
  204. /* try recv rtcp packet */
  205. rc = udp_poll_recv(sess->rtcp_fd, (struct sockaddr*)&addr, &addrlen, buf, n);
  206. if (rc > 0) {
  207. if (is_addr_equal(&sess->remote_rtcp_addr, &addr)) {
  208. handle_rtcp_packet(sess, buf, n);
  209. return rc;
  210. }
  211. }
  212. return -1;
  213. }
  214. static int recv_rtcp(rtp_session_t *sess, unsigned *flags)
  215. {
  216. int ret;
  217. char tmp[MAX_RTCP_BUF];
  218. if (flags)
  219. *flags = 0;
  220. ret = recv_rtcp_raw(sess, tmp, sizeof(tmp));
  221. if (ret > 0 && rtp_state_on_recv_rtcp(sess->rtpstat, tmp, ret) == 0) {
  222. unsigned f = 0;
  223. int left = ret;
  224. while (left > 0) {
  225. rtcp_common_t *common = (rtcp_common_t*)&tmp[ret - left];
  226. switch (common->pt) {
  227. case RTCP_SDES:
  228. f |= RTP_SESSION_HAS_SDES;
  229. break;
  230. case RTCP_SR:
  231. f |= RTP_SESSION_HAS_SR;
  232. break;
  233. case RTCP_RR:
  234. f |= RTP_SESSION_HAS_RR;
  235. break;
  236. case RTCP_BYE:
  237. f |= RTP_SESSION_HAS_BYE;
  238. break;
  239. case RTCP_APP:
  240. f |= RTP_SESSION_HAS_APP;
  241. break;
  242. case RTCP_FIR:
  243. f |= RTP_SESSION_HAS_FIR;
  244. break;
  245. case RTCP_NACK:
  246. f |= RTP_SESSION_HAS_NACK;
  247. break;
  248. case RTCP_RTPFB:
  249. handle_rtcp_feedback_packet(sess, (char *)common, &f);
  250. break;
  251. default:
  252. break;
  253. }
  254. left -= (ntohs(common->length)+1)*4;
  255. }
  256. if (flags)
  257. *flags = f;
  258. return 0;
  259. }
  260. return -1;
  261. }
  262. TOOLKIT_API int rtp_session_create(const char *ip,
  263. unsigned short start_port,
  264. unsigned short num_port,
  265. rtp_session_t **pp_s)
  266. {
  267. return rtp_session_create2(inet_addr(ip), start_port, num_port, pp_s);
  268. }
  269. TOOLKIT_API int rtp_session_create2(unsigned long local_ip,
  270. unsigned short start_port,
  271. unsigned short num_port,
  272. rtp_session_t **pp_s)
  273. {
  274. rtp_session_t *sess;
  275. unsigned short rtp_port, end_port;
  276. int rtp_fd = INVALID_SOCKET;
  277. int rtcp_fd = INVALID_SOCKET;
  278. if ((start_port&1) || num_port<2)
  279. return -1;
  280. end_port = start_port + num_port;
  281. for (rtp_port = start_port; rtp_port < end_port; rtp_port+=2)
  282. {
  283. rtp_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  284. if (rtp_fd == INVALID_SOCKET)
  285. return -2;
  286. rtcp_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  287. if (rtcp_fd == INVALID_SOCKET)
  288. {
  289. closesocket(rtp_fd);
  290. return -3;
  291. }
  292. if (bind_rtp_socket_pair(rtp_fd, rtcp_fd, local_ip, htons(rtp_port), htons(rtp_port+1)) == 0)
  293. {
  294. u_long mode = 1;
  295. _ioctlsocket(rtp_fd, FIONBIO, &mode);
  296. _ioctlsocket(rtcp_fd, FIONBIO, &mode);
  297. enable_udp_connreset(rtp_fd, FALSE);
  298. enable_udp_connreset(rtcp_fd, FALSE);
  299. break;
  300. }
  301. if (rtp_fd != INVALID_SOCKET)
  302. {
  303. closesocket(rtp_fd);
  304. }
  305. if (rtcp_fd != INVALID_SOCKET)
  306. {
  307. closesocket(rtcp_fd);
  308. }
  309. }
  310. if (rtp_port == end_port)
  311. return -4;
  312. sess = malloc(sizeof(struct rtp_session_t));
  313. sess->local_rtp_addr.sin_family = AF_INET;
  314. sess->local_rtp_addr.sin_port = htons(rtp_port);
  315. sess->local_rtp_addr.sin_addr.s_addr = local_ip;
  316. sess->local_rtcp_addr.sin_family = AF_INET;
  317. sess->local_rtcp_addr.sin_port = htons(rtp_port+1);
  318. sess->local_rtcp_addr.sin_addr.s_addr = local_ip;
  319. sess->rtp_fd = rtp_fd;
  320. sess->rtcp_fd = rtcp_fd;
  321. sess->rtpstat = rtp_state_create(-1);
  322. *pp_s = sess;
  323. return 0;
  324. }
  325. TOOLKIT_API int rtp_session_destroy(rtp_session_t *sess)
  326. {
  327. if (!sess)
  328. return -1;
  329. if (sess->rtpstat)
  330. rtp_state_destroy(sess->rtpstat);
  331. if (sess->rtp_fd != INVALID_SOCKET)
  332. closesocket(sess->rtp_fd);
  333. if (sess->rtcp_fd != INVALID_SOCKET)
  334. closesocket(sess->rtcp_fd);
  335. free(sess);
  336. return 0;
  337. }
  338. TOOLKIT_API int rtp_session_reset(rtp_session_t *sess,
  339. unsigned flags,
  340. const char *remote_ip, /* remote address , network byte order, NULL for wait for peer to connect in, in NAT traverse case */
  341. unsigned short remote_rtp_port,
  342. unsigned short remote_rtcp_port)
  343. {
  344. return rtp_session_reset2(sess, flags, inet_addr(remote_ip), remote_rtp_port, remote_rtcp_port);
  345. }
  346. TOOLKIT_API int rtp_session_reset2(rtp_session_t *sess,
  347. unsigned flags,
  348. unsigned long iremote_ip, /* remote address , network byte order */
  349. unsigned short remote_rtp_port,
  350. unsigned short remote_rtcp_port) // if rtcp port == 0, no rtcp
  351. {
  352. if (!sess || !sess->rtpstat)
  353. return -1;
  354. if (!iremote_ip) {
  355. remote_rtp_port = 0;
  356. remote_rtcp_port = 0;
  357. }
  358. sess->remote_rtp_addr.sin_family = AF_INET;
  359. sess->remote_rtp_addr.sin_port = htons(remote_rtp_port);
  360. sess->remote_rtp_addr.sin_addr.s_addr = iremote_ip;
  361. sess->remote_rtcp_addr.sin_family = AF_INET;
  362. sess->remote_rtcp_addr.sin_port = htons(remote_rtcp_port);
  363. sess->remote_rtcp_addr.sin_addr.s_addr = iremote_ip;
  364. sess->flags = flags;
  365. rtp_state_reset(sess->rtpstat, GetTickCount(), 0, 0);
  366. rtp_state_set_rtcp_sdes_string(sess->rtpstat, RTCP_SDES_CNAME, "vvvrtp_statevvv");
  367. /* clear all kernel buffer */
  368. {
  369. int rc = 1;
  370. struct sockaddr_in addr;
  371. int addrlen = sizeof(addr);
  372. char tmp[MAX_RTCP_BUF];
  373. while (rc > 0) {
  374. rc = udp_poll_recv(sess->rtp_fd, (struct sockaddr*)&addr, &addrlen, tmp, sizeof(tmp));
  375. }
  376. rc = 1;
  377. while (rc > 0) {
  378. rc = udp_poll_recv(sess->rtcp_fd, (struct sockaddr*)&addr, &addrlen, tmp, sizeof(tmp));
  379. }
  380. }
  381. return 0;
  382. }
  383. TOOLKIT_API int rtp_session_send(rtp_session_t *sess,
  384. unsigned *rtcp_rx_flags,
  385. unsigned pt,
  386. unsigned mark,
  387. unsigned delta_ts,
  388. const char *buf,
  389. int n)
  390. {
  391. return rtp_session_send_hook(sess, rtcp_rx_flags, pt, mark, delta_ts, buf, n, 0, 0);
  392. }
  393. TOOLKIT_API int rtp_session_send_hook(rtp_session_t *sess,
  394. unsigned *rtcp_rx_flags,
  395. unsigned pt,
  396. unsigned mark,
  397. unsigned delta_ts,
  398. const char *buf,
  399. int n,
  400. void (*on_tx_hook)(const char *buf, int size, void *arg), void *hook_arg)
  401. {
  402. rtp_hdr hdr;
  403. int ret;
  404. if (!sess || !buf || n <= 0)
  405. return -1;
  406. rtp_state_fill_rtp(sess->rtpstat, &hdr, pt, mark, delta_ts);
  407. return rtp_session_send_hook2(sess, rtcp_rx_flags, &hdr, buf, n, on_tx_hook, hook_arg);
  408. }
  409. TOOLKIT_API int rtp_session_send_hook2(rtp_session_t *sess,
  410. unsigned *rtcp_rx_flags,
  411. const rtp_hdr *hdr,
  412. const char *buf,
  413. int n,
  414. void (*on_tx_hook)(const char *buf, int size, void *arg), void *hook_arg)
  415. {
  416. int ret;
  417. if (!sess || !buf || n <= 0)
  418. return -1;
  419. if (rtcp_rx_flags)
  420. *rtcp_rx_flags = 0;
  421. if (!(sess->flags & RTP_SESSION_FLAG_NO_RTCP)) {
  422. //only in sendonly we process recv_rtcp in rtp_session_send_hook function.
  423. if (!(sess->flags & RTP_SESSION_FLAG_RECVONLY)) {
  424. if (sess->remote_rtcp_addr.sin_port != 0)
  425. recv_rtcp(sess, rtcp_rx_flags);
  426. }
  427. }
  428. {
  429. static int ss_seq = 0;
  430. if (++ss_seq == 60) {
  431. ret = 0;
  432. } else {
  433. ret = udp_block_send2(sess->rtp_fd, (struct sockaddr*)&sess->remote_rtp_addr,
  434. sizeof(struct sockaddr_in), (char*)hdr, sizeof(*hdr), buf, n);
  435. }
  436. }
  437. if (on_tx_hook) {
  438. int size = sizeof(*hdr) + n;
  439. char *tbuf = (char*)malloc(size);
  440. memcpy(tbuf, hdr, sizeof(*hdr));
  441. memcpy(tbuf+sizeof(*hdr), buf, n);
  442. (*on_tx_hook)(tbuf, size, hook_arg);
  443. free(tbuf);
  444. }
  445. if (ret != 0)
  446. return ret;
  447. rtp_state_on_send_rtp(sess->rtpstat, sizeof(*hdr)+n);
  448. if (!(sess->flags & RTP_SESSION_FLAG_NO_RTCP)) {
  449. if (rtp_state_need_send_rtcp(sess->rtpstat, TRUE) && sess->remote_rtcp_addr.sin_port != 0) {
  450. char tmp[MAX_RTCP_BUF];
  451. u__int64_t mxtbr;
  452. ret = rtp_state_rtcp_make_sr(sess->rtpstat, tmp, sizeof(tmp));
  453. udp_block_send(sess->rtcp_fd, (struct sockaddr*)&sess->remote_rtcp_addr,
  454. sizeof(struct sockaddr_in), tmp, ret);
  455. //retry send tmmbr
  456. if (rtp_state_get_tmmbr_wait_send_maxbitrate(sess->rtpstat, &mxtbr) == 0){
  457. rtp_session_send_rtcp_fb_tmmbr(sess, mxtbr);
  458. }
  459. }
  460. }
  461. return 0;
  462. }
  463. TOOLKIT_API int rtp_session_send_raw(rtp_session_t *sess,
  464. unsigned *rtcp_rx_flags,
  465. const char *buf,
  466. int n)
  467. {
  468. int ret;
  469. if (!sess || !buf || n <= 0)
  470. return -1;
  471. if (rtcp_rx_flags)
  472. *rtcp_rx_flags = 0;
  473. if (!(sess->flags & RTP_SESSION_FLAG_NO_RTCP)) {
  474. if (!(sess->flags & RTP_SESSION_FLAG_RECVONLY)) {
  475. if (sess->remote_rtcp_addr.sin_port != 0)
  476. recv_rtcp(sess, rtcp_rx_flags);
  477. }
  478. }
  479. ret = udp_block_send(sess->rtp_fd, (struct sockaddr*)&sess->remote_rtp_addr,
  480. sizeof(struct sockaddr_in), buf, n);
  481. if (ret != 0)
  482. return ret;
  483. rtp_state_on_send_rtp(sess->rtpstat, n);
  484. if (!(sess->flags & RTP_SESSION_FLAG_NO_RTCP)) {
  485. if (rtp_state_need_send_rtcp(sess->rtpstat, TRUE) && sess->remote_rtcp_addr.sin_port != 0) {
  486. char tmp[MAX_RTCP_BUF];
  487. u__int64_t mxtbr;
  488. ret = rtp_state_rtcp_make_sr(sess->rtpstat, tmp, sizeof(tmp));
  489. udp_block_send(sess->rtcp_fd, (struct sockaddr*)&sess->remote_rtcp_addr,
  490. sizeof(struct sockaddr_in), tmp, ret);
  491. //retry send tmmbr
  492. if (rtp_state_get_tmmbr_wait_send_maxbitrate(sess->rtpstat, &mxtbr) == 0){
  493. rtp_session_send_rtcp_fb_tmmbr(sess, mxtbr);
  494. }
  495. }
  496. }
  497. return 0;
  498. }
  499. TOOLKIT_API int rtp_session_send_rtcp_h261_fir(rtp_session_t *sess)
  500. {
  501. if (sess && !(sess->flags & RTP_SESSION_FLAG_NO_RTCP)) {
  502. char tmp[MAX_RTCP_BUF];
  503. int n;
  504. n = rtp_state_rtcp_make_h261_fir(sess->rtpstat, tmp, sizeof(tmp));
  505. udp_block_send(sess->rtcp_fd, (struct sockaddr*)&sess->remote_rtcp_addr,
  506. sizeof(struct sockaddr_in), tmp, n);
  507. } else {
  508. return -1;
  509. }
  510. return 0;
  511. }
  512. TOOLKIT_API int rtp_session_send_rtcp_fb_tmmbr(rtp_session_t *sess, u__int64_t mxtbr) {
  513. if (sess && !(sess->flags & RTP_SESSION_FLAG_NO_RTCP)) {
  514. char tmp[MAX_RTCP_BUF];
  515. int n;
  516. n = rtp_state_rtcp_make_rtcp_fb_tmmbr(sess->rtpstat, tmp, sizeof(tmp), mxtbr, IP_UDP_OVERHEAD);
  517. udp_block_send(sess->rtcp_fd, (struct sockaddr*)&sess->remote_rtcp_addr,
  518. sizeof(struct sockaddr_in), tmp, n);
  519. } else {
  520. return -1;
  521. }
  522. return 0;
  523. }
  524. TOOLKIT_API int rtp_session_recv_hook(rtp_session_t *sess,
  525. unsigned *pt,
  526. unsigned *mark,
  527. unsigned *ts,
  528. unsigned short *seq,
  529. char *buf,
  530. int n,
  531. void (*on_rx_hook)(const char *buf, int size, void *arg), void *hook_arg)
  532. {
  533. int result;
  534. rtp_hdr hdr;
  535. if (!sess || !buf || n <= 0)
  536. return -1;
  537. result = rtp_session_recv_hook2(sess, &hdr, buf, n, on_rx_hook, hook_arg);
  538. if (result > 0) {
  539. if (pt)
  540. *pt = hdr.pt;
  541. if (mark)
  542. *mark = hdr.m;
  543. if (ts)
  544. *ts = ntohl(hdr.ts);
  545. if (seq)
  546. *seq = ntohs(hdr.seq);
  547. }
  548. return result;
  549. }
  550. TOOLKIT_API int rtp_session_recv_hook2(rtp_session_t *sess,
  551. rtp_hdr *hdr,
  552. char *buf,
  553. int n,
  554. void (*on_rx_hook)(const char *buf, int size, void *arg), void *hook_arg)
  555. {
  556. int ret;
  557. int max_cnt;
  558. int i;
  559. struct sockaddr_in addr = {0};
  560. int addrlen = sizeof(addr);
  561. if (!sess || !buf || n <= 0)
  562. return -1;
  563. max_cnt = 5;
  564. for (i = 0 ; i < max_cnt; ++i) {
  565. ret = udp_poll_recv2(sess->rtp_fd, (struct sockaddr*)&addr, &addrlen, (char*)hdr, sizeof(*hdr), buf, n);
  566. if (ret > 0) {
  567. if (on_rx_hook) {
  568. if (ret <= sizeof(*hdr)) {
  569. (*on_rx_hook)((char*)hdr, ret, hook_arg);
  570. } else {
  571. char *tbuf = (char*)malloc(ret);
  572. memcpy(tbuf, (char*)hdr, sizeof(*hdr));
  573. memcpy(tbuf+sizeof(*hdr), buf, ret - sizeof(*hdr));
  574. (*on_rx_hook)(tbuf, ret, hook_arg);
  575. free(tbuf);
  576. }
  577. }
  578. if (is_addr_equal(&sess->remote_rtp_addr, &addr)) {
  579. if (rtp_state_on_recv_rtp(sess->rtpstat, hdr, ret)==0) {
  580. break;
  581. }
  582. }
  583. } else {
  584. return -1;
  585. }
  586. }
  587. if (i >= 5)
  588. return -1;
  589. return ret - sizeof(*hdr);
  590. }
  591. TOOLKIT_API int rtp_session_recv(rtp_session_t *sess,
  592. unsigned *pt,
  593. unsigned *mark,
  594. unsigned *ts,
  595. unsigned short *seq,
  596. char *buf,
  597. int n)
  598. {
  599. return rtp_session_recv_hook(sess, pt, mark, ts, seq, buf, n, 0, 0);
  600. }
  601. TOOLKIT_API int rtp_session_recv_raw(rtp_session_t *sess, char *buf, int n)
  602. {
  603. int ret;
  604. int max_cnt;
  605. int i;
  606. struct sockaddr_in addr;
  607. int addrlen = sizeof(addr);
  608. if (!sess || !buf || n <= 0)
  609. return -1;
  610. max_cnt = 5;
  611. for (i = 0 ; i < max_cnt; ++i) {
  612. ret = udp_poll_recv(sess->rtp_fd, (struct sockaddr*)&addr, &addrlen, buf, n);
  613. if (ret > 0) {
  614. if (is_addr_equal(&sess->remote_rtp_addr, &addr)) {
  615. rtp_hdr *p_hdr = (rtp_hdr*)&buf[0];
  616. if (rtp_state_on_recv_rtp(sess->rtpstat, p_hdr, ret)==0) {
  617. break;
  618. }
  619. }
  620. }
  621. }
  622. if (i >= 5)
  623. return -1;
  624. return ret;
  625. }
  626. TOOLKIT_API int rtp_session_recv_rtcp(rtp_session_t *sess, unsigned *rtcp_rx_flags)
  627. {
  628. if (!sess || !rtcp_rx_flags)
  629. return -1;
  630. *rtcp_rx_flags = 0;
  631. if (!(sess->flags & RTP_SESSION_FLAG_NO_RTCP)) {
  632. if (sess->remote_rtcp_addr.sin_port != 0) {
  633. recv_rtcp(sess, rtcp_rx_flags);
  634. }
  635. }
  636. return 0;
  637. }
  638. TOOLKIT_API int rtp_session_advance_timestamp(rtp_session_t *sess, unsigned int delta_ts)
  639. {
  640. if (!sess)
  641. return -1;
  642. return rtp_state_advance_timestamp(sess->rtpstat, delta_ts);
  643. }
  644. TOOLKIT_API int rtp_session_get_rtcp_stat(rtp_session_t *sess, rtcp_statistics *stat)
  645. {
  646. if (!sess || !stat)
  647. return -1;
  648. return rtp_state_get_stat(sess->rtpstat, stat);
  649. }
  650. TOOLKIT_API rtp_state *rtp_session_get_rtp_state(rtp_session_t *sess)
  651. {
  652. if (!sess)
  653. return 0;
  654. return sess->rtpstat;
  655. }
  656. TOOLKIT_API int rtp_session_get_local_ip(rtp_session_t *sess, unsigned long *p_local_ip)
  657. {
  658. if (!sess || !p_local_ip)
  659. return -1;
  660. *p_local_ip = sess->local_rtp_addr.sin_addr.s_addr;
  661. return 0;
  662. }
  663. TOOLKIT_API int rtp_session_get_local_rtp_port(rtp_session_t *sess, unsigned short *p_rtp)
  664. {
  665. if (!sess || !p_rtp)
  666. return -1;
  667. *p_rtp = ntohs(sess->local_rtp_addr.sin_port);
  668. return 0;
  669. }
  670. TOOLKIT_API int rtp_session_get_local_rtcp_port(rtp_session_t *sess, unsigned short *p_rtcp)
  671. {
  672. if (!sess || !p_rtcp)
  673. return -1;
  674. *p_rtcp = ntohs(sess->local_rtcp_addr.sin_port);
  675. return 0;
  676. }
  677. TOOLKIT_API int rtp_session_get_remote_ip(rtp_session_t *sess, unsigned long *p_remote_ip)
  678. {
  679. if (!sess || !p_remote_ip)
  680. return -1;
  681. *p_remote_ip = sess->remote_rtp_addr.sin_addr.s_addr;
  682. return 0;
  683. }
  684. TOOLKIT_API int rtp_session_get_remote_rtp_port(rtp_session_t *sess, unsigned short *p_rtp)
  685. {
  686. if (!sess || !p_rtp)
  687. return -1;
  688. *p_rtp = ntohs(sess->remote_rtp_addr.sin_port);
  689. return 0;
  690. }
  691. TOOLKIT_API int rtp_session_get_remote_rtcp_port(rtp_session_t *sess, unsigned short *p_rtcp)
  692. {
  693. if (!sess || !p_rtcp)
  694. return -1;
  695. *p_rtcp = ntohs(sess->remote_rtcp_addr.sin_port);
  696. return 0;
  697. }
  698. TOOLKIT_API int rtp_session_get_raw_fd(rtp_session_t *sess, int *rtp_fd, int *rtcp_fd)
  699. {
  700. if (!sess)
  701. return -1;
  702. if (rtp_fd)
  703. *rtp_fd = sess->rtp_fd;
  704. if (rtcp_fd)
  705. *rtcp_fd = sess->rtcp_fd;
  706. return 0;
  707. }