diff options
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_agent.c | 30 | ||||
-rw-r--r-- | channels/chan_alsa.c | 2 | ||||
-rw-r--r-- | channels/chan_features.c | 26 | ||||
-rw-r--r-- | channels/chan_h323.c | 14 | ||||
-rw-r--r-- | channels/chan_iax2.c | 15 | ||||
-rw-r--r-- | channels/chan_jingle.c | 14 | ||||
-rw-r--r-- | channels/chan_local.c | 27 | ||||
-rw-r--r-- | channels/chan_mgcp.c | 16 | ||||
-rw-r--r-- | channels/chan_misdn.c | 14 | ||||
-rw-r--r-- | channels/chan_oss.c | 13 | ||||
-rw-r--r-- | channels/chan_phone.c | 19 | ||||
-rw-r--r-- | channels/chan_sip.c | 46 | ||||
-rw-r--r-- | channels/chan_skinny.c | 15 | ||||
-rw-r--r-- | channels/chan_vpb.cc | 55 | ||||
-rw-r--r-- | channels/chan_zap.c | 155 | ||||
-rw-r--r-- | channels/iax2-parser.c | 9 |
16 files changed, 341 insertions, 129 deletions
diff --git a/channels/chan_agent.c b/channels/chan_agent.c index 0a9b8906a..4eeffe99c 100644 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -238,7 +238,8 @@ static AST_LIST_HEAD_STATIC(agents, agent_pvt); /*!< Holds the list of agents (l static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause); static int agent_devicestate(void *data); static void agent_logoff_maintenance(struct agent_pvt *p, char *loginchan, long logintime, const char *uniqueid, char *logcommand); -static int agent_digit(struct ast_channel *ast, char digit); +static int agent_digit_begin(struct ast_channel *ast, char digit); +static int agent_digit_end(struct ast_channel *ast, char digit); static int agent_call(struct ast_channel *ast, char *dest, int timeout); static int agent_hangup(struct ast_channel *ast); static int agent_answer(struct ast_channel *ast); @@ -258,7 +259,8 @@ static const struct ast_channel_tech agent_tech = { .capabilities = -1, .requester = agent_request, .devicestate = agent_devicestate, - .send_digit = agent_digit, + .send_digit_begin = agent_digit_begin, + .send_digit_end = agent_digit_end, .call = agent_call, .hangup = agent_hangup, .answer = agent_answer, @@ -491,7 +493,8 @@ static struct ast_frame *agent_read(struct ast_channel *ast) } } break; - case AST_FRAME_DTMF: + case AST_FRAME_DTMF_BEGIN: + case AST_FRAME_DTMF_END: if (!p->acknowledged && (f->subclass == '#')) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name); @@ -511,7 +514,9 @@ static struct ast_frame *agent_read(struct ast_channel *ast) ast_frfree(f); f = &ast_null_frame; } - break; + default: + /* pass everything else on through */ + break; } } @@ -603,15 +608,22 @@ static int agent_indicate(struct ast_channel *ast, int condition, const void *da return res; } -static int agent_digit(struct ast_channel *ast, char digit) +static int agent_digit_begin(struct ast_channel *ast, char digit) { struct agent_pvt *p = ast->tech_pvt; int res = -1; ast_mutex_lock(&p->lock); - if (p->chan) - res = p->chan->tech->send_digit(p->chan, digit); - else - res = 0; + ast_senddigit_begin(p->chan, digit); + ast_mutex_unlock(&p->lock); + return res; +} + +static int agent_digit_end(struct ast_channel *ast, char digit) +{ + struct agent_pvt *p = ast->tech_pvt; + int res = -1; + ast_mutex_lock(&p->lock); + ast_senddigit_end(p->chan, digit); ast_mutex_unlock(&p->lock); return res; } diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c index 5a4d6276f..4237ba800 100644 --- a/channels/chan_alsa.c +++ b/channels/chan_alsa.c @@ -203,7 +203,7 @@ static const struct ast_channel_tech alsa_tech = { .description = tdesc, .capabilities = AST_FORMAT_SLINEAR, .requester = alsa_request, - .send_digit = alsa_digit, + .send_digit_end = alsa_digit, .send_text = alsa_text, .hangup = alsa_hangup, .answer = alsa_answer, diff --git a/channels/chan_features.c b/channels/chan_features.c index d1feadbea..66b6da3e3 100644 --- a/channels/chan_features.c +++ b/channels/chan_features.c @@ -95,7 +95,8 @@ static AST_LIST_HEAD_STATIC(features, feature_pvt); #define SUB_THREEWAY 2 /* Three-way call */ static struct ast_channel *features_request(const char *type, int format, void *data, int *cause); -static int features_digit(struct ast_channel *ast, char digit); +static int features_digit_begin(struct ast_channel *ast, char digit); +static int features_digit_end(struct ast_channel *ast, char digit); static int features_call(struct ast_channel *ast, char *dest, int timeout); static int features_hangup(struct ast_channel *ast); static int features_answer(struct ast_channel *ast); @@ -109,7 +110,8 @@ static const struct ast_channel_tech features_tech = { .description = tdesc, .capabilities = -1, .requester = features_request, - .send_digit = features_digit, + .send_digit_begin = features_digit_begin, + .send_digit_end = features_digit_end, .call = features_call, .hangup = features_hangup, .answer = features_answer, @@ -300,7 +302,7 @@ static int features_indicate(struct ast_channel *ast, int condition, const void return res; } -static int features_digit(struct ast_channel *ast, char digit) +static int features_digit_begin(struct ast_channel *ast, char digit) { struct feature_pvt *p = ast->tech_pvt; int res = -1; @@ -310,7 +312,23 @@ static int features_digit(struct ast_channel *ast, char digit) ast_mutex_lock(&p->lock); x = indexof(p, ast, 0); if (!x && p->subchan) - res = ast_senddigit(p->subchan, digit); + res = ast_senddigit_begin(p->subchan, digit); + ast_mutex_unlock(&p->lock); + + return res; +} + +static int features_digit_end(struct ast_channel *ast, char digit) +{ + struct feature_pvt *p = ast->tech_pvt; + int res = -1; + int x; + + /* Queue up a frame representing the indication as a control frame */ + ast_mutex_lock(&p->lock); + x = indexof(p, ast, 0); + if (!x && p->subchan) + res = ast_senddigit_end(p->subchan, digit); ast_mutex_unlock(&p->lock); return res; } diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 6b956e517..dc498a2d9 100644 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -220,7 +220,8 @@ static int restart_monitor(void); static int h323_do_reload(void); static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause); -static int oh323_digit(struct ast_channel *c, char digit); +static int oh323_digit_begin(struct ast_channel *c, char digit); +static int oh323_digit_end(struct ast_channel *c, char digit); static int oh323_call(struct ast_channel *c, char *dest, int timeout); static int oh323_hangup(struct ast_channel *c); static int oh323_answer(struct ast_channel *c); @@ -235,7 +236,8 @@ static const struct ast_channel_tech oh323_tech = { .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1), .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER, .requester = oh323_request, - .send_digit = oh323_digit, + .send_digit_begin = oh323_digit_begin, + .send_digit_end = oh323_digit_end, .call = oh323_call, .hangup = oh323_hangup, .answer = oh323_answer, @@ -381,11 +383,17 @@ static void oh323_destroy(struct oh323_pvt *pvt) ast_mutex_unlock(&iflock); } +static int oh323_digit_begin(struct ast_channel *chan, char digit) +{ + /* XXX Implement me, plz, kthx */ + return 0; +} + /** * Send (play) the specified digit to the channel. * */ -static int oh323_digit(struct ast_channel *c, char digit) +static int oh323_digit_end(struct ast_channel *c, char digit) { struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; char *token; diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 1d404c3fb..60841e0ae 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -776,7 +776,8 @@ static int expire_registry(void *data); static int iax2_answer(struct ast_channel *c); static int iax2_call(struct ast_channel *c, char *dest, int timeout); static int iax2_devicestate(void *data); -static int iax2_digit(struct ast_channel *c, char digit); +static int iax2_digit_begin(struct ast_channel *c, char digit); +static int iax2_digit_end(struct ast_channel *c, char digit); static int iax2_do_register(struct iax2_registry *reg); static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan); static int iax2_hangup(struct ast_channel *c); @@ -809,7 +810,8 @@ static const struct ast_channel_tech iax2_tech = { .properties = AST_CHAN_TP_WANTSJITTER, .requester = iax2_request, .devicestate = iax2_devicestate, - .send_digit = iax2_digit, + .send_digit_begin = iax2_digit_begin, + .send_digit_end = iax2_digit_end, .send_text = iax2_sendtext, .send_image = iax2_sendimage, .send_html = iax2_sendhtml, @@ -2379,9 +2381,14 @@ static int iax2_transmit(struct iax_frame *fr) -static int iax2_digit(struct ast_channel *c, char digit) +static int iax2_digit_begin(struct ast_channel *c, char digit) { - return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF, digit, 0, NULL, 0, -1); + return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1); +} + +static int iax2_digit_end(struct ast_channel *c, char digit) +{ + return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1); } static int iax2_sendtext(struct ast_channel *c, const char *text) diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c index b3d7ea68a..a44b42085 100644 --- a/channels/chan_jingle.c +++ b/channels/chan_jingle.c @@ -171,7 +171,8 @@ AST_MUTEX_DEFINE_STATIC(jinglelock); /*!< Protect the interface list (of jingle_ /* Forward declarations */ static struct ast_channel *jingle_request(const char *type, int format, void *data, int *cause); -static int jingle_digit(struct ast_channel *ast, char digit); +static int jingle_digit_begin(struct ast_channel *ast, char digit); +static int jingle_digit_end(struct ast_channel *ast, char digit); static int jingle_call(struct ast_channel *ast, char *dest, int timeout); static int jingle_hangup(struct ast_channel *ast); static int jingle_answer(struct ast_channel *ast); @@ -194,7 +195,8 @@ static const struct ast_channel_tech jingle_tech = { .description = "Jingle Channel Driver", .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1), .requester = jingle_request, - .send_digit = jingle_digit, + .send_digit_begin = jingle_digit_begin, + .send_digit_end = jingle_digit_end, .bridge = ast_rtp_bridge, .call = jingle_call, .hangup = jingle_hangup, @@ -1181,7 +1183,13 @@ static int jingle_indicate(struct ast_channel *ast, int condition, const void *d return res; } -static int jingle_digit(struct ast_channel *ast, char digit) +static int jingle_digit_begin(struct ast_channel *chan, char digit) +{ + /* XXX Does jingle have a concept of the length of a dtmf digit ? */ + return 0; +} + +static int jingle_digit_end(struct ast_channel *ast, char digit) { struct jingle_pvt *p = ast->tech_pvt; struct jingle *client = p->parent; diff --git a/channels/chan_local.c b/channels/chan_local.c index a9b0582f9..fec9c6273 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -67,7 +67,8 @@ static const char tdesc[] = "Local Proxy Channel Driver"; #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0) static struct ast_channel *local_request(const char *type, int format, void *data, int *cause); -static int local_digit(struct ast_channel *ast, char digit); +static int local_digit_begin(struct ast_channel *ast, char digit); +static int local_digit_end(struct ast_channel *ast, char digit); static int local_call(struct ast_channel *ast, char *dest, int timeout); static int local_hangup(struct ast_channel *ast); static int local_answer(struct ast_channel *ast); @@ -85,7 +86,8 @@ static const struct ast_channel_tech local_tech = { .description = tdesc, .capabilities = -1, .requester = local_request, - .send_digit = local_digit, + .send_digit_begin = local_digit_begin, + .send_digit_end = local_digit_end, .call = local_call, .hangup = local_hangup, .answer = local_answer, @@ -327,11 +329,11 @@ static int local_indicate(struct ast_channel *ast, int condition, const void *da return res; } -static int local_digit(struct ast_channel *ast, char digit) +static int local_digit_begin(struct ast_channel *ast, char digit) { struct local_pvt *p = ast->tech_pvt; int res = -1; - struct ast_frame f = { AST_FRAME_DTMF, }; + struct ast_frame f = { AST_FRAME_DTMF_BEGIN, }; int isoutbound; ast_mutex_lock(&p->lock); @@ -339,6 +341,23 @@ static int local_digit(struct ast_channel *ast, char digit) f.subclass = digit; res = local_queue_frame(p, isoutbound, &f, ast); ast_mutex_unlock(&p->lock); + + return res; +} + +static int local_digit_end(struct ast_channel *ast, char digit) +{ + struct local_pvt *p = ast->tech_pvt; + int res = -1; + struct ast_frame f = { AST_FRAME_DTMF_END, }; + int isoutbound; + + ast_mutex_lock(&p->lock); + isoutbound = IS_OUTBOUND(ast, p); + f.subclass = digit; + res = local_queue_frame(p, isoutbound, &f, ast); + ast_mutex_unlock(&p->lock); + return res; } diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index c77b8a61e..05ab81edf 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -427,7 +427,8 @@ static struct ast_frame *mgcp_read(struct ast_channel *ast); static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame); static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen); static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); -static int mgcp_senddigit(struct ast_channel *ast, char digit); +static int mgcp_senddigit_begin(struct ast_channel *ast, char digit); +static int mgcp_senddigit_end(struct ast_channel *ast, char digit); static int mgcp_devicestate(void *data); static const struct ast_channel_tech mgcp_tech = { @@ -444,7 +445,8 @@ static const struct ast_channel_tech mgcp_tech = { .write = mgcp_write, .indicate = mgcp_indicate, .fixup = mgcp_fixup, - .send_digit = mgcp_senddigit, + .send_digit_begin = mgcp_senddigit_begin, + .send_digit_end = mgcp_senddigit_end, .bridge = ast_rtp_bridge, }; @@ -1221,7 +1223,13 @@ static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) return 0; } -static int mgcp_senddigit(struct ast_channel *ast, char digit) +static int mgcp_senddigit_begin(struct ast_channel *ast, char digit) +{ + /* Let asterisk play inband indications */ + return -1; +} + +static int mgcp_senddigit_end(struct ast_channel *ast, char digit) { struct mgcp_subchannel *sub = ast->tech_pvt; char tmp[4]; @@ -1233,7 +1241,7 @@ static int mgcp_senddigit(struct ast_channel *ast, char digit) ast_mutex_lock(&sub->lock); transmit_notify_request(sub, tmp); ast_mutex_unlock(&sub->lock); - return -1; + return -1; /* Return non-zero so that Asterisk will stop the inband indications */ } /*! diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 9631a8cb5..201d38c39 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -2006,7 +2006,13 @@ static int misdn_answer(struct ast_channel *ast) return 0; } -static int misdn_digit(struct ast_channel *ast, char digit ) +static int misdn_digit_begin(struct ast_channel *chan, char digit) +{ + /* XXX Modify this callback to support Asterisk controlling the length of DTMF */ + return 0; +} + +static int misdn_digit_end(struct ast_channel *ast, char digit ) { struct chan_list *p; @@ -2983,7 +2989,8 @@ static struct ast_channel_tech misdn_tech = { .description="Channel driver for mISDN Support (Bri/Pri)", .capabilities= AST_FORMAT_ALAW , .requester=misdn_request, - .send_digit=misdn_digit, + .send_digit_begin=misdn_digit_begin, + .send_digit_end=misdn_digit_end, .call=misdn_call, .bridge=misdn_bridge, .hangup=misdn_hangup, @@ -3001,7 +3008,8 @@ static struct ast_channel_tech misdn_tech_wo_bridge = { .description="Channel driver for mISDN Support (Bri/Pri)", .capabilities=AST_FORMAT_ALAW , .requester=misdn_request, - .send_digit=misdn_digit, + .send_digit_begin=misdn_digit_begin, + .send_digit_end=misdn_digit_end, .call=misdn_call, .hangup=misdn_hangup, .answer=misdn_answer, diff --git a/channels/chan_oss.c b/channels/chan_oss.c index b2981463c..e40aacb0f 100644 --- a/channels/chan_oss.c +++ b/channels/chan_oss.c @@ -407,7 +407,8 @@ static int setformat(struct chan_oss_pvt *o, int mode); static struct ast_channel *oss_request(const char *type, int format, void *data , int *cause); -static int oss_digit(struct ast_channel *c, char digit); +static int oss_digit_begin(struct ast_channel *c, char digit); +static int oss_digit_end(struct ast_channel *c, char digit); static int oss_text(struct ast_channel *c, const char *text); static int oss_hangup(struct ast_channel *c); static int oss_answer(struct ast_channel *c); @@ -423,7 +424,8 @@ static const struct ast_channel_tech oss_tech = { .description = tdesc, .capabilities = AST_FORMAT_SLINEAR, .requester = oss_request, - .send_digit = oss_digit, + .send_digit_begin = oss_digit_begin, + .send_digit_end = oss_digit_end, .send_text = oss_text, .hangup = oss_hangup, .answer = oss_answer, @@ -757,7 +759,12 @@ static int setformat(struct chan_oss_pvt *o, int mode) /* * some of the standard methods supported by channels. */ -static int oss_digit(struct ast_channel *c, char digit) +static int oss_digit_begin(struct ast_channel *c, char digit) +{ + return 0; +} + +static int oss_digit_end(struct ast_channel *c, char digit) { /* no better use for received digits than print them */ ast_verbose( " << Console Received digit %c >> \n", digit); diff --git a/channels/chan_phone.c b/channels/chan_phone.c index 87e971abb..bb31ebae6 100644 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -161,7 +161,8 @@ static char cid_num[AST_MAX_EXTENSION]; static char cid_name[AST_MAX_EXTENSION]; static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause); -static int phone_digit(struct ast_channel *ast, char digit); +static int phone_digit_begin(struct ast_channel *ast, char digit); +static int phone_digit_end(struct ast_channel *ast, char digit); static int phone_call(struct ast_channel *ast, char *dest, int timeout); static int phone_hangup(struct ast_channel *ast); static int phone_answer(struct ast_channel *ast); @@ -177,7 +178,8 @@ static const struct ast_channel_tech phone_tech = { .description = tdesc, .capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW, .requester = phone_request, - .send_digit = phone_digit, + .send_digit_begin = phone_digit_begin, + .send_digit_end = phone_digit_end, .call = phone_call, .hangup = phone_hangup, .answer = phone_answer, @@ -192,7 +194,8 @@ static struct ast_channel_tech phone_tech_fxs = { .type = "Phone", .description = tdesc, .requester = phone_request, - .send_digit = phone_digit, + .send_digit_begin = phone_digit_begin, + .send_digit_end = phone_digit_end, .call = phone_call, .hangup = phone_hangup, .answer = phone_answer, @@ -240,7 +243,13 @@ static int phone_fixup(struct ast_channel *old, struct ast_channel *new) return 0; } -static int phone_digit(struct ast_channel *ast, char digit) +static int phone_digit_begin(struct ast_channel *chan, char digit) +{ + /* XXX Modify this callback to let Asterisk support controlling the length of DTMF */ + return 0; +} + +static int phone_digit_end(struct ast_channel *ast, char digit) { struct phone_pvt *p; int outdigit; @@ -329,7 +338,7 @@ static int phone_call(struct ast_channel *ast, char *dest, int timeout) { digit++; while (*digit) - phone_digit(ast, *digit++); + phone_digit_end(ast, *digit++); } } diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 948dc3bc6..aed8b5828 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -743,9 +743,10 @@ struct sip_auth { #define SIP_PAGE2_CALL_ONHOLD (3 << 23) /*!< Call states */ #define SIP_PAGE2_CALL_ONHOLD_ONEDIR (1 << 23) /*!< 23: One directional hold */ #define SIP_PAGE2_CALL_ONHOLD_INACTIVE (2 << 24) /*!< 24: Inactive */ +#define SIP_PAGE2_RFC2833_COMPENSATE (1 << 26) #define SIP_PAGE2_FLAGS_TO_COPY \ - (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT) + (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE) /* SIP packet flags */ #define SIP_PKT_DEBUG (1 << 0) /*!< Debug this packet */ @@ -1161,7 +1162,8 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame); static int sip_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen); static int sip_transfer(struct ast_channel *ast, const char *dest); static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); -static int sip_senddigit(struct ast_channel *ast, char digit); +static int sip_senddigit_begin(struct ast_channel *ast, char digit); +static int sip_senddigit_end(struct ast_channel *ast, char digit); /*--- Transmitting responses and requests */ static int sipsock_read(int *id, int fd, short events, void *ignore); @@ -1512,7 +1514,8 @@ static const struct ast_channel_tech sip_tech = { .indicate = sip_indicate, .transfer = sip_transfer, .fixup = sip_fixup, - .send_digit = sip_senddigit, + .send_digit_begin = sip_senddigit_begin, + .send_digit_end = sip_senddigit_end, .bridge = ast_rtp_bridge, .send_text = sip_sendtext, }; @@ -2515,12 +2518,14 @@ static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer) ast_log(LOG_DEBUG, "Setting NAT on RTP to %s\n", natflags ? "On" : "Off"); ast_rtp_setnat(r->rtp, natflags); ast_rtp_setdtmf(r->rtp, ast_test_flag(&r->flags[0], SIP_DTMF) != SIP_DTMF_INFO); + ast_rtp_setdtmfcompensate(r->rtp, ast_test_flag(&r->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); } if (r->vrtp) { if (option_debug) ast_log(LOG_DEBUG, "Setting NAT on VRTP to %s\n", natflags ? "On" : "Off"); ast_rtp_setnat(r->vrtp, natflags); ast_rtp_setdtmf(r->vrtp, 0); + ast_rtp_setdtmfcompensate(r->vrtp, 0); } if (r->udptl) { if (option_debug) @@ -3441,9 +3446,31 @@ static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) return ret; } +static int sip_senddigit_begin(struct ast_channel *ast, char digit) +{ + struct sip_pvt *p = ast->tech_pvt; + int res = 0; + + ast_mutex_lock(&p->lock); + switch (ast_test_flag(&p->flags[0], SIP_DTMF)) { + case SIP_DTMF_INBAND: + res = -1; /* Tell Asterisk to generate inband indications */ + break; + case SIP_DTMF_RFC2833: + if (p->rtp) + ast_rtp_senddigit_begin(p->rtp, digit); + break; + default: + break; + } + ast_mutex_unlock(&p->lock); + + return res; +} + /*! \brief Send DTMF character on SIP channel within one call, we're able to transmit in many methods simultaneously */ -static int sip_senddigit(struct ast_channel *ast, char digit) +static int sip_senddigit_end(struct ast_channel *ast, char digit) { struct sip_pvt *p = ast->tech_pvt; int res = 0; @@ -3455,13 +3482,14 @@ static int sip_senddigit(struct ast_channel *ast, char digit) break; case SIP_DTMF_RFC2833: if (p->rtp) - ast_rtp_senddigit(p->rtp, digit); + ast_rtp_senddigit_end(p->rtp, digit); break; case SIP_DTMF_INBAND: - res = -1; + res = -1; /* Tell Asterisk to stop inband indications */ break; } ast_mutex_unlock(&p->lock); + return res; } @@ -4049,10 +4077,12 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si return NULL; } ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_INFO); + ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); ast_rtp_settos(p->rtp, global_tos_audio); if (p->vrtp) { ast_rtp_settos(p->vrtp, global_tos_video); ast_rtp_setdtmf(p->vrtp, 0); + ast_rtp_setdtmfcompensate(p->vrtp, 0); } if (p->udptl) ast_udptl_settos(p->udptl, global_tos_audio); @@ -12835,6 +12865,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int extract_uri(p, req); /* Get the Contact URI */ build_contact(p); /* Build our contact header */ ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_INFO); + ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); if (!replace_id && gotdest) { /* No matching extension found */ if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) { @@ -14856,6 +14887,9 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask } else if (!strcasecmp(v->name, "t38pt_tcp")) { ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT_TCP); ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_T38SUPPORT_TCP); + } else if (!strcasecmp(v->name, "rfc2833compensate")) { + ast_set_flag(&mask[1], SIP_PAGE2_RFC2833_COMPENSATE); + ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RFC2833_COMPENSATE); } return res; diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index b05fabb9b..97c12455e 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -1013,7 +1013,8 @@ static struct ast_frame *skinny_read(struct ast_channel *ast); static int skinny_write(struct ast_channel *ast, struct ast_frame *frame); static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen); static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); -static int skinny_senddigit(struct ast_channel *ast, char digit); +static int skinny_senddigit_begin(struct ast_channel *ast, char digit); +static int skinny_senddigit_end(struct ast_channel *ast, char digit); static const struct ast_channel_tech skinny_tech = { .type = "Skinny", @@ -1028,7 +1029,8 @@ static const struct ast_channel_tech skinny_tech = { .write = skinny_write, .indicate = skinny_indicate, .fixup = skinny_fixup, - .send_digit = skinny_senddigit, + .send_digit_begin = skinny_senddigit_begin, + .send_digit_end = skinny_senddigit_end, /* .bridge = ast_rtp_bridge, */ }; @@ -2467,7 +2469,12 @@ static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan return 0; } -static int skinny_senddigit(struct ast_channel *ast, char digit) +static int skinny_senddigit_begin(struct ast_channel *ast, char digit) +{ + return -1; /* Start inband indications */ +} + +static int skinny_senddigit_end(struct ast_channel *ast, char digit) { #if 0 struct skinny_subchannel *sub = ast->tech_pvt; @@ -2478,7 +2485,7 @@ static int skinny_senddigit(struct ast_channel *ast, char digit) sprintf(tmp, "%d", digit); transmit_tone(d->session, digit); #endif - return -1; + return -1; /* Stop inband indications */ } static char *control2str(int ind) { diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc index 0a98590d9..26e1beea0 100644 --- a/channels/chan_vpb.cc +++ b/channels/chan_vpb.cc @@ -341,9 +341,9 @@ static struct vpb_pvt { static struct ast_channel *vpb_new(struct vpb_pvt *i, enum ast_channel_state state, char *context); static void *do_chanreads(void *pvt); - static struct ast_channel *vpb_request(const char *type, int format, void *data, int *cause); -static int vpb_digit(struct ast_channel *ast, char digit); +static int vpb_digit_begin(struct ast_channel *ast, char digit); +static int vpb_digit_end(struct ast_channel *ast, char digit); static int vpb_call(struct ast_channel *ast, char *dest, int timeout); static int vpb_hangup(struct ast_channel *ast); static int vpb_answer(struct ast_channel *ast); @@ -360,9 +360,8 @@ static struct ast_channel_tech vpb_tech = { properties: 0, requester: vpb_request, devicestate: NULL, - send_digit: vpb_digit, - send_digit_begin: NULL, - send_digit_end: NULL, + send_digit_begin: vpb_digit_begin, + send_digit_end: vpb_digit_end, call: vpb_call, hangup: vpb_hangup, answer: vpb_answer, @@ -389,9 +388,8 @@ static struct ast_channel_tech vpb_tech_indicate = { properties: 0, requester: vpb_request, devicestate: NULL, - send_digit: vpb_digit, - send_digit_begin: NULL, - send_digit_end: NULL, + send_digit_begin: vpb_digit_begin, + send_digit_end: vpb_digit_end, call: vpb_call, hangup: vpb_hangup, answer: vpb_answer, @@ -863,11 +861,11 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e) vpb_timer_stop(p->ring_timer); vpb_timer_start(p->ring_timer); } else - f.frametype = -1; /* ignore ring on station port. */ + f.frametype = AST_FRAME_NULL; /* ignore ring on station port. */ break; case VPB_RING_OFF: - f.frametype = -1; + f.frametype = AST_FRAME_NULL; break; case VPB_TIMEREXP: @@ -876,12 +874,12 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e) p->state = VPB_STATE_PLAYBUSY; vpb_timer_stop(p->busy_timer); vpb_timer_start(p->busy_timer); - f.frametype = -1; + f.frametype = AST_FRAME_NULL; } else if (e->data == p->ringback_timer_id) { playtone(p->handle, &Ringbacktone); vpb_timer_stop(p->ringback_timer); vpb_timer_start(p->ringback_timer); - f.frametype = -1; + f.frametype = AST_FRAME_NULL; } else if (e->data == p->ring_timer_id) { /* We didnt get another ring in time! */ if (p->owner->_state != AST_STATE_UP) { @@ -890,23 +888,23 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e) f.subclass = AST_CONTROL_HANGUP; } else { vpb_timer_stop(p->ring_timer); - f.frametype = -1; + f.frametype = AST_FRAME_NULL; } } else { - f.frametype = -1; /* Ignore. */ + f.frametype = AST_FRAME_NULL; /* Ignore. */ } break; case VPB_DTMF_DOWN: case VPB_DTMF: if (use_ast_dtmfdet){ - f.frametype = -1; + f.frametype = AST_FRAME_NULL; } else if (p->owner->_state == AST_STATE_UP) { f.frametype = AST_FRAME_DTMF; f.subclass = e->data; } else - f.frametype = -1; + f.frametype = AST_FRAME_NULL; break; case VPB_TONEDETECT: @@ -950,11 +948,11 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e) f.subclass = AST_CONTROL_HANGUP; } else { p->lastgrunt = ast_tvnow(); - f.frametype = -1; + f.frametype = AST_FRAME_NULL; } } else { - f.frametype = -1; + f.frametype = AST_FRAME_NULL; } break; @@ -970,7 +968,7 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e) f.subclass = AST_CONTROL_HANGUP; #else ast_log(LOG_NOTICE,"%s: Got call progress callback but blind dialing \n", p->dev); - f.frametype = -1; + f.frametype = AST_FRAME_NULL; #endif break; @@ -983,14 +981,14 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e) if (p->owner->_state == AST_STATE_UP) f.subclass = AST_CONTROL_HANGUP; else - f.frametype = -1; + f.frametype = AST_FRAME_NULL; } break; case VPB_LOOP_ONHOOK: if (p->owner->_state == AST_STATE_UP) f.subclass = AST_CONTROL_HANGUP; else - f.frametype = -1; + f.frametype = AST_FRAME_NULL; break; case VPB_STATION_ONHOOK: f.subclass = AST_CONTROL_HANGUP; @@ -1009,22 +1007,22 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e) if (option_verbose > 1) ast_verbose(VERBOSE_PREFIX_2 "%s: Dialend\n", p->dev); } else { - f.frametype = -1; + f.frametype = AST_FRAME_NULL; } break; case VPB_PLAY_UNDERFLOW: - f.frametype = -1; + f.frametype = AST_FRAME_NULL; vpb_reset_play_fifo_alarm(p->handle); break; case VPB_RECORD_OVERFLOW: - f.frametype = -1; + f.frametype = AST_FRAME_NULL; vpb_reset_record_fifo_alarm(p->handle); break; default: - f.frametype = -1; + f.frametype = AST_FRAME_NULL; break; } @@ -1831,7 +1829,12 @@ static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) return 0; } -static int vpb_digit(struct ast_channel *ast, char digit) +static int vpb_digit_begin(struct ast_channel *ast, char digit) +{ + /* XXX Modify this callback to let Asterisk control the length of DTMF */ + return 0; +} +static int vpb_digit_end(struct ast_channel *ast, char digit) { struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt; char s[2]; diff --git a/channels/chan_zap.c b/channels/chan_zap.c index ae3e94277..7c860ff50 100644 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -690,10 +690,12 @@ static struct zt_pvt { #endif int polarity; int dsp_features; + char begindigit; } *iflist = NULL, *ifend = NULL; static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause); -static int zt_digit(struct ast_channel *ast, char digit); +static int zt_digit_begin(struct ast_channel *ast, char digit); +static int zt_digit_end(struct ast_channel *ast, char digit); static int zt_sendtext(struct ast_channel *c, const char *text); static int zt_call(struct ast_channel *ast, char *rdest, int timeout); static int zt_hangup(struct ast_channel *ast); @@ -711,7 +713,8 @@ static const struct ast_channel_tech zap_tech = { .description = tdesc, .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW, .requester = zt_request, - .send_digit = zt_digit, + .send_digit_begin = zt_digit_begin, + .send_digit_end = zt_digit_end, .send_text = zt_sendtext, .call = zt_call, .hangup = zt_hangup, @@ -1002,45 +1005,113 @@ static int unalloc_sub(struct zt_pvt *p, int x) return 0; } -static int zt_digit(struct ast_channel *ast, char digit) +static int digit_to_dtmfindex(char digit) { - ZT_DIAL_OPERATION zo; - struct zt_pvt *p; + if (isdigit(digit)) + return ZT_TONE_DTMF_BASE + (digit - '0'); + else if (digit >= 'A' && digit <= 'D') + return ZT_TONE_DTMF_A + (digit - 'A'); + else if (digit >= 'a' && digit <= 'd') + return ZT_TONE_DTMF_A + (digit - 'a'); + else if (digit == '*') + return ZT_TONE_DTMF_s; + else if (digit == '#') + return ZT_TONE_DTMF_p; + else + return -1; +} + +static int zt_digit_begin(struct ast_channel *chan, char digit) +{ + struct zt_pvt *pvt; + int index; + int dtmf = -1; + + pvt = chan->tech_pvt; + + ast_mutex_lock(&pvt->lock); + + index = zt_get_index(chan, pvt, 0); + + if ((index != SUB_REAL) || !pvt->owner) + goto out; + +#ifdef HAVE_PRI + if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { + if (pvt->setup_ack) { + if (!pri_grab(pvt, pvt->pri)) { + pri_information(pvt->pri->pri, pvt->call, digit); + pri_rel(pvt->pri); + } else + ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); + } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { + int res; + ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit); + res = strlen(pvt->dialdest); + pvt->dialdest[res++] = digit; + pvt->dialdest[res] = '\0'; + } + goto out; + } +#endif + if ((dtmf = digit_to_dtmfindex(digit)) == -1) + goto out; + + if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &dtmf)) { + int res; + ZT_DIAL_OPERATION zo = { + .op = ZT_DIAL_OP_APPEND, + .dialstr[0] = 'T', + .dialstr[1] = digit, + .dialstr[2] = 0, + }; + if ((res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_DIAL, &zo))) + ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit); + else + pvt->dialing = 1; + } else { + ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit); + pvt->dialing = 1; + pvt->begindigit = digit; + } + +out: + ast_mutex_unlock(&pvt->lock); + + return 0; /* Tell Asterisk not to generate inband indications */ +} + +static int zt_digit_end(struct ast_channel *chan, char digit) +{ + struct zt_pvt *pvt; int res = 0; int index; - p = ast->tech_pvt; - ast_mutex_lock(&p->lock); - index = zt_get_index(ast, p, 0); - if ((index == SUB_REAL) && p->owner) { + + pvt = chan->tech_pvt; + + ast_mutex_lock(&pvt->lock); + + index = zt_get_index(chan, pvt, 0); + + if ((index != SUB_REAL) || !pvt->owner || pvt->pulse) + goto out; + #ifdef HAVE_PRI - if ((p->sig == SIG_PRI) && (ast->_state == AST_STATE_DIALING) && !p->proceeding) { - if (p->setup_ack) { - if (!pri_grab(p, p->pri)) { - pri_information(p->pri->pri,p->call,digit); - pri_rel(p->pri); - } else - ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); - } else if (strlen(p->dialdest) < sizeof(p->dialdest) - 1) { - ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit); - res = strlen(p->dialdest); - p->dialdest[res++] = digit; - p->dialdest[res] = '\0'; - } - } else { -#else - { + /* This means that the digit was already sent via PRI signalling */ + if (pvt->sig == SIG_PRI && !pvt->begindigit) + goto out; #endif - zo.op = ZT_DIAL_OP_APPEND; - zo.dialstr[0] = 'T'; - zo.dialstr[1] = digit; - zo.dialstr[2] = 0; - if ((res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &zo))) - ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit); - else - p->dialing = 1; - } + + if (pvt->begindigit) { + ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit); + res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, -1); + pvt->dialing = 0; + pvt->begindigit = 0; } - ast_mutex_unlock(&p->lock); + +out: + ast_mutex_unlock(&pvt->lock); + return res; } @@ -3543,21 +3614,14 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); if (res & (ZT_EVENT_PULSEDIGIT | ZT_EVENT_DTMFUP)) { - if (res & ZT_EVENT_PULSEDIGIT) - p->pulsedial = 1; - else - p->pulsedial = 0; + p->pulsedial = (res & ZT_EVENT_PULSEDIGIT) ? 1 : 0; ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); #ifdef HAVE_PRI if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) { /* absorb event */ } else { #endif - /* Send a DTMF event for 'legacy' channels and all applications, - and a DTMF_BEGIN event for channels that handle variable duration - DTMF events - */ - p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; + p->subs[index].f.frametype = AST_FRAME_DTMF_END; p->subs[index].f.subclass = res & 0xff; #ifdef HAVE_PRI } @@ -3571,9 +3635,6 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff); /* Mute conference */ zt_confmute(p, 1); - /* Send a DTMF_BEGIN event for devices that want variable - duration DTMF events - */ p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; p->subs[index].f.subclass = res & 0xff; return &p->subs[index].f; diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c index 94aaf4c70..56c45e242 100644 --- a/channels/iax2-parser.c +++ b/channels/iax2-parser.c @@ -395,7 +395,7 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s { const char *frames[] = { "(0?)", - "DTMF ", + "DTMF_E ", "VOICE ", "VIDEO ", "CONTROL", @@ -404,7 +404,10 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s "TEXT ", "IMAGE ", "HTML ", - "CNG " }; + "CNG ", + "MODEM ", + "DTMF_B ", + }; const char *iaxs[] = { "(0?)", "NEW ", @@ -508,7 +511,7 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s } else { class = frames[(int)fh->type]; } - if (fh->type == AST_FRAME_DTMF) { + if (fh->type == AST_FRAME_DTMF_BEGIN || fh->type == AST_FRAME_DTMF_END) { sprintf(subclass2, "%c", fh->csub); subclass = subclass2; } else if (fh->type == AST_FRAME_IAX) { |