|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- /*
- C->S:
- SETUP rtsp://example.com/foo/bar/baz.rm RTSP/1.0
- CSeq: 302
- Transport: RTP/AVP;unicast;client_port=4588-4589
-
- S->C:
- RTSP/1.0 200 OK
- CSeq: 302
- Date: 23 Jan 1997 15:35:06 GMT
- Session: 47112344
- Transport: RTP/AVP;unicast;client_port=4588-4589;server_port=6256-6257
- */
- #include "rtsp-client-internal.h"
-
- static const char* sc_rtsp_setup = "SETUP %s RTSP/1.0\r\n"
- "CSeq: %u\r\n"
- "%s" // Session: %s\r\n
- "%s" // Authorization: Digest xxx
- "%s" // Transport: RTP/AVP;unicast;client_port=6000-6001
- "User-Agent: %s\r\n"
- "\r\n";
-
- int rtsp_addr_is_multicast(const char* ip);
-
- static int rtsp_client_media_setup(struct rtsp_client_t* rtsp, int i)
- {
- int len;
- char transport[128];
- char session[sizeof(rtsp->session[0].session) + 12], *p;
-
- assert(i < rtsp->media_count);
- assert(RTSP_SETUP == rtsp->state);
- if (i >= rtsp->media_count) return -1;
-
- transport[0] = session[0] = '\0';
- p = rtsp->session[0].session;
- len = (rtsp->aggregate && *p) ? snprintf(session, sizeof(session), "Session: %s\r\n", p) : 0;
- assert(len >= 0 && len < sizeof(session));
-
- switch (rtsp->transport[i].transport) {
- case RTSP_TRANSPORT_RTP_TCP:
- len = snprintf(transport, sizeof(transport), "Transport: RTP/AVP/TCP;interleaved=%d-%d\r\n", rtsp->transport[i].interleaved1, rtsp->transport[i].interleaved2);
- break;
-
- case RTSP_TRANSPORT_RTP_UDP:
- if(0 == rtsp->transport[i].multicast)
- 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);
- else if(*rtsp->transport[i].destination)
- 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);
- else
- 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);
- break;
-
- case RTSP_TRANSPORT_RAW:
- if(0 == rtsp->transport[i].multicast)
- 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);
- else if(*rtsp->transport[i].destination)
- 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);
- else
- 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);
- break;
-
- default:
- assert(0);
- return -1;
- }
- assert(len >= 0 && len < sizeof(transport));
-
- len = rtsp_client_authenrization(rtsp, "SETUP", rtsp->media[i].uri, NULL, 0, rtsp->authenrization, sizeof(rtsp->authenrization));
- len = snprintf(rtsp->req, sizeof(rtsp->req), sc_rtsp_setup, rtsp->media[i].uri, rtsp->cseq++, session, rtsp->authenrization, transport, USER_AGENT);
- return (len > 0 && len < sizeof(rtsp->req) && len == rtsp->handler.send(rtsp->param, rtsp->media[i].uri, rtsp->req, len)) ? 0 : -1;
- }
-
- int rtsp_client_setup(struct rtsp_client_t* rtsp, const char* sdp, int len)
- {
- int i, r;
- unsigned short port[2];
- struct rtsp_media_t *m;
- struct rtsp_header_transport_t *t;
-
- if (NULL == sdp || 0 == *sdp || len < 1)
- return -1;
-
- r = rtsp_media_sdp(sdp, len, rtsp->media, sizeof(rtsp->media)/sizeof(rtsp->media[0]));
- if (r < 0 || r > sizeof(rtsp->media) / sizeof(rtsp->media[0]))
- return r < 0 ? r : -E2BIG; // too many media stream
-
- rtsp->media_count = r;
- for (i = 0; i < rtsp->media_count; i++)
- {
- m = rtsp->media + i;
- t = rtsp->transport + i;
-
- // rfc 2326 C.1.1 Control URL (p80)
- // If found at the session level, the attribute indicates the URL for aggregate control
- rtsp_media_set_url(m, rtsp->baseuri, rtsp->location, rtsp->uri);
-
- port[0] = (unsigned short)m->port[0];
- port[1] = (unsigned short)m->port[1];
- snprintf(t->source, sizeof(t->source), "%s", m->source);
- snprintf(t->destination, sizeof(t->destination), "%s", m->address);
- r = rtsp->handler.rtpport(rtsp->param, i, t->source, port, t->destination, sizeof(t->destination));
- if (r < 0)
- return r;
-
- if(RTSP_TRANSPORT_RTP_TCP == r)
- {
- t->transport = RTSP_TRANSPORT_RTP_TCP;
- t->interleaved1 = 0==port[0] ? 2 * (unsigned short)i : port[0];
- t->interleaved2 = 0==port[1] ? t->interleaved1 + 1 : port[1];
- }
- else if((RTSP_TRANSPORT_RTP_UDP == r || RTSP_TRANSPORT_RAW == r) && rtsp_addr_is_multicast(t->destination))
- {
- assert(0 == t->rtp.u.client_port1 % 2);
- t->transport = r;
- t->multicast = 1;
- t->rtp.m.ttl = 16; // default RTT
- t->rtp.m.port1 = port[0];
- t->rtp.m.port2 = 0 == port[1] ? t->rtp.m.port1 + 1 : port[1];
- }
- else if(RTSP_TRANSPORT_RTP_UDP == r || RTSP_TRANSPORT_RAW == r)
- {
- assert(0 == t->rtp.u.client_port1 % 2);
- t->transport = r;
- t->multicast = 0;
- t->rtp.u.client_port1 = port[0];
- t->rtp.u.client_port2 = 0 == port[1] ? t->rtp.u.client_port1 + 1 : port[1];
- }
- else if (0 == r)
- {
- // ignore media
- if (i + 1 < rtsp->media_count)
- memmove(rtsp->media + i, rtsp->media + i + 1, sizeof(rtsp->media[0]) * (rtsp->media_count - i - 1));
- rtsp->media_count--;
- i--; // redo
- continue;
- }
- else
- {
- assert(0);
- return -1;
- }
- }
-
- rtsp->aggregate = (rtsp->media_count > 1 && rtsp->media[0].session_uri[0]) ? 1 : 0;
- if (rtsp->aggregate)
- {
- snprintf(rtsp->aggregate_uri, sizeof(rtsp->aggregate_uri), "%s", rtsp->media[0].session_uri);
- }
- else if(rtsp->media_count > 1)
- {
- // fix some IPC set Content-Base only
- const char* base;
- base = rtsp->baseuri[0] ? rtsp->baseuri : rtsp->location;
- rtsp->aggregate = base[0] ? 1 : 0;
- if(rtsp->aggregate)
- snprintf(rtsp->aggregate_uri, sizeof(rtsp->aggregate_uri), "%s", base);
- }
-
- rtsp->state = RTSP_SETUP;
- rtsp->progress = 0;
- return rtsp_client_media_setup(rtsp, rtsp->progress);
- }
-
- int rtsp_client_setup_onreply(struct rtsp_client_t* rtsp, void* parser)
- {
- int code;
- const char *session;
- const char *transport;
- struct rtsp_header_range_t* range;
-
- assert(RTSP_SETUP == rtsp->state);
- assert(rtsp->progress < rtsp->media_count);
-
- code = http_get_status_code(parser);
- if (200 == code)
- {
- session = http_get_header_by_name(parser, "Session");
- transport = http_get_header_by_name(parser, "Transport");
- if (!session || 0 != rtsp_header_session(session, &rtsp->session[rtsp->progress])
- || !transport || 0 != rtsp_header_transport(transport, &rtsp->transport[rtsp->progress]))
- {
- printf("Get rtsp transport error.\n");
- return -EINVAL;
- }
-
- //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));
- assert(strlen(session) < sizeof(rtsp->session[0].session));
- assert(!rtsp->aggregate || 0 == strcmp(rtsp->session[0].session, rtsp->session[rtsp->progress].session));
-
- if (rtsp->media_count == ++rtsp->progress)
- {
- assert(rtsp->media_count > 0);
- range = &rtsp->media[0].range;
- 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);
- }
- else
- {
- // setup next media
- return rtsp_client_media_setup(rtsp, rtsp->progress);
- }
- }
- else if (401 == code)
- {
- // Unauthorized
- const char* authenticate;
- authenticate = http_get_header_by_name(parser, "WWW-Authenticate");
- if (authenticate)
- {
- rtsp_client_www_authenticate(rtsp, authenticate);
- }
- return -EACCES; // try again
- }
- else if (461 == code)
- {
- // Unsupported Transport
- return -1;
- }
- else
- {
- return -1;
- }
- }
|