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

📄 iax.c

📁 来自网络的iaxclient的协议栈源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 /* * libiax: An implementation of Inter-Asterisk eXchange * * Copyright (C) 2001, Linux Support Services, Inc. * * Mark Spencer <markster@linux-support.net> * Frik Strecker <frik@gatherworks.com> * * This program is free software, distributed under the terms of * the GNU Lesser (Library) General Public License */#ifdef HAVE_CONFIG_H#include "config.h"#endif#if defined(WIN32)  ||  defined(_WIN32_WCE)#undef __STRICT_ANSI__ //for strdup with ms#if defined(_WIN32_WCE)#define strdup _strdup#else#include <process.h>#include <fcntl.h>#include <io.h>#include <errno.h>#endif#include <string.h>#include <windows.h>#include <winsock.h>#include <time.h>#include <stdlib.h>#include <malloc.h>#include <stdarg.h>#include <stdio.h>#include <limits.h>#define	snprintf _snprintf#if defined(_MSC_VER)#define	close		closesocket#if !defined(_WIN32_WCE)#define inline      __inline#endif#endif#ifdef __cplusplusextern "C" {#endifvoid gettimeofday(struct timeval *tv, void /*struct timezone*/ *tz);#ifdef __cplusplus}#endif#else#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/time.h>#include <stdlib.h>#ifdef __GNUC__#ifndef __USE_SVID#define __USE_SVID#endif#endif#include <string.h>#include <stdarg.h>#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <sys/select.h>#include <netinet/in.h>#include <arpa/inet.h>#include <time.h>#ifndef MACOSX#include <malloc.h>#ifndef SOLARIS#include <error.h>#endif#endif#endif#include "jitterbuf.h"#include "iax-client.h"#include "md5.h"/* Define socket options for IAX2 sockets, based on platform * availability of flags */#if defined(WIN32)  ||  defined(_WIN32_WCE)#define IAX_SOCKOPTS 0#else#ifdef MACOSX#define IAX_SOCKOPTS MSG_DONTWAIT#else#ifdef SOLARIS#define IAX_SOCKOPTS MSG_DONTWAIT#else  /* Linux and others */#define IAX_SOCKOPTS MSG_DONTWAIT | MSG_NOSIGNAL#endif#endif#endif#ifdef SNOM_HACK/* The snom phone seems to improperly execute memset in some cases */#include "../../snom_phonecore2/include/snom_memset.h"#endif/* Voice TS Prediction causes libiax2 to clean up the timestamps on * outgoing frames.  It works best with either continuous voice, or * callers who call iax_send_cng to indicate DTX for silence */#define USE_VOICE_TS_PREDICTION#define MIN_RETRY_TIME 10#define MAX_RETRY_TIME 4000#define MEMORY_SIZE 1000#define TRANSFER_NONE  0#define TRANSFER_BEGIN 1#define TRANSFER_READY 2#define TRANSFER_REL   3/* Video frames bypass jitterbuffer */static int video_bypass_jitterbuffer = 0;/* UDP Socket (file descriptor) */static int netfd = -1;/* Max timeouts */static const int maxretries = 10;/* configurable jitterbuffer options */static long jb_target_extra = -1;/* external global networking replacements */static iax_sendto_t   iax_sendto = (iax_sendto_t) sendto;static iax_recvfrom_t iax_recvfrom = (iax_recvfrom_t) recvfrom;/* ping interval (seconds) */static int ping_time = 10;static void send_ping(void *session);struct iax_session {	/* Private data */	void *pvt;	/* session-local Sendto function */	iax_sendto_t sendto;	/* Is voice quelched (e.g. hold) */	int quelch;	/* Codec Pref Order */	char codec_order[32];	/* Codec Pref Order Index*/	int codec_order_len;	/* Last received voice format */	int voiceformat;	/* Last transmitted voice format */	int svoiceformat;	/* Last received video format */	int videoformat;	/* Last transmitted video format */	int svideoformat;	/* Per session capability */	int capability;	/* Last received timestamp */	unsigned int last_ts;	/* Last transmitted timestamp */	unsigned int lastsent;#ifdef USE_VOICE_TS_PREDICTION	/* Next predicted voice ts */	unsigned int nextpred;	/* True if the last voice we transmitted was not silence/CNG */	int notsilenttx;#endif	/* Our last measured ping time */	unsigned int pingtime;	/* Address of peer */	struct sockaddr_in peeraddr;	/* Our call number */	int callno;	/* Peer's call number */	int peercallno;	/* Our next outgoing sequence number */	unsigned char oseqno;	/* Next sequence number they have not yet acknowledged */	unsigned char rseqno;	/* Our last received incoming sequence number */	unsigned char iseqno;	/* Last acknowledged sequence number */	unsigned char aseqno;	/* Last sequence number we VNAKd */	unsigned char lastvnak;	/* Time value that we base our transmission on */	struct timeval offset;	/* Time value we base our delivery on */	struct timeval rxcore;	/* Current link state */	int state;	/* Expected Username */	char username[MAXSTRLEN];	/* Expected Secret */	char secret[MAXSTRLEN];	/* Refresh if applicable */	int refresh;	/* ping scheduler id */	int pingid;	/* Transfer stuff */	struct sockaddr_in transfer;	int transferring;	int transfercallno;	int transferid;	int transferpeer;	/* for attended transfer */	int transfer_moh;	/* for music on hold while performing attended transfer */	jitterbuf *jb;	struct iax_netstat remote_netstats;	/* For linking if there are multiple connections */	struct iax_session *next;};char iax_errstr[256];#define IAXERROR snprintf(iax_errstr, sizeof(iax_errstr),#ifdef DEBUG_SUPPORT#ifdef DEBUG_DEFAULTstatic int debug = 1;#elsestatic int debug = 0;#endifvoid iax_enable_debug(void){	debug = 1;}void iax_disable_debug(void){	debug = 0;}void iax_set_private(struct iax_session *s, void *ptr){	s->pvt = ptr;}void *iax_get_private(struct iax_session *s){	return s->pvt;}void iax_set_sendto(struct iax_session *s, iax_sendto_t ptr){	s->sendto = ptr;}/* This is a little strange, but to debug you call DEBU(G "Hello World!\n"); */#if defined(WIN32)  ||  defined(_WIN32_WCE)#define G __FILE__, __LINE__,#else#define G __FILE__, __LINE__, __PRETTY_FUNCTION__,#endif#define DEBU __debug#if defined(WIN32)  ||  defined(_WIN32_WCE)static int __debug(char *file, int lineno, char *fmt, ...){	va_list args;	va_start(args, fmt);	if (debug) {		fprintf(stderr, "%s line %d: ", file, lineno);		vfprintf(stderr, fmt, args);	}	va_end(args);	return 0;}#elsestatic int __debug(char *file, int lineno, char *func, char *fmt, ...){	va_list args;	va_start(args, fmt);	if (debug) {		fprintf(stderr, "%s line %d in %s: ", file, lineno, func);		vfprintf(stderr, fmt, args);	}	va_end(args);	return 0;}#endif#else /* No debug support */#if defined(WIN32)  ||  defined(_WIN32_WCE)#define	DEBU#else#define DEBU(fmt...) \    do {} while(0)#endif#define G#endiftypedef void (*sched_func)(void *);struct iax_sched {	/* These are scheduled things to be delivered */	struct timeval when;	/* If event is non-NULL then we're delivering an event */	struct iax_event *event;	/* If frame is non-NULL then we're transmitting a frame */	struct iax_frame *frame;	/* If func is non-NULL then we should call it */	sched_func func;	/* and pass it this argument */	void *arg;	/* Easy linking */	struct iax_sched *next;};static struct iax_sched *schedq = NULL;static struct iax_session *sessions = NULL;static int callnums = 1;static int transfer_id = 1;		/* for attended transfer */void iax_set_private(struct iax_session *s, void *ptr){	s->pvt = ptr;}void *iax_get_private(struct iax_session *s){	return s->pvt;}void iax_set_sendto(struct iax_session *s, iax_sendto_t ptr){	s->sendto = ptr;}unsigned int iax_session_get_capability(struct iax_session *s){	return s->capability;}static int inaddrcmp(struct sockaddr_in *sin1, struct sockaddr_in *sin2){	return (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) || (sin1->sin_port != sin2->sin_port);}static int iax_sched_add(struct iax_event *event, struct iax_frame *frame, sched_func func, void *arg, int ms){	/* Schedule event to be delivered to the client	   in ms milliseconds from now, or a reliable frame to be retransmitted */	struct iax_sched *sched, *cur, *prev = NULL;	if (!event && !frame && !func) {		DEBU(G "No event, no frame, no func?  what are we scheduling?\n");		return -1;	}	//fprintf(stderr, "scheduling event %d ms from now\n", ms);	sched = (struct iax_sched*)malloc(sizeof(struct iax_sched));	if (sched) {		memset(sched, 0, sizeof(struct iax_sched));		gettimeofday(&sched->when, NULL);		sched->when.tv_sec += (ms / 1000);		ms = ms % 1000;		sched->when.tv_usec += (ms * 1000);		if (sched->when.tv_usec > 1000000) {			sched->when.tv_usec -= 1000000;			sched->when.tv_sec++;		}		sched->event = event;		sched->frame = frame;		sched->func = func;		sched->arg = arg;		/* Put it in the list, in order */		cur = schedq;		while(cur && ((cur->when.tv_sec < sched->when.tv_sec) ||					 ((cur->when.tv_usec <= sched->when.tv_usec) &&					  (cur->when.tv_sec == sched->when.tv_sec)))) {				prev = cur;				cur = cur->next;		}		sched->next = cur;		if (prev) {			prev->next = sched;		} else {			schedq = sched;		}		return 0;	} else {		DEBU(G "Out of memory!\n");		return -1;	}}static int iax_sched_del(struct iax_event *event, struct iax_frame *frame, sched_func func, void *arg, int all){	struct iax_sched *cur, *tmp, *prev = NULL;	cur = schedq;	while (cur) {		if (cur->event == event && cur->frame == frame && cur->func == func && cur->arg == arg) {			if (prev)				prev->next = cur->next;			else				schedq = cur->next;			tmp = cur;			cur = cur->next;			free(tmp);			if (!all)				return -1;		} else {			prev = cur;			cur = cur->next;		}	}	return 0;}int iax_time_to_next_event(void){	struct timeval tv;	struct iax_sched *cur = schedq;	int ms, min = 999999999;	/* If there are no pending events, we don't need to timeout */	if (!cur)		return -1;	gettimeofday(&tv, NULL);	while(cur) {		ms = (cur->when.tv_sec - tv.tv_sec) * 1000 +		     (cur->when.tv_usec - tv.tv_usec) / 1000;		if (ms < min)			min = ms;		cur = cur->next;	}	if (min < 0)		min = 0;	return min;}struct iax_session *iax_session_new(void){	struct iax_session *s;	s = (struct iax_session *)malloc(sizeof(struct iax_session));	if (s) {		jb_conf jbconf;		memset(s, 0, sizeof(struct iax_session));		/* Initialize important fields */		s->voiceformat = -1;		s->svoiceformat = -1;		s->videoformat = -1;		/* Default pingtime to 100 ms -- should cover most decent net connections */		s->pingtime = 100;		/* XXX Not quite right -- make sure it's not in use, but that won't matter		   unless you've had at least 65k calls.  XXX */		s->callno = callnums++;		if (callnums > 32767)			callnums = 1;		s->peercallno = 0;		s->lastvnak = -1;		s->transferpeer = 0; /* for attended transfer */		s->next = sessions;		s->sendto = iax_sendto;		s->pingid = -1;		s->jb = jb_new();		if ( !s->jb )		{			free(s);			return 0;		}		jbconf.max_jitterbuf = 0;		jbconf.resync_threshold = 1000;		jbconf.max_contig_interp = 0;		jbconf.target_extra = jb_target_extra;		jb_setconf(s->jb, &jbconf);		sessions = s;	}	return s;}static int iax_session_valid(struct iax_session *session){	/* Return -1 on a valid iax session pointer, 0 on a failure */	struct iax_session *cur = sessions;	while(cur) {		if (session == cur)

⌨️ 快捷键说明

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