📄 iax.c
字号:
fh->csub = AST_HTML_LDCOMPLETE; iax_reliable_xmit(&f); break; case IAX_EVENT_VOICE: ts = ntohl(fh->ts); if (event->event.voice.datalen > left) { strcpy(iax_errstr, "Voice frame too large\n"); } /* Don't do anything if we're quelching audio */ if (session->quelch) break; /* If the voice format is the same, and the top of our timestamp is the same, then we stick with a mini-frame, otherwise we send a large frame */ if ((event->event.voice.format == session->svoiceformat) && ((session->lastvoicets & 0xFFFF0000) == (ts & 0xFFFF0000))) { /* We can send a mini-frame since we're using the same voice format and don't need a timestamp update. */ f.datalen += event->event.voice.datalen; f.datalen -= sizeof(struct iax_full_hdr) - sizeof(struct iax_mini_hdr); memcpy(mh->data, event->event.voice.data, event->event.voice.datalen); mh->ts = htons((short)(ts & 0x0000FFFF)); mh->callno = htons((short)session->callno); session->lastvoicets = ts; iax_xmit_frame(&f); } else { /* Send a full frame for our voice frame */ fh->type = AST_FRAME_VOICE; fh->csub = compress_subclass(event->event.voice.format); session->svoiceformat = event->event.voice.format; fh->seqno = htons((short) session->oseqno++); memcpy(fh->data, event->event.voice.data, event->event.voice.datalen); f.datalen += event->event.voice.datalen; session->lastvoicets = ts; iax_reliable_xmit(&f); } break; case IAX_EVENT_IMAGE: fh->type = AST_FRAME_IMAGE; fh->csub = compress_subclass(event->event.image.format); fh->seqno = htons((short) session->oseqno++); memcpy(fh->data, event->event.image.data, event->event.image.datalen); f.datalen += event->event.image.datalen; iax_reliable_xmit(&f); break; case IAX_EVENT_DIAL: fh->type = AST_FRAME_IAX; fh->seqno = htons(session->oseqno++); fh->csub = IAX_COMMAND_DIAL; MYSNPRINTF "%s", event->event.dial.number); f.datalen += strlen(requeststr); iax_reliable_xmit(&f); break; case IAX_EVENT_DPREQ: fh->type = AST_FRAME_IAX; fh->seqno = htons(session->oseqno++); fh->csub = IAX_COMMAND_DPREQ; MYSNPRINTF "%s", event->event.dpreq.number); f.datalen += strlen(requeststr); iax_reliable_xmit(&f); break; case IAX_EVENT_TXREPLY: /* Transmit an IAX Transmit request */ fh->type = AST_FRAME_IAX; fh->seqno = htons(0); fh->csub = IAX_COMMAND_TXCNT; fh->dcallno = htons((short)session->transfercallno); f.transferpacket = 1; iax_reliable_xmit(&f); break; case IAX_EVENT_TXREJECT: /* Reject the IAX transfer -- the peer couldn't see us or we couldn't see them */ fh->type = AST_FRAME_IAX; fh->seqno = htons(session->oseqno++); fh->csub = IAX_COMMAND_TXREJ; iax_reliable_xmit(&f); break; case IAX_EVENT_TXACCEPT: /* Accept a connect request */ fh->type = AST_FRAME_IAX; fh->seqno = htons(0); fh->csub = IAX_COMMAND_TXACC; fh->dcallno = htons((short)session->transfercallno); f.transferpacket = 1; f.retries = -1; iax_xmit_frame(&f); break; case IAX_EVENT_TXREADY: /* We've been accepted on the transfer. Notify the gateway that we're ready */ fh->type = AST_FRAME_IAX; fh->seqno = htons(session->oseqno++); fh->csub = IAX_COMMAND_TXREADY; iax_reliable_xmit(&f); break; case IAX_EVENT_QUELCH: fh->type = AST_FRAME_IAX; fh->seqno = htons(session->oseqno++); fh->csub = IAX_COMMAND_QUELCH; iax_reliable_xmit(&f); break; case IAX_EVENT_UNQUELCH: fh->type = AST_FRAME_IAX; fh->seqno = htons(session->oseqno++); fh->csub = IAX_COMMAND_UNQUELCH; iax_reliable_xmit(&f); break; default: DEBU(G "Don't know how to send a %d event\n", event->etype); IAXERROR "Unknown event type.\n"); } return 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; free(session); return; } prev = cur; cur = cur->next; }}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_REGREP: 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_do_event(event->session, event); iax_event_free(event); break; case IAX_EVENT_PING: event->etype = IAX_EVENT_PONG; iax_do_event(event->session, event); iax_event_free(event); break; default: return event; } } } return NULL;}int iax_send_dtmf(struct iax_session *session, char digit){ /* Send a DTMF digit */ struct iax_event e; e.etype = IAX_EVENT_DTMF; e.event.dtmf.digit = digit; return iax_do_event(session, &e);}int iax_send_voice(struct iax_session *session, int format, char *data, int datalen){ /* Send a (possibly compressed) voice frame */ struct iax_event e; e.etype = IAX_EVENT_VOICE; e.event.voice.format = format; e.event.voice.data = data; e.event.voice.datalen = datalen; return iax_do_event(session, &e);}int iax_send_image(struct iax_session *session, int format, char *data, int datalen){ /* Send an image frame */ struct iax_event e; e.etype = IAX_EVENT_IMAGE; e.event.image.format = format; e.event.image.data = data; e.event.image.datalen = datalen; return iax_do_event(session, &e);}int iax_register(struct iax_session *session, char *server, char *peer, char *secret, int refresh){ /* Send a registration request */ struct iax_event e; char *tmp = strdup(server); int res; if (!tmp) return -1; e.etype = IAX_EVENT_REGREQ; e.event.regrequest.server = tmp; if (strchr(e.event.regrequest.server, ':')) { strtok(e.event.regrequest.server, ":"); e.event.regrequest.portno = atoi(strtok(NULL, ":")); } else e.event.regrequest.portno = IAX_DEFAULT_PORTNO; e.event.regrequest.peer = peer; e.event.regrequest.secret = secret; e.event.regrequest.refresh = refresh; res = iax_do_event(session, &e); free(tmp); return res;}int iax_reject(struct iax_session *session, char *reason){ struct iax_event e; e.etype = IAX_EVENT_REJECT; e.event.reject.reason = reason; return iax_do_event(session, &e);}int iax_hangup(struct iax_session *session, char *byemsg){ struct iax_event e; e.etype = IAX_EVENT_HANGUP; e.event.hangup.byemsg = byemsg; return iax_do_event(session, &e);}int iax_sendurl(struct iax_session *session, char *url){ struct iax_event e; e.etype = IAX_EVENT_URL; e.event.url.url = url; return iax_do_event(session, &e);}int iax_ring_announce(struct iax_session *session){ struct iax_event e; e.etype = IAX_EVENT_RINGA; return iax_do_event(session, &e);}int iax_lag_request(struct iax_session *session){ struct iax_event e; e.etype = IAX_EVENT_LAGRQ; return iax_do_event(session, &e);}int iax_busy(struct iax_session *session){ struct iax_event e; e.etype = IAX_EVENT_BUSY; return iax_do_event(session, &e);}int iax_accept(struct iax_session *session){ struct iax_event e; e.etype = IAX_EVENT_ACCEPT; return iax_do_event(session, &e);}int iax_answer(struct iax_session *session){ struct iax_event e; e.etype = IAX_EVENT_ANSWER; return iax_do_event(session, &e);}int iax_load_complete(struct iax_session *session){ struct iax_event e; e.etype = IAX_EVENT_LDCOMPLETE; return iax_do_event(session, &e);}int iax_send_url(struct iax_session *session, char *url, int link){ struct iax_event e; e.etype = IAX_EVENT_URL; e.event.url.link = link; e.event.url.url = url; return iax_do_event(session, &e);}int iax_send_text(struct iax_session *session, char *text){ struct iax_event e; e.etype = IAX_EVENT_TEXT; snprintf(e.event.text.text, sizeof(e.event.text.text), "%s", text); return iax_do_event(session, &e);}int iax_send_unlink(struct iax_session *session){ struct iax_event e; e.etype = IAX_EVENT_UNLINK; return iax_do_event(session, &e);}int iax_send_link_reject(struct iax_session *session){ struct iax_event e; e.etype = IAX_EVENT_LINKREJECT; return iax_do_event(session, &e);}int iax_auth_reply(struct iax_session *session, char *password, char *challenge, int methods){ struct iax_event e; char reply[16]; struct MD5Context md5; char realreply[256]; e.etype = IAX_EVENT_AUTHRP; if ((methods & IAX_AUTHMETHOD_MD5) && challenge) { e.event.authreply.authmethod = IAX_AUTHMETHOD_MD5; 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); e.event.authreply.reply = realreply; } else { e.event.authreply.authmethod = IAX_AUTHMETHOD_PLAINTEXT; e.event.authreply.reply = password; } return iax_do_event(session, &e);}void iax_set_formats(int fmt){ sformats = fmt;}int iax_dial(struct iax_session *session, char *number){ struct iax_event e; e.etype = IAX_EVENT_DIAL; e.event.dial.number = number; return iax_do_event(session, &e);}int iax_quelch(struct iax_session *session){ struct iax_event e; e.etype = IAX_EVENT_QUELCH; return iax_do_event(session, &e);}int iax_unquelch(struct iax_session *session){ struct iax_event e; e.etype = IAX_EVENT_UNQUELCH; return iax_do_event(session, &e);}int iax_dialplan_request(struct iax_session *session, char *number){ struct iax_event e; e.etype = IAX_EVENT_DPREQ; e.event.dpreq.number = number; return iax_do_event(session, &e);}int iax_call(struct iax_session *session, char *callerid, char *ich, char *lang, int wait){ struct iax_event e; char *tmp = ich ? strdup(ich) : NULL; char *part1, *part2; int res; /* We start by parsing up the temporary variable which is of the form of: [user@]peer[:portno][/exten[@context]] */ if (!tmp) { IAXERROR "Invalid IAX Call Handle\n"); DEBU(G "Invalid IAX Call Handle\n"); return -1; } e.event.connect.callerid = callerid; e.event.connect.formats = sformats; e.event.connect.version = IAX_PROTO_VERSION; e.event.connect.language = lang; e.etype = IAX_EVENT_CONNECT; /* 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, '@')) { e.event.connect.username = strtok(part1, "@"); e.event.connect.hostname = strtok(NULL, "@"); } else { e.event.connect.username = NULL; e.event.connect.hostname = part1; } if (e.event.connect.username && strchr(e.event.connect.username, ':')) { e.event.connect.username = strtok(e.event.connect.username, ":"); e.event.connect.secret = strtok(NULL, ":"); } if (strchr(e.event.connect.hostname, ':')) { strtok(e.event.connect.hostname, ":"); e.event.connect.portno = atoi(strtok(NULL, ":")); } else { e.event.connect.portno = IAX_DEFAULT_PORTNO; } if (part2) { e.event.connect.exten = strtok(part2, "@"); e.event.connect.dnid = e.event.connect.exten; e.event.connect.context = strtok(NULL, "@"); } else { e.event.connect.exten = NULL; e.event.connect.dnid = NULL; e.event.connect.context = NULL; } res = iax_do_event(session, &e); free(tmp); 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) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -