diff options
author | Patrick McHardy <kaber@trash.net> | 2011-06-17 08:11:11 +0200 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-06-17 08:11:11 +0200 |
commit | 9364aaccb699c6d19ac2cbe760c208b34ba7838a (patch) | |
tree | 28c0aef25a69f14117caf64e09fc9597d2c915ea /channels | |
parent | 84c94e92c153057470194aadf7ae22a2569f1bd4 (diff) | |
parent | 62b90dd0a4ea809bdb11bc27288b6acf717edcd8 (diff) |
Merge 192.168.0.100:/repos/git/asterisk
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_local.c | 22 | ||||
-rw-r--r-- | channels/chan_sip.c | 100 | ||||
-rw-r--r-- | channels/chan_skinny.c | 160 | ||||
-rw-r--r-- | channels/sip/include/sip.h | 3 |
4 files changed, 170 insertions, 115 deletions
diff --git a/channels/chan_local.c b/channels/chan_local.c index 0ceb432b0..3c16fc51a 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -217,6 +217,7 @@ static void awesome_locking(struct local_pvt *p, struct ast_channel **outchan, s *outchan = p->chan; } +/* Called with ast locked */ static int local_setoption(struct ast_channel *ast, int option, void * data, int datalen) { int res = 0; @@ -225,27 +226,22 @@ static int local_setoption(struct ast_channel *ast, int option, void * data, int ast_chan_write_info_t *write_info; if (option != AST_OPTION_CHANNEL_WRITE) { - res = -1; - goto setoption_cleanup; + return -1; } write_info = data; if (write_info->version != AST_CHAN_WRITE_INFO_T_VERSION) { ast_log(LOG_ERROR, "The chan_write_info_t type has changed, and this channel hasn't been updated!\n"); - res = -1; - goto setoption_cleanup; + return -1; } /* get the tech pvt */ - ast_channel_lock(ast); if (!(p = ast->tech_pvt)) { - ast_channel_unlock(ast); - res = -1; - goto setoption_cleanup; + return -1; } ao2_ref(p, 1); - ast_channel_unlock(ast); + ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */ /* get the channel we are supposed to write to */ ao2_lock(p); @@ -272,6 +268,7 @@ setoption_cleanup: if (otherchan) { ast_channel_unref(otherchan); } + ast_channel_lock(ast); /* Lock back before we leave */ return res; } @@ -348,6 +345,7 @@ static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct return bridged; } +/* Called with ast locked */ static int local_queryoption(struct ast_channel *ast, int option, void *data, int *datalen) { struct local_pvt *p; @@ -361,21 +359,18 @@ static int local_queryoption(struct ast_channel *ast, int option, void *data, in } /* for some reason the channel is not locked in channel.c when this function is called */ - ast_channel_lock(ast); if (!(p = ast->tech_pvt)) { - ast_channel_unlock(ast); return -1; } ao2_lock(p); if (!(tmp = IS_OUTBOUND(ast, p) ? p->owner : p->chan)) { ao2_unlock(p); - ast_channel_unlock(ast); return -1; } ast_channel_ref(tmp); ao2_unlock(p); - ast_channel_unlock(ast); + ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */ ast_channel_lock(tmp); if (!(bridged = ast_bridged_channel(tmp))) { @@ -394,6 +389,7 @@ query_cleanup: if (tmp) { tmp = ast_channel_unref(tmp); } + ast_channel_lock(ast); /* Lock back before we leave */ return res; } diff --git a/channels/chan_sip.c b/channels/chan_sip.c index bcb4ea73a..4c0e2a66c 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -4262,15 +4262,23 @@ static int sip_setoption(struct ast_channel *chan, int option, void *data, int d int res = -1; struct sip_pvt *p = chan->tech_pvt; + sip_pvt_lock(p); + switch (option) { case AST_OPTION_FORMAT_READ: - res = ast_rtp_instance_set_read_format(p->rtp, (struct ast_format *) data); + if (p->rtp) { + res = ast_rtp_instance_set_read_format(p->rtp, (struct ast_format *) data); + } break; case AST_OPTION_FORMAT_WRITE: - res = ast_rtp_instance_set_write_format(p->rtp, (struct ast_format *) data); + if (p->rtp) { + res = ast_rtp_instance_set_write_format(p->rtp, (struct ast_format *) data); + } break; case AST_OPTION_MAKE_COMPATIBLE: - res = ast_rtp_instance_make_compatible(chan, p->rtp, (struct ast_channel *) data); + if (p->rtp) { + res = ast_rtp_instance_make_compatible(chan, p->rtp, (struct ast_channel *) data); + } break; case AST_OPTION_DIGIT_DETECT: if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || @@ -4298,6 +4306,8 @@ static int sip_setoption(struct ast_channel *chan, int option, void *data, int d break; } + sip_pvt_unlock(p); + return res; } @@ -4309,16 +4319,16 @@ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int struct sip_pvt *p = (struct sip_pvt *) chan->tech_pvt; char *cp; + sip_pvt_lock(p); + switch (option) { case AST_OPTION_T38_STATE: /* Make sure we got an ast_t38_state enum passed in */ if (*datalen != sizeof(enum ast_t38_state)) { ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option. Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen); - return -1; + break; } - sip_pvt_lock(p); - /* Now if T38 support is enabled we need to look and see what the current state is to get what we want to report back */ if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) { switch (p->t38.state) { @@ -4337,8 +4347,6 @@ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int } } - sip_pvt_unlock(p); - *((enum ast_t38_state *) data) = state; res = 0; @@ -4370,6 +4378,8 @@ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int break; } + sip_pvt_unlock(p); + return res; } @@ -5061,6 +5071,7 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog) } ast_rtp_instance_set_timeout(dialog->vrtp, global_rtptimeout); ast_rtp_instance_set_hold_timeout(dialog->vrtp, global_rtpholdtimeout); + ast_rtp_instance_set_keepalive(dialog->vrtp, global_rtpholdtimeout); ast_rtp_instance_set_prop(dialog->vrtp, AST_RTP_PROPERTY_RTCP, 1); } @@ -5071,12 +5082,14 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog) } ast_rtp_instance_set_timeout(dialog->trtp, global_rtptimeout); ast_rtp_instance_set_hold_timeout(dialog->trtp, global_rtpholdtimeout); + ast_rtp_instance_set_keepalive(dialog->trtp, global_rtpholdtimeout); ast_rtp_instance_set_prop(dialog->trtp, AST_RTP_PROPERTY_RTCP, 1); } ast_rtp_instance_set_timeout(dialog->rtp, global_rtptimeout); ast_rtp_instance_set_hold_timeout(dialog->rtp, global_rtpholdtimeout); + ast_rtp_instance_set_keepalive(dialog->rtp, global_rtpkeepalive); ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_RTCP, 1); ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); @@ -5144,6 +5157,7 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer) ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); ast_rtp_instance_set_timeout(dialog->rtp, peer->rtptimeout); ast_rtp_instance_set_hold_timeout(dialog->rtp, peer->rtpholdtimeout); + ast_rtp_instance_set_keepalive(dialog->rtp, peer->rtpkeepalive); /* Set Frame packetization */ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(dialog->rtp), dialog->rtp, &dialog->prefs); dialog->autoframing = peer->autoframing; @@ -5151,10 +5165,12 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer) if (dialog->vrtp) { /* Video */ ast_rtp_instance_set_timeout(dialog->vrtp, peer->rtptimeout); ast_rtp_instance_set_hold_timeout(dialog->vrtp, peer->rtpholdtimeout); + ast_rtp_instance_set_keepalive(dialog->vrtp, peer->rtpkeepalive); } if (dialog->trtp) { /* Realtime text */ ast_rtp_instance_set_timeout(dialog->trtp, peer->rtptimeout); ast_rtp_instance_set_hold_timeout(dialog->trtp, peer->rtpholdtimeout); + ast_rtp_instance_set_keepalive(dialog->trtp, peer->rtpkeepalive); } /* XXX TODO: get fields directly from peer only as they are needed using dialog->relatedpeer */ @@ -6344,7 +6360,11 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame) } if (p) { sip_pvt_lock(p); - if (p->rtp) { + if (p->t38.state == T38_ENABLED) { + /* drop frame, can't sent VOICE frames while in T.38 mode */ + sip_pvt_unlock(p); + break; + } else if (p->rtp) { /* If channel is not up, activate early media session */ if ((ast->_state != AST_STATE_UP) && !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && @@ -6355,12 +6375,9 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame) transmit_provisional_response(p, "183 Session Progress", &p->initreq, TRUE); ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); } - } else if (p->t38.state == T38_ENABLED) { - /* drop frame, can't sent VOICE frames while in T.38 mode */ - } else { - p->lastrtptx = time(NULL); - res = ast_rtp_instance_write(p->rtp, frame); } + p->lastrtptx = time(NULL); + res = ast_rtp_instance_write(p->rtp, frame); } sip_pvt_unlock(p); } @@ -7274,12 +7291,19 @@ static struct ast_frame *sip_read(struct ast_channel *ast) /* If we detect a CNG tone and fax detection is enabled then send us off to the fax extension */ if (faxdetected && ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT_CNG)) { - ast_channel_lock(ast); if (strcmp(ast->exten, "fax")) { const char *target_context = S_OR(ast->macrocontext, ast->context); + /* We need to unlock 'ast' here because + * ast_exists_extension has the potential to start and + * stop an autoservice on the channel. Such action is + * prone to deadlock if the channel is locked. + */ + sip_pvt_unlock(p); ast_channel_unlock(ast); if (ast_exists_extension(ast, target_context, "fax", 1, S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) { + ast_channel_lock(ast); + sip_pvt_lock(p); ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension due to CNG detection\n", ast->name); pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); if (ast_async_goto(ast, target_context, "fax", 1)) { @@ -7287,10 +7311,10 @@ static struct ast_frame *sip_read(struct ast_channel *ast) } fr = &ast_null_frame; } else { + ast_channel_lock(ast); + sip_pvt_lock(p); ast_log(LOG_NOTICE, "FAX CNG detected but no fax extension\n"); } - } else { - ast_channel_unlock(ast); } } @@ -15749,8 +15773,12 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of, p->callingpres = peer->callingpres; } ast_string_field_set(p, fullcontact, peer->fullcontact); - if (!ast_strlen_zero(peer->context)) + if (!ast_strlen_zero(peer->context)) { ast_string_field_set(p, context, peer->context); + } + if (!ast_strlen_zero(peer->messagecontext)) { + ast_string_field_set(p, messagecontext, peer->messagecontext); + } ast_string_field_set(p, peersecret, peer->secret); ast_string_field_set(p, peermd5secret, peer->md5secret); ast_string_field_set(p, language, peer->language); @@ -16080,6 +16108,10 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a if (ast_strlen_zero(peer->secret) && ast_strlen_zero(peer->md5secret)) { ast_string_field_set(p, context, peer->context); } + if (!ast_strlen_zero(peer->messagecontext)) { + ast_string_field_set(p, messagecontext, peer->messagecontext); + } + ast_string_field_set(p, peername, peer->name); peer = unref_peer(peer, "from find_peer() in receive_message"); } } @@ -16100,7 +16132,19 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a res = ast_msg_set_to(msg, "%s", to); res |= ast_msg_set_from(msg, "%s", get_in_brackets(from)); res |= ast_msg_set_body(msg, "%s", ast_str_buffer(buf)); - res |= ast_msg_set_context(msg, "%s", p->context); + + if (!ast_strlen_zero(p->messagecontext)) { + res |= ast_msg_set_context(msg, "%s", p->messagecontext); + } else if (!ast_strlen_zero(sip_cfg.messagecontext)) { + res |= ast_msg_set_context(msg, "%s", sip_cfg.messagecontext); + } else { + res |= ast_msg_set_context(msg, "%s", p->context); + } + + if (!ast_strlen_zero(p->peername)) { + res |= ast_msg_set_var(msg, "SIP_PEERNAME", p->peername); + } + res |= ast_msg_set_exten(msg, "%s", p->exten); if (res) { @@ -25368,11 +25412,19 @@ static void check_rtp_timeout(struct sip_pvt *dialog, time_t t) } /* If we have no timers set, return now */ - if (!ast_rtp_instance_get_timeout(dialog->rtp) && !ast_rtp_instance_get_hold_timeout(dialog->rtp)) { + if (!ast_rtp_instance_get_keepalive(dialog->rtp) && !ast_rtp_instance_get_timeout(dialog->rtp) && !ast_rtp_instance_get_hold_timeout(dialog->rtp)) { dialog_unlink_rtpcheck(dialog); return; } + /* Check AUDIO RTP keepalives */ + if (dialog->lastrtptx && ast_rtp_instance_get_keepalive(dialog->rtp) && + (t > dialog->lastrtptx + ast_rtp_instance_get_keepalive(dialog->rtp))) { + /* Need to send an empty RTP packet */ + dialog->lastrtptx = time(NULL); + ast_rtp_instance_sendcng(dialog->rtp, 0); + } + /*! \todo Check video RTP keepalives Do we need to move the lastrtptx to the RTP structure to have one for audio and one @@ -26671,6 +26723,7 @@ static void set_peer_defaults(struct sip_peer *peer) ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY); ast_copy_flags(&peer->flags[2], &global_flags[2], SIP_PAGE3_FLAGS_TO_COPY); ast_string_field_set(peer, context, sip_cfg.default_context); + ast_string_field_set(peer, messagecontext, sip_cfg.messagecontext); ast_string_field_set(peer, subscribecontext, sip_cfg.default_subscribecontext); ast_string_field_set(peer, language, default_language); ast_string_field_set(peer, mohinterpret, default_mohinterpret); @@ -26965,6 +27018,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str } else if (!strcasecmp(v->name, "context")) { ast_string_field_set(peer, context, v->value); ast_set_flag(&peer->flags[1], SIP_PAGE2_HAVEPEERCONTEXT); + } else if (!strcasecmp(v->name, "outofcall_message_context")) { + ast_string_field_set(peer, messagecontext, v->value); } else if (!strcasecmp(v->name, "subscribecontext")) { ast_string_field_set(peer, subscribecontext, v->value); } else if (!strcasecmp(v->name, "fromdomain")) { @@ -27351,7 +27406,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str * specified, use that address instead. */ /* XXX May need to revisit the final argument; does the realtime DB store whether * the original contact was over TLS or not? XXX */ - if (!ast_test_flag(&peer->flags[0], SIP_NAT_RPORT_PRESENT) || ast_sockaddr_isnull(&peer->addr)) { + if (!ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) || ast_sockaddr_isnull(&peer->addr)) { __set_address_from_contact(fullcontact->str, &peer->addr, 0); } } @@ -27653,6 +27708,7 @@ static int reload_config(enum channelreloadreason reason) sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT; sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS; sip_cfg.auth_message_requests = DEFAULT_AUTH_MESSAGE; + sip_cfg.messagecontext[0] = '\0'; sip_cfg.accept_outofcall_message = DEFAULT_ACCEPT_OUTOFCALL_MESSAGE; sip_cfg.allowsubscribe = FALSE; sip_cfg.disallowed_methods = SIP_UNKNOWN; @@ -27906,6 +27962,8 @@ static int reload_config(enum channelreloadreason reason) sip_cfg.auth_message_requests = ast_true(v->value) ? 1 : 0; } else if (!strcasecmp(v->name, "accept_outofcall_message")) { sip_cfg.accept_outofcall_message = ast_true(v->value) ? 1 : 0; + } else if (!strcasecmp(v->name, "outofcall_message_context")) { + ast_copy_string(sip_cfg.messagecontext, v->value, sizeof(sip_cfg.messagecontext)); } else if (!strcasecmp(v->name, "mohinterpret")) { ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret)); } else if (!strcasecmp(v->name, "mohsuggest")) { diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index b90ba7eba..ea7d16c9e 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -1126,6 +1126,10 @@ static int callnums = 1; #define SKINNY_ALERT 0x24 #define SKINNY_REORDER 0x25 #define SKINNY_CALLWAITTONE 0x2D +#define SKINNY_ZIPZIP 0x31 +#define SKINNY_ZIP 0x32 +#define SKINNY_BEEPBONK 0x33 +#define SKINNY_BARGIN 0x43 #define SKINNY_NOTONE 0x7F #define SKINNY_LAMP_OFF 1 @@ -1164,18 +1168,10 @@ static const char * const skinny_cxmodes[] = { /* driver scheduler */ static struct ast_sched_context *sched = NULL; -static struct io_context *io; -/* Protect the monitoring thread, so only one process can kill or start it, and not - when it's doing something critical. */ -AST_MUTEX_DEFINE_STATIC(monlock); /* Protect the network socket */ AST_MUTEX_DEFINE_STATIC(netlock); -/* This is the thread for the monitor which checks for input on the channels - which are not currently in use. */ -static pthread_t monitor_thread = AST_PTHREADT_NULL; - /* Wait up to 16 seconds for first digit */ static int firstdigittimeout = 16000; @@ -1215,7 +1211,9 @@ struct skinny_subchannel { int blindxfer; int xferor; int substate; - + int aa_sched; + int aa_beep; + int aa_mute; AST_LIST_ENTRY(skinny_subchannel) list; struct skinny_subchannel *related; @@ -1712,6 +1710,16 @@ static struct ast_variable *add_var(const char *buf, struct ast_variable *list) return list; } +static int skinny_sched_del(int sched_id) +{ + return ast_sched_del(sched, sched_id); +} + +static int skinny_sched_add(int when, ast_sched_cb callback, const void *data) +{ + return ast_sched_add(sched, when, callback, data); +} + /* It's quicker/easier to find the subchannel when we know the instance number too */ static struct skinny_subchannel *find_subchannel_by_instance_reference(struct skinny_device *d, int instance, int reference) { @@ -2235,7 +2243,7 @@ static void transmit_speaker_mode(struct skinny_device *d, int mode) req->data.setspeaker.mode = htolel(mode); transmit_response(d, req); } -/* + static void transmit_microphone_mode(struct skinny_device *d, int mode) { struct skinny_req *req; @@ -2246,7 +2254,6 @@ static void transmit_microphone_mode(struct skinny_device *d, int mode) req->data.setmicrophone.mode = htolel(mode); transmit_response(d, req); } -*/ static void transmit_callinfo(struct skinny_subchannel *sub) { @@ -4044,7 +4051,13 @@ static void *skinny_ss(void *data) return NULL; } - +static int skinny_autoanswer_cb(const void *data) +{ + struct skinny_subchannel *sub = (struct skinny_subchannel *)data; + sub->aa_sched = 0; + setsubstate(sub, SKINNY_CONNECTED); + return 0; +} static int skinny_call(struct ast_channel *ast, char *dest, int timeout) { @@ -4052,6 +4065,8 @@ static int skinny_call(struct ast_channel *ast, char *dest, int timeout) struct skinny_subchannel *sub = ast->tech_pvt; struct skinny_line *l = sub->line; struct skinny_device *d = l->device; + struct ast_var_t *current; + int doautoanswer = 0; if (!d->registered) { ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest); @@ -4075,8 +4090,40 @@ static int skinny_call(struct ast_channel *ast, char *dest, int timeout) ast_queue_control(ast, AST_CONTROL_BUSY); return -1; } - + + AST_LIST_TRAVERSE(&ast->varshead, current, entries) { + if (!(strcasecmp(ast_var_name(current),"SKINNY_AUTOANSWER"))) { + if (d->hookstate == SKINNY_ONHOOK && !sub->aa_sched) { + char buf[24]; + int aatime; + char *stringp = buf, *curstr; + ast_copy_string(buf, ast_var_value(current), sizeof(buf)); + curstr = strsep(&stringp, ":"); + ast_verb(3, "test %s\n", curstr); + aatime = atoi(curstr); + while ((curstr = strsep(&stringp, ":"))) { + if (!(strcasecmp(curstr,"BEEP"))) { + sub->aa_beep = 1; + } else if (!(strcasecmp(curstr,"MUTE"))) { + sub->aa_mute = 1; + } + } + if (skinnydebug) + ast_verb(3, "Sub %d - setting autoanswer time=%dms %s%s\n", sub->callid, aatime, sub->aa_beep?"BEEP ":"", sub->aa_mute?"MUTE":""); + if (aatime) { + //sub->aa_sched = ast_sched_add(sched, aatime, skinny_autoanswer_cb, sub); + sub->aa_sched = skinny_sched_add(aatime, skinny_autoanswer_cb, sub); + } else { + doautoanswer = 1; + } + } + } + } + setsubstate(sub, SUBSTATE_RINGIN); + if (doautoanswer) { + setsubstate(sub, SUBSTATE_CONNECTED); + } return res; } @@ -4637,6 +4684,13 @@ static void setsubstate(struct skinny_subchannel *sub, int state) if (sub->substate == SUBSTATE_ONHOOK) { return; } + + if (state != SUBSTATE_RINGIN && sub->aa_sched) { + skinny_sched_del(sub->aa_sched); + sub->aa_sched = 0; + sub->aa_beep = 0; + sub->aa_mute = 0; + } if ((state == SUBSTATE_RINGIN) && ((d->hookstate == SKINNY_OFFHOOK) || (AST_LIST_NEXT(AST_LIST_FIRST(&l->sub), list)))) { actualstate = SUBSTATE_CALLWAIT; @@ -4789,6 +4843,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); transmit_connect(d, sub); } + transmit_ringer_mode(d, SKINNY_RING_OFF); transmit_activatecallplane(d, l); transmit_stop_tone(d, l->instance, sub->callid); transmit_callinfo(sub); @@ -4798,6 +4853,12 @@ static void setsubstate(struct skinny_subchannel *sub, int state) if (!sub->rtp) { start_rtp(sub); } + if (sub->aa_beep) { + transmit_start_tone(d, SKINNY_ZIP, l->instance, sub->callid); + } + if (sub->aa_mute) { + transmit_microphone_mode(d, SKINNY_MICOFF); + } if (sub->substate == SUBSTATE_RINGIN || sub->substate == SUBSTATE_CALLWAIT) { ast_queue_control(sub->owner, AST_CONTROL_ANSWER); } @@ -6499,59 +6560,6 @@ static void *accept_thread(void *ignore) return 0; } -static void *do_monitor(void *data) -{ - int res; - - /* This thread monitors all the interfaces which are not yet in use - (and thus do not have a separate thread) indefinitely */ - /* From here on out, we die whenever asked */ - for(;;) { - pthread_testcancel(); - /* Wait for sched or io */ - res = ast_sched_wait(sched); - if ((res < 0) || (res > 1000)) { - res = 1000; - } - res = ast_io_wait(io, res); - ast_mutex_lock(&monlock); - if (res >= 0) { - ast_sched_runq(sched); - } - ast_mutex_unlock(&monlock); - } - /* Never reached */ - return NULL; - -} - -static int restart_monitor(void) -{ - /* If we're supposed to be stopped -- stay stopped */ - if (monitor_thread == AST_PTHREADT_STOP) - return 0; - - ast_mutex_lock(&monlock); - if (monitor_thread == pthread_self()) { - ast_mutex_unlock(&monlock); - ast_log(LOG_WARNING, "Cannot kill myself\n"); - return -1; - } - if (monitor_thread != AST_PTHREADT_NULL) { - /* Wake up the thread */ - pthread_kill(monitor_thread, SIGURG); - } else { - /* Start a new monitor */ - if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { - ast_mutex_unlock(&monlock); - ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); - return -1; - } - } - ast_mutex_unlock(&monlock); - return 0; -} - static int skinny_devicestate(void *data) { struct skinny_line *l; @@ -6591,7 +6599,6 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca if (!tmpc) { ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); } - restart_monitor(); return tmpc; } @@ -7425,13 +7432,13 @@ static int load_module(void) sched = ast_sched_context_create(); if (!sched) { ast_log(LOG_WARNING, "Unable to create schedule context\n"); + return AST_MODULE_LOAD_FAILURE; } - io = io_context_create(); - if (!io) { - ast_log(LOG_WARNING, "Unable to create I/O context\n"); + if (ast_sched_start_thread(sched)) { + ast_sched_context_destroy(sched); + sched = NULL; + return AST_MODULE_LOAD_FAILURE; } - /* And start the monitor for the first time */ - restart_monitor(); return AST_MODULE_LOAD_SUCCESS; } @@ -7483,15 +7490,6 @@ static int unload_module(void) delete_devices(); - ast_mutex_lock(&monlock); - if ((monitor_thread != AST_PTHREADT_NULL) && (monitor_thread != AST_PTHREADT_STOP)) { - pthread_cancel(monitor_thread); - pthread_kill(monitor_thread, SIGURG); - pthread_join(monitor_thread, NULL); - } - monitor_thread = AST_PTHREADT_STOP; - ast_mutex_unlock(&monlock); - ast_mutex_lock(&netlock); if (accept_t && (accept_t != AST_PTHREADT_STOP)) { pthread_cancel(accept_t); diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index 0eb8be350..e8dba3067 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -691,6 +691,7 @@ struct sip_settings { int legacy_useroption_parsing; /*!< Whether to strip useroptions in URI via semicolons */ int matchexternaddrlocally; /*!< Match externaddr/externhost setting against localnet setting */ char regcontext[AST_MAX_CONTEXT]; /*!< Context for auto-extensions */ + char messagecontext[AST_MAX_CONTEXT]; /*!< Default context for out of dialog msgs. */ unsigned int disallowed_methods; /*!< methods that we should never try to use */ int notifyringing; /*!< Send notifications on ringing */ int notifyhold; /*!< Send notifications on hold */ @@ -939,6 +940,7 @@ struct sip_pvt { AST_STRING_FIELD(useragent); /*!< User agent in SIP request */ AST_STRING_FIELD(exten); /*!< Extension where to start */ AST_STRING_FIELD(context); /*!< Context for this call */ + AST_STRING_FIELD(messagecontext); /*!< Default context for outofcall messages. */ AST_STRING_FIELD(subscribecontext); /*!< Subscribecontext */ AST_STRING_FIELD(subscribeuri); /*!< Subscribecontext */ AST_STRING_FIELD(fromdomain); /*!< Domain to show in the from field */ @@ -1172,6 +1174,7 @@ struct sip_peer { AST_STRING_FIELD(description); /*!< Description of this peer */ AST_STRING_FIELD(remotesecret); /*!< Remote secret (trunks, remote devices) */ AST_STRING_FIELD(context); /*!< Default context for incoming calls */ + AST_STRING_FIELD(messagecontext); /*!< Default context for outofcall messages. */ AST_STRING_FIELD(subscribecontext); /*!< Default context for subscriptions */ AST_STRING_FIELD(username); /*!< Temporary username until registration */ AST_STRING_FIELD(accountcode); /*!< Account code */ |