⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsp.c

📁 spook是一个linux下开源的流媒体服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
static int rtsp_udp_setup( struct session *s, int track,				struct req *req, char *t ){	char *p, *end, trans[128];	int cport, server_port;	if( ! ( p = strstr( t, "client_port" ) ) || *(p + 11) != '=' )		return -1;	cport = strtol( p + 12, &end, 10 );	if( end == p + 12 ) return -1;	spook_log( SL_DEBUG, "client requested UDP port %d", cport );	if( connect_udp_endpoint( s->ep[track], req->conn->client_addr.sin_addr,				cport, &server_port ) < 0 )		return -1;	spook_log( SL_VERBOSE, "our port is %d, client port is %d",			server_port, cport );	sprintf( trans, "RTP/AVP;unicast;client_port=%d-%d;server_port=%d-%d",		cport, cport + 1, server_port, server_port + 1 );	add_header( req->resp, "Transport", trans );	return 0;}static int rtsp_interleave_setup( struct session *s, int track,				struct req *req, char *t ){	struct rtsp_conn *rc = (struct rtsp_conn *)req->conn->proto_state;	char *p, *end, trans[128];	int rtp_chan = -1, rtcp_chan = -1, i;	if( ( p = strstr( t, "interleaved" ) ) )	{		if( *(p + 11) != '=' ) return -1;		rtp_chan = strtol( p + 12, &end, 10 );		rtcp_chan = rtp_chan + 1; // XXX make better parser		if( end == p + 12 ) return -1;		if( rtp_chan < 0 || rtcp_chan < 0 ||				rtp_chan >= MAX_INTERLEAVE_CHANNELS ||				rtcp_chan >= MAX_INTERLEAVE_CHANNELS )			return -1;		spook_log( SL_VERBOSE, "requested interleave channels %d-%d",				rtp_chan, rtcp_chan );		if( rc && ( rc->ichan[rtp_chan].ep ||					rc->ichan[rtcp_chan].ep ) )			return -1;	} else	{		spook_log( SL_VERBOSE, "requested any interleave channel" );		if( rc )		{			for( i = 0; i < MAX_INTERLEAVE_CHANNELS; i += 2 )				if( ! rc->ichan[i].ep && ! rc->ichan[i + 1].ep )					break;			if( i >= MAX_INTERLEAVE_CHANNELS ) return -1;			rtp_chan = i;			rtcp_chan = i + 1;		} else		{			rtp_chan = 0;			rtcp_chan = 1;		}	}	if( ! rc )	{		rc = (struct rtsp_conn *)malloc( sizeof( struct rtsp_conn ) );		if( ! rc )		{			spook_log( SL_ERR,				"out of memory on malloc rtsp_conn" );			return -1;		}		for( i = 0; i < MAX_INTERLEAVE_CHANNELS; ++i )			rc->ichan[i].ep = NULL;		req->conn->proto_state = rc;	}	rc->ichan[rtp_chan].ep = s->ep[track];	rc->ichan[rtp_chan].rtcp = 0;	rc->ichan[rtcp_chan].ep = s->ep[track];	rc->ichan[rtcp_chan].rtcp = 1;	connect_interleaved_endpoint( s->ep[track], req->conn,						rtp_chan, rtcp_chan );	sprintf( trans, "RTP/AVP/TCP;unicast;interleaved=%d-%d",			rtp_chan, rtcp_chan );	add_header( req->resp, "Transport", trans );	return 0;}static int handle_SETUP( struct req *req ){	char *t, *sh, path[256];	int track, ret;	struct session *s;	struct rtsp_session *rs = NULL;	struct rtsp_location *loc;	if( ! ( loc = find_rtsp_location( req->req->sl.req.uri,					path, &track ) ) ||			track < 0 || track >= MAX_TRACKS )	{		rtsp_send_error( req, 404, "Not Found" );		return 0;	}	if( loc->realm[0] && rtsp_verify_auth( req, loc->realm,				loc->username, loc->password ) < 0 )		return 0;	if( ! ( t = get_header( req->req, "Transport" ) ) )	{		// XXX better error reply		rtsp_send_error( req, 461, "Unspecified Transport" );		return 0;	}	if( ! ( sh = get_header( req->req, "Session" ) ) )	{		if( ! ( s = loc->open( path, loc->private ) ) )		{			rtsp_send_error( req, 404, "Not Found" );			return 0;		}		sprintf( s->addr, "IP4 %s",				inet_ntoa( req->conn->client_addr.sin_addr ) );	} else if( ! ( rs = get_session( sh ) ) )	{		rtsp_send_error( req, 454, "Session Not Found" );		return 0;	} else s = rs->sess;	if( s->ep[track] )	{		// XXX better error reply		rtsp_send_error( req, 461, "Unsupported Transport" );		return 0;	}	if( s->setup( s, track ) < 0 )	{		rtsp_send_error( req, 404, "Not Found" );		if( ! rs ) s->teardown( s, NULL );		return 0;	}	spook_log( SL_DEBUG, "setting up RTP (%s)", t );	rtsp_create_reply( req, 200, "OK" );	if( ! strncasecmp( t, "RTP/AVP/TCP", 11 ) )		ret = rtsp_interleave_setup( s, track, req, t );	else if( ( ! strncasecmp( t, "RTP/AVP", 7 ) && t[7] != '/' ) ||			! strncasecmp( t, "RTP/AVP/UDP", 11 ) )		ret = rtsp_udp_setup( s, track, req, t );	else ret = -1;	if( ret < 0 )	{		free_pmsg( req->resp );		rtsp_send_error( req, 461, "Unsupported Transport" );		s->teardown( s, s->ep[track] );	} else	{		if( ! rs ) rs = new_rtsp_session( s );		add_header( req->resp, "Session", rs->id );		log_request( req, 200, 0 );		tcp_send_pmsg( req->conn, req->resp, -1 );	}	return 0;}static int handle_PLAY( struct req *req ){	struct rtsp_session *rs;	double start;	int have_start = 0, i, p, ret;	char *range, hdr[512];	if( ! ( rs = get_session( get_header( req->req, "Session" ) ) ) )	{		rtsp_send_error( req, 454, "Session Not Found" );		return 0;	}	range = get_header( req->req, "Range" );	if( range && sscanf( range, "npt=%lf-", &start ) == 1 )	{		have_start = 1;		spook_log( SL_VERBOSE,			"starting streaming for session %s at position %.4f",			rs->id, start );	} else spook_log( SL_VERBOSE,			"starting streaming for session %s", rs->id );	rs->sess->play( rs->sess, have_start ? &start : NULL );	rtsp_create_reply( req, 200, "OK" );	add_header( req->resp, "Session", rs->id );	if( have_start && start >= 0 )	{		spook_log( SL_DEBUG, "backend seeked to %.4f", start );		sprintf( hdr, "npt=%.4f-", start );		add_header( req->resp, "Range", hdr );		p = 0;		for( i = 0; i < MAX_TRACKS; ++i )		{			if( ! rs->sess->ep[i] ) continue;			ret = snprintf( hdr + p, sizeof( hdr ) - p,				"url=%s/track%d;seq=%d;rtptime=%u,",				req->req->sl.req.uri, i,				rs->sess->ep[i]->seqnum,				rs->sess->ep[i]->last_timestamp );			if( ret >= sizeof( hdr ) - p )			{				p = -1;				break;			}			p += ret;		}		if( p > 0 )		{			hdr[p - 1] = 0; /* Kill last comma */			add_header( req->resp, "RTP-Info", hdr );		}	}	log_request( req, 200, 0 );	tcp_send_pmsg( req->conn, req->resp, -1 );	return 0;}static int handle_PAUSE( struct req *req ){	struct rtsp_session *rs;	if( ! ( rs = get_session( get_header( req->req, "Session" ) ) ) )	{		rtsp_send_error( req, 454, "Session Not Found" );		return 0;	}	if( ! rs->sess->pause )	{		rtsp_send_error( req, 501, "Not Implemented" );		return 0;	}	spook_log( SL_VERBOSE, "pausing session %s", rs->id );	rs->sess->pause( rs->sess );	rtsp_create_reply( req, 200, "OK" );	add_header( req->resp, "Session", rs->id );	log_request( req, 200, 0 );	tcp_send_pmsg( req->conn, req->resp, -1 );	return 0;}static int handle_TEARDOWN( struct req *req ){	struct rtsp_location *loc;	struct rtsp_session *rs;	int track;	if( ! ( loc = find_rtsp_location( req->req->sl.req.uri,						NULL, &track ) ) ||			track >= MAX_TRACKS )	{		rtsp_send_error( req, 404, "Not Found" );		return 0;	}	if( ! ( rs = get_session( get_header( req->req, "Session" ) ) ) )	{		rtsp_send_error( req, 454, "Session Not Found" );		return 0;	}	spook_log( SL_VERBOSE, "tearing down %s in session %s",			req->req->sl.req.uri, rs->id );	rtsp_create_reply( req, 200, "OK" );	add_header( req->resp, "Session", rs->id );	/* This might destroy the session, so do it after creating the reply */	rs->sess->teardown( rs->sess, track < 0 ? NULL : rs->sess->ep[track] );	log_request( req, 200, 0 );	tcp_send_pmsg( req->conn, req->resp, -1 );	return 0;}static int handle_unknown( struct req *req ){	rtsp_send_error( req, 501, "Not Implemented" );	return 0;}int rtsp_handle_msg( struct req *req ){	int ret;	if( ! strcasecmp( req->req->sl.req.method, "OPTIONS" ) )		ret = handle_OPTIONS( req );	else if( ! strcasecmp( req->req->sl.req.method, "DESCRIBE" ) )		ret = handle_DESCRIBE( req );	else if( ! strcasecmp( req->req->sl.req.method, "SETUP" ) )		ret = handle_SETUP( req );	else if( ! strcasecmp( req->req->sl.req.method, "PLAY" ) )		ret = handle_PLAY( req );	else if( ! strcasecmp( req->req->sl.req.method, "PAUSE" ) )		ret = handle_PAUSE( req );	else if( ! strcasecmp( req->req->sl.req.method, "TEARDOWN" ) )		ret = handle_TEARDOWN( req );	else ret = handle_unknown( req );	return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -