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

📄 iax.c

📁 IAX client库, 一个VOIP的库. 支持H.323和SIP, PBX就是采用的它
💻 C
📖 第 1 页 / 共 5 页
字号:
int iax_send_url(struct iax_session *session, char *url, int link){	return send_command(session, AST_FRAME_HTML, link ? AST_HTML_LINKURL : AST_HTML_URL, 0, url, strlen(url), -1);}int iax_send_text(struct iax_session *session, char *text){	return send_command(session, AST_FRAME_TEXT, 0, 0, text, strlen(text), -1);}int iax_send_unlink(struct iax_session *session){	return send_command(session, AST_FRAME_HTML, AST_HTML_UNLINK, 0, NULL, 0, -1);}int iax_send_link_reject(struct iax_session *session){	return send_command(session, AST_FRAME_HTML, AST_HTML_LINKREJECT, 0, NULL, 0, -1);}static int iax_send_pong(struct iax_session *session, unsigned int ts){        struct iax_ie_data ied;        memset(&ied, 0, sizeof(ied));#ifdef NEWJB	{	    jb_info stats;	    jb_getinfo(session->jb, &stats);	    iax_ie_append_int(&ied,IAX_IE_RR_JITTER, stats.jitter);	    /* XXX: should be short-term loss pct.. */	    if(stats.frames_in == 0) stats.frames_in = 1;	    iax_ie_append_int(&ied,IAX_IE_RR_LOSS, 		((0xff & (stats.frames_lost * 100 / stats.frames_in)) << 24 | (stats.frames_lost & 0x00ffffff)));	    iax_ie_append_int(&ied,IAX_IE_RR_PKTS, stats.frames_in);	    iax_ie_append_short(&ied,IAX_IE_RR_DELAY, stats.current - stats.min);	    iax_ie_append_int(&ied,IAX_IE_RR_DROPPED, stats.frames_dropped);	    iax_ie_append_int(&ied,IAX_IE_RR_OOO, stats.frames_ooo);	}#else	    iax_ie_append_int(&ied,IAX_IE_RR_JITTER, session->jitter);	    /* don't know, don't send! iax_ie_append_int(&ied,IAX_IE_RR_LOSS, 0); */	    /* don't know, don't send! iax_ie_append_int(&ied,IAX_IE_RR_PKTS, stats.frames_in); */	    /* don't know, don't send! iax_ie_append_short(&ied,IAX_IE_RR_DELAY, stats.current - stats.min); */#endif	return send_command(session, AST_FRAME_IAX, IAX_COMMAND_PONG, ts, ied.buf, ied.pos, -1);}/* external API; deprecated since we send pings ourselves now (finally) */int iax_send_ping(struct iax_session *session){	return send_command(session, AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);}/* scheduled ping sender; sends ping, then reschedules */static void send_ping(void *s){	struct iax_session *session = (struct iax_session *)s;	/* important, eh? */	if(!iax_session_valid(session)) return;	send_command(session, AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);	session->pingid = iax_sched_add(NULL,NULL, send_ping, (void *)session, ping_time * 1000);	return;}static int iax_send_lagrp(struct iax_session *session, unsigned int ts){	return send_command(session, AST_FRAME_IAX, IAX_COMMAND_LAGRP, ts, NULL, 0, -1);}static int iax_send_txcnt(struct iax_session *session){	struct iax_ie_data ied;	memset(&ied, 0, sizeof(ied));	iax_ie_append_int(&ied, IAX_IE_TRANSFERID, session->transferid);	return send_command_transfer(session, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);}static int iax_send_txrej(struct iax_session *session){	struct iax_ie_data ied;	memset(&ied, 0, sizeof(ied));	iax_ie_append_int(&ied, IAX_IE_TRANSFERID, session->transferid);	return send_command_transfer(session, AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, ied.buf, ied.pos);}static int iax_send_txaccept(struct iax_session *session){	struct iax_ie_data ied;	memset(&ied, 0, sizeof(ied));	iax_ie_append_int(&ied, IAX_IE_TRANSFERID, session->transferid);	return send_command_transfer(session, AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, ied.buf, ied.pos);}static int iax_send_txready(struct iax_session *session){	struct iax_ie_data ied;	memset(&ied, 0, sizeof(ied));	/* see asterisk chan_iax2.c */	iax_ie_append_short(&ied, IAX_IE_CALLNO, session->callno);	return send_command(session, AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied.buf, ied.pos, -1);}int iax_auth_reply(struct iax_session *session, char *password, char *challenge, int methods){	char reply[16];	struct MD5Context md5;	char realreply[256];	struct iax_ie_data ied;	memset(&ied, 0, sizeof(ied));	if ((methods & IAX_AUTH_MD5) && challenge) {		MD5Init(&md5);		MD5Update(&md5, (const unsigned char *) challenge, strlen(challenge));		MD5Update(&md5, (const unsigned char *) password, strlen(password));		MD5Final((unsigned char *) reply, &md5);		bzero(realreply, sizeof(realreply));		convert_reply(realreply, (unsigned char *) reply);		iax_ie_append_str(&ied, IAX_IE_MD5_RESULT, realreply);	} else {		iax_ie_append_str(&ied, IAX_IE_MD5_RESULT, password);	}	return send_command(session, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);}static int iax_regauth_reply(struct iax_session *session, char *password, char *challenge, int methods){	char reply[16];	struct MD5Context md5;	char realreply[256];	struct iax_ie_data ied;	memset(&ied, 0, sizeof(ied));	iax_ie_append_str(&ied, IAX_IE_USERNAME, session->username);	iax_ie_append_short(&ied, IAX_IE_REFRESH, session->refresh);	if ((methods & IAX_AUTHMETHOD_MD5) && challenge) {		MD5Init(&md5);		MD5Update(&md5, (const unsigned char *) challenge, strlen(challenge));		MD5Update(&md5, (const unsigned char *) password, strlen(password));		MD5Final((unsigned char *) reply, &md5);		bzero(realreply, sizeof(realreply));		convert_reply(realreply, (unsigned char *) reply);		iax_ie_append_str(&ied, IAX_IE_MD5_RESULT, realreply);	} else {		iax_ie_append_str(&ied, IAX_IE_MD5_RESULT, password);	}	return send_command(session, AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);}int iax_dial(struct iax_session *session, char *number){	struct iax_ie_data ied;	memset(&ied, 0, sizeof(ied));	iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, number);	return send_command(session, AST_FRAME_IAX, IAX_COMMAND_DIAL, 0, ied.buf, ied.pos, -1);}int iax_quelch(struct iax_session *session){	return send_command(session, AST_FRAME_IAX, IAX_COMMAND_QUELCH, 0, NULL, 0, -1);}int iax_unquelch(struct iax_session *session){	return send_command(session, AST_FRAME_IAX, IAX_COMMAND_UNQUELCH, 0, NULL, 0, -1);}int iax_dialplan_request(struct iax_session *session, char *number){	struct iax_ie_data ied;	memset(&ied, 0, sizeof(ied));	iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, number);	return send_command(session, AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);}int iax_call(struct iax_session *session, char *cidnum, char *cidname, char *ich, char *lang, int wait, int formats, int capabilities){	char tmp[256]="";	char *part1, *part2;	int res;	int portno;	char *username, *hostname, *secret, *context, *exten, *dnid;	struct iax_ie_data ied;	struct hostent *hp;	/* We start by parsing up the temporary variable which is of the form of:	   [user@]peer[:portno][/exten[@context]] */	if (!ich) {		IAXERROR "Invalid IAX Call Handle\n");		DEBU(G "Invalid IAX Call Handle\n");		return -1;	}	memset(&ied, 0, sizeof(ied));	strncpy(tmp, ich, sizeof(tmp) - 1);		iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);	if (cidnum)		iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, cidnum);	if (cidname)		iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, cidname);		session->capability = capabilities;	session->pingid = iax_sched_add(NULL,NULL, send_ping, (void *)session, 2 * 1000);	/* XXX We should have a preferred format XXX */	iax_ie_append_int(&ied, IAX_IE_FORMAT, formats);	iax_ie_append_int(&ied, IAX_IE_CAPABILITY, capabilities);	if (lang)		iax_ie_append_str(&ied, IAX_IE_LANGUAGE, lang);		/* Part 1 is [user[:password]@]peer[:port] */	part1 = strtok(tmp, "/");	/* Part 2 is exten[@context] if it is anything all */	part2 = strtok(NULL, "/");		if (strchr(part1, '@')) {		username = strtok(part1, "@");		hostname = strtok(NULL, "@");	} else {		username = NULL;		hostname = part1;	}		if (username && strchr(username, ':')) {		username = strtok(username, ":");		secret = strtok(NULL, ":");	} else		secret = NULL;	if(username)	  strncpy(session->username, username, sizeof(session->username) - 1);	if(secret)	  strncpy(session->secret, secret, sizeof(session->secret) - 1);		if (strchr(hostname, ':')) {		strtok(hostname, ":");		portno = atoi(strtok(NULL, ":"));	} else {		portno = IAX_DEFAULT_PORTNO;	}	if (part2) {		exten = strtok(part2, "@");		dnid = exten;		context = strtok(NULL, "@");	} else {		exten = NULL;		dnid = NULL;		context = NULL;	}	if (username)		iax_ie_append_str(&ied, IAX_IE_USERNAME, username);	if (exten && strlen(exten))		iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, exten);	if (dnid && strlen(dnid))		iax_ie_append_str(&ied, IAX_IE_DNID, dnid);	if (context && strlen(context))		iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);	/* Setup host connection */	hp = gethostbyname(hostname);	if (!hp) {		snprintf(iax_errstr, sizeof(iax_errstr), "Invalid hostname: %s", hostname);		return -1;	}	memcpy(&session->peeraddr.sin_addr, hp->h_addr, sizeof(session->peeraddr.sin_addr));	session->peeraddr.sin_port = htons(portno);	session->peeraddr.sin_family = AF_INET;	res = send_command(session, AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);	if (res < 0)		return res;	if (wait) {		DEBU(G "Waiting not yet implemented\n");		return -1;	}	return res;}static int calc_rxstamp(struct iax_session *session){	struct timeval tv;	int ms;	if (!session->rxcore.tv_sec && !session->rxcore.tv_usec) {		gettimeofday(&session->rxcore, NULL);	}		gettimeofday(&tv, NULL);	ms = (tv.tv_sec - session->rxcore.tv_sec) * 1000 +		 (tv.tv_usec - session->rxcore.tv_usec) / 1000;		return ms;}static int match(struct sockaddr_in *sin, short callno, short dcallno, struct iax_session *cur){	if ((cur->peeraddr.sin_addr.s_addr == sin->sin_addr.s_addr) &&		(cur->peeraddr.sin_port == sin->sin_port)) {		/* This is the main host */		if ((cur->peercallno == callno) || 			((dcallno == cur->callno) && !cur->peercallno)) {			/* That's us.  Be sure we keep track of the peer call number */			cur->peercallno = callno;			return 1;		}	}	if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&	    (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {		/* We're transferring */		if (dcallno == cur->callno)			return 1;	}	return 0;}/* splitted match into 2 passes otherwise causing problem of matching   up the wrong session using the dcallno and the peercallno because   during a transfer (2 IAX channels on the same client/system) the   same peercallno (from two different asterisks) exist in more than	one session. */static int forward_match(struct sockaddr_in *sin, short callno, short dcallno, struct iax_session *cur){	if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&		(cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {		/* We're transferring */		if (dcallno == cur->callno)		{			return 1;		}	}	if ((cur->peeraddr.sin_addr.s_addr == sin->sin_addr.s_addr) &&		(cur->peeraddr.sin_port == sin->sin_port)) {		if (dcallno == cur->callno && dcallno != 0)  {					/* That's us.  Be sure we keep track of the peer call number */			if (cur->peercallno == 0) {				cur->peercallno = callno;			}			return 1;		}	}	return 0;}static int reverse_match(struct sockaddr_in *sin, short callno, struct iax_session *cur){	if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&		(cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {		/* We're transferring */		if (callno == cur->peercallno)  {			return 1;		}	}	if ((cur->peeraddr.sin_addr.s_addr == sin->sin_addr.s_addr) &&		(cur->peeraddr.sin_port == sin->sin_port)) {		if (callno == cur->peercallno)  {			return 1;		}	}	return 0;}static struct iax_session *iax_find_session(struct sockaddr_in *sin, 											short callno, 											short dcallno,											int makenew){	struct iax_session *cur = sessions;	while(cur) {		if (forward_match(sin, callno, dcallno, cur)) {			return cur;		}		cur = cur->next;	}	cur = sessions;	while(cur) {		if (reverse_match(sin, callno, cur)) {			return cur;		}		cur = cur->next;	}	if (makenew && !dcallno) {		cur = iax_session_new();		cur->peercallno = callno;		cur->peeraddr.sin_addr.s_addr = sin->sin_addr.s_addr;		cur->peeraddr.sin_port = sin->sin_port;		cur->peeraddr.sin_family = AF_INET;		cur->pingid = iax_sched_add(NULL,NULL, send_ping, (void *)cur, 2 * 1000);		DEBU(G "Making new session, peer callno %d, our callno %d\n", callno, cur->callno);	} else {		DEBU(G "No session, peer = %d, us = %d\n", callno, dcallno);	}	return cur;	}#ifdef EXTREME_DEBUGstatic int display_time(int ms){	static int oldms = -1;	if (oldms < 0) {		DEBU(G "First measure\n");		oldms = ms;		return 0;	}	DEBU(G "Time from last frame is %d ms\n", ms - oldms);	oldms = ms;	return 0;}#endif#define FUDGE 1#ifdef NEWJB/* From chan_iax2/steve davies:  need to get permission from steve or digium, I guess */static long unwrap_timestamp(long ts, long last){        int x;        if ( (ts & 0xFFFF0000) == (last & 0xFFFF0000) ) {                x = ts - last;                if (x < -50000) {                        /* Sudden big jump backwards in timestamp:                           What likely happened here is that miniframe timestamp has circled but we haven't                           gotten the update from the main packet.  We'll just pretend that we did, and                           update the timestamp appropriately. */                        ts = ( (last & 0xFFFF0000) + 0x10000) | (ts & 0xFFFF);                                DEBU(G "schedule_delivery: pushed forward timestamp\n");                }                if (x > 50000) {                        /* Sudden apparent big jump forwards in timestamp:                           What's likely happened is this is an old miniframe belonging to the previous                           top-16-bit timestamp that has turned up out of order.                           Adjust the timestamp appropriately. */                        ts = ( (last & 0xFFFF0000) - 0x10000) | (ts & 0xFFFF);                                DEBU(G "schedule_delivery: pushed back timestamp\n");                }        }	return ts;}#endifstatic struct iax_event *schedule_delivery(struct iax_event *e, unsigned int ts, int updatehistory){	/* 	 * This is the core of the IAX jitterbuffer delivery mechanism: 	 * Dynamically adjust the jitterbuffer and decide how long to wait	 * before delivering the packet.	 */	int ms, x;	int drops[MEMORY_SIZE];	int min, max=0, maxone=0, y, z, match;#ifdef EXTREME_DEBUG		DEBU(G "[%p] We are at %d, packet is for %d\n", e->session, calc_rxstamp(e->session), ts);#endif	

⌨️ 快捷键说明

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