mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	No response sent for SIP CC subscribe/resubscribe request.
Asterisk does not send a response if we try to subscribe for call completion after we have received a 180 Ringing. You can only subscribe for call completion when the call has been cleared. When we receive the 180 Ringing, for this call, its call-completion state is 'CC_AVAILABLE'. If we then send a subscribe message to Asterisk, it trys to change the call-completion state to 'CC_CALLER_REQUESTED'. Because this is an invalid state change, it just ignores the message. The only state Asterisk will accept our subscribe message is in the 'CC_CALLER_OFFERED' state. Asterisk will go into the 'CC_CALLER_OFFERED' when the SIP client clears the call by sending a CANCEL. Asterisk should always send a response. Even if its a negative one. The fix is to allow for the CCSS core to notify a CC agent that a failure has occurred when CC is requested. The "ack" callback is replaced with a "respond" callback. The "respond" callback has a parameter indicating either a successful response or a specific type of failure that may need to be communicated to the requester. (closes issue #18336) Reported by: GeorgeKonopacki Tested by: mmichelson, rmudgett JIRA SWP-2633 (closes issue #18337) Reported by: GeorgeKonopacki Tested by: mmichelson JIRA SWP-2634 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@307879 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		
							
								
								
									
										39
									
								
								main/ccss.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								main/ccss.c
									
									
									
									
									
								
							| @@ -2205,7 +2205,7 @@ static void check_callback_sanity(const struct ast_cc_agent_callbacks *callbacks | ||||
| 	ast_assert(callbacks->init != NULL); | ||||
| 	ast_assert(callbacks->start_offer_timer != NULL); | ||||
| 	ast_assert(callbacks->stop_offer_timer != NULL); | ||||
| 	ast_assert(callbacks->ack != NULL); | ||||
| 	ast_assert(callbacks->respond != NULL); | ||||
| 	ast_assert(callbacks->status_request != NULL); | ||||
| 	ast_assert(callbacks->start_monitoring != NULL); | ||||
| 	ast_assert(callbacks->callee_available != NULL); | ||||
| @@ -2267,7 +2267,7 @@ static struct ast_cc_agent *cc_agent_init(struct ast_channel *caller_chan, | ||||
| static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan); | ||||
| static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent); | ||||
| static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent); | ||||
| static void cc_generic_agent_ack(struct ast_cc_agent *agent); | ||||
| static void cc_generic_agent_respond(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason); | ||||
| static int cc_generic_agent_status_request(struct ast_cc_agent *agent); | ||||
| static int cc_generic_agent_stop_ringing(struct ast_cc_agent *agent); | ||||
| static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent); | ||||
| @@ -2279,7 +2279,7 @@ static struct ast_cc_agent_callbacks generic_agent_callbacks = { | ||||
| 	.init = cc_generic_agent_init, | ||||
| 	.start_offer_timer = cc_generic_agent_start_offer_timer, | ||||
| 	.stop_offer_timer = cc_generic_agent_stop_offer_timer, | ||||
| 	.ack = cc_generic_agent_ack, | ||||
| 	.respond = cc_generic_agent_respond, | ||||
| 	.status_request = cc_generic_agent_status_request, | ||||
| 	.stop_ringing = cc_generic_agent_stop_ringing, | ||||
| 	.start_monitoring = cc_generic_agent_start_monitoring, | ||||
| @@ -2403,7 +2403,7 @@ static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void cc_generic_agent_ack(struct ast_cc_agent *agent) | ||||
| static void cc_generic_agent_respond(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason) | ||||
| { | ||||
| 	/* The generic agent doesn't have to do anything special to | ||||
| 	 * acknowledge a CC request. Just return. | ||||
| @@ -2625,6 +2625,7 @@ static struct cc_core_instance *cc_core_init_instance(struct ast_channel *caller | ||||
| } | ||||
|  | ||||
| struct cc_state_change_args { | ||||
| 	struct cc_core_instance *core_instance;/*!< Holds reference to core instance. */ | ||||
| 	enum cc_state state; | ||||
| 	int core_id; | ||||
| 	char debug[1]; | ||||
| @@ -2773,6 +2774,8 @@ static int cc_caller_requested(struct cc_core_instance *core_instance, struct cc | ||||
| { | ||||
| 	if (!ast_cc_request_is_within_limits()) { | ||||
| 		ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n"); | ||||
| 		core_instance->agent->callbacks->respond(core_instance->agent, | ||||
| 			AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY); | ||||
| 		ast_cc_failed(core_instance->core_id, "Too many requests in the system"); | ||||
| 		return -1; | ||||
| 	} | ||||
| @@ -2811,7 +2814,8 @@ static int cc_active(struct cc_core_instance *core_instance, struct cc_state_cha | ||||
| 	 *    call monitor's unsuspend callback. | ||||
| 	 */ | ||||
| 	if (previous_state == CC_CALLER_REQUESTED) { | ||||
| 		core_instance->agent->callbacks->ack(core_instance->agent); | ||||
| 		core_instance->agent->callbacks->respond(core_instance->agent, | ||||
| 			AST_CC_AGENT_RESPONSE_SUCCESS); | ||||
| 		manager_event(EVENT_FLAG_CC, "CCRequestAcknowledged", | ||||
| 			"CoreID: %d\r\n" | ||||
| 			"Caller: %s\r\n", | ||||
| @@ -2948,15 +2952,19 @@ static int cc_do_state_change(void *datap) | ||||
| 	ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %d requested. Reason: %s\n", | ||||
| 			args->core_id, args->state, args->debug); | ||||
|  | ||||
| 	if (!(core_instance = find_cc_core_instance(args->core_id))) { | ||||
| 		ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n", args->core_id); | ||||
| 		ast_free(args); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	core_instance = args->core_instance; | ||||
|  | ||||
| 	if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) { | ||||
| 		ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n", | ||||
| 				args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state)); | ||||
| 		if (args->state == CC_CALLER_REQUESTED) { | ||||
| 			/* | ||||
| 			 * For out-of-order requests, we need to let the requester know that | ||||
| 			 * we can't handle the request now. | ||||
| 			 */ | ||||
| 			core_instance->agent->callbacks->respond(core_instance->agent, | ||||
| 				AST_CC_AGENT_RESPONSE_FAILURE_INVALID); | ||||
| 		} | ||||
| 		ast_free(args); | ||||
| 		cc_unref(core_instance, "Unref core instance from when it was found earlier"); | ||||
| 		return -1; | ||||
| @@ -2978,6 +2986,7 @@ static int cc_request_state_change(enum cc_state state, const int core_id, const | ||||
| 	int debuglen; | ||||
| 	char dummy[1]; | ||||
| 	va_list aq; | ||||
| 	struct cc_core_instance *core_instance; | ||||
| 	struct cc_state_change_args *args; | ||||
| 	/* This initial call to vsnprintf is simply to find what the | ||||
| 	 * size of the string needs to be | ||||
| @@ -2993,12 +3002,22 @@ static int cc_request_state_change(enum cc_state state, const int core_id, const | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	core_instance = find_cc_core_instance(core_id); | ||||
| 	if (!core_instance) { | ||||
| 		ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n", | ||||
| 			core_id); | ||||
| 		ast_free(args); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	args->core_instance = core_instance; | ||||
| 	args->state = state; | ||||
| 	args->core_id = core_id; | ||||
| 	vsnprintf(args->debug, debuglen, debug, ap); | ||||
|  | ||||
| 	res = ast_taskprocessor_push(cc_core_taskprocessor, cc_do_state_change, args); | ||||
| 	if (res) { | ||||
| 		cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); | ||||
| 		ast_free(args); | ||||
| 	} | ||||
| 	return res; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user