summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES4
-rw-r--r--apps/app_voicemail.c24
-rw-r--r--configs/samples/pjsip.conf.sample5
-rw-r--r--contrib/ast-db-manage/config/versions/d7983954dd96_add_ps_endpoints_notify_early_inuse_.py30
-rw-r--r--formats/format_g729.c2
-rw-r--r--include/asterisk/res_pjsip.h2
-rw-r--r--include/asterisk/res_pjsip_presence_xml.h3
-rw-r--r--include/asterisk/sdp_options.h25
-rw-r--r--main/pbx_app.c7
-rw-r--r--main/sdp_options.c33
-rw-r--r--main/sdp_private.h2
-rw-r--r--main/sdp_state.c9
-rw-r--r--res/res_pjsip.c7
-rw-r--r--res/res_pjsip/pjsip_configuration.c1
-rw-r--r--res/res_pjsip/presence_xml.c9
-rw-r--r--res/res_pjsip_dialog_info_body_generator.c10
-rw-r--r--res/res_pjsip_pidf_body_generator.c2
-rw-r--r--res/res_pjsip_pidf_eyebeam_body_supplement.c2
-rw-r--r--res/res_pjsip_xpidf_body_generator.c2
19 files changed, 162 insertions, 17 deletions
diff --git a/CHANGES b/CHANGES
index 9bfa506d3..9cd579b65 100644
--- a/CHANGES
+++ b/CHANGES
@@ -30,6 +30,10 @@ res_pjsip
Some SIP phones like Mitel/Aastra or Snom keep the line busy until
receive "200 OK".
+ * A new endpoint option "notify_early_inuse_ringing" was added to control
+ whether to notify dialog-info state 'early' or 'confirmed' on Ringing
+ when already INUSE.
+
res_agi
------------------
* The EAGI() application will now look for a dialplan variable named
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 8f50e1106..a95168013 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -13134,10 +13134,25 @@ static void imap_logout(const char *mailbox_id)
return;
}
+ ast_mutex_lock(&vms->lock);
vms->mailstream = mail_close(vms->mailstream);
+ ast_mutex_unlock(&vms->lock);
+
vmstate_delete(vms);
}
+static void imap_close_subscribed_mailboxes(void)
+{
+ struct mwi_sub *mwi_sub;
+
+ AST_RWLIST_RDLOCK(&mwi_subs);
+ AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
+ if (!ast_strlen_zero(mwi_sub->mailbox)) {
+ imap_logout(mwi_sub->mailbox);
+ }
+ }
+ AST_RWLIST_UNLOCK(&mwi_subs);
+}
#endif
static int handle_unsubscribe(void *datap)
@@ -13591,7 +13606,11 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
strcpy(listen_control_restart_key, DEFAULT_LISTEN_CONTROL_RESTART_KEY);
strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);
- /* Free all the users structure */
+#ifdef IMAP_STORAGE
+ imap_close_subscribed_mailboxes();
+#endif
+
+ /* Free all the users structure */
free_vm_users();
/* Free all the zones structure */
@@ -14985,6 +15004,9 @@ static int unload_module(void)
ast_unload_realtime("voicemail");
ast_unload_realtime("voicemail_data");
+#ifdef IMAP_STORAGE
+ imap_close_subscribed_mailboxes();
+#endif
free_vm_users();
free_vm_zones();
return res;
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index a992ff8b6..3b93bb61f 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -774,6 +774,11 @@
; transfer (default: "yes"). The value "no" is useful
; for some SIP phones (Mitel/Aastra, Snom) which expect
; a sip/frag "200 OK" after REFER has been accepted.
+;notify_early_inuse_ringing = ; Whether to notifies dialog-info 'early'
+ ; on INUSE && RINGING state (default: "no").
+ ; The value "yes" is useful for some SIP phones
+ ; (Cisco SPA) to be able to indicate and pick up
+ ; ringing devices.
;==========================AUTH SECTION OPTIONS=========================
;[auth]
diff --git a/contrib/ast-db-manage/config/versions/d7983954dd96_add_ps_endpoints_notify_early_inuse_.py b/contrib/ast-db-manage/config/versions/d7983954dd96_add_ps_endpoints_notify_early_inuse_.py
new file mode 100644
index 000000000..e1dcdd133
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/d7983954dd96_add_ps_endpoints_notify_early_inuse_.py
@@ -0,0 +1,30 @@
+"""add ps_endpoints.notify_early_inuse_ringing
+
+Revision ID: d7983954dd96
+Revises: 86bb1efa278d
+Create Date: 2017-06-05 15:44:41.152280
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'd7983954dd96'
+down_revision = '86bb1efa278d'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+YESNO_NAME = 'yesno_values'
+YESNO_VALUES = ['yes', 'no']
+
+def upgrade():
+ ############################# Enums ##############################
+
+ # yesno_values have already been created, so use postgres enum object
+ # type to get around "already created" issue - works okay with mysql
+ yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
+
+ op.add_column('ps_endpoints', sa.Column('notify_early_inuse_ringing', yesno_values))
+
+def downgrade():
+ op.drop_column('ps_endpoints', 'notify_early_inuse_ringing')
diff --git a/formats/format_g729.c b/formats/format_g729.c
index 1e523062e..91dc855f1 100644
--- a/formats/format_g729.c
+++ b/formats/format_g729.c
@@ -19,7 +19,7 @@
/*! \file
*
* \brief Save to raw, headerless G729 data.
- * \note This is not an encoder/decoder. The codec fo g729 is only
+ * \note This is not an encoder/decoder. The codec for g729 is only
* available with a commercial license from Digium, due to patent
* restrictions. Check http://www.digium.com for information.
* \arg Extensions: g729
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 8c589ef85..b9c50adda 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -769,6 +769,8 @@ struct ast_sip_endpoint {
unsigned int allow_overlap;
/*! Whether to notifies all the progress details on blind transfer */
unsigned int refer_blind_progress;
+ /*! Whether to notifies dialog-info 'early' on INUSE && RINGING state */
+ unsigned int notify_early_inuse_ringing;
};
/*! URI parameter for symmetric transport */
diff --git a/include/asterisk/res_pjsip_presence_xml.h b/include/asterisk/res_pjsip_presence_xml.h
index deed0901e..55b79ad6e 100644
--- a/include/asterisk/res_pjsip_presence_xml.h
+++ b/include/asterisk/res_pjsip_presence_xml.h
@@ -69,7 +69,8 @@ void ast_sip_sanitize_xml(const char *input, char *output, size_t len);
* \param[out] local_state
*/
void ast_sip_presence_exten_state_to_str(int state, char **statestring,
- char **pidfstate, char **pidfnote, enum ast_sip_pidf_state *local_state);
+ char **pidfstate, char **pidfnote, enum ast_sip_pidf_state *local_state,
+ unsigned int notify_early_inuse_ringing);
/*!
* \brief Create XML attribute
diff --git a/include/asterisk/sdp_options.h b/include/asterisk/sdp_options.h
index f49b79483..b8c1bbd56 100644
--- a/include/asterisk/sdp_options.h
+++ b/include/asterisk/sdp_options.h
@@ -522,4 +522,29 @@ void ast_sdp_options_set_ssrc(struct ast_sdp_options *options, unsigned int ssrc
*/
unsigned int ast_sdp_options_get_ssrc(const struct ast_sdp_options *options);
+/*!
+ * \brief Set the SDP options scheduler context used to create new streams of the type.
+ * \since 15.0.0
+ *
+ * \param options SDP Options
+ * \param type Media type the scheduler context is for.
+ * \param sched Scheduler context to use for the specified media type.
+ *
+ * \return Nothing
+ */
+void ast_sdp_options_set_sched_type(struct ast_sdp_options *options,
+ enum ast_media_type type, struct ast_sched_context *sched);
+
+/*!
+ * \brief Get the SDP options scheduler context used to create new streams of the type.
+ * \since 15.0.0
+ *
+ * \param options SDP Options
+ * \param type Media type the format cap represents.
+ *
+ * \return The stored scheduler context to create new streams of the type.
+ */
+struct ast_sched_context *ast_sdp_options_get_sched_type(const struct ast_sdp_options *options,
+ enum ast_media_type type);
+
#endif /* _ASTERISK_SDP_OPTIONS_H */
diff --git a/main/pbx_app.c b/main/pbx_app.c
index e0609db70..ec6bc7589 100644
--- a/main/pbx_app.c
+++ b/main/pbx_app.c
@@ -394,6 +394,11 @@ int ast_unregister_application(const char *app)
struct ast_app *cur;
int cmp;
+ /* Anticipate need for conlock in unreference_cached_app(), in order to avoid
+ * possible deadlock with pbx_extension_helper()/pbx_findapp()
+ */
+ ast_rdlock_contexts();
+
AST_RWLIST_WRLOCK(&apps);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
cmp = strcasecmp(app, cur->name);
@@ -416,6 +421,8 @@ int ast_unregister_application(const char *app)
AST_RWLIST_TRAVERSE_SAFE_END;
AST_RWLIST_UNLOCK(&apps);
+ ast_unlock_contexts();
+
return cur ? 0 : -1;
}
diff --git a/main/sdp_options.c b/main/sdp_options.c
index ab8fb2973..a938583c6 100644
--- a/main/sdp_options.c
+++ b/main/sdp_options.c
@@ -77,6 +77,39 @@ DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_impl, impl);
DEFINE_GETTERS_SETTERS_FOR(enum ast_sdp_options_encryption, encryption);
DEFINE_GETTERS_SETTERS_FOR(unsigned int, ssrc);
+struct ast_sched_context *ast_sdp_options_get_sched_type(const struct ast_sdp_options *options, enum ast_media_type type)
+{
+ struct ast_sched_context *sched = NULL;
+
+ switch (type) {
+ case AST_MEDIA_TYPE_AUDIO:
+ case AST_MEDIA_TYPE_VIDEO:
+ case AST_MEDIA_TYPE_IMAGE:
+ case AST_MEDIA_TYPE_TEXT:
+ sched = options->sched[type];
+ break;
+ case AST_MEDIA_TYPE_UNKNOWN:
+ case AST_MEDIA_TYPE_END:
+ break;
+ }
+ return sched;
+}
+
+void ast_sdp_options_set_sched_type(struct ast_sdp_options *options, enum ast_media_type type, struct ast_sched_context *sched)
+{
+ switch (type) {
+ case AST_MEDIA_TYPE_AUDIO:
+ case AST_MEDIA_TYPE_VIDEO:
+ case AST_MEDIA_TYPE_IMAGE:
+ case AST_MEDIA_TYPE_TEXT:
+ options->sched[type] = sched;
+ break;
+ case AST_MEDIA_TYPE_UNKNOWN:
+ case AST_MEDIA_TYPE_END:
+ break;
+ }
+}
+
static void set_defaults(struct ast_sdp_options *options)
{
options->dtmf = DEFAULT_DTMF;
diff --git a/main/sdp_private.h b/main/sdp_private.h
index a0b63df03..62228a5c8 100644
--- a/main/sdp_private.h
+++ b/main/sdp_private.h
@@ -35,6 +35,8 @@ struct ast_sdp_options {
/*! RTP Engine Name */
AST_STRING_FIELD(rtp_engine);
);
+ /*! Scheduler context for the media stream types (Mainly for RTP) */
+ struct ast_sched_context *sched[AST_MEDIA_TYPE_END];
struct {
unsigned int rtp_symmetric:1;
unsigned int udptl_symmetric:1;
diff --git a/main/sdp_state.c b/main/sdp_state.c
index 0f06bf9e3..99421ad4d 100644
--- a/main/sdp_state.c
+++ b/main/sdp_state.c
@@ -151,12 +151,6 @@ static void sdp_state_capabilities_free(struct sdp_state_capabilities *capabilit
ast_free(capabilities);
}
-/* TODO
- * This isn't set anywhere yet.
- */
-/*! \brief Scheduler for RTCP purposes */
-static struct ast_sched_context *sched;
-
/*! \brief Internal function which creates an RTP instance */
static struct sdp_state_rtp *create_rtp(const struct ast_sdp_options *options,
enum ast_media_type media_type)
@@ -185,7 +179,8 @@ static struct sdp_state_rtp *create_rtp(const struct ast_sdp_options *options,
return NULL;
}
- rtp->instance = ast_rtp_instance_new(options->rtp_engine, sched, media_address, NULL);
+ rtp->instance = ast_rtp_instance_new(options->rtp_engine,
+ ast_sdp_options_get_sched_type(options, media_type), media_address, NULL);
if (!rtp->instance) {
ast_log(LOG_ERROR, "Unable to create RTP instance using RTP engine '%s'\n",
options->rtp_engine);
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index d994f2824..f6d63c640 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -971,6 +971,13 @@
will not send the progress details, but immediately will send "200 OK".
</para></description>
</configOption>
+ <configOption name="notify_early_inuse_ringing" default="no">
+ <synopsis>Whether to notifies dialog-info 'early' on InUse&amp;Ringing state</synopsis>
+ <description><para>
+ Control whether dialog-info subscriptions get 'early' state
+ on Ringing when already INUSE.
+ </para></description>
+ </configOption>
</configObject>
<configObject name="auth">
<synopsis>Authentication type</synopsis>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 679c8837d..7a05f87f0 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1940,6 +1940,7 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtcp_mux", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtcp_mux));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_overlap", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allow_overlap));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "refer_blind_progress", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, refer_blind_progress));
+ ast_sorcery_object_field_register(sip_sorcery, "endpoint", "notify_early_inuse_ringing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, notify_early_inuse_ringing));
if (ast_sip_initialize_sorcery_transport()) {
ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
diff --git a/res/res_pjsip/presence_xml.c b/res/res_pjsip/presence_xml.c
index c991a0d68..1aca307e5 100644
--- a/res/res_pjsip/presence_xml.c
+++ b/res/res_pjsip/presence_xml.c
@@ -82,7 +82,8 @@ void ast_sip_sanitize_xml(const char *input, char *output, size_t len)
}
void ast_sip_presence_exten_state_to_str(int state, char **statestring, char **pidfstate,
- char **pidfnote, enum ast_sip_pidf_state *local_state)
+ char **pidfnote, enum ast_sip_pidf_state *local_state,
+ unsigned int notify_early_inuse_ringing)
{
switch (state) {
case AST_EXTENSION_RINGING:
@@ -92,7 +93,11 @@ void ast_sip_presence_exten_state_to_str(int state, char **statestring, char **p
*pidfnote = "Ringing";
break;
case (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING):
- *statestring = "confirmed";
+ if (notify_early_inuse_ringing) {
+ *statestring = "early";
+ } else {
+ *statestring = "confirmed";
+ }
*local_state = NOTIFY_INUSE;
*pidfstate = "busy";
*pidfnote = "Ringing";
diff --git a/res/res_pjsip_dialog_info_body_generator.c b/res/res_pjsip_dialog_info_body_generator.c
index 5006b9efb..7c386e3b2 100644
--- a/res/res_pjsip_dialog_info_body_generator.c
+++ b/res/res_pjsip_dialog_info_body_generator.c
@@ -107,6 +107,8 @@ static int dialog_info_generate_body_content(void *body, void *data)
enum ast_sip_pidf_state local_state;
unsigned int version;
char version_str[32], sanitized[PJSIP_MAX_URL_SIZE];
+ struct ast_sip_endpoint *endpoint = NULL;
+ unsigned int notify_early_inuse_ringing = 0;
if (!local || !state_data->datastores) {
return -1;
@@ -120,8 +122,12 @@ static int dialog_info_generate_body_content(void *body, void *data)
stripped = ast_strip_quoted(local, "<", ">");
ast_sip_sanitize_xml(stripped, sanitized, sizeof(sanitized));
+ if (state_data->sub && (endpoint = ast_sip_subscription_get_endpoint(state_data->sub))) {
+ notify_early_inuse_ringing = endpoint->notify_early_inuse_ringing;
+ ao2_cleanup(endpoint);
+ }
ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring,
- &pidfstate, &pidfnote, &local_state);
+ &pidfstate, &pidfnote, &local_state, notify_early_inuse_ringing);
ast_sip_presence_xml_create_attr(state_data->pool, dialog_info, "xmlns", "urn:ietf:params:xml:ns:dialog-info");
@@ -133,7 +139,7 @@ static int dialog_info_generate_body_content(void *body, void *data)
dialog = ast_sip_presence_xml_create_node(state_data->pool, dialog_info, "dialog");
ast_sip_presence_xml_create_attr(state_data->pool, dialog, "id", state_data->exten);
- if (state_data->exten_state == AST_EXTENSION_RINGING) {
+ if (!ast_strlen_zero(statestring) && !strcmp(statestring, "early")) {
ast_sip_presence_xml_create_attr(state_data->pool, dialog, "direction", "recipient");
}
diff --git a/res/res_pjsip_pidf_body_generator.c b/res/res_pjsip_pidf_body_generator.c
index 25f063915..cc10082ad 100644
--- a/res/res_pjsip_pidf_body_generator.c
+++ b/res/res_pjsip_pidf_body_generator.c
@@ -58,7 +58,7 @@ static int pidf_generate_body_content(void *body, void *data)
struct ast_sip_exten_state_data *state_data = data;
ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring,
- &pidfstate, &pidfnote, &local_state);
+ &pidfstate, &pidfnote, &local_state, 0);
if (!pjpidf_pres_add_note(state_data->pool, pres, pj_cstr(&note, pidfnote))) {
ast_log(LOG_WARNING, "Unable to add note to PIDF presence\n");
diff --git a/res/res_pjsip_pidf_eyebeam_body_supplement.c b/res/res_pjsip_pidf_eyebeam_body_supplement.c
index cc6dfd125..a0f50fdde 100644
--- a/res/res_pjsip_pidf_eyebeam_body_supplement.c
+++ b/res/res_pjsip_pidf_eyebeam_body_supplement.c
@@ -80,7 +80,7 @@ static int pidf_supplement_body(void *body, void *data)
enum ast_sip_pidf_state local_state;
ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring,
- &pidfstate, &pidfnote, &local_state);
+ &pidfstate, &pidfnote, &local_state, 0);
add_eyebeam(state_data->pool, pres, pidfstate);
return 0;
diff --git a/res/res_pjsip_xpidf_body_generator.c b/res/res_pjsip_xpidf_body_generator.c
index 924046549..41f6224d1 100644
--- a/res/res_pjsip_xpidf_body_generator.c
+++ b/res/res_pjsip_xpidf_body_generator.c
@@ -63,7 +63,7 @@ static int xpidf_generate_body_content(void *body, void *data)
pj_xml_node *msnsubstatus;
ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring,
- &pidfstate, &pidfnote, &local_state);
+ &pidfstate, &pidfnote, &local_state, 0);
ast_sip_presence_xml_find_node_attr(state_data->pool, pres, "atom", "id",
&atom, &attr);