Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

225 řádky
8.3KB

  1. /*
  2. C->S:
  3. SETUP rtsp://example.com/foo/bar/baz.rm RTSP/1.0
  4. CSeq: 302
  5. Transport: RTP/AVP;unicast;client_port=4588-4589
  6. S->C:
  7. RTSP/1.0 200 OK
  8. CSeq: 302
  9. Date: 23 Jan 1997 15:35:06 GMT
  10. Session: 47112344
  11. Transport: RTP/AVP;unicast;client_port=4588-4589;server_port=6256-6257
  12. */
  13. #include "rtsp-client-internal.h"
  14. static const char* sc_rtsp_setup = "SETUP %s RTSP/1.0\r\n"
  15. "CSeq: %u\r\n"
  16. "%s" // Session: %s\r\n
  17. "%s" // Authorization: Digest xxx
  18. "%s" // Transport: RTP/AVP;unicast;client_port=6000-6001
  19. "User-Agent: %s\r\n"
  20. "\r\n";
  21. int rtsp_addr_is_multicast(const char* ip);
  22. static int rtsp_client_media_setup(struct rtsp_client_t* rtsp, int i)
  23. {
  24. int len;
  25. char transport[128];
  26. char session[sizeof(rtsp->session[0].session) + 12], *p;
  27. assert(i < rtsp->media_count);
  28. assert(RTSP_SETUP == rtsp->state);
  29. if (i >= rtsp->media_count) return -1;
  30. transport[0] = session[0] = '\0';
  31. p = rtsp->session[0].session;
  32. len = (rtsp->aggregate && *p) ? snprintf(session, sizeof(session), "Session: %s\r\n", p) : 0;
  33. assert(len >= 0 && len < sizeof(session));
  34. switch (rtsp->transport[i].transport) {
  35. case RTSP_TRANSPORT_RTP_TCP:
  36. len = snprintf(transport, sizeof(transport), "Transport: RTP/AVP/TCP;interleaved=%d-%d\r\n", rtsp->transport[i].interleaved1, rtsp->transport[i].interleaved2);
  37. break;
  38. case RTSP_TRANSPORT_RTP_UDP:
  39. if(0 == rtsp->transport[i].multicast)
  40. len = snprintf(transport, sizeof(transport), "Transport: RTP/AVP;unicast;client_port=%hu-%hu\r\n", rtsp->transport[i].rtp.u.client_port1, rtsp->transport[i].rtp.u.client_port2);
  41. else if(*rtsp->transport[i].destination)
  42. len = snprintf(transport, sizeof(transport), "Transport: RTP/AVP;multicast;destination=%s;port=%hu-%hu;ttl=%d\r\n", rtsp->transport[i].destination, rtsp->transport[i].rtp.m.port1, rtsp->transport[i].rtp.m.port2, rtsp->transport[i].rtp.m.ttl);
  43. else
  44. len = snprintf(transport, sizeof(transport), "Transport: RTP/AVP;multicast;port=%hu-%hu;ttl=%d\r\n", rtsp->transport[i].rtp.m.port1, rtsp->transport[i].rtp.m.port2, rtsp->transport[i].rtp.m.ttl);
  45. break;
  46. case RTSP_TRANSPORT_RAW:
  47. if(0 == rtsp->transport[i].multicast)
  48. len = snprintf(transport, sizeof(transport), "Transport: RAW/RAW/UDP;unicast;client_port=%hu-%hu\r\n", rtsp->transport[i].rtp.u.client_port1, rtsp->transport[i].rtp.u.client_port2);
  49. else if(*rtsp->transport[i].destination)
  50. len = snprintf(transport, sizeof(transport), "Transport: RAW/RAW/UDP;multicast;destination=%s;port=%hu-%hu;ttl=%d\r\n", rtsp->transport[i].destination, rtsp->transport[i].rtp.m.port1, rtsp->transport[i].rtp.m.port2, rtsp->transport[i].rtp.m.ttl);
  51. else
  52. len = snprintf(transport, sizeof(transport), "Transport: RAW/RAW/UDP;multicast;port=%hu-%hu;ttl=%d\r\n", rtsp->transport[i].rtp.m.port1, rtsp->transport[i].rtp.m.port2, rtsp->transport[i].rtp.m.ttl);
  53. break;
  54. default:
  55. assert(0);
  56. return -1;
  57. }
  58. assert(len >= 0 && len < sizeof(transport));
  59. len = rtsp_client_authenrization(rtsp, "SETUP", rtsp->media[i].uri, NULL, 0, rtsp->authenrization, sizeof(rtsp->authenrization));
  60. len = snprintf(rtsp->req, sizeof(rtsp->req), sc_rtsp_setup, rtsp->media[i].uri, rtsp->cseq++, session, rtsp->authenrization, transport, USER_AGENT);
  61. return (len > 0 && len < sizeof(rtsp->req) && len == rtsp->handler.send(rtsp->param, rtsp->media[i].uri, rtsp->req, len)) ? 0 : -1;
  62. }
  63. int rtsp_client_setup(struct rtsp_client_t* rtsp, const char* sdp, int len)
  64. {
  65. int i, r;
  66. unsigned short port[2];
  67. struct rtsp_media_t *m;
  68. struct rtsp_header_transport_t *t;
  69. if (NULL == sdp || 0 == *sdp || len < 1)
  70. return -1;
  71. r = rtsp_media_sdp(sdp, len, rtsp->media, sizeof(rtsp->media)/sizeof(rtsp->media[0]));
  72. if (r < 0 || r > sizeof(rtsp->media) / sizeof(rtsp->media[0]))
  73. return r < 0 ? r : -E2BIG; // too many media stream
  74. rtsp->media_count = r;
  75. for (i = 0; i < rtsp->media_count; i++)
  76. {
  77. m = rtsp->media + i;
  78. t = rtsp->transport + i;
  79. // rfc 2326 C.1.1 Control URL (p80)
  80. // If found at the session level, the attribute indicates the URL for aggregate control
  81. rtsp_media_set_url(m, rtsp->baseuri, rtsp->location, rtsp->uri);
  82. port[0] = (unsigned short)m->port[0];
  83. port[1] = (unsigned short)m->port[1];
  84. snprintf(t->source, sizeof(t->source), "%s", m->source);
  85. snprintf(t->destination, sizeof(t->destination), "%s", m->address);
  86. r = rtsp->handler.rtpport(rtsp->param, i, t->source, port, t->destination, sizeof(t->destination));
  87. if (r < 0)
  88. return r;
  89. if(RTSP_TRANSPORT_RTP_TCP == r)
  90. {
  91. t->transport = RTSP_TRANSPORT_RTP_TCP;
  92. t->interleaved1 = 0==port[0] ? 2 * (unsigned short)i : port[0];
  93. t->interleaved2 = 0==port[1] ? t->interleaved1 + 1 : port[1];
  94. }
  95. else if((RTSP_TRANSPORT_RTP_UDP == r || RTSP_TRANSPORT_RAW == r) && rtsp_addr_is_multicast(t->destination))
  96. {
  97. assert(0 == t->rtp.u.client_port1 % 2);
  98. t->transport = r;
  99. t->multicast = 1;
  100. t->rtp.m.ttl = 16; // default RTT
  101. t->rtp.m.port1 = port[0];
  102. t->rtp.m.port2 = 0 == port[1] ? t->rtp.m.port1 + 1 : port[1];
  103. }
  104. else if(RTSP_TRANSPORT_RTP_UDP == r || RTSP_TRANSPORT_RAW == r)
  105. {
  106. assert(0 == t->rtp.u.client_port1 % 2);
  107. t->transport = r;
  108. t->multicast = 0;
  109. t->rtp.u.client_port1 = port[0];
  110. t->rtp.u.client_port2 = 0 == port[1] ? t->rtp.u.client_port1 + 1 : port[1];
  111. }
  112. else if (0 == r)
  113. {
  114. // ignore media
  115. if (i + 1 < rtsp->media_count)
  116. memmove(rtsp->media + i, rtsp->media + i + 1, sizeof(rtsp->media[0]) * (rtsp->media_count - i - 1));
  117. rtsp->media_count--;
  118. i--; // redo
  119. continue;
  120. }
  121. else
  122. {
  123. assert(0);
  124. return -1;
  125. }
  126. }
  127. rtsp->aggregate = (rtsp->media_count > 1 && rtsp->media[0].session_uri[0]) ? 1 : 0;
  128. if (rtsp->aggregate)
  129. {
  130. snprintf(rtsp->aggregate_uri, sizeof(rtsp->aggregate_uri), "%s", rtsp->media[0].session_uri);
  131. }
  132. else if(rtsp->media_count > 1)
  133. {
  134. // fix some IPC set Content-Base only
  135. const char* base;
  136. base = rtsp->baseuri[0] ? rtsp->baseuri : rtsp->location;
  137. rtsp->aggregate = base[0] ? 1 : 0;
  138. if(rtsp->aggregate)
  139. snprintf(rtsp->aggregate_uri, sizeof(rtsp->aggregate_uri), "%s", base);
  140. }
  141. rtsp->state = RTSP_SETUP;
  142. rtsp->progress = 0;
  143. return rtsp_client_media_setup(rtsp, rtsp->progress);
  144. }
  145. int rtsp_client_setup_onreply(struct rtsp_client_t* rtsp, void* parser)
  146. {
  147. int code;
  148. const char *session;
  149. const char *transport;
  150. struct rtsp_header_range_t* range;
  151. assert(RTSP_SETUP == rtsp->state);
  152. assert(rtsp->progress < rtsp->media_count);
  153. code = http_get_status_code(parser);
  154. if (200 == code)
  155. {
  156. session = http_get_header_by_name(parser, "Session");
  157. transport = http_get_header_by_name(parser, "Transport");
  158. if (!session || 0 != rtsp_header_session(session, &rtsp->session[rtsp->progress])
  159. || !transport || 0 != rtsp_header_transport(transport, &rtsp->transport[rtsp->progress]))
  160. {
  161. printf("Get rtsp transport error.\n");
  162. return -EINVAL;
  163. }
  164. //assert(rtsp->media[rtsp->progress].transport.transport != RTSP_TRANSPORT_RTP_TCP || (rtsp->media[rtsp->progress].transport.rtp.u.client_port1== rtsp->media[rtsp->progress].transport.interleaved1 && rtsp->media[rtsp->progress].transport.rtp.u.client_port2 == rtsp->media[rtsp->progress].transport.interleaved2));
  165. assert(strlen(session) < sizeof(rtsp->session[0].session));
  166. assert(!rtsp->aggregate || 0 == strcmp(rtsp->session[0].session, rtsp->session[rtsp->progress].session));
  167. if (rtsp->media_count == ++rtsp->progress)
  168. {
  169. assert(rtsp->media_count > 0);
  170. range = &rtsp->media[0].range;
  171. return rtsp->handler.onsetup(rtsp->param, rtsp->session[rtsp->progress].timeout / 1000, RTSP_RANGE_TIME_NORMAL==range->from_value && RTSP_RANGE_TIME_NORMAL==range->to_value ? range->to - range->from : -1);
  172. }
  173. else
  174. {
  175. // setup next media
  176. return rtsp_client_media_setup(rtsp, rtsp->progress);
  177. }
  178. }
  179. else if (401 == code)
  180. {
  181. // Unauthorized
  182. const char* authenticate;
  183. authenticate = http_get_header_by_name(parser, "WWW-Authenticate");
  184. if (authenticate)
  185. {
  186. rtsp_client_www_authenticate(rtsp, authenticate);
  187. }
  188. return -EACCES; // try again
  189. }
  190. else if (461 == code)
  191. {
  192. // Unsupported Transport
  193. return -1;
  194. }
  195. else
  196. {
  197. return -1;
  198. }
  199. }