// RFC2326 10.6 PAUSE (p36) // 1. A PAUSE request discards all queued PLAY requests. However, the pause // point in the media stream MUST be maintained. A subsequent PLAY // request without Range header resumes from the pause point. int rtsp_server_pause(struct rtsp_server_t* rtsp, const char* uri) { int64_t npt = -1L; const char *prange, *psession; struct rtsp_header_range_t range; prange = rtsp_get_header_by_name(rtsp->parser, "range"); psession = rtsp_get_header_by_name(rtsp->parser, "Session"); rtsp->session.session[0] = 0; // clear session value if (!psession || 0 != rtsp_header_session(psession, &rtsp->session)) { // 454 Session Not Found return rtsp_server_reply(rtsp, 454); } if (prange && 0 == rtsp_header_range(prange, &range)) { npt = range.from; // 10.6 The normal play time for the stream is set to the pause point. (p36) assert(range.type == RTSP_RANGE_NPT); // 3.6 Normal Play Time (p17) assert(range.to_value == RTSP_RANGE_TIME_NOVALUE); // 457 Invalid Range //rtsp_server_reply(req, 457, NULL); //return; } return rtsp->handler.onpause(rtsp->param, rtsp, uri, rtsp->session.session, -1L == npt ? NULL : &npt); }
// RFC2326 10.6 PAUSE (p36) // 1. A PAUSE request discards all queued PLAY requests. However, the pause // point in the media stream MUST be maintained. A subsequent PLAY // request without Range header resumes from the pause point. static void rtsp_server_pause(struct rtsp_server_request_t *req, void* parser, const char* uri) { int64_t npt = -1L; const char *prange, *psession; struct rtsp_header_range_t range; struct rtsp_header_session_t session; struct rtsp_server_context_t* ctx = req->server; prange = rtsp_get_header_by_name(parser, "range"); psession = rtsp_get_header_by_name(parser, "Session"); if(!psession || 0 != rtsp_header_session(psession, &session)) { // 454 Session Not Found rtsp_server_reply(req, 454); return; } if(prange && 0 == rtsp_header_range(prange, &range)) { npt = range.from; // 10.6 The normal play time for the stream is set to the pause point. (p36) assert(range.type == RTSP_RANGE_NPT); // 3.6 Normal Play Time (p17) assert(range.to_value == RTSP_RANGE_TIME_NOVALUE); // 457 Invalid Range //rtsp_server_reply(req, 457); //return; } ctx->handler.pause(ctx->ptr, req, uri, session.session, -1L==npt?NULL:&npt); }
static void rtsp_server_play(struct rtsp_server_request_t *req, void* parser, const char* uri) { int64_t npt = -1L; double scale = 0.0f; const char *pscale, *prange, *psession; struct rtsp_header_range_t range; struct rtsp_header_session_t session; struct rtsp_server_context_t* ctx = req->server; pscale = rtsp_get_header_by_name(parser, "scale"); prange = rtsp_get_header_by_name(parser, "range"); psession = rtsp_get_header_by_name(parser, "Session"); if(!psession || 0 != rtsp_header_session(psession, &session)) { // 454 (Session Not Found) rtsp_server_reply(req, 454); return; } if(pscale) { scale = atof(pscale); } if(prange && 0 == rtsp_header_range(prange, &range)) { npt = range.from; } ctx->handler.play(ctx->ptr, req, uri, session.session, -1L==npt?NULL:&npt, pscale?&scale:NULL); }
static void rtsp_server_setup(struct rtsp_server_request_t *req, void *parser, const char* uri) { size_t n; const char *psession, *ptransport; struct rtsp_header_session_t session; struct rtsp_header_transport_t transport[16]; struct rtsp_server_context_t* ctx = req->server; psession = rtsp_get_header_by_name(parser, "Session"); ptransport = rtsp_get_header_by_name(parser, "Transport"); memset(transport, 0, sizeof(transport)); n = sizeof(transport)/sizeof(transport[0]); if(!ptransport || 0 != rtsp_header_transport_ex(ptransport, transport, &n) || 0 == n) { // 461 Unsupported Transport rtsp_server_reply(req, 461); return; } assert(n > 0); if(psession && 0 == rtsp_header_session(psession, &session)) { ctx->handler.setup(ctx->ptr, req, uri, session.session, transport, n); } else { ctx->handler.setup(ctx->ptr, req, uri, NULL, transport, n); } }
int rtsp_client_setup_onreply(struct rtsp_client_t* rtsp, void* parser) { int code; const char *session; const char *transport; assert(RTSP_SETUP == rtsp->state); assert(rtsp->progress < rtsp->media_count); code = rtsp_get_status_code(parser); if (200 == code) { session = rtsp_get_header_by_name(parser, "Session"); transport = rtsp_get_header_by_name(parser, "Transport"); if (!session || 0 != rtsp_header_session(session, &rtsp->media[rtsp->progress].session) || !transport || 0 != rtsp_header_transport(transport, &rtsp->media[rtsp->progress].transport)) { printf("Get rtsp transport error.\n"); return -EINVAL; } assert(strlen(session) < sizeof(rtsp->media[0].session.session)); assert(!rtsp->aggregate || 0 == strcmp(rtsp->media[0].session.session, rtsp->media[rtsp->progress].session.session)); if (rtsp->media_count == ++rtsp->progress) { return rtsp->handler.onsetup(rtsp->param); } else { // setup next media return rtsp_client_media_setup(rtsp); } } else if (401 == code) { // Unauthorized const char* authenticate; authenticate = rtsp_get_header_by_name(parser, "WWW-Authenticate"); if (authenticate) { rtsp_client_www_authenticate(rtsp, authenticate); } return -EACCES; // try again } else { return -1; } }
static void rtsp_server_teardown(struct rtsp_server_request_t *req, void *parser, const char* uri) { const char *psession; struct rtsp_header_session_t session; struct rtsp_server_context_t* ctx = req->server; psession = rtsp_get_header_by_name(parser, "Session"); if(!psession || 0 != rtsp_header_session(psession, &session)) { // 454 (Session Not Found) rtsp_server_reply(req, 454); return; } ctx->handler.teardown(ctx->ptr, req, uri, session.session); }