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

📄 iax.c

📁 IAX协议客户端源码
💻 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 <stdarg.h>#include <stdio.h>#include <limits.h>#if !defined(_WIN32_WCE)#include <sys/timeb.h>#endif#define	snprintf _snprintf#if defined(_MSC_VER)#define	close		closesocket#if !defined(_WIN32_WCE)#define inline      __inline#endif#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>#if !defined(MACOSX) && !defined(__OpenBSD__)#include <malloc.h>#if !defined(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#if defined(SOLARIS) || defined(__OpenBSD__)#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;/* To use or not to use the jitterbuffer */static int iax_use_jitterbuffer = 1;/* 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;	/* Timestamp of the last transmitted video frame */	unsigned int lastvsent;#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;	/* Unregister reason */	char unregreason[MAXSTRLEN];	/* 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_enable_jitterbuffer(void){	iax_use_jitterbuffer = 1;}void iax_disable_jitterbuffer(void){	iax_use_jitterbuffer = 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(const char *file, int lineno, const 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(const char *file, int lineno, const char *func, const 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#endifvoid iax_seed_random(){#if defined(HAVE_SRANDOMDEV)	srandomdev();#elif defined(HAVE_SRANDOM)	srandom((unsigned int)time(0));#elif defined(HAVE_SRAND48)	srand48((long int)time(0));#else	srand((unsigned int)time(0));#endif}int iax_random(){#if defined(HAVE_RANDOM)	return (int)random();#elif defined(HAVE_LRAND48)	return (int)lrand48();#else	return rand();#endif}typedef 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;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));		sched->when = iax_tvnow();		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;	tv = iax_tvnow();	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 = calloc(1, sizeof(struct iax_session));	if (s) {		jb_conf jbconf;		/* 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;#ifdef USE_VOICE_TS_PREDICTION		s->nextpred = 0;#endif		s->jb = jb_new();		if ( !s->jb )

⌨️ 快捷键说明

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