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

📄 pmsg.c

📁 spook是一个linux下开源的流媒体服务器
💻 C
字号:
/* * 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 <stdarg.h>#include <fcntl.h>#include <ctype.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <pthread.h>#include <errno.h>#include <log.h>#include <pmsg.h>#include <config.h>char *add_pmsg_string( struct pmsg *msg, char *s ){	int len = strlen( s ) + 1;	char *p;	if( msg->msg_len + len > msg->max_len ) return NULL;	p = msg->msg + msg->msg_len;	msg->msg_len += len;	strcpy( p, s );	return p;}static int inline delim( char *d, int len, char term1, char term2 ){	int s;	for( s = 0; s < len; ++s )		if( d[s] == term1 || d[s] == term2 ||			       d[s] == '\r' || d[s] == '\n' )			break;	return s;}int parse_pmsg( struct pmsg *msg ){	int i = 0;	unsigned char *d = msg->msg;	int len = msg->msg_len;	msg->header_count = 0;	/* Was it all whitespace? */	if( len - i < 4 ) return -1;	/* Check for a slash in the first word */	for( i = 0; i < len && d[i] != ' ' && d[i] != '/'; ++i );	if( i == len ) return -1;	/* Responses begin with "PROTO/" */	if( d[i] == '/' )	{		msg->type = PMSG_RESP;		/* The first word is the protocol name and version */		msg->proto_id = d;		i = delim( d, len, ' ', 0 );		/* Check for a space following the version number */		if( d[i] != ' ' ) return -1;		d[i++] = 0;		while( i < len && d[i] == ' ' ) ++i;		/* The next word is the 3-digit response code, then a space */		if( len - i < 4 || ! isdigit( d[i] ) || ! isdigit( d[i+1] )				|| ! isdigit( d[i+2] ) || d[i+3] != ' ' )			return -1;		msg->sl.stat.code = atoi( d + i );		i += 4;		while( i < len && d[i] == ' ' ) ++i;		/* The rest of the line is the textual response */		msg->sl.stat.reason = d + i;		i += delim( d + i, len - i, 0, 0 );		d[i++] = 0;	} else	{		msg->type = PMSG_REQ;		/* The first word is the method */		msg->sl.req.method = d;		i = delim( d, len, ' ', 0 );		/* Then a space */		if( i >= len || d[i] != ' ' ) return -1;		d[i++] = 0;		while( i < len && d[i] == ' ' ) ++i;		/* The second word is the URI */		msg->sl.req.uri = d + i;		i += delim( d + i, len - i, ' ', 0 );		/* Then a space */		if( i >= len || d[i] != ' ' ) return -1;		d[i++] = 0;		while( i < len && d[i] == ' ' ) ++i;		/* The last word is the protocol name and version */		msg->proto_id = d + i;		i += delim( d + i, len - i, 0, 0 );		d[i++] = 0;	}	/* Skip any trailing space */	while( i < len && d[i] == ' ' ) ++i;	/* Skip the \r if we didn't kill it already */	if( i < len && d[i] == '\r' ) ++i;	/* We should be at the end of the line now */	if( i >= len || d[i++] != '\n' ) return -1;	/* Now, parse all the header lines */	for(;;)	{		/* There may be a \r here if we're at the end of the headers */		if( i < len && d[i] == '\r' ) ++i;		/* If there's no more data, we're done */		if( i == len ) return len;		/* If there's a newline, we're at the end of the headers */		if( d[i] == '\n' ) return i + 1;		/* XXX headers beginning with whitespace are continuations */		if( d[i] == '\t' || d[i] == ' ' ) return -1;		/* The first thing on the line is the header name */		msg->fields[msg->header_count].name = d + i;		/* The name ends with optional spaces then a colon */		i += delim( d + i, len - i, ' ', ':' );		if( i >= len ) return -1;		/* If the optional spaces are present, skip them */		if( d[i] == ' ' )		{			d[i++] = 0;			while( i < len && d[i] == ' ' ) ++i;		}		/* Make sure the colon is present */		if( i >= len || d[i] != ':' ) return -1;		d[i++] = 0;		/* Skip any whitespace after the colon */		while( i < len && ( d[i] == ' ' || d[i] == '\t' ) ) ++i;		/* Everything else on the line is the header data */		msg->fields[msg->header_count].value = d + i;		i += delim( d + i, len - i, 0, 0 );		d[i++] = 0;		/* We should be at the end of the line now */		if( i >= len || d[i++] != '\n' ) return -1;		++msg->header_count;	}}char *get_header( struct pmsg *msg, char *name ){	int i;	for( i = 0; i < msg->header_count; ++i )		if( ! strcasecmp( msg->fields[i].name, name ) )			return msg->fields[i].value;	return NULL;}int add_header( struct pmsg *msg, char *name, char *value ){	if( msg->header_count == MAX_FIELDS ) return -1;	/* Put the name and value back-to-back at the end of the message */	msg->fields[msg->header_count].name = add_pmsg_string( msg, name );	if( ! msg->fields[msg->header_count].name ) return -1;	msg->fields[msg->header_count].value = add_pmsg_string( msg, value );	if( ! msg->fields[msg->header_count].value ) return -1;	++msg->header_count;	return 0;}int add_header_printf( struct pmsg *msg, char *name, char *fmt, ... ){	va_list ap;	int len;	/* do the vsnprintf first to clean up the stack */	va_start( ap, fmt );	len = vsnprintf( msg->msg + msg->msg_len, msg->max_len - msg->msg_len,			fmt, ap );	va_end( ap );	/* check for errors */	if( msg->header_count == MAX_FIELDS ) return -1;	/* vsnprintf will return the length of the formatted string	 * regardless of length, although the actual output may be truncated */	if( msg->msg_len + len >= msg->max_len ) return -1;	msg->fields[msg->header_count].value = msg->msg + msg->msg_len;	msg->msg_len += len + 1;	/* add the name */	msg->fields[msg->header_count].name = add_pmsg_string( msg, name );	if( ! msg->fields[msg->header_count].name ) return -1;	++msg->header_count;	return 0;}int replace_header( struct pmsg *msg, char *name, char *value ){	int i;	for( i = 0; i < msg->header_count; ++i )		if( ! strcasecmp( msg->fields[i].name, name ) )		{			/* If we can't reuse the space from the original value,			 * we have to allocate space for the new value at the			 * end of the message */			if( strlen( msg->fields[i].value ) < strlen( value ) )			{				char *p = add_pmsg_string( msg, value );				if( ! p ) return -1;				msg->fields[i].value = p;			} else strcpy( msg->fields[i].value, value );			return 0;		}	/* It doesn't exist, so we'll insert it as new */	return add_header( msg, name, value );}int copy_headers( struct pmsg *dest, struct pmsg *src, char *name ){	int i, count = 0;	for( i = 0; i < src->header_count; ++i )		if( ! strcasecmp( src->fields[i].name, name ) )		{			add_header( dest, src->fields[i].name,					src->fields[i].value );			++count;		}	return count;}/* get_param() returns 1 for found, 0 for not found, -1 for error */int get_param( char *value, char *tag, char *dest, int size ){	int taglen, i;	char *c;	if( ! value ) return -1;	taglen = strlen( tag );	for( c = value; c; c = strchr( c, ';' ) )	{		++c;		if( ! strncasecmp( c, tag, taglen ) )		{			c += taglen;			if( *c == 0 || *c == ';' ) /* Value-less tag */			{				if( dest && size > 0 ) *dest = 0;				return 1;			} else if( *c == '=' ) /* Tag has an associated value */			{				if( ! dest || size <= 0 ) return 1;				++c;				for( i = 0; *c && *c != ';' && i < size;						++i, ++c )					dest[i] = *c;				if( i == size ) return -1;				dest[i] = 0;				return 1;			} /* Otherwise, it's a false hit */		}	}	return 0;}struct pmsg *new_pmsg( int size ){	struct pmsg *msg;	void *v;	if( ! ( v = malloc( sizeof( struct pmsg ) + size ) ) )	{		spook_log( SL_ERR, "unable to allocate memory for message" );		return NULL;	}	msg = (struct pmsg *)v;	msg->msg = v + sizeof( struct pmsg );	msg->max_len = size;	msg->msg_len = 0;	msg->header_count = 0;	msg->proto_id = NULL;	return msg;}void free_pmsg( struct pmsg *msg ){	free( msg );}

⌨️ 快捷键说明

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