From bab6ebc54949133dfd46ed79def9dd6ff455f75d Mon Sep 17 00:00:00 2001
From: Nathan Neulinger <nneul@neulinger.org>
Date: Thu, 11 Jul 2013 13:14:44 -0500
Subject: [PATCH] skinny: improve cleanup of devices during registration and
 unregistration, resolves some weird state issues when devices get
 disconnected

---
 src/mod/endpoints/mod_skinny/mod_skinny.c    | 47 ++++++++++++++------
 src/mod/endpoints/mod_skinny/mod_skinny.h    |  1 +
 src/mod/endpoints/mod_skinny/skinny_server.c | 10 ++++-
 3 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c
index 6845ab2070..790eb7836c 100644
--- a/src/mod/endpoints/mod_skinny/mod_skinny.c
+++ b/src/mod/endpoints/mod_skinny/mod_skinny.c
@@ -1315,25 +1315,12 @@ static int flush_listener_callback(void *pArg, int argc, char **argv, char **col
 	return 0;
 }
 
-static void flush_listener(listener_t *listener)
+void skinny_clean_listener_from_db(listener_t *listener)
 {
-
 	if(!zstr(listener->device_name)) {
 		skinny_profile_t *profile = listener->profile;
 		char *sql;
 
-		if ((sql = switch_mprintf(
-						"SELECT '%q', value, '%q', '%q', '%d' "
-						"FROM skinny_lines "
-						"WHERE device_name='%s' AND device_instance=%d "
-						"ORDER BY position",
-						profile->name, profile->domain, listener->device_name, listener->device_instance,
-						listener->device_name, listener->device_instance
-					 ))) {
-			skinny_execute_sql_callback(profile, profile->sql_mutex, sql, flush_listener_callback, NULL);
-			switch_safe_free(sql);
-		}
-
 		if ((sql = switch_mprintf(
 						"DELETE FROM skinny_devices "
 						"WHERE name='%s' and instance=%d",
@@ -1358,6 +1345,38 @@ static void flush_listener(listener_t *listener)
 			switch_safe_free(sql);
 		}
 
+		if ((sql = switch_mprintf(
+						"DELETE FROM skinny_active_lines "
+						"WHERE device_name='%s' and device_instance=%d",
+						listener->device_name, listener->device_instance))) {
+			skinny_execute_sql(profile, sql, profile->sql_mutex);
+			switch_safe_free(sql);
+		}
+
+	}
+}
+
+static void flush_listener(listener_t *listener)
+{
+
+	if(!zstr(listener->device_name)) {
+		skinny_profile_t *profile = listener->profile;
+		char *sql;
+
+		if ((sql = switch_mprintf(
+						"SELECT '%q', value, '%q', '%q', '%d' "
+						"FROM skinny_lines "
+						"WHERE device_name='%s' AND device_instance=%d "
+						"ORDER BY position",
+						profile->name, profile->domain, listener->device_name, listener->device_instance,
+						listener->device_name, listener->device_instance
+					 ))) {
+			skinny_execute_sql_callback(profile, profile->sql_mutex, sql, flush_listener_callback, NULL);
+			switch_safe_free(sql);
+		}
+
+		skinny_clean_listener_from_db(listener);
+
 		strcpy(listener->device_name, "");
 	}
 }
diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h
index e0e3515da4..717bcd0378 100644
--- a/src/mod/endpoints/mod_skinny/mod_skinny.h
+++ b/src/mod/endpoints/mod_skinny/mod_skinny.h
@@ -271,6 +271,7 @@ switch_bool_t skinny_execute_sql_callback(skinny_profile_t *profile,
 uint8_t listener_is_ready(listener_t *listener);
 switch_status_t kill_listener(listener_t *listener, void *pvt);
 switch_status_t keepalive_listener(listener_t *listener, void *pvt);
+void skinny_clean_listener_from_db(listener_t *listener);
 
 /*****************************************************************************/
 /* CHANNEL FUNCTIONS */
diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c
index c3c8f9029b..2b7031186d 100644
--- a/src/mod/endpoints/mod_skinny/skinny_server.c
+++ b/src/mod/endpoints/mod_skinny/skinny_server.c
@@ -964,8 +964,8 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r
 
 	if (!zstr(listener->device_name)) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
-				"A device is already registred on this listener.\n");
-		send_register_reject(listener, "A device is already registred on this listener");
+				"A device is already registered on this listener.\n");
+		send_register_reject(listener, "A device is already registered on this listener");
 		return SWITCH_STATUS_FALSE;
 	}
 
@@ -993,6 +993,9 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r
 		goto end;
 	}
 
+	/* clean up all traces before adding to database */
+	skinny_clean_listener_from_db(listener);
+
 	if ((sql = switch_mprintf(
 					"INSERT INTO skinny_devices "
 					"(name, user_id, instance, ip, type, max_streams, codec_string) "
@@ -1952,6 +1955,9 @@ switch_status_t skinny_handle_unregister(listener_t *listener, skinny_message_t
 	/* Close socket */
 	switch_clear_flag_locked(listener, LFLAG_RUNNING);
 
+	/* Clear this device from database and any active lines/etc. */
+	skinny_clean_listener_from_db(listener);
+
 	return SWITCH_STATUS_SUCCESS;
 }