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

📄 rtsp.c

📁 spook是一个linux下开源的流媒体服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2004 Nathan Lutchansky <lutchann@litech.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <sys/types.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <event.h>#include <log.h>#include <frame.h>#include <stream.h>#include <pmsg.h>#include <rtp.h>#include <conf_parse.h>void write_access_log( char *path, struct sockaddr *addr, int code, char *req,		int length, char *referer, char *user_agent );struct rtsp_session {	struct rtsp_session *next;	struct rtsp_session *prev;	char id[32];	struct session *sess;};struct rtsp_location {	struct loc_node node;	char realm[128];	char username[128];	char password[128];	open_func open;	void *private;};struct rtsp_conn {	struct {		struct rtp_endpoint *ep;		int rtcp;	} ichan[MAX_INTERLEAVE_CHANNELS];};static struct rtsp_location *rtsp_loc_list = NULL;static struct rtsp_session *sess_list = NULL;static char *get_local_path( char *path ){	char *c;	static char *root = "/";	if( strncasecmp( path, "rtsp://", 7 ) ) return NULL;	for( c = path + 7; *c != '/'; ++c ) if( *c == 0 ) return root;	return c;}static struct loc_node *node_find_location( struct loc_node *list,						char *path, int len ){	struct loc_node *loc;	for( loc = list; loc; loc = loc->next )		if( ! strncmp( path, loc->path, strlen( loc->path ) )				&& ( loc->path[len] == '/'					|| loc->path[len] == 0 ) )			return loc;	return NULL;}static struct rtsp_location *find_rtsp_location( char *uri, char *base, int *track ){	char *path, *c, *end;	int len;	if( ! ( path = get_local_path( uri ) ) ) return NULL;	len = strlen( path );	if( track )	{		*track = -1;		if( ( c = strrchr( path, '/' ) ) &&				! strncmp( c, "/track", 6 ) )		{			*track = strtol( c + 6, &end, 10 );			if( ! *end ) len -= strlen( c );		}	}	if( len > 1 && path[len - 1] == '/' ) --len;	if( base )	{		strncpy( base, path, len );		base[len] = 0;	}	return (struct rtsp_location *)node_find_location(			(struct loc_node *)rtsp_loc_list, path, len );}static void init_location( struct loc_node *node, char *path,				struct loc_node **list ){	node->next = *list;	node->prev = NULL;	if( node->next ) node->next->prev = node;	*list = node;	strcpy( node->path, path );}void new_rtsp_location( char *path, char *realm, char *username, char *password,			open_func open, void *private ){	struct rtsp_location *loc;	loc = (struct rtsp_location *)malloc( sizeof( struct rtsp_location ) );	init_location( (struct loc_node *)loc, path,			(struct loc_node **)&rtsp_loc_list );	if( realm ) strcpy( loc->realm, realm );	else loc->realm[0] = 0;	if( username ) strcpy( loc->username, username );	else loc->username[0] = 0;	if( password ) strcpy( loc->password, password );	else loc->password[0] = 0;	loc->open = open;	loc->private = private;}static void rtsp_session_close( struct session *sess ){	struct rtsp_session *rs = (struct rtsp_session *)sess->control_private;	spook_log( SL_DEBUG, "freeing session %s", rs->id );	if( rs->next ) rs->next->prev = rs->prev;	if( rs->prev ) rs->prev->next = rs->next;	else sess_list = rs->next;	free( rs );}static struct rtsp_session *new_rtsp_session( struct session *sess ){	struct rtsp_session *rs;	rs = (struct rtsp_session *)malloc( sizeof( struct rtsp_session ) );	rs->next = sess_list;	rs->prev = NULL;	if( rs->next ) rs->next->prev = rs;	sess_list = rs;	random_id( rs->id, 30 );	rs->sess = sess;	sess->control_private = rs;	sess->control_close = rtsp_session_close;	return rs;}static struct rtsp_session *get_session( char *id ){	struct rtsp_session *rs;	if( ! id ) return NULL;	for( rs = sess_list; rs; rs = rs->next )		if( ! strcmp( rs->id, id ) ) break;	return rs;}void rtsp_conn_disconnect( struct conn *c ){	struct rtsp_conn *rc = (struct rtsp_conn *)c->proto_state;	int i;	for( i = 0; i < MAX_INTERLEAVE_CHANNELS; ++i )		if( rc->ichan[i].ep && ! rc->ichan[i].rtcp )			rc->ichan[i].ep->session->teardown(					rc->ichan[i].ep->session,					rc->ichan[i].ep );	free( rc );}void interleave_disconnect( struct conn *c, int chan ){	struct rtsp_conn *rc = (struct rtsp_conn *)c->proto_state;	rc->ichan[chan].ep = NULL;}int interleave_recv( struct conn *c, int chan, unsigned char *d, int len ){	struct rtsp_conn *rc = (struct rtsp_conn *)c->proto_state;	if( chan >= MAX_INTERLEAVE_CHANNELS || ! rc->ichan[chan].ep ) return -1;	if( rc->ichan[chan].rtcp )		interleave_recv_rtcp( rc->ichan[chan].ep, d, len );	return 0;}int interleave_send( struct conn *c, int chan, struct iovec *v, int count ){	unsigned char head[4];	int len = 0, i;	for( i = 0; i < count; ++i ) len += v[i].iov_len;	if( avail_send_buf( c ) < len + 4 ) return 1;	head[0] = '$';	head[1] = chan;	PUT_16( head + 2, len );	send_data( c, head, 4 );	for( i = 0; i < count; ++i )		send_data( c, v[i].iov_base, v[i].iov_len );	return 0;}static void log_request( struct req *req, int code, int length ){	char *ref, *ua;	ref = get_header( req->req, "referer" );	ua = get_header( req->req, "user-agent" );	write_access_log( NULL, (struct sockaddr *)&req->conn->client_addr,		code, req->conn->req_buf, length,		ref ? ref : "-", ua ? ua : "-" );}static int rtsp_create_reply( struct req *req, int code, char *reason ){	if( ! ( req->resp = new_pmsg( 512 ) ) ) return -1;	req->resp->type = PMSG_RESP;	req->resp->proto_id = add_pmsg_string( req->resp, "RTSP/1.0" );	req->resp->sl.stat.code = code;	req->resp->sl.stat.reason = add_pmsg_string( req->resp, reason );	copy_headers( req->resp, req->req, "CSeq" );	return 0;}static void rtsp_send_error( struct req *req, int code, char *reason ){	log_request( req, code, 0 );	rtsp_create_reply( req, code, reason );	tcp_send_pmsg( req->conn, req->resp, -1 );}static int rtsp_verify_auth( struct req *req, char *realm,				char *username, char *password ){	int ret = check_digest_response( req->req, realm, username, password );	if( ret > 0 ) return 0;	log_request( req, 401, 0 );	rtsp_create_reply( req, 401, "Unauthorized" );	add_digest_challenge( req->resp, realm, ret == 0 ? 1 : 0 );	tcp_send_pmsg( req->conn, req->resp, -1 );	return -1;}static int handle_OPTIONS( struct req *req ){	rtsp_create_reply( req, 200, "OK" );	add_header( req->resp, "Public",			"DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE" );	log_request( req, 200, 0 );	tcp_send_pmsg( req->conn, req->resp, -1 );	return 0;}static int handle_DESCRIBE( struct req *req ){	char sdp[8192], path[256], hdr[512];	int sdp_len;	struct rtsp_location *loc;	struct session *sess;	spook_log( SL_DEBUG, "describing streams under '%s'", req->req->sl.req.uri );	if( ! ( loc = find_rtsp_location( req->req->sl.req.uri,						path, NULL ) ) ||			! ( sess = loc->open( path, loc->private ) ) )	{		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;	sdp_len = sizeof( sdp ) - 2;	if( sess->get_sdp( sess, sdp, &sdp_len, req->req->sl.req.uri ) > 0 )	{		rtsp_create_reply( req, 200, "OK" );		sprintf( hdr, "%s/", req->req->sl.req.uri );		add_header( req->resp, "Content-Base", hdr );		add_header( req->resp, "Content-Type", "application/sdp" );		log_request( req, 200, sdp_len );		if( tcp_send_pmsg( req->conn, req->resp, sdp_len ) >= 0 )			send_data( req->conn, sdp, sdp_len );	} else rtsp_send_error( req, 404, "Not Found" );	sess->teardown( sess, NULL );	return 0;}

⌨️ 快捷键说明

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