📄 iax.c
字号:
static int send_command(struct iax_session *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno){ return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0, 0);}static int send_command_final(struct iax_session *i, char type, int command, unsigned int ts, 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); if (r >= 0) destroy_session(i); return r;}static int send_command_immediate(struct iax_session *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno){ return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0, 0);}static int send_command_transfer(struct iax_session *i, char type, int command, unsigned int ts, char *data, int datalen){ return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0, 0);}static int send_command_samples(struct iax_session *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno, int samples){ return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0, samples);}int iax_transfer(struct iax_session *session, 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){ 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; } memset(&session->rxcore, 0, sizeof(session->rxcore)); memset(&session->offset, 0, sizeof(session->offset)); memset(&session->history, 0, sizeof(session->history));#ifdef NEWJB { /* Reset jitterbuffer */ jb_frame frame; while(jb_getall(session->jb,&frame) == JB_OK) iax_event_free(frame.data); jb_reset(session->jb); }#endif session->jitterbuffer = 0; session->jitter = 0; session->lag = 0; if (! preserveSeq) { /* Reset sequence numbers */ session->aseqno = 0; session->oseqno = 0; session->iseqno = 0; } session->lastsent = 0; session->last_ts = 0; session->lastvoicets = 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; s->transfer_moh = 0;}static void destroy_session(struct iax_session *session){ struct iax_session *cur, *prev=NULL; struct iax_sched *curs, *prevs=NULL, *nexts=NULL; int loop_cnt=0; curs = schedq; while(curs) { nexts = curs->next; if (curs->frame && curs->frame->session == session) { /* Just mark these frames as if they've been sent */ curs->frame->retries = -1; } else if (curs->event && curs->event->session == session) { if (prevs) prevs->next = nexts; else schedq = nexts; if (curs->event) iax_event_free(curs->event); free(curs); } else { prevs = curs; } curs = nexts; loop_cnt++; } cur = sessions; while(cur) { if (cur == session) { if (prev) prev->next = session->next; else sessions = session->next;#ifdef NEWJB { jb_frame frame; while(jb_getall(session->jb,&frame) == JB_OK) iax_event_free(frame.data); jb_destroy(session->jb); }#endif free(session); return; } prev = cur; cur = cur->next; }}static int iax_send_lagrp(struct iax_session *session, unsigned int ts);static int iax_send_pong(struct iax_session *session, unsigned int ts);static struct iax_event *handle_event(struct iax_event *event){ /* We have a candidate event to be delievered. Be sure the session still exists. */ if (event) { if (iax_session_valid(event->session)) { /* Lag requests are never actually sent to the client, but other than that are handled as normal packets */ switch(event->etype) { case IAX_EVENT_REJECT: case IAX_EVENT_HANGUP: /* Destroy this session -- it's no longer valid */ destroy_session(event->session); return event; case IAX_EVENT_LAGRQ: event->etype = IAX_EVENT_LAGRP; iax_send_lagrp(event->session, event->ts); iax_event_free(event); break; case IAX_EVENT_PING: event->etype = IAX_EVENT_PONG; iax_send_pong(event->session, event->ts); iax_event_free(event); break; default: return event; } } else iax_event_free(event); } return NULL;}static int iax2_vnak(struct iax_session *session){ return send_command_immediate(session, AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, session->iseqno);}int iax_send_dtmf(struct iax_session *session, char digit){ return send_command(session, AST_FRAME_DTMF, digit, 0, NULL, 0, -1);}int iax_send_voice(struct iax_session *session, int format, char *data, int datalen, int samples){ /* Send a (possibly compressed) voice frame */ if (!session->quelch) return send_command_samples(session, AST_FRAME_VOICE, format, 0, data, datalen, -1, samples); return 0;}int iax_send_cng(struct iax_session *session, int level, char *data, int datalen){ session->notsilenttx = 0; return send_command(session, AST_FRAME_CNG, level, 0, data, datalen, -1);}int iax_send_image(struct iax_session *session, int format, char *data, int datalen){ /* Send an image frame */ return send_command(session, AST_FRAME_IMAGE, format, 0, data, datalen, -1);}int iax_register(struct iax_session *session, char *server, char *peer, char *secret, int refresh){ /* Send a registration request */ char tmp[256]; char *p; int res; int portno = IAX_DEFAULT_PORTNO; struct iax_ie_data ied; struct hostent *hp; tmp[255] = '\0'; strncpy(tmp, server, sizeof(tmp) - 1); p = strchr(tmp, ':'); if (p) { *p = '\0'; portno = atoi(p+1); } memset(&ied, 0, sizeof(ied)); if (secret) strncpy(session->secret, secret, sizeof(session->secret) - 1); else strcpy(session->secret, ""); /* Connect first */ hp = gethostbyname(tmp); if (!hp) { snprintf(iax_errstr, sizeof(iax_errstr), "Invalid hostname: %s", tmp); 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; strncpy(session->username, peer, sizeof(session->username) - 1); session->refresh = refresh; iax_ie_append_str(&ied, IAX_IE_USERNAME, peer); iax_ie_append_short(&ied, IAX_IE_REFRESH, refresh); res = send_command(session, AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); return res;}int iax_reject(struct iax_session *session, char *reason){ struct iax_ie_data ied; memset(&ied, 0, sizeof(ied)); iax_ie_append_str(&ied, IAX_IE_CAUSE, reason ? reason : "Unspecified"); return send_command_final(session, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);}int iax_hangup(struct iax_session *session, char *byemsg){ struct iax_ie_data ied; memset(&ied, 0, sizeof(ied)); iax_ie_append_str(&ied, IAX_IE_CAUSE, byemsg ? byemsg : "Normal clearing"); return send_command_final(session, AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);}int iax_sendurl(struct iax_session *session, char *url){ return send_command(session, AST_FRAME_HTML, AST_HTML_URL, 0, url, strlen(url), -1);}int iax_ring_announce(struct iax_session *session){ return send_command(session, AST_FRAME_CONTROL, AST_CONTROL_RINGING, 0, NULL, 0, -1);}int iax_lag_request(struct iax_session *session){ return send_command(session, AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);}int iax_busy(struct iax_session *session){ return send_command(session, AST_FRAME_CONTROL, AST_CONTROL_BUSY, 0, NULL, 0, -1);}int iax_accept(struct iax_session *session, int format){ struct iax_ie_data ied; memset(&ied, 0, sizeof(ied)); iax_ie_append_int(&ied, IAX_IE_FORMAT, format); return send_command(session, AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied.buf, ied.pos, -1);}int iax_answer(struct iax_session *session){ return send_command(session, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);}int iax_load_complete(struct iax_session *session){ return send_command(session, AST_FRAME_HTML, AST_HTML_LDCOMPLETE, 0, NULL, 0, -1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -