Revision
16751
Author
sathieu
Date
2010-02-24 05:58:15 -0600 (Wed, 24 Feb 2010)

Log Message

Skinny: Milestone 1 : device level (API)

skinny device *
skinny device <device_name>

Modified Paths

Diff

Modified: freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.c (16750 => 16751)


--- freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.c	2010-02-24 11:58:07 UTC (rev 16750)
+++ freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.c	2010-02-24 11:58:15 UTC (rev 16751)
@@ -113,7 +113,7 @@
 	char deviceName[16];
 	uint32_t userId;
 	uint32_t instance;
-	uint32_t ip;
+	struct in_addr ip;
 	uint32_t deviceType;
 	uint32_t maxStreams;
 };
@@ -156,13 +156,15 @@
 	char deviceName[16];
 	uint32_t userId;
 	uint32_t instance;
-	uint32_t ip;
+	struct in_addr ip;
 	uint32_t deviceType;
 	uint32_t maxStreams;
 	uint16_t port;
 };
 typedef struct skinny_device skinny_device_t;
 
+typedef switch_status_t (*skinny_command_t) (char **argv, int argc, switch_stream_handle_t *stream);
+
 /*****************************************************************************/
 /* LISTENERS TYPES */
 /*****************************************************************************/
@@ -189,7 +191,7 @@
 
 typedef struct listener listener_t;
 
-typedef switch_status_t (*skinny_listener_callback_func_t) (listener_t *listener);
+typedef switch_status_t (*skinny_listener_callback_func_t) (listener_t *listener, void *pvt);
 
 static struct {
 	switch_socket_t *sock;
@@ -218,7 +220,7 @@
 
 
 /* LISTENER FUNCTIONS */
-static switch_status_t keepalive_listener(listener_t *listener);
+static switch_status_t keepalive_listener(listener_t *listener, void *pvt);
 
 /*****************************************************************************/
 /* CHANNEL FUNCTIONS */
@@ -735,7 +737,7 @@
 			reply->data.reg_ack.secondaryKeepAlive = globals.keep_alive;
 			/* TODO send CapabilitiesReqMessage (and parse the CapabilitiesResMessage) */
 			/* TODO event */
-			keepalive_listener(listener);
+			keepalive_listener(listener, NULL);
 			break;
 		case PORT_MESSAGE:
 			/* Nothing to do */
@@ -744,7 +746,7 @@
 			reply = switch_core_alloc(listener->pool, 12);
 			reply->type = KEEP_ALIVE_ACK_MESSAGE;
 			reply->length = 4;
-			keepalive_listener(listener);
+			keepalive_listener(listener, NULL);
 			break;
 		/* TODO */
 		default:
@@ -807,13 +809,13 @@
 }
 
 
-static void walk_listeners(skinny_listener_callback_func_t callback)
+static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt)
 {
 	listener_t *l;
 
 	switch_mutex_lock(globals.listener_mutex);
 	for (l = listen_list.listeners; l; l = l->next) {
-		callback(l);
+		callback(l, pvt);
 	}
 	switch_mutex_unlock(globals.listener_mutex);
 
@@ -825,6 +827,47 @@
 	/* TODO */
 }
 
+static listener_t *find_listener(char *device_name)
+{
+	listener_t *l, *r = NULL;
+	skinny_device_t *device;
+
+	switch_mutex_lock(globals.listener_mutex);
+	for (l = listen_list.listeners; l; l = l->next) {
+		if (l->device) {
+			device = l->device;
+			if(!strcasecmp(device->deviceName,device_name)) {
+				if (switch_thread_rwlock_tryrdlock(l->rwlock) == SWITCH_STATUS_SUCCESS) {
+					r = l;
+				}
+				break;
+			}
+		}
+	}
+	switch_mutex_unlock(globals.listener_mutex);
+	return r;
+}
+
+static switch_status_t dump_listener(listener_t *listener, void *pvt)
+{
+	switch_stream_handle_t *stream = (switch_stream_handle_t *) pvt;
+	const char *line = "=================================================================================================";
+	skinny_device_t *device;
+	if(listener->device) {
+		device = listener->device;
+		stream->write_function(stream, "%s\n", line);
+		stream->write_function(stream, "DeviceName    \t%s\n", switch_str_nil(device->deviceName));
+		stream->write_function(stream, "UserId        \t%d\n", device->userId);
+		stream->write_function(stream, "Instance      \t%d\n", device->instance);
+		stream->write_function(stream, "IP            \t%s\n", inet_ntoa(device->ip));
+		stream->write_function(stream, "DeviceType    \t%d\n", device->deviceType);
+		stream->write_function(stream, "MaxStreams    \t%d\n", device->maxStreams);
+		stream->write_function(stream, "Port          \t%d\n", device->port);
+		stream->write_function(stream, "%s\n", line);
+	}
+	return SWITCH_STATUS_SUCCESS;
+}
+
 static void close_socket(switch_socket_t **sock)
 {
 	switch_mutex_lock(listen_list.sock_mutex);
@@ -836,7 +879,7 @@
 	switch_mutex_unlock(listen_list.sock_mutex);
 }
 
-static switch_status_t kill_listener(listener_t *listener)
+static switch_status_t kill_listener(listener_t *listener, void *pvt)
 {
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Killing listener.\n");
 	switch_clear_flag(listener, LFLAG_RUNNING);
@@ -844,15 +887,15 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
-static switch_status_t kill_expired_listener(listener_t *listener)
+static switch_status_t kill_expired_listener(listener_t *listener, void *pvt)
 {
 	if(listener->expire_time < switch_epoch_time_now(NULL)) {
-		return kill_listener(listener);
+		return kill_listener(listener, pvt);
 	}
 	return SWITCH_STATUS_SUCCESS;
 }
 
-static switch_status_t keepalive_listener(listener_t *listener)
+static switch_status_t keepalive_listener(listener_t *listener, void *pvt)
 {
 	switch_assert(listener);
 	
@@ -895,7 +938,7 @@
 
 	switch_socket_opt_set(listener->sock, SWITCH_SO_NONBLOCK, TRUE);
 	switch_set_flag_locked(listener, LFLAG_RUNNING);
-	keepalive_listener(listener);
+	keepalive_listener(listener, NULL);
 	add_listener(listener);
 
 
@@ -1140,15 +1183,110 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+static switch_status_t cmd_device(char **argv, int argc, switch_stream_handle_t *stream)
+{
+	listener_t *listener;
+	if (argc != 1) {
+		stream->write_function(stream, "Invalid Args!\n");
+		return SWITCH_STATUS_SUCCESS;
+	}
+	
+	if (argv[0] && !strcasecmp(argv[0], "*")) {
+		walk_listeners(dump_listener, stream);
+	} else {
+		listener=find_listener(argv[0]);
+		if(listener) {
+			dump_listener(listener, stream);
+		}
+	}
+	
+	return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_API(skinny_function)
+{
+	char *argv[1024] = { 0 };
+	int argc = 0;
+	char *mycmd = NULL;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
+	skinny_command_t func = NULL;
+	const char *usage_string = "USAGE:\n"
+		"--------------------------------------------------------------------------------\n"
+		"skinny help\n"
+		"skinny device *\n"
+		"skinny device <device_name>\n"
+		"--------------------------------------------------------------------------------\n";
+	if (session) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	if (zstr(cmd)) {
+		stream->write_function(stream, "%s", usage_string);
+		goto done;
+	}
+
+	if (!(mycmd = strdup(cmd))) {
+		status = SWITCH_STATUS_MEMERR;
+		goto done;
+	}
+
+	if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || !argv[0]) {
+		stream->write_function(stream, "%s", usage_string);
+		goto done;
+	}
+
+	if (!strcasecmp(argv[0], "device")) {
+		func = cmd_device;
+	} else if (!strcasecmp(argv[0], "help")) {
+		stream->write_function(stream, "%s", usage_string);
+		goto done;
+	}
+	
+	if (func) {
+		status = func(&argv[1], argc - 1, stream);
+	} else {
+		stream->write_function(stream, "Unknown Command [%s]\n", argv[0]);
+	}
+
+  done:
+	switch_safe_free(mycmd);
+	return status;
+}
+
 static void event_handler(switch_event_t *event)
 {
 	if (event->event_id == SWITCH_EVENT_HEARTBEAT) {
-		walk_listeners(kill_expired_listener);
+		walk_listeners(kill_expired_listener, NULL);
 	}
 }
 
+static switch_status_t skinny_list_devices(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+	switch_console_callback_match_t *my_matches = NULL;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+	listener_t *l;
+	skinny_device_t *device;
+
+	switch_mutex_lock(globals.listener_mutex);
+	for (l = listen_list.listeners; l; l = l->next) {
+		if(l->device) {
+			device = l->device;
+			switch_console_push_match(&my_matches, device->deviceName);
+		}
+	}
+	switch_mutex_unlock(globals.listener_mutex);
+
+	if (my_matches) {
+		*matches = my_matches;
+		status = SWITCH_STATUS_SUCCESS;
+	}
+	
+	return status;
+}
+
 SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
 {
+	switch_api_interface_t *api_interface;
 
 	module_pool = pool;
 
@@ -1174,6 +1312,12 @@
 	skinny_endpoint_interface->state_handler = &skinny_state_handlers;
 
 
+	SWITCH_ADD_API(api_interface, "skinny", "Skinny Controls", skinny_function, "<cmd> <args>");
+	switch_console_set_complete("add skinny help");
+	switch_console_set_complete("add skinny device *");
+	switch_console_set_complete("add skinny device ::skinny::list_devices");
+
+	switch_console_add_complete_func("::skinny::list_devices", skinny_list_devices);
 	/* indicate that the module should continue to be loaded */
 	return SWITCH_STATUS_SUCCESS;
 }
@@ -1191,13 +1335,13 @@
 
 	running = 0;
 
-	walk_listeners(kill_listener);
+	walk_listeners(kill_listener, NULL);
 
 	close_socket(&listen_list.sock);
 
 	while (globals.listener_threads) {
 		switch_yield(100000);
-		walk_listeners(kill_listener);
+		walk_listeners(kill_listener, NULL);
 		if (++sanity >= 200) {
 			break;
 		}