diff options
-rw-r--r-- | UPGRADE.txt | 7 | ||||
-rwxr-xr-x | contrib/ast-db-manage/config/versions/4c573e7135bd_fix_tos_field_types.py | 61 | ||||
-rw-r--r-- | include/asterisk/acl.h | 11 | ||||
-rw-r--r-- | main/acl.c | 6 | ||||
-rw-r--r-- | res/res_pjsip/config_transport.c | 39 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_configuration.c | 43 |
6 files changed, 163 insertions, 4 deletions
diff --git a/UPGRADE.txt b/UPGRADE.txt index b996f072c..a3e808c7f 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -27,6 +27,13 @@ PJSIP: PJSIP contacts, this means that the schema has been updated to add a user_agent column. An alembic revision has been added to facilitate this update. +Realtime Configuration: + - PJSIP endpoint columns 'tos_audio' and 'tos_video' have been changed from yes/no + enumerators to string values. 'cos_audio' and 'cos_video' have been changed from + yes/no enumerators to integer values. PJSIP transport column 'tos' has been + changed from a yes/no enumerator to a string value. 'cos' has been changed from + a yes/no enumerator to an integer value. + From 12.0.0 to 12.1.0: * The sound_place_into_conference sound used in Confbridge is now deprecated and is no longer functional since it has been broken since its inception diff --git a/contrib/ast-db-manage/config/versions/4c573e7135bd_fix_tos_field_types.py b/contrib/ast-db-manage/config/versions/4c573e7135bd_fix_tos_field_types.py new file mode 100755 index 000000000..51e8fa9ca --- /dev/null +++ b/contrib/ast-db-manage/config/versions/4c573e7135bd_fix_tos_field_types.py @@ -0,0 +1,61 @@ +"""Fix tos and cos field types + +Revision ID: 4c573e7135bd +Revises: 21e526ad3040 +Create Date: 2014-03-05 12:16:56.618630 + +""" + +# revision identifiers, used by Alembic. +revision = '4c573e7135bd' +down_revision = '21e526ad3040' + +from alembic import op +from alembic import context +import sqlalchemy as sa +from sqlalchemy.dialects.postgresql import ENUM + +YESNO_NAME = 'yesno_values' +YESNO_VALUES = ['yes', 'no'] + +def upgrade(): + op.alter_column('ps_endpoints', 'tos_audio', + type_=sa.String(10)) + op.alter_column('ps_endpoints', 'tos_video', + type_=sa.String(10)) + op.alter_column('ps_transports', 'tos', + type_=sa.String(10)) + + # Can't cast YENO_VALUES to Integers, so dropping and adding is required + op.drop_column('ps_endpoints', 'cos_audio') + op.drop_column('ps_endpoints', 'cos_video') + op.drop_column('ps_transports', 'cos') + + op.add_column('ps_endpoints', sa.Column('cos_audio', sa.Integer)) + op.add_column('ps_endpoints', sa.Column('cos_video', sa.Integer)) + op.add_column('ps_transports', sa.Column('cos', sa.Integer)) + pass + + +def downgrade(): + + yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False) + + # Can't cast string to YESNO_VALUES, so dropping and adding is required + op.drop_column('ps_endpoints', 'tos_audio') + op.drop_column('ps_endpoints', 'tos_video') + op.drop_column('ps_transports', 'tos') + + op.add_column('ps_endpoints', sa.Column('tos_audio', yesno_values)) + op.add_column('ps_endpoints', sa.Column('tos_video', yesno_values)) + op.add_column('ps_transports', sa.Column('tos', yesno_values)) + + # Can't cast integers to YESNO_VALUES, so dropping and adding is required + op.drop_column('ps_endpoints', 'cos_audio') + op.drop_column('ps_endpoints', 'cos_video') + op.drop_column('ps_transports', 'cos') + + op.add_column('ps_endpoints', sa.Column('cos_audio', yesno_values)) + op.add_column('ps_endpoints', sa.Column('cos_video', yesno_values)) + op.add_column('ps_transports', sa.Column('cos', yesno_values)) + pass diff --git a/include/asterisk/acl.h b/include/asterisk/acl.h index d1773b6b1..502e7f447 100644 --- a/include/asterisk/acl.h +++ b/include/asterisk/acl.h @@ -358,6 +358,17 @@ int ast_str2tos(const char *value, unsigned int *tos); const char *ast_tos2str(unsigned int tos); /*! + * \brief Convert a TOS value into its string representation + * and create a dynamically allocated copy + * + * \param tos The TOS value to look up + * \param buf pointer to character pointer where string will be duplicated to + * + * \note The string allocated at buf must be free'd + */ +void ast_tos2str_buf(unsigned int tos, char **buf); + +/*! * \brief Retrieve a named ACL * * \details diff --git a/main/acl.c b/main/acl.c index c341125fd..a55e87458 100644 --- a/main/acl.c +++ b/main/acl.c @@ -894,6 +894,12 @@ const char *ast_tos2str(unsigned int tos) return "unknown"; } +void ast_tos2str_buf(unsigned int tos, char **buf) +{ + const char *tos_string = ast_tos2str(tos); + *buf = ast_strdup(tos_string); +} + int ast_get_ip(struct ast_sockaddr *addr, const char *hostname) { return ast_get_ip_or_srv(addr, hostname, NULL); diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c index 3c11dcc70..58d0f1577 100644 --- a/res/res_pjsip/config_transport.c +++ b/res/res_pjsip/config_transport.c @@ -121,9 +121,11 @@ static void *transport_alloc(const char *name) static void set_qos(struct ast_sip_transport *transport, pj_qos_params *qos) { + int tos_as_dscp = transport->tos >> 2; + if (transport->tos) { qos->flags |= PJ_QOS_PARAM_HAS_DSCP; - qos->dscp_val = transport->tos; + qos->dscp_val = tos_as_dscp; } if (transport->cos) { qos->flags |= PJ_QOS_PARAM_HAS_SO_PRIO; @@ -448,6 +450,39 @@ static int localnet_to_str(const void *obj, const intptr_t *args, char **buf) return 0; } +/*! \brief Custom handler for TOS setting */ +static int transport_tos_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) +{ + struct ast_sip_transport *transport = obj; + unsigned int value; + + if (ast_str2tos(var->value, &value)) { + ast_log(LOG_ERROR, "Error configuring transport '%s' - Could not " + "interpret 'tos' value '%s'\n", + ast_sorcery_object_get_id(transport), var->value); + return -1; + } + + if (value % 4) { + value = value >> 2; + value = value << 2; + ast_log(LOG_WARNING, + "transport '%s' - 'tos' value '%s' uses bits that are " + "discarded when converted to DSCP. Using equivalent %d instead.\n", + ast_sorcery_object_get_id(transport), var->value, value); + } + + transport->tos = value; + return 0; +} + +static int tos_to_str(const void *obj, const intptr_t *args, char **buf) +{ + const struct ast_sip_transport *transport = obj; + ast_tos2str_buf(transport->tos, buf); + return 0; +} + static struct ao2_container *cli_get_container(void) { RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup); @@ -581,7 +616,7 @@ int ast_sip_initialize_sorcery_transport(void) ast_sorcery_object_field_register_custom(sorcery, "transport", "method", "", transport_tls_method_handler, tls_method_to_str, 0, 0); ast_sorcery_object_field_register_custom(sorcery, "transport", "cipher", "", transport_tls_cipher_handler, transport_tls_cipher_to_str, 0, 0); ast_sorcery_object_field_register_custom(sorcery, "transport", "local_net", "", transport_localnet_handler, localnet_to_str, 0, 0); - ast_sorcery_object_field_register(sorcery, "transport", "tos", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_transport, tos)); + ast_sorcery_object_field_register_custom(sorcery, "transport", "tos", "0", transport_tos_handler, tos_to_str, 0, 0); ast_sorcery_object_field_register(sorcery, "transport", "cos", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_transport, cos)); ast_sip_register_endpoint_formatter(&endpoint_transport_formatter); diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index deb374e6e..994987b7a 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -758,6 +758,45 @@ static int t38udptl_ec_to_str(const void *obj, const intptr_t *args, char **buf) return 0; } +static int tos_handler(const struct aco_option *opt, + struct ast_variable *var, void *obj) +{ + struct ast_sip_endpoint *endpoint = obj; + unsigned int value; + + if (ast_str2tos(var->value, &value)) { + ast_log(LOG_ERROR, "Error configuring endpoint '%s' - Could not " + "interpret '%s' value '%s'\n", + ast_sorcery_object_get_id(endpoint), var->name, var->value); + return -1; + } + + if (!strcmp(var->name, "tos_audio")) { + endpoint->media.tos_audio = value; + } else if (!strcmp(var->name, "tos_video")) { + endpoint->media.tos_video = value; + } else { + /* If we reach this point, someone called the tos_handler when they shouldn't have. */ + ast_assert(0); + return -1; + } + return 0; +} + +static int tos_audio_to_str(const void *obj, const intptr_t *args, char **buf) +{ + const struct ast_sip_endpoint *endpoint = obj; + ast_tos2str_buf(endpoint->media.tos_audio, buf); + return 0; +} + +static int tos_video_to_str(const void *obj, const intptr_t *args, char **buf) +{ + const struct ast_sip_endpoint *endpoint = obj; + ast_tos2str_buf(endpoint->media.tos_video, buf); + return 0; +} + static int set_var_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) { @@ -1586,8 +1625,8 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_transfer", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allowtransfer)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_owner", "-", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpowner)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_session", "Asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpsession)); - ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tos_audio", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.tos_audio)); - ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tos_video", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.tos_video)); + ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_audio", "0", tos_handler, tos_audio_to_str, 0, 0); + ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_video", "0", tos_handler, tos_video_to_str, 0, 0); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_audio", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_audio)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_video", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_video)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_subscribe", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.allow)); |