📄 iax.c
字号:
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 + -