[svn-commits] kmoore: branch kmoore/pjsip_commands r395256 - /team/kmoore/pjsip_commands/res/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jul 24 11:02:50 CDT 2013


Author: kmoore
Date: Wed Jul 24 11:02:48 2013
New Revision: 395256

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=395256
Log:
Add unregistration commands, fix refcounting bugs

Modified:
    team/kmoore/pjsip_commands/res/res_sip_outbound_registration.c

Modified: team/kmoore/pjsip_commands/res/res_sip_outbound_registration.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/pjsip_commands/res/res_sip_outbound_registration.c?view=diff&rev=395256&r1=395255&r2=395256
==============================================================================
--- team/kmoore/pjsip_commands/res/res_sip_outbound_registration.c (original)
+++ team/kmoore/pjsip_commands/res/res_sip_outbound_registration.c Wed Jul 24 11:02:48 2013
@@ -30,6 +30,7 @@
 #include "asterisk/res_sip.h"
 #include "asterisk/module.h"
 #include "asterisk/taskprocessor.h"
+#include "asterisk/cli.h"
 
 /*** DOCUMENTATION
 	<configInfo name="res_sip_outbound_registration" language="en_US">
@@ -90,6 +91,17 @@
 			</configObject>
 		</configFile>
 	</configInfo>
+	<manager name="PJSIPUnregister" language="en_US">
+		<synopsis>
+			Unregister an outbound registration.
+		</synopsis>
+		<syntax>
+			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+			<parameter name="Registration" required="true">
+				<para>The registration to unregister.</para>
+			</parameter>
+		</syntax>
+	</manager>
  ***/
 
 /*! \brief Amount of buffer time (in seconds) before expiration that we re-register at */
@@ -218,7 +230,7 @@
 /*! \brief Timer callback function, used just for registrations */
 static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
 {
-	RAII_VAR(struct sip_outbound_registration_client_state *, client_state, entry->user_data, ao2_cleanup);
+	struct sip_outbound_registration_client_state *client_state = entry->user_data;
 
 	ao2_ref(client_state, +1);
 	if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
@@ -342,7 +354,10 @@
 		pjsip_tx_data *tdata;
 		if (!ast_sip_create_request_with_auth(response->client_state->sip_outbound_auths, response->client_state->num_outbound_auths,
 				response->rdata, response->tsx, &tdata)) {
-			pjsip_regc_send(response->client_state->client, tdata);
+			ao2_ref(response->client_state, +1);
+			if (pjsip_regc_send(response->client_state->client, tdata) != PJ_SUCCESS) {
+				ao2_cleanup(response->client_state);
+			}
 			return 0;
 		}
 		/* Otherwise, fall through so the failure is processed appropriately */
@@ -397,6 +412,7 @@
 	response->code = param->code;
 	response->expiration = param->expiration;
 	response->client_state = client_state;
+	ao2_ref(response->client_state, +1);
 
 	if (param->rdata) {
 		struct pjsip_retry_after_hdr *retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER, NULL);
@@ -405,8 +421,6 @@
 		response->tsx = pjsip_rdata_get_tsx(param->rdata);
 		pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
 	}
-
-	ao2_ref(response->client_state, +1);
 
 	if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
 		ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
@@ -750,6 +764,145 @@
 	}
 	return 0;
 }
+
+static struct sip_outbound_registration *find_registration(const char *registration_name)
+{
+	return ast_sorcery_retrieve_by_id(
+		ast_sip_get_sorcery(),
+		"registration",
+		registration_name);
+}
+
+static int unregister_task(void *obj)
+{
+	RAII_VAR(struct sip_outbound_registration*, registration, obj, ao2_cleanup);
+	struct pjsip_regc *client = registration->state->client_state->client;
+	pjsip_tx_data *tdata;
+
+	if (pjsip_regc_unregister(client, &tdata) != PJ_SUCCESS) {
+		return 0;
+	}
+
+	ao2_ref(registration->state->client_state, +1);
+	if (pjsip_regc_send(client, tdata) != PJ_SUCCESS) {
+		ao2_cleanup(registration->state->client_state);
+	}
+
+	return 0;
+}
+
+static int queue_unregister(struct sip_outbound_registration *registration)
+{
+	ao2_ref(registration, +1);
+	if (ast_sip_push_task(registration->state->client_state->serializer, unregister_task, registration)) {
+		ao2_cleanup(registration);
+		return -1;
+	}
+	return 0;
+}
+
+static char *cli_complete_registration(const char *line, const char *word,
+int pos, int state)
+{
+	char *result = NULL;
+	int wordlen;
+	int which = 0;
+	struct sip_outbound_registration *registration;
+	RAII_VAR(struct ao2_container *, registrations, NULL, ao2_cleanup);
+	struct ao2_iterator i;
+
+	if (pos != 2) {
+		return NULL;
+	}
+
+	wordlen = strlen(word);
+	registrations = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
+		AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+	if (!registrations) {
+		return NULL;
+	}
+
+	i = ao2_iterator_init(registrations, 0);
+	while ((registration = ao2_iterator_next(&i))) {
+		const char *name = ast_sorcery_object_get_id(registration);
+		if (!strncasecmp(word, name, wordlen) && ++which > state) {
+			result = ast_strdup(name);
+		}
+
+		ao2_cleanup(registration);
+		if (result) {
+			break;
+		}
+	}
+	ao2_iterator_destroy(&i);
+	return result;
+}
+
+static char *cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	RAII_VAR(struct sip_outbound_registration *, registration, NULL, ao2_cleanup);
+	const char *registration_name;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "pjsip unregister";
+		e->usage =
+			"Usage: pjsip unregister <registration>\n"
+			"       Send a SIP REGISTER request to the specified outbound registration with an expiration of 0.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return cli_complete_registration(a->line, a->word, a->pos, a->n);
+	}
+
+	if (a->argc != 3) {
+		return CLI_SHOWUSAGE;
+	}
+
+	registration_name = a->argv[2];
+
+	registration = find_registration(registration_name);
+	if (!registration) {
+		ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
+		return CLI_FAILURE;
+	}
+
+	if (queue_unregister(registration)) {
+		ast_cli(a->fd, "Failed to queue unregistration");
+		return 0;
+	}
+
+	return CLI_SUCCESS;
+}
+
+static int ami_unregister(struct mansession *s, const struct message *m)
+{
+	const char *registration_name = astman_get_header(m, "Registration");
+	RAII_VAR(struct sip_outbound_registration *, registration, NULL, ao2_cleanup);
+
+	if (ast_strlen_zero(registration_name)) {
+		astman_send_error(s, m, "Registration parameter missing.");
+		return 0;
+	}
+
+	registration = find_registration(registration_name);
+	if (!registration) {
+		astman_send_error(s, m, "Unable to retrieve registration entry\n");
+		return 0;
+	}
+
+
+	if (queue_unregister(registration)) {
+		astman_send_ack(s, m, "Failed to queue unregistration");
+		return 0;
+	}
+
+	astman_send_ack(s, m, "Unregistration sent");
+	return 0;
+}
+
+static struct ast_cli_entry cli_outbound_registration[] = {
+	AST_CLI_DEFINE(cli_unregister, "Send an REGISTER request to an outbound registration target with a expiration of 0")
+};
 
 static int load_module(void)
 {
@@ -773,6 +926,8 @@
 	ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
 	sip_outbound_registration_perform_all();
 
+	ast_cli_register_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
+	ast_manager_register_xml("PJSIPUnregister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_unregister);
 	return AST_MODULE_LOAD_SUCCESS;
 }
 
@@ -785,6 +940,8 @@
 
 static int unload_module(void)
 {
+	ast_cli_unregister_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
+	ast_manager_unregister("PJSIPUnregister");
 	return 0;
 }
 




More information about the svn-commits mailing list