// 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);
}
Esempio n. 2
0
void rtsp_server_reply_describe(void* rtsp, int code, const char* sdp)
{
	rfc822_datetime_t datetime;
	struct rtsp_server_request_t *req;
	req = (struct rtsp_server_request_t *)rtsp;

	if(200 != code)
	{
		rtsp_server_reply(req, code);
		return;
	}

	datetime_format(time(NULL), datetime);
	snprintf(req->reply, sizeof(req->reply), 
			"RTSP/1.0 200 OK\r\n"
			"CSeq: %u\r\n"
			"Date: %s\r\n"
			"Content-Type: application/sdp\r\n"
			"Content-Length: %lu\r\n"
			"\r\n"
			"%s", 
			req->cseq, datetime, strlen(sdp), sdp);

	req->transport->send(req->session, req->reply, strlen(req->reply));
}
Esempio n. 3
0
void rtsp_server_reply_setup(void* rtsp, int code, const char* session, const char* transport)
{
	rfc822_datetime_t datetime;
	struct rtsp_server_request_t *req;
	req = (struct rtsp_server_request_t *)rtsp;

	if(200 != code)
	{
		rtsp_server_reply(req, code);
		return;
	}

	datetime_format(time(NULL), datetime);

	// RTP/AVP;unicast;client_port=4588-4589;server_port=6256-6257
	snprintf(req->reply, sizeof(req->reply), 
			"RTSP/1.0 200 OK\r\n"
			"CSeq: %u\r\n"
			"Date: %s\r\n"
			"Session: %s\r\n"
			"Transport: %s\r\n"
			"\r\n",
			req->cseq, datetime, session, transport);

	req->transport->send(req->session, req->reply, strlen(req->reply));
}
Esempio n. 4
0
// 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);
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
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);
	}
}
Esempio n. 7
0
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);
}
Esempio n. 8
0
void rtsp_server_reply_play(void* rtsp, int code, const int64_t *nptstart, const int64_t *nptend, const char* rtp)
{
	char range[64] = {0};
	char rtpinfo[256] = {0};
	rfc822_datetime_t datetime;
	struct rtsp_server_request_t *req;
	req = (struct rtsp_server_request_t *)rtsp;

	if(200 != code)
	{
		rtsp_server_reply(req, code);
		return;
	}

	if(rtp)
	{
		snprintf(rtpinfo, sizeof(rtpinfo), "RTP-Info: %s\r\n", rtp);
	}

	if(nptstart)
	{
		if(nptend)
			snprintf(range, sizeof(range), "Range: %.3f-%.3f\r\n", (float)(*nptstart/1000.0f), (float)(*nptend/1000.0f));
		else
			snprintf(range, sizeof(range), "Range: %.3f-\r\n", (float)(*nptstart/1000.0f));
	}

	datetime_format(time(NULL), datetime);
	// smpte=0:10:22-;time=19970123T153600Z
	snprintf(req->reply, sizeof(req->reply), 
		"RTSP/1.0 200 OK\r\n"
		"CSeq: %u\r\n"
		"Date: %s\r\n"
		"%s" // Range
		"%s" // RTP-Info
		"\r\n",
		req->cseq, datetime, range, rtpinfo);

	req->transport->send(req->session, req->reply, strlen(req->reply));
}
Esempio n. 9
0
void rtsp_server_reply_teardown(void* rtsp, int code)
{
	struct rtsp_server_request_t *req;
	req = (struct rtsp_server_request_t *)rtsp;
	rtsp_server_reply(req, code);
}
Esempio n. 10
0
static void rtsp_server_handle(struct rtsp_server_request_t *req, void* parser)
{
	int major, minor;
	const char* uri;
	const char* method;

	req->parser = parser;
	rtsp_get_version(parser, &major, &minor);
	if(1 != major && 0 != minor)
	{
		//505 RTSP Version Not Supported
		rtsp_server_reply(req, 505);
		return;
	}

	if(0 != rtsp_get_header_by_name2(parser, "CSeq", (int*)&req->cseq))
	{
		// 400 Bad Request
		rtsp_server_reply(req, 400);
		return;
	}

	uri = rtsp_get_request_uri(parser);
	method = rtsp_get_request_method(parser);

	switch(*method)
	{
	case 'o':
	case 'O':
		if(0 == stricmp("OPTIONS", method))
		{
			rtsp_server_options(req, parser, uri);
			return;
		}
		break;

	case 'd':
	case 'D':
		if(0 == stricmp("DESCRIBE", method))
		{
			rtsp_server_describe(req, parser, uri);
			return;
		}
		break;

	case 's':
	case 'S':
		if(0 == stricmp("SETUP", method))
		{
			rtsp_server_setup(req, parser, uri);
			return;
		}
		break;

	case 'p':
	case 'P':
		if(0 == stricmp("PLAY", method))
		{
			rtsp_server_play(req, parser, uri);
			return;
		}
		else if(0 == stricmp("PAUSE", method))
		{
			rtsp_server_pause(req, parser, uri);
			return;
		}
		break;

	case 't':
	case 'T':
		if(0 == stricmp("TEARDOWN", method))
		{
			rtsp_server_teardown(req, parser, uri);
			return;
		}
		break;
	}

	// 501 Not implemented
	rtsp_server_reply(req, 501);
}