📄 iax.c
字号:
}
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, unsigned 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, unsigned 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, unsigned char *data, int datalen)
{
/* Send an image frame */
return send_command(session, AST_FRAME_IMAGE, format, 0, data, datalen, -1);
}
int tiax_send_pfc_poke(struct iax_session *session, char *server)
{
return 0;
}
int tiax_send_iep(struct iax_session *session,char *server, char *inviter,char *invitee)
{
/* 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));
/* 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, (unsigned char *) peer);
// iax_ie_append_short(&ied, IAX_IE_REFRESH, refresh);
if(inviter)
iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, (unsigned char *) inviter);
if(invitee)
iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, (unsigned char *) invitee);
res = send_command(session, AST_FRAME_IAX, IAX_COMMAND_IEP, 0, ied.buf, ied.pos, -1);
return res;
}
int tiax_send_nattrv(struct iax_session *session, char *server, char *callerid, 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));
/* 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, (unsigned char *) peer);
iax_ie_append_short(&ied, IAX_IE_REFRESH, refresh);
if(callerid)
iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, (unsigned char *) callerid);
res = send_command(session, AST_FRAME_IAX, IAX_COMMAND_NATTRV, 0, ied.buf, ied.pos, -1);
return res;
}
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);
session->peeraddr.sin_addr.s_addr = inet_addr(tmp);
//return -1;
}
else
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, (unsigned char *) 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_register_release(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);
session->peeraddr.sin_addr.s_addr = inet_addr(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, (unsigned char *) peer);
iax_ie_append_short(&ied, IAX_IE_REFRESH, refresh);
res = send_command(session, AST_FRAME_IAX, IAX_COMMAND_REGREL, 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 ? (unsigned char *) reason : (unsigned char *) "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;
iax_sched_del(NULL, NULL, send_ping, (void *) session, 1);
memset(&ied, 0, sizeof(ied));
iax_ie_append_str(&ied, IAX_IE_CAUSE, byemsg ? (unsigned char *) byemsg : (unsigned char *) "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, (unsigned char *) 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);
}
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, (unsigned char *) url, strlen(url), -1);
}
int iax_send_text(struct iax_session *session, char *text)
{
return send_command(session, AST_FRAME_TEXT, 0, 0, (unsigned char *) text, strlen(text) + 1, -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.losspct/1000)) << 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -