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

📄 rtp.c

📁 网络MPEG4IP流媒体开发源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * FILE:     rtp.c * AUTHOR:   Colin Perkins   <csp@isi.edu> * MODIFIED: Orion Hodson    <o.hodson@cs.ucl.ac.uk> *           Markus Germeier <mager@tzi.de> *           Bill Fenner     <fenner@research.att.com> *           Timur Friedman  <timur@research.att.com> * * The routines in this file implement the Real-time Transport Protocol, * RTP, as specified in RFC1889 with current updates under discussion in * the IETF audio/video transport working group. Portions of the code are * derived from the algorithms published in that specification. * * $Revision$  * $Date$ *  * Copyright (c) 1998-2001 University College London * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, is permitted provided that the following conditions  * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by the Computer Science *      Department at University College London. * 4. Neither the name of the University nor of the Department may be used *    to endorse or promote products derived from this software without *    specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#include "config_unix.h"#include "config_win32.h"#include "memory.h"#include "debug.h"#include "net_udp.h"#include "crypt_random.h"#include "rijndael-api-fst.h"#include "drand48.h"#include "gettimeofday.h"#include "qfDES.h"#include "md5.h"#include "ntp.h"#include "rtp.h"typedef struct {        uint32_t key;   /* Original allocation number   */        uint32_t size;  /* Size of allocation requested */        uint32_t pad;   /* Alignment padding to 8 bytes */        uint32_t magic; /* Magic number                 */} chk_header;	  extern int chk_header_okay(const chk_header *ch);/* * Encryption stuff. */#define MAX_ENCRYPTION_PAD 16static int rijndael_initialize(struct rtp *session, u_char *hash, int hash_len);static int rijndael_decrypt(void *ifptr, uint8_t *data,		    unsigned int *size);static int rijndael_encrypt(void *ifptr, uint8_t *data,	    unsigned int *size);static int des_initialize(struct rtp *session, u_char *hash, int hash_len);static int des_decrypt(void *ifptr, uint8_t *data,	       unsigned int *size);static int des_encrypt(void *ifptr, uint8_t *data,	       unsigned int *size);#define MAX_DROPOUT    3000#define MAX_MISORDER   100#define MIN_SEQUENTIAL 2/* * Definitions for the RTP/RTCP packets on the wire... */#define RTP_SEQ_MOD        0x10000#define RTP_MAX_SDES_LEN   256#define RTP_LOWER_LAYER_OVERHEAD 28	/* IPv4 + UDP */#define RTCP_SR   200#define RTCP_RR   201#define RTCP_SDES 202#define RTCP_BYE  203#define RTCP_APP  204typedef struct {#ifdef WORDS_BIGENDIAN	unsigned short  version:2;	/* packet type            */	unsigned short  p:1;		/* padding flag           */	unsigned short  count:5;	/* varies by payload type */	unsigned short  pt:8;		/* payload type           */#else	unsigned short  count:5;	/* varies by payload type */	unsigned short  p:1;		/* padding flag           */	unsigned short  version:2;	/* packet type            */	unsigned short  pt:8;		/* payload type           */#endif	uint16_t        length;		/* packet length          */} rtcp_common;typedef struct {	rtcp_common   common;		union {		struct {			rtcp_sr		sr;			rtcp_rr       	rr[1];		/* variable-length list */		} sr;		struct {			uint32_t        ssrc;		/* source this RTCP packet is coming from */			rtcp_rr       	rr[1];		/* variable-length list */		} rr;		struct rtcp_sdes_t {			uint32_t	ssrc;			rtcp_sdes_item 	item[1];	/* list of SDES */		} sdes;		struct {			uint32_t        ssrc[1];	/* list of sources */							/* can't express the trailing text... */		} bye;		struct {			uint32_t        ssrc;           			uint8_t         name[4];			uint8_t         data[1];		} app;	} r;} rtcp_t;typedef struct _rtcp_rr_wrapper {	struct _rtcp_rr_wrapper	*next;	struct _rtcp_rr_wrapper	*prev;        uint32_t                 reporter_ssrc;	rtcp_rr			*rr;	struct timeval		*ts;	/* Arrival time of this RR */} rtcp_rr_wrapper;/* * The RTP database contains source-specific information needed  * to make it all work.  */typedef struct _source {	struct _source	*next;	struct _source	*prev;	uint32_t	 ssrc;	char		*cname;	char		*name;	char		*email;	char		*phone;	char		*loc;	char		*tool;	char		*note;	char		*priv;	rtcp_sr		*sr;	struct timeval	 last_sr;	struct timeval	 last_active;	int		 should_advertise_sdes;	/* TRUE if this source is a CSRC which we need to advertise SDES for */	int		 sender;	int		 got_bye;		/* TRUE if we've received an RTCP bye from this source */	uint32_t	 base_seq;	uint16_t	 max_seq;	uint32_t	 bad_seq;	uint32_t	 cycles;	int		 received;	int		 received_prior;	int		 expected_prior;	int		 probation;	uint32_t	 jitter;	uint32_t	 transit;	uint32_t	 magic;			/* For debugging... */} source;/* The size of the hash table used to hold the source database. *//* Should be large enough that we're unlikely to get collisions *//* when sources are added, but not too large that we waste too  *//* much memory. Sedgewick ("Algorithms", 2nd Ed, Addison-Wesley *//* 1988) suggests that this should be around 1/10th the number  *//* of entries that we expect to have in the database and should *//* be a prime number. Everything continues to work if this is   *//* too low, it just goes slower... for now we assume around 100 *//* participants is a sensible limit so we set this to 11.       */   #define RTP_DB_SIZE	11/* *  Options for an RTP session are stored in the "options" struct. */typedef struct {	int 	promiscuous_mode;	int	wait_for_rtcp;	int	filter_my_packets;} options;/* * Encryption function types */// moved to rtp.h by nori/* * typedef int (*rtp_encrypt_func)(struct rtp *, unsigned char *data, *				unsigned int size); * * typedef int (*rtp_decrypt_func)(struct rtp *, unsigned char *data, *				unsigned int size); */typedef int (*rtcp_send_f)(struct rtp *s, uint8_t *buffer, int buflen);/* * The "struct rtp" defines an RTP session. */struct rtp {	socket_udp	*rtp_socket;	socket_udp	*rtcp_socket;	char		*addr;	uint16_t	 rx_port;	uint16_t	 tx_port;	int		 ttl;	uint32_t	 my_ssrc;	int		 last_advertised_csrc;	source		*db[RTP_DB_SIZE];        rtcp_rr_wrapper  rr[RTP_DB_SIZE][RTP_DB_SIZE]; 	/* Indexed by [hash(reporter)][hash(reportee)] */	options		*opt;	uint8_t		*userdata;	int		 invalid_rtp_count;	int		 invalid_rtcp_count;	int		 bye_count;	int		 csrc_count;	int		 ssrc_count;	int		 ssrc_count_prev;		/* ssrc_count at the time we last recalculated our RTCP interval */	int		 sender_count;	int		 initial_rtcp;	int		 sending_bye;			/* TRUE if we're in the process of sending a BYE packet */	double		 avg_rtcp_size;	int		 we_sent;	double		 rtcp_bw;			/* RTCP bandwidth fraction, in octets per second. */	struct timeval	 last_update;	struct timeval	 last_rtp_send_time;	struct timeval	 last_rtcp_send_time;	struct timeval	 next_rtcp_send_time;	double		 rtcp_interval;	int		 sdes_count_pri;	int		 sdes_count_sec;	int		 sdes_count_ter;	uint16_t	 rtp_seq;	uint32_t	 rtp_pcount;	uint32_t	 rtp_bcount;    char *encryption_algorithm; 	int encryption_enabled; 	rtp_encrypt_func encrypt_func; 	rtp_decrypt_func decrypt_func; 	int encryption_pad_length;  int encryption_lenadd;  void *encrypt_userdata; // added by nori 	union { 		struct { 			keyInstance keyInstEncrypt; 			keyInstance keyInstDecrypt; 			cipherInstance cipherInst; 		} rijndael; 		struct { 			char            *encryption_key; 		} des; 	} crypto_state;	rtp_callback	 callback;  rtcp_send_f rtcp_send;  rtcp_send_packet_t rtcp_send_packet;	uint32_t	 magic;				/* For debugging...  */};static int filter_event(struct rtp *session, uint32_t ssrc){	int	filter;	rtp_get_option(session, RTP_OPT_FILTER_MY_PACKETS, &filter);	return filter && (ssrc == rtp_my_ssrc(session));}static double tv_diff(struct timeval curr_time, struct timeval prev_time){    /* Return curr_time - prev_time */    double	ct, pt;    ct = (double) curr_time.tv_sec + (((double) curr_time.tv_usec) / 1000000.0);    pt = (double) prev_time.tv_sec + (((double) prev_time.tv_usec) / 1000000.0);    return (ct - pt);}static void tv_add(struct timeval *ts, double offset){	/* Add offset seconds to ts */	double offset_sec, offset_usec;	offset_usec = modf(offset, &offset_sec) * 1000000;	ts->tv_sec  += (long) offset_sec;	ts->tv_usec += (long) offset_usec;	if (ts->tv_usec > 1000000) {		ts->tv_sec++;		ts->tv_usec -= 1000000;	}}static int tv_gt(struct timeval a, struct timeval b){	/* Returns (a>b) */	if (a.tv_sec > b.tv_sec) {		return TRUE;	}	if (a.tv_sec < b.tv_sec) {		return FALSE;	}	ASSERT(a.tv_sec == b.tv_sec);	return a.tv_usec > b.tv_usec;}static uint32_t next_csrc(struct rtp *session){	/* This returns each source marked "should_advertise_sdes" in turn. */	int	 chain, cc;	source	*s;	cc = 0;	for (chain = 0; chain < RTP_DB_SIZE; chain++) {		/* Check that the linked lists making up the chains in */		/* the hash table are correctly linked together...     */		for (s = session->db[chain]; s != NULL; s = s->next) {			if (s->should_advertise_sdes) {				if (cc == session->last_advertised_csrc) {                                        session->last_advertised_csrc++;                                        if (session->last_advertised_csrc == session->csrc_count) {                                                session->last_advertised_csrc = 0;                                        }					return s->ssrc;				} else {					cc++;				}			}		}	}	/* We should never get here... */	abort();}static int ssrc_hash(uint32_t ssrc){	/* Hash from an ssrc to a position in the source database.   */	/* Assumes that ssrc values are uniformly distributed, which */	/* should be true but probably isn't (Rosenberg has reported */	/* that many implementations generate ssrc values which are  */	/* not uniformly distributed over the space, and the H.323   */	/* spec requires that they are non-uniformly distributed).   */	/* This routine is written as a function rather than inline  */	/* code to allow it to be made smart in future: probably we  */	/* should run MD5 on the ssrc and derive a hash value from   */	/* that, to ensure it's more uniformly distributed?          */	return ssrc % RTP_DB_SIZE;}static void insert_rr(struct rtp *session, uint32_t reporter_ssrc, rtcp_rr *rr, struct timeval *ts){        /* Insert the reception report into the receiver report      */        /* database. This database is a two dimensional table of     */        /* rr_wrappers indexed by hashes of reporter_ssrc and        */        /* reportee_src.  The rr_wrappers in the database are        */        /* sentinels to reduce conditions in list operations.        */	/* The ts is used to determine when to timeout this rr.      */        rtcp_rr_wrapper *cur, *start;        start = &session->rr[ssrc_hash(reporter_ssrc)][ssrc_hash(rr->ssrc)];        cur   = start->next;        while (cur != start) {                if (cur->reporter_ssrc == reporter_ssrc && cur->rr->ssrc == rr->ssrc) {                        /* Replace existing entry in the database  */                        xfree(cur->rr);			xfree(cur->ts);                        cur->rr = rr;			cur->ts = (struct timeval *) xmalloc(sizeof(struct timeval));			memcpy(cur->ts, ts, sizeof(struct timeval));                        return;

⌨️ 快捷键说明

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