From ba1950a75dc1896153dd0f5cd9d8b85bc2909d7d Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 24 Feb 2010 11:58:15 +0000 Subject: [PATCH] Skinny: Milestone 1 : device level (API) skinny device * skinny device git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16751 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/endpoints/mod_skinny/mod_skinny.c | 176 ++++++++++++++++++++-- 1 file changed, 160 insertions(+), 16 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index f3c46cbe85..04b9b153ba 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -113,7 +113,7 @@ struct register_message { 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 @@ struct skinny_device { 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 @@ struct listener { 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 @@ static switch_status_t channel_kill_channel(switch_core_session_t *session, int /* 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 @@ static switch_status_t skinny_parse_request(listener_t *listener, skinny_message 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 @@ static switch_status_t skinny_parse_request(listener_t *listener, skinny_message 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 remove_listener(listener_t *listener) } -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 @@ static void flush_listener(listener_t *listener, switch_bool_t flush_log, switch /* 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 @@ static void close_socket(switch_socket_t **sock) 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 @@ static switch_status_t kill_listener(listener_t *listener) 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 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) 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 @@ static switch_status_t load_skinny_config(void) 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 \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 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load) skinny_endpoint_interface->state_handler = &skinny_state_handlers; + SWITCH_ADD_API(api_interface, "skinny", "Skinny Controls", skinny_function, " "); + 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 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown) 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; }