diff options
-rw-r--r-- | apps/app_queue.c | 20 | ||||
-rw-r--r-- | configs/samples/rtp.conf.sample | 14 | ||||
-rw-r--r-- | include/asterisk/rtp_engine.h | 10 | ||||
-rw-r--r-- | main/rtp_engine.c | 19 | ||||
-rw-r--r-- | res/res_clialiases.c | 8 | ||||
-rw-r--r-- | res/res_hep.c | 2 | ||||
-rw-r--r-- | res/res_musiconhold.c | 4 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 45 | ||||
-rw-r--r-- | res/res_smdi.c | 44 |
9 files changed, 132 insertions, 34 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c index e3a4e22a9..6aea58ccb 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -1572,6 +1572,7 @@ struct member { char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */ char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */ char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */ + int state_id; /*!< Extension state callback id (if using hint) */ char membername[80]; /*!< Member name to use in queue logs */ int penalty; /*!< Are we a last resort? */ int calls; /*!< Number of calls serviced by this member */ @@ -2629,12 +2630,21 @@ static int get_queue_member_status(struct member *cur) return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten)); } +static void destroy_queue_member_cb(void *obj) +{ + struct member *mem = obj; + + if (mem->state_id != -1) { + ast_extension_state_del(mem->state_id, extension_state_cb); + } +} + /*! \brief allocate space for new queue member and set fields based on parameters passed */ static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse) { struct member *cur; - if ((cur = ao2_alloc(sizeof(*cur), NULL))) { + if ((cur = ao2_alloc(sizeof(*cur), destroy_queue_member_cb))) { cur->ringinuse = ringinuse; cur->penalty = penalty; cur->paused = paused; @@ -2661,6 +2671,10 @@ static struct member *create_queue_member(const char *interface, const char *mem ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten)); ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context)); + + cur->state_id = ast_extension_state_add(cur->state_context, cur->state_exten, extension_state_cb, NULL); + } else { + cur->state_id = -1; } cur->status = get_queue_member_status(cur); } @@ -11081,8 +11095,6 @@ static int unload_module(void) device_state_sub = stasis_unsubscribe_and_join(device_state_sub); - ast_extension_state_del(0, extension_state_cb); - ast_unload_realtime("queue_members"); ao2_cleanup(queues); ao2_cleanup(pending_members); @@ -11240,8 +11252,6 @@ static int load_module(void) err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_dump_type); err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_ringnoanswer_type); - ast_extension_state_add(NULL, NULL, extension_state_cb, NULL); - if (err) { unload_module(); return AST_MODULE_LOAD_DECLINE; diff --git a/configs/samples/rtp.conf.sample b/configs/samples/rtp.conf.sample index 9bc3de3cf..de9d59007 100644 --- a/configs/samples/rtp.conf.sample +++ b/configs/samples/rtp.conf.sample @@ -21,9 +21,17 @@ rtpend=20000 ; rtcpinterval = 5000 ; Milliseconds between rtcp reports ;(min 500, max 60000, default 5000) ; -; Enable strict RTP protection. This will drop RTP packets that -; do not come from the source of the RTP stream. This option is -; enabled by default. +; Enable strict RTP protection. This will drop RTP packets that do not come +; from the recoginized source of the RTP stream. Strict RTP qualifies RTP +; packet stream sources before accepting them upon initial connection and +; when the connection is renegotiated (e.g., transfers and direct media). +; Initial connection and renegotiation starts a learning mode to qualify +; stream source addresses. Once Asterisk has recognized a stream it will +; allow other streams to qualify and replace the current stream for 5 +; seconds after starting learning mode. Once learning mode completes the +; current stream is locked in and cannot change until the next +; renegotiation. +; This option is enabled by default. ; strictrtp=yes ; ; Number of packets containing consecutive sequence values needed diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h index f9d686aca..c77be4584 100644 --- a/include/asterisk/rtp_engine.h +++ b/include/asterisk/rtp_engine.h @@ -1383,6 +1383,16 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload); /*! + * \brief Determine the type of RTP stream media from the codecs mapped. + * \since 13.19.0 + * + * \param codecs Codecs structure to look in + * + * \return Media type or AST_MEDIA_TYPE_UNKNOWN if no codecs mapped. + */ +enum ast_media_type ast_rtp_codecs_get_stream_type(struct ast_rtp_codecs *codecs); + +/*! * \brief Retrieve rx payload mapped information by payload type * * \param codecs Codecs structure to look in diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 2431ffc0c..68c53e7ff 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -1176,6 +1176,25 @@ void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp ast_rwlock_unlock(&codecs->codecs_lock); } +enum ast_media_type ast_rtp_codecs_get_stream_type(struct ast_rtp_codecs *codecs) +{ + enum ast_media_type stream_type = AST_MEDIA_TYPE_UNKNOWN; + int payload; + struct ast_rtp_payload_type *type; + + ast_rwlock_rdlock(&codecs->codecs_lock); + for (payload = 0; payload < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++payload) { + type = AST_VECTOR_GET(&codecs->payload_mapping_rx, payload); + if (type && type->asterisk_format) { + stream_type = ast_format_get_type(type->format); + break; + } + } + ast_rwlock_unlock(&codecs->codecs_lock); + + return stream_type; +} + struct ast_rtp_payload_type *ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload) { struct ast_rtp_payload_type *type = NULL; diff --git a/res/res_clialiases.c b/res/res_clialiases.c index 1a2fc6939..337c31c97 100644 --- a/res/res_clialiases.c +++ b/res/res_clialiases.c @@ -103,7 +103,7 @@ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_ struct cli_alias tmp = { .cli_entry.command = e->command, }; - char *generator; + char *generator = NULL; const char *line; /* Try to find the alias based on the CLI entry */ @@ -118,14 +118,10 @@ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_ case CLI_GENERATE: line = a->line; line += (strlen(alias->alias)); - if (!strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) { - generator = NULL; - } else if (!ast_strlen_zero(a->word)) { + if (strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) { struct ast_str *real_cmd = ast_str_alloca(strlen(alias->real_cmd) + strlen(line) + 1); ast_str_append(&real_cmd, 0, "%s%s", alias->real_cmd, line); generator = ast_cli_generator(ast_str_buffer(real_cmd), a->word, a->n); - } else { - generator = ast_cli_generator(alias->real_cmd, a->word, a->n); } ao2_ref(alias, -1); return generator; diff --git a/res/res_hep.c b/res/res_hep.c index 25b4d13b1..ba036d70f 100644 --- a/res/res_hep.c +++ b/res/res_hep.c @@ -421,7 +421,7 @@ int hepv3_is_loaded(void) { RAII_VAR(struct module_config *, config, ao2_global_obj_ref(global_config), ao2_cleanup); - return (config != NULL) ? 1 : 0; + return config && config->general->enabled; } struct hepv3_capture_info *hepv3_create_capture_info(const void *payload, size_t len) diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index ef1b81c2a..17e91b70c 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -333,6 +333,7 @@ static int ast_moh_files_next(struct ast_channel *chan) } } else { state->announcement = 0; + state->samples = 0; } if (!state->class->total_files) { @@ -1934,6 +1935,9 @@ static char *handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struc ast_cli(a->fd, "Class: %s\n", class->name); ast_cli(a->fd, "\tMode: %s\n", S_OR(class->mode, "<none>")); ast_cli(a->fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>")); + if (ast_test_flag(class, MOH_ANNOUNCEMENT)) { + ast_cli(a->fd, "\tAnnouncement: %s\n", S_OR(class->announcement, "<none>")); + } if (ast_test_flag(class, MOH_CUSTOM)) { ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>")); ast_cli(a->fd, "\tKill Escalation Delay: %zu ms\n", class->kill_delay / 1000); diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index bdc83301e..51e509c77 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -256,6 +256,8 @@ struct rtp_learning_info { struct timeval received; /*!< The time of the first received packet */ int max_seq; /*!< The highest sequence number received */ int packets; /*!< The number of remaining packets before the source is accepted */ + /*! Type of media stream carried by the RTP instance */ + enum ast_media_type stream_type; }; #ifdef HAVE_OPENSSL_SRTP @@ -3095,18 +3097,30 @@ static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t info->received = ast_tvnow(); } - /* - * Protect against packet floods by checking that we - * received the packet sequence in at least the minimum - * allowed time. - */ - if (ast_tvzero(info->received)) { - info->received = ast_tvnow(); - } else if (!info->packets && (ast_tvdiff_ms(ast_tvnow(), info->received) < learning_min_duration )) { - /* Packet flood; reset */ - info->packets = learning_min_sequential - 1; - info->received = ast_tvnow(); + switch (info->stream_type) { + case AST_MEDIA_TYPE_UNKNOWN: + case AST_MEDIA_TYPE_AUDIO: + /* + * Protect against packet floods by checking that we + * received the packet sequence in at least the minimum + * allowed time. + */ + if (ast_tvzero(info->received)) { + info->received = ast_tvnow(); + } else if (!info->packets + && ast_tvdiff_ms(ast_tvnow(), info->received) < learning_min_duration) { + /* Packet flood; reset */ + info->packets = learning_min_sequential - 1; + info->received = ast_tvnow(); + } + break; + case AST_MEDIA_TYPE_VIDEO: + case AST_MEDIA_TYPE_IMAGE: + case AST_MEDIA_TYPE_TEXT: + case AST_MEDIA_TYPE_END: + break; } + info->max_seq = seq; return info->packets; @@ -5951,6 +5965,15 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc * source and we should switch to it. */ if (!ast_sockaddr_cmp(&rtp->rtp_source_learn.proposed_address, &addr)) { + if (rtp->rtp_source_learn.stream_type == AST_MEDIA_TYPE_UNKNOWN) { + struct ast_rtp_codecs *codecs; + + codecs = ast_rtp_instance_get_codecs(instance); + rtp->rtp_source_learn.stream_type = + ast_rtp_codecs_get_stream_type(codecs); + ast_verb(4, "%p -- Strict RTP qualifying stream type: %s\n", + rtp, ast_codec_media_type2str(rtp->rtp_source_learn.stream_type)); + } if (!rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) { /* Accept the new RTP stream */ ast_verb(4, "%p -- Strict RTP switching source address to %s\n", diff --git a/res/res_smdi.c b/res/res_smdi.c index e2b2e1b06..612a4b87b 100644 --- a/res/res_smdi.c +++ b/res/res_smdi.c @@ -586,9 +586,8 @@ static void *smdi_read(void *iface_p) struct ast_smdi_interface *iface = iface_p; struct ast_smdi_md_message *md_msg; struct ast_smdi_mwi_message *mwi_msg; - char c = '\0'; char *cp = NULL; - int i; + int i, c; int start = 0; /* read an smdi message */ @@ -616,7 +615,14 @@ static void *smdi_read(void *iface_p) /* read the message desk number */ for (i = 0; i < sizeof(md_msg->mesg_desk_num) - 1; i++) { - md_msg->mesg_desk_num[i] = fgetc(iface->file); + c = fgetc(iface->file); + if (c == EOF) { + ast_log(LOG_ERROR, "Unexpected EOF while reading MD message\n"); + ao2_ref(md_msg, -1); + ao2_ref(iface, -1); + return NULL; + } + md_msg->mesg_desk_num[i] = (char) c; ast_debug(1, "Read a '%c'\n", md_msg->mesg_desk_num[i]); } @@ -626,7 +632,14 @@ static void *smdi_read(void *iface_p) /* read the message desk terminal number */ for (i = 0; i < sizeof(md_msg->mesg_desk_term) - 1; i++) { - md_msg->mesg_desk_term[i] = fgetc(iface->file); + c = fgetc(iface->file); + if (c == EOF) { + ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n"); + ao2_ref(md_msg, -1); + ao2_ref(iface, -1); + return NULL; + } + md_msg->mesg_desk_term[i] = (char) c; ast_debug(1, "Read a '%c'\n", md_msg->mesg_desk_term[i]); } @@ -635,7 +648,14 @@ static void *smdi_read(void *iface_p) ast_debug(1, "The message desk terminal is '%s'\n", md_msg->mesg_desk_term); /* read the message type */ - md_msg->type = fgetc(iface->file); + c = fgetc(iface->file); + if (c == EOF) { + ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n"); + ao2_ref(md_msg, -1); + ao2_ref(iface, -1); + return NULL; + } + md_msg->type = (char) c; ast_debug(1, "Message type is '%c'\n", md_msg->type); @@ -717,7 +737,7 @@ static void *smdi_read(void *iface_p) /* discard the 'I' (from 'MWI') */ fgetc(iface->file); - + /* read the forwarding station number (may be blank) */ cp = &mwi_msg->fwd_st[0]; for (i = 0; i < sizeof(mwi_msg->fwd_st) - 1; i++) { @@ -740,8 +760,16 @@ static void *smdi_read(void *iface_p) ast_copy_string(mwi_msg->name, mwi_msg->fwd_st, sizeof(mwi_msg->name)); /* read the mwi failure cause */ - for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++) - mwi_msg->cause[i] = fgetc(iface->file); + for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++) { + c = fgetc(iface->file); + if (c == EOF) { + ast_log(LOG_ERROR, "Unexpected EOF while reading MWI message\n"); + ao2_ref(mwi_msg, -1); + ao2_ref(iface, -1); + return NULL; + } + mwi_msg->cause[i] = (char) c; + } mwi_msg->cause[sizeof(mwi_msg->cause) - 1] = '\0'; |