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

📄 iax.c

📁 来自网络的iaxclient的协议栈源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	int x;	int power=-1;	/* If it's 128 or smaller, just return it */	if (subclass < IAX_FLAG_SC_LOG)		return subclass;	/* Otherwise find its power */	for (x = 0; x < IAX_MAX_SHIFT; x++) {		if (subclass & (1 << x)) {			if (power > -1) {				DEBU(G "Can't compress subclass %d\n", subclass);				return 0;			} else				power = x;		}	}	return power | IAX_FLAG_SC_LOG;}static int iax_send(struct iax_session *pvt, struct ast_frame *f, unsigned int ts, int seqno, int now, int transfer, int final, int fullframe){	/* Queue a packet for delivery on a given private structure.  Use "ts" for	   timestamp, or calculate if ts is 0.  Send immediately without retransmission	   or delayed, with retransmission */	struct ast_iax2_full_hdr *fh;	struct ast_iax2_mini_hdr *mh;	struct ast_iax2_video_hdr *vh;	//unsigned char buf[5120]; //fd: changed max packet size[5120];	unsigned char buf[32 * 1024]; //Mihai: let's see if this is where it crashes	struct iax_frame *fr;	int res;	int sendmini=0;	unsigned int lastsent;	unsigned int fts;	if (!pvt)	{		IAXERROR "No private structure for packet?\n");		return -1;	}	/* this must come before the next call to calc_timestamp() since	 calc_timestamp() will change lastsent to the returned value */	lastsent = pvt->lastsent;	/* Calculate actual timestamp */	fts = calc_timestamp(pvt, ts, f);	if (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L))		/* High two bits are the same on timestamp, or sending on a trunk */ &&		(f->frametype == AST_FRAME_VOICE)		/* is a voice frame */ &&		(f->subclass == pvt->svoiceformat)		/* is the same type */ )	{		/* Force immediate rather than delayed transmission */		now = 1;		/* Mark that mini-style frame is appropriate */		sendmini = 1;	}	/* Bitmask taken from chan_iax2.c... I must ask Mark Spencer for this? I think not... */	if ( f->frametype == AST_FRAME_VIDEO )	{		if (((fts & 0xFFFF8000L) == (lastsent & 0xFFFF8000L))			/* High two bits are the same on timestamp, or sending on a trunk */ &&		((f->subclass & ~0x01) == pvt->svideoformat)			/* is the same type */ )		{			/* Force immediate rather than delayed transmission */			now = 1;			/* Mark that mini-style frame is appropriate */			sendmini = 1;		} else		{			/* we want to send a fullframe and be able to retransmit it */			now = 0;			sendmini = 0;		}	}	/* if requested, force a full frame */	if ( fullframe )	{		now = 0;		sendmini = 0;	}		/* Allocate an iax_frame */	if (now)	{		fr = (struct iax_frame *) buf;	} else	{		fr = iax_frame_new(DIRECTION_OUTGRESS, f->datalen);		if ( fr == NULL )		{			IAXERROR "Out of memory\n");			return -1;		}	}		/* Copy our prospective frame into our immediate or retransmitted wrapper */	iax_frame_wrap(fr, f);	fr->ts = fts;	if (!fr->ts)	{		IAXERROR "timestamp is 0?\n");		if (!now)			iax_frame_free(fr);		return -1;	}	fr->callno = pvt->callno;	fr->transfer = transfer;	fr->final = final;	fr->session = pvt;	if (!sendmini)	{		/* We need a full frame */		if (seqno > -1)			fr->oseqno = seqno;		else			fr->oseqno = pvt->oseqno++;		fr->iseqno = pvt->iseqno;		fh = (struct ast_iax2_full_hdr *)(((char *)fr->af.data) - sizeof(struct ast_iax2_full_hdr));		fh->scallno = htons(fr->callno | IAX_FLAG_FULL);		fh->ts = htonl(fr->ts);		fh->oseqno = fr->oseqno;		if (transfer)		{			fh->iseqno = 0;		} else			fh->iseqno = fr->iseqno;			/* Keep track of the last thing we've acknowledged */		pvt->aseqno = fr->iseqno;		fh->type = fr->af.frametype & 0xFF;		if (f->frametype == AST_FRAME_VIDEO)			fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6);		else			fh->csub = compress_subclass(fr->af.subclass);		if (transfer)		{			fr->dcallno = pvt->transfercallno;		} else			fr->dcallno = pvt->peercallno;		fh->dcallno = htons(fr->dcallno);		fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr);		fr->data = fh;		fr->retries = maxretries;		/* Retry after 2x the ping time has passed */		fr->retrytime = pvt->pingtime * 2;		if (fr->retrytime < MIN_RETRY_TIME)			fr->retrytime = MIN_RETRY_TIME;		if (fr->retrytime > MAX_RETRY_TIME)			fr->retrytime = MAX_RETRY_TIME;		/* Acks' don't get retried */		if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK))			fr->retries = -1;		if (f->frametype == AST_FRAME_VOICE)		{			pvt->svoiceformat = f->subclass;		}		else if (f->frametype == AST_FRAME_VIDEO)		{			pvt->svideoformat = f->subclass & ~0x1;		}		if (now)		{			res = iax_xmit_frame(fr);		} else			res = iax_reliable_xmit(fr);	} else	{		if (fr->af.frametype == AST_FRAME_VIDEO)		{			/* Video frame have no sequence number */			fr->oseqno = -1;			fr->iseqno = -1;			vh = (struct ast_iax2_video_hdr *)(((char* )fr->af.data) - sizeof(struct ast_iax2_video_hdr));			vh->zeros = 0;			vh->callno = htons(0x8000 | fr->callno);			vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0));			fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);			fr->data = vh;			fr->retries = -1;			res = iax_xmit_frame(fr);		} else		{			/* Mini-frames have no sequence number */			fr->oseqno = -1;			fr->iseqno = -1;			/* Mini frame will do */			mh = (struct ast_iax2_mini_hdr *)(((char *)fr->af.data) - sizeof(struct ast_iax2_mini_hdr));			mh->callno = htons(fr->callno);			mh->ts = htons(fr->ts & 0xFFFF);			fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);			fr->data = mh;			fr->retries = -1;			res = iax_xmit_frame(fr);		}	}	if( !now && fr!=NULL )		iax_frame_free( fr );	return res;}#if 0static int iax_predestroy(struct iax_session *pvt){	if (!pvt) {		return -1;	}	if (!pvt->alreadygone) {		/* No more pings or lagrq's */		if (pvt->pingid > -1)			ast_sched_del(sched, pvt->pingid);		if (pvt->lagid > -1)			ast_sched_del(sched, pvt->lagid);		if (pvt->autoid > -1)			ast_sched_del(sched, pvt->autoid);		if (pvt->initid > -1)			ast_sched_del(sched, pvt->initid);		pvt->pingid = -1;		pvt->lagid = -1;		pvt->autoid = -1;		pvt->initid = -1;		pvt->alreadygone = 1;	}	return 0;}#endifstatic int __send_command(struct iax_session *i, char type, int command,		unsigned int ts, unsigned char *data, int datalen, int seqno,		int now, int transfer, int final, int fullframe, int samples){	struct ast_frame f;	f.frametype = type;	f.subclass = command;	f.datalen = datalen;	f.samples = samples;	f.mallocd = 0;	f.offset = 0;#ifdef __GNUC__	f.src = (char *) __FUNCTION__;#else	f.src = (char *) __FILE__;#endif	f.data = data;	return iax_send(i, &f, ts, seqno, now, transfer, final, fullframe);}static int send_command(struct iax_session *i, char type, int command, unsigned int ts, unsigned char *data, int datalen, int seqno){	return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0, 0, 0);}static int send_command_video(struct iax_session *i, char type, int command, unsigned int ts, unsigned char *data, int datalen, int seqno, int fullframe){	return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0, fullframe, 0);}static int send_command_final(struct iax_session *i, char type, int command, unsigned int ts, unsigned char *data, int datalen, int seqno){#if 0	/* It is assumed that the callno has already been locked */	iax_predestroy(i);#endif	int r;	r = __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1, 0, 0);	if (r >= 0) destroy_session(i);	return r;}static int send_command_immediate(struct iax_session *i, char type, int command, unsigned int ts, unsigned char *data, int datalen, int seqno){	return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0, 0, 0);}static int send_command_transfer(struct iax_session *i, char type, int command, unsigned int ts, unsigned char *data, int datalen){	return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0, 0, 0);}static int send_command_samples(struct iax_session *i, char type, int command, unsigned int ts, unsigned char *data, int datalen, int seqno, int samples){	return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0, 0, samples);}int iax_transfer(struct iax_session *session, const char *number){	static int res;				//Return Code	struct iax_ie_data ied;			//IE Data Structure (Stuff To Send)	// Clear The Memory Used For IE Buffer	memset(&ied, 0, sizeof(ied));	// Copy The Transfer Destination Into The IE Structure	iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, number);	// Send The Transfer Command - Asterisk Will Handle The Rest!	res = send_command(session, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);	// Return Success	return 0;}static void stop_transfer(struct iax_session *session){	struct iax_sched *sch;	sch = schedq;	while(sch) {		if (sch->frame && (sch->frame->session == session))					sch->frame->retries = -1;		sch = sch->next;	}}	/* stop_transfer */static void complete_transfer(struct iax_session *session, int peercallno, int xfr2peer, int preserveSeq){	jb_frame frame;	session->peercallno = peercallno;	/* Change from transfer to session now */	if (xfr2peer) {		memcpy(&session->peeraddr, &session->transfer, sizeof(session->peeraddr));		memset(&session->transfer, 0, sizeof(session->transfer));		session->transferring = TRANSFER_NONE;		session->transferpeer = 0;		session->transfer_moh = 0;		/* Force retransmission of a real voice packet, and reset all timing */		session->svoiceformat = -1;		session->voiceformat = 0;		session->svideoformat = -1;		session->videoformat = 0;	}	memset(&session->rxcore, 0, sizeof(session->rxcore));	memset(&session->offset, 0, sizeof(session->offset));	/* Reset jitterbuffer */	while(jb_getall(session->jb,&frame) == JB_OK)		iax_event_free((struct iax_event *)frame.data);	jb_reset(session->jb);	if (! preserveSeq)	{		/* Reset sequence numbers */		session->aseqno = 0;		session->oseqno = 0;		session->iseqno = 0;	}	session->lastsent = 0;	session->last_ts = 0;	session->pingtime = 30;	/* We have to dump anything we were going to (re)transmit now that we've been	   transferred since they're all invalid and for the old host. */	stop_transfer(session);}	/* complete_transfer */int iax_setup_transfer(struct iax_session *org_session, struct iax_session *new_session){	int res;	struct iax_ie_data ied0;	struct iax_ie_data ied1;	struct iax_session *s0 = org_session;	struct iax_session *s1 = new_session;	memset(&ied0, 0, sizeof(ied0));	memset(&ied1, 0, sizeof(ied1));	/* reversed setup */	iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &s1->peeraddr);	iax_ie_append_short(&ied0, IAX_IE_CALLNO, s1->peercallno);	iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transfer_id);	iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &s0->peeraddr);	iax_ie_append_short(&ied1, IAX_IE_CALLNO, s0->peercallno);	iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transfer_id);	s0->transfer = s1->peeraddr;	s1->transfer = s0->peeraddr;	s0->transferid = transfer_id;	s1->transferid = transfer_id;	s0->transfercallno = s0->peercallno;	s1->transfercallno = s1->peercallno;	s0->transferring = TRANSFER_BEGIN;	s1->transferring = TRANSFER_BEGIN;	s0->transferpeer = s1->callno;	s1->transferpeer = s0->callno;	transfer_id++;	if (transfer_id > 32767)		transfer_id = 1;	res = send_command(s0, AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);	if (res < 0) {		return -1;	}	res = send_command(s1, AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);	if (res < 0) {		return -1;	}	return 0;}static int iax_finish_transfer(struct iax_session *s, short new_peer){	int res;	struct iax_ie_data ied;	memset(&ied, 0, sizeof(ied));	iax_ie_append_short(&ied, IAX_IE_CALLNO, new_peer);	res = send_command(s, AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied.buf, ied.pos, -1);	complete_transfer(s, new_peer, 0, 1);	return res;}static struct iax_session *iax_find_session2(short callno){	struct iax_session *cur = sessions;	while(cur) {		if (callno == cur->callno && callno != 0)  {			return cur;		}		cur = cur->next;	}	return NULL;}static int iax_handle_txready(struct iax_session *s){	struct iax_session *s0, *s1;	short s0_org_peer, s1_org_peer;	if (s->transfer_moh) {		s->transfer_moh = 0;		iax_unquelch(s);	}	complete_transfer(s, s->peercallno, 0, 1);	s->transferring = TRANSFER_REL;	s0 = s;	s1 = iax_find_session2(s0->transferpeer);	if (s1 != NULL &&	    s1->callno == s0->transferpeer &&	    s0->transferring == TRANSFER_REL &&	    s1->transferring == TRANSFER_REL) {		s0_org_peer = s0->peercallno;		s1_org_peer = s1->peercallno;		iax_finish_transfer(s0, s1_org_peer);		iax_finish_transfer(s1, s0_org_peer);		return 1;	}	return 0;}static void iax_handle_txreject(struct iax_session *s){	struct iax_session *s0, *s1;	s0 = s;	s1 = iax_find_session2(s0->transferpeer);	if (s1 != NULL &&		 s0->transferpeer == s1->callno &&		 s1->transferring) {		if (s1->transfer_moh) {			s1->transfer_moh = 0;			send_command_immediate(s1, AST_FRAME_IAX, IAX_COMMAND_UNQUELCH, 0, NULL, 0, s1->iseqno);		}	}	if (s0->transfer_moh) {		s0->transfer_moh = 0;		send_command_immediate(s0, AST_FRAME_IAX, IAX_COMMAND_UNQUELCH, 0, NULL, 0, s0->iseqno);	}	memset(&s->transfer, 0, sizeof(s->transfer));	s->transferring = TRANSFER_NONE;	s->transferpeer = 0;

⌨️ 快捷键说明

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