📄 iax.c
字号:
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) { jb_frame frame; if (prev) prev->next = session->next; else sessions = session->next; while(jb_getall(session->jb,&frame) == JB_OK) iax_event_free((struct iax_event *)frame.data); jb_destroy(session->jb); 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 ( event->etype == IAX_EVENT_NULL ) return 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) { /* the user on the outside may need to look at the session so we will not free it here anymore we will test for hangup event in iax_event_free and do it there. */ 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; case IAX_EVENT_POKE: event->etype = IAX_EVENT_PONG; iax_send_pong(event->session, event->ts); destroy_session(event->session); iax_event_free(event); break; default: return event; } } else iax_event_free(event); } return NULL;}static int iax2_vnak(struct iax_session *session){ /* send vnak just once for a given sequence number */ if ( (unsigned char)(session->lastvnak - session->iseqno) < 128 ) { return 0; } session->lastvnak = session->iseqno; 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){#ifdef USE_VOICE_TS_PREDICTION session->notsilenttx = 0;#endif 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 iax_send_video(struct iax_session *session, int format, unsigned char *data, int datalen, int fullframe){ if (!session->quelch) { int res = send_command_video(session, AST_FRAME_VIDEO, format, 0, data, datalen, -1, fullframe); return res; } return 0;}int iax_send_video_trunk(struct iax_session *session, int format, char *data, int datalen, int fullframe, int ntrunk){ static int my_lastts = 0; if ( ntrunk == 0 ) my_lastts = calc_timestamp(session, 0, NULL); if ( !session->quelch ) { return send_command_video(session, AST_FRAME_VIDEO, format, my_lastts, (unsigned char *)data, datalen, -1, fullframe); } return 0;}int iax_video_bypass_jitter(struct iax_session *s, int mode){ video_bypass_jitterbuffer = mode; return 0;}int iax_register(struct iax_session *session, const char *server, const char *peer, const 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; iax_sched_del(NULL, NULL, send_ping, (void *) session, 1); 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, (unsigned char *)url, (int)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_congestion(struct iax_session *session){ return send_command(session, AST_FRAME_CONTROL, AST_CONTROL_CONGESTION, 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, const char *url, int link){ return send_command(session, AST_FRAME_HTML, link ? AST_HTML_LINKURL : AST_HTML_URL, 0, (unsigned char *)url, (int)strlen(url), -1);}int iax_send_text(struct iax_session *session, const char *text){ return send_command(session, AST_FRAME_TEXT, 0, 0, (unsigned char *)text, (int)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; jb_info stats; memset(&ied, 0, sizeof(ied)); 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, (unsigned short)(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); 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; memset(&ied, 0, sizeof(ied)); if ((methods & IAX_AUTH_MD5) && challenge) { MD5Init(&md5); MD5Update(&md5, (const unsigned char *) challenge, (unsigned int)strlen(challenge)); MD5Update(&md5, (const unsigned char *) password, (unsigned int)strlen(password)); MD5Final((unsigned char *) reply, &md5); memset(realreply, 0, sizeof(realreply)); convert_reply(realreply, (unsigned char *) reply); iax_ie_append_str(&ied, IAX_IE_MD5_RESULT, realreply); } else { iax_ie_append_str(&ied, IAX_IE_MD5_RESULT, password); } return send_command(session, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);}static int iax_regauth_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; memset(&ied, 0, sizeof(ied)); iax_ie_append_str(&ied, IAX_IE_USERNAME, session->username); iax_ie_append_short(&ied, IAX_IE_REFRESH, session->refresh); if ((methods & IAX_AUTHMETHOD_MD5) && challenge) { MD5Init(&md5); MD5Update(&md5, (const unsigned char *) challenge, (unsigned int)strlen(challenge)); MD5Update(&md5, (const unsigned char *) password, (unsigned int)strlen(password)); MD5Final((unsigned char *) reply, &md5); memset(realreply, 0, sizeof(realreply)); convert_reply(realreply, (unsigned char *) reply); iax_ie_append_str(&ied, IAX_IE_MD5_RESULT, realreply); } else { iax_ie_append_str(&ied, IAX_IE_MD5_RESULT, password); } return send_command(session, AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);}int iax_dial(struct iax_session *session, char *number){ struct iax_ie_data ied; memset(&ied, 0, sizeof(ied)); iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, number); return send_command(session, AST_FRAME_IAX, IAX_COMMAND_DIAL, 0, ied.buf, ied.pos, -1);}int iax_quelch(struct iax_session *session){ return send_command(session, AST_FRAME_IAX, IAX_COMMAND_QUELCH, 0, NULL, 0, -1);}int iax_unquelch(struct iax_session *session){ return send_command(session, AST_FRAME_IAX, IAX_COMMAND_UNQUELCH, 0, NULL, 0, -1);}int iax_dialplan_request(struct iax_session *session, char *number){ struct iax_ie_data ied; memset(&ied, 0, sizeof(ied)); iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, number); return send_command(session, AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);}static inline int which_bit(unsigned int i){ char x; for(x = 0; x < 32; x++) { if ((1U << x) == i) { return x + 1; } } return 0;}char iax_pref_codec_add(struct iax_session *session, unsigned int format){ int diff = (int) 'A'; session->codec_order[session->codec_order_len++] = (which_bit(format)) + diff; session->codec_order[session->codec_order_len] = '\0'; return session->codec_order[session->codec_order_len-1];}void iax_pref_codec_del(struct iax_session *session, unsigned int format){ int diff = (int) 'A'; int x; char old[32]; char remove = which_bit(format) + diff; strncpy(old, session->codec_order, sizeof(old)); session->codec_order_len = 0; for (x = 0; x < (int) strlen(old); x++) { if (old[x] != remove) { session->codec_order[session->codec_order_len++] = old[x]; } } session->codec_order[session->codec_order_len] = '\0';}int iax_pref_codec_get(struct iax_session *session, unsigned int *array, int len){ int diff = (int) 'A'; int x; for (x = 0; x < session->codec_order_len && x < len; x++) { array[x] = (1 << (session->codec_order[x] - diff - 1)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -