25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

239 satır
6.9KB

  1. // RFC 2326 Real Time Streaming Protocol (RTSP)
  2. // 12.39 Transport (p58)
  3. //
  4. // Transport = "Transport" ":" 1#transport-spec
  5. // transport-spec = transport-protocol/profile[/lower-transport] *parameter
  6. // transport-protocol = "RTP"
  7. // profile = "AVP"
  8. // lower-transport = "TCP" | "UDP"
  9. // parameter = ( "unicast" | "multicast" )
  10. // | ";" "destination" [ "=" address ]
  11. // | ";" "interleaved" "=" channel [ "-" channel ]
  12. // | ";" "append"
  13. // | ";" "ttl" "=" ttl
  14. // | ";" "layers" "=" 1*DIGIT
  15. // | ";" "port" "=" port [ "-" port ]
  16. // | ";" "client_port" "=" port [ "-" port ]
  17. // | ";" "server_port" "=" port [ "-" port ]
  18. // | ";" "ssrc" "=" ssrc
  19. // | ";" "mode" = <"> 1\#mode <">
  20. // ttl = 1*3(DIGIT)
  21. // port = 1*5(DIGIT)
  22. // ssrc = 8*8(HEX)
  23. // channel = 1*3(DIGIT)
  24. // address = host
  25. // mode = <"> *Method <"> | Method
  26. //
  27. // Transport: RTP/AVP;unicast;client_port=4588-4589;server_port=6256-6257
  28. // Transport: RTP/AVP;multicast;ttl=127;mode="PLAY",RTP/AVP;unicast;client_port=3456-3457;mode="PLAY"
  29. // RTP Port define
  30. // RFC 3550: 11. RTP over Network and Transport Protocols (p56)
  31. // 1. For UDP and similar protocols, RTP should use an even destination port number and
  32. // the corresponding RTCP stream should use the next higher (odd) destination port number.
  33. // 2. For applications that take a single port number as a parameter and derive the RTP and RTCP port
  34. // pair from that number, if an odd number is supplied then the application should replace that
  35. // number with the next lower (even) number to use as the base of the port pair.
  36. #include "rtsp-header-transport.h"
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <assert.h>
  41. #if defined(_WIN32) || defined(_WIN64) || defined(OS_WINDOWS)
  42. #define strcasecmp _stricmp
  43. #define strncasecmp _strnicmp
  44. #endif
  45. #define TRANSPORT_SPECIAL ",;\r\n"
  46. int rtsp_header_transport(const char* field, struct rtsp_header_transport_t* t)
  47. {
  48. const char* p1;
  49. const char* p = field;
  50. size_t n;
  51. memset(t, 0, sizeof(*t));
  52. t->multicast = 0; // default unicast
  53. t->transport = RTSP_TRANSPORT_RTP_UDP;
  54. while(p && *p)
  55. {
  56. p1 = strpbrk(p, TRANSPORT_SPECIAL);
  57. n = p1 ? (size_t)(p1 - p) : strlen(p); // ptrdiff_t -> size_t
  58. switch(*p)
  59. {
  60. case 'r':
  61. case 'R':
  62. if(11 == n && 0 == strncasecmp("RTP/AVP/UDP", p, 11))
  63. {
  64. t->transport = RTSP_TRANSPORT_RTP_UDP;
  65. }
  66. else if(11 == n && 0 == strncasecmp("RTP/AVP/TCP", p, 11))
  67. {
  68. t->transport = RTSP_TRANSPORT_RTP_TCP;
  69. }
  70. else if(11 == n && 0 == strncasecmp("RAW/RAW/UDP", p, 11))
  71. {
  72. t->transport = RTSP_TRANSPORT_RAW;
  73. }
  74. else if(7 == n && 0 == strncasecmp("RTP/AVP", p, 7))
  75. {
  76. t->transport = RTSP_TRANSPORT_RTP_UDP;
  77. }
  78. break;
  79. case 'u':
  80. case 'U':
  81. if(7 == n && 0 == strncasecmp("unicast", p, 7))
  82. {
  83. t->multicast = 0;
  84. }
  85. break;
  86. case 'm':
  87. case 'M':
  88. if(9 == n && 0 == strncasecmp("multicast", p, 9))
  89. {
  90. t->multicast = 1;
  91. }
  92. else if(n > 5 && 0 == strncasecmp("mode=", p, 5))
  93. {
  94. if( (11==n && 0 == strcasecmp("\"PLAY\"", p+5)) || (9==n && 0 == strcasecmp("PLAY", p+5)) )
  95. t->mode = RTSP_TRANSPORT_PLAY;
  96. else if( (13==n && 0 == strcasecmp("\"RECORD\"", p+5)) || (11==n && 0 == strcasecmp("RECORD", p+5)) )
  97. t->mode = RTSP_TRANSPORT_RECORD;
  98. }
  99. break;
  100. case 'd':
  101. case 'D':
  102. if(n >= 12 && 0 == strncasecmp("destination=", p, 12))
  103. {
  104. if(n-12 >= sizeof(t->destination)) return -1;
  105. memcpy(t->destination, p+12, n - 12);
  106. t->destination[n-12] = '\0';
  107. }
  108. break;
  109. case 's':
  110. case 'S':
  111. if(n >= 7 && 0 == strncasecmp("source=", p, 7))
  112. {
  113. if(n-7 >= sizeof(t->source)) return -1;
  114. memcpy(t->source, p+7, n - 7);
  115. t->source[n-7] = '\0';
  116. }
  117. else if(13 == n && 0 == strncasecmp("ssrc=", p, 5))
  118. {
  119. // unicast only
  120. assert(0 == t->multicast);
  121. t->rtp.u.ssrc = (unsigned int)strtoul(p+5, NULL, 16);
  122. }
  123. else if(2 == sscanf(p, "server_port=%hu-%hu", &t->rtp.u.server_port1, &t->rtp.u.server_port2))
  124. {
  125. assert(0 == t->multicast);
  126. }
  127. else if(1 == sscanf(p, "server_port=%hu", &t->rtp.u.server_port1))
  128. {
  129. assert(0 == t->multicast);
  130. t->rtp.u.server_port1 = t->rtp.u.server_port1 / 2 * 2; // RFC 3550 (p56)
  131. t->rtp.u.server_port2 = t->rtp.u.server_port1 + 1;
  132. }
  133. break;
  134. case 'a':
  135. if(6 == n && 0 == strcasecmp("append", p))
  136. {
  137. t->append = 1;
  138. }
  139. break;
  140. case 'p':
  141. if(2 == sscanf(p, "port=%hu-%hu", &t->rtp.m.port1, &t->rtp.m.port2))
  142. {
  143. assert(1 == t->multicast);
  144. }
  145. else if(1 == sscanf(p, "port=%hu", &t->rtp.m.port1))
  146. {
  147. assert(1 == t->multicast);
  148. t->rtp.m.port1 = t->rtp.m.port1 / 2 * 2; // RFC 3550 (p56)
  149. t->rtp.m.port2 = t->rtp.m.port1 + 1;
  150. }
  151. break;
  152. case 'c':
  153. if(2 == sscanf(p, "client_port=%hu-%hu", &t->rtp.u.client_port1, &t->rtp.u.client_port2))
  154. {
  155. assert(0 == t->multicast);
  156. }
  157. else if(1 == sscanf(p, "client_port=%hu", &t->rtp.u.client_port1))
  158. {
  159. assert(0 == t->multicast);
  160. t->rtp.u.client_port1 = t->rtp.u.client_port1 / 2 * 2; // RFC 3550 (p56)
  161. t->rtp.u.client_port2 = t->rtp.u.client_port1 + 1;
  162. }
  163. break;
  164. case 'i':
  165. if(2 == sscanf(p, "interleaved=%d-%d", &t->interleaved1, &t->interleaved2))
  166. {
  167. }
  168. else if(1 == sscanf(p, "interleaved=%d", &t->interleaved1))
  169. {
  170. t->interleaved2 = t->interleaved1 + 1;
  171. }
  172. break;
  173. case 't':
  174. if(1 == sscanf(p, "ttl=%d", &t->rtp.m.ttl))
  175. {
  176. assert(1 == t->multicast);
  177. }
  178. break;
  179. case 'l':
  180. if(1 == sscanf(p, "layers=%d", &t->layer))
  181. {
  182. }
  183. break;
  184. }
  185. if(NULL == p1 || '\r' == *p1 || '\n' == *p1 || '\0' == *p1 || ',' == *p1)
  186. break;
  187. p = p1 + 1;
  188. }
  189. return 0;
  190. }
  191. #if defined(DEBUG) || defined(_DEBUG)
  192. void rtsp_header_transport_test(void)
  193. {
  194. struct rtsp_header_transport_t t;
  195. memset(&t, 0, sizeof(t));
  196. assert(0 == rtsp_header_transport("RTP/AVP;unicast;client_port=4588-4589;server_port=6256-6257;ssrc=08abe80f", &t)); // rfc2326 p61
  197. assert(t.transport==RTSP_TRANSPORT_RTP_UDP);
  198. assert(t.multicast==0 && t.rtp.u.client_port1==4588 && t.rtp.u.client_port2==4589 && t.rtp.u.server_port1==6256 && t.rtp.u.server_port2==6257);
  199. assert(t.rtp.u.ssrc == 0x08abe80f);
  200. memset(&t, 0, sizeof(t));
  201. assert(0 == rtsp_header_transport("RTP/AVP;multicast;ttl=127;mode=\"PLAY\"", &t)); // rfc2326 p61
  202. assert(t.transport==RTSP_TRANSPORT_RTP_UDP);
  203. assert(t.multicast==1 && 127==t.rtp.m.ttl && RTSP_TRANSPORT_PLAY==t.mode);
  204. memset(&t, 0, sizeof(t));
  205. assert(0 == rtsp_header_transport("RTP/AVP/TCP;interleaved=0-1", &t)); // rfc2326 p40
  206. assert(t.transport == RTSP_TRANSPORT_RTP_TCP);
  207. assert(t.interleaved1 == 0 && t.interleaved2 == 1);
  208. memset(&t, 0, sizeof(t));
  209. assert(0 == rtsp_header_transport("RTP/AVP;unicast;source=192.168.111.333.444.555.666.777.888.999.000.123", &t)); // rfc2326 p61
  210. assert(t.transport==RTSP_TRANSPORT_RTP_UDP);
  211. assert(t.multicast==0 && 0==strncmp("192.168.111.333.444.555.666.777.888.999.000.123", t.source, sizeof(t.source)-1) && strlen(t.source)<sizeof(t.source));
  212. }
  213. #endif