From 506d3768a1fcfc30efad286a7844e90a56e62b26 Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Wed, 29 Jul 2009 09:08:31 +0000 Subject: [PATCH] skypiax: patch from Seven Du for hunting IDLE channels in a round-robin way (RR interface vs ANY interface). patch from Seven Du for removing interface as #'interface_id' and #'interface_name'. gmaruzz (meh) patch interface_remove() not to alter the global 'running' variable (it would cause all running signaling and API thread to exit) but to use a newly added tech_pvt->running variable. Also, changed behavior of interface_exists() for correct identification when using #interface_name and #interface_id. PLEASE TEST IT HEAVILY git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14410 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/endpoints/mod_skypiax/mod_skypiax.c | 165 +++++++++++++++--- src/mod/endpoints/mod_skypiax/skypiax.h | 2 + .../endpoints/mod_skypiax/skypiax_protocol.c | 22 +-- 3 files changed, 155 insertions(+), 34 deletions(-) diff --git a/src/mod/endpoints/mod_skypiax/mod_skypiax.c b/src/mod/endpoints/mod_skypiax/mod_skypiax.c index bb888ccf91..969b2a717b 100644 --- a/src/mod/endpoints/mod_skypiax/mod_skypiax.c +++ b/src/mod/endpoints/mod_skypiax/mod_skypiax.c @@ -86,7 +86,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown); SWITCH_MODULE_DEFINITION(mod_skypiax, mod_skypiax_load, mod_skypiax_shutdown, NULL); SWITCH_STANDARD_API(sk_function); /* BEGIN: Changes here */ -#define SK_SYNTAX "list || reload || console || remove interface_name || skype_API_msg" +#define SK_SYNTAX "list [full] || console || skype_API_msg || remove || reload" /* END: Changes heres */ SWITCH_STANDARD_API(skypiax_function); #define SKYPIAX_SYNTAX "interface_name skype_API_msg" @@ -111,7 +111,9 @@ static struct { int codec_rates_last; unsigned int flags; int fd; - int calls; + int calls; + int real_interfaces; + int next_interface; char hold_music[256]; private_t SKYPIAX_INTERFACES[SKYPIAX_MAX_INTERFACES]; switch_mutex_t *mutex; @@ -211,20 +213,45 @@ void skypiax_tech_init(private_t * tech_pvt, switch_core_session_t * session) } /* BEGIN: Changes here */ -static switch_status_t interface_exists(char *skype_user) +static switch_status_t interface_exists(char *interface) { int i; + int interface_id; + + if ( *interface == '#') { /* look by interface id or interface name */ + interface++; + switch_assert(interface); + interface_id = atoi(interface); + + /* take a number as interface id */ + if ( interface_id > 0 || (interface_id == 0 && strcmp(interface, "0") == 0 )) { + if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) { + return SWITCH_STATUS_SUCCESS; + } + } else { + + for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) { + if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].name, interface) == 0) { + return SWITCH_STATUS_SUCCESS; + break; + } + } + } + } else { /* look by skype_user */ + + for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) { if (strlen(globals.SKYPIAX_INTERFACES[i].name)) { - if (strcmp(globals.SKYPIAX_INTERFACES[i].skype_user, skype_user) == 0) { + if (strcmp(globals.SKYPIAX_INTERFACES[i].name, interface) == 0) { return SWITCH_STATUS_SUCCESS; } } } + } return SWITCH_STATUS_FALSE; } -static switch_status_t remove_interface(char *skype_user) +static switch_status_t remove_interface(char *interface) { int x = 100; unsigned int howmany = 8; @@ -232,26 +259,48 @@ static switch_status_t remove_interface(char *skype_user) private_t *tech_pvt = NULL; switch_status_t status; - running = 0; + //running = 0; - for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) { - if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].skype_user, skype_user) == 0) { + + if ( *interface == '#') { /* remove by interface id or interface name */ + interface++; + switch_assert(interface); + interface_id = atoi(interface); + + if ( interface_id > 0 || (interface_id == 0 && strcmp(interface, "0") == 0 )) { + /* take a number as interface id */ tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id]; - break; + } else { + + for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) { + if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].name, interface) == 0) { + tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id]; + break; + } + } + } + } else { /* remove by skype_user */ + for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) { + if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].skype_user, interface) == 0) { + tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id]; + break; + } } } if (!tech_pvt) { - DEBUGA_SKYPE("interface for skype user '%s' does not exist\n", SKYPIAX_P_LOG, - skype_user); + DEBUGA_SKYPE("interface '%s' does not exist\n", SKYPIAX_P_LOG, + interface); goto end; } if (strlen(globals.SKYPIAX_INTERFACES[interface_id].session_uuid_str)) { - DEBUGA_SKYPE("interface for skype user '%s' is busy\n", SKYPIAX_P_LOG, skype_user); + DEBUGA_SKYPE("interface '%s' is busy\n", SKYPIAX_P_LOG, interface); goto end; } + globals.SKYPIAX_INTERFACES[interface_id].running=0; + if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) { #ifdef WIN32 switch_file_write(tech_pvt->SkypiaxHandles.fdesc[1], "sciutati", &howmany); // let's the controldev_thread die @@ -300,10 +349,16 @@ static switch_status_t remove_interface(char *skype_user) } memset(&globals.SKYPIAX_INTERFACES[interface_id], '\0', sizeof(private_t)); - DEBUGA_SKYPE("interface for skype user '%s' deleted successfully\n", SKYPIAX_P_LOG, - skype_user); + + switch_mutex_lock(globals.mutex); + globals.real_interfaces--; + switch_mutex_unlock(globals.mutex); + + DEBUGA_SKYPE("interface '%s' deleted successfully\n", SKYPIAX_P_LOG, + interface); + globals.SKYPIAX_INTERFACES[interface_id].running=1; end: - running = 1; + //running = 1; return SWITCH_STATUS_SUCCESS; } @@ -333,6 +388,7 @@ static switch_status_t channel_on_init(switch_core_session_t * session) switch_channel_set_state(channel, CS_ROUTING); switch_mutex_lock(globals.mutex); globals.calls++; + switch_mutex_unlock(globals.mutex); DEBUGA_SKYPE("%s CHANNEL INIT\n", SKYPIAX_P_LOG, switch_channel_get_name(channel)); @@ -716,9 +772,14 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t * sess /* we've been asked for the "ANY" interface, let's find the first idle interface */ DEBUGA_SKYPE("Finding one available skype interface\n", SKYPIAX_P_LOG); tech_pvt = find_available_skypiax_interface(NULL); - if (tech_pvt) - found = 1; + if (tech_pvt) found = 1; + } else if(strncmp("RR", interface_name, strlen(interface_name)) == 0) { + /* Find the first idle interface using Round Robin */ + DEBUGA_SKYPE("Finding one available skype interface RR\n", SKYPIAX_P_LOG); + tech_pvt = find_available_skypiax_interface_rr(); + if (tech_pvt) found = 1; } + for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) { /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */ if (strlen(globals.SKYPIAX_INTERFACES[i].name) @@ -815,7 +876,7 @@ static void *SWITCH_THREAD_FUNC skypiax_signaling_thread_func(switch_thread_t * (void *) tech_pvt); while (forever) { - if (!running) + if (!(running && tech_pvt->running)) break; res = skypiax_signaling_read(tech_pvt); if (res == CALLFLOW_INCOMING_HANGUP) { @@ -983,7 +1044,7 @@ static switch_status_t load_config(int reload_type) /* BEGIN: Changes here */ if (reload_type == SOFT_RELOAD) { - if (interface_exists(skype_user) == SWITCH_STATUS_SUCCESS) { + if (interface_exists(name) == SWITCH_STATUS_SUCCESS) { continue; } } @@ -1049,6 +1110,8 @@ static switch_status_t load_config(int reload_type) memset(&newconf, '\0', sizeof(newconf)); globals.SKYPIAX_INTERFACES[interface_id] = newconf; + globals.SKYPIAX_INTERFACES[interface_id].running = 1; + tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id]; @@ -1189,6 +1252,9 @@ static switch_status_t load_config(int reload_type) for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) { if (strlen(globals.SKYPIAX_INTERFACES[i].name)) { + /* How many real intterfaces */ + globals.real_interfaces = i + 1; + tech_pvt = &globals.SKYPIAX_INTERFACES[i]; DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].interface_id=%s\n", @@ -1550,6 +1616,48 @@ private_t *find_available_skypiax_interface(private_t * tech_pvt) else return NULL; } + +private_t *find_available_skypiax_interface_rr(void) +{ + private_t *tech_pvt = NULL; + int i; + /* int num_interfaces = SKYPIAX_MAX_INTERFACES; */ + int num_interfaces = globals.real_interfaces; + + switch_mutex_lock(globals.mutex); + + /* Fact is the real interface start from 1 */ + if (globals.next_interface == 0) globals.next_interface = 1; + + for (i = 0; i < num_interfaces; i++) { + int interface_id; + + interface_id = globals.next_interface + i; + interface_id = interface_id < num_interfaces ? interface_id : interface_id - num_interfaces + 1; + + if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) { + int skype_state = 0; + + tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id]; + skype_state = tech_pvt->interface_state; + DEBUGA_SKYPE("skype interface: %d, name: %s, state: %d\n", SKYPIAX_P_LOG, interface_id, + globals.SKYPIAX_INTERFACES[interface_id].name, skype_state); + if (SKYPIAX_STATE_DOWN == skype_state || 0 == skype_state) { + /*set to Dialing state to avoid other thread fint it, don't know if it is safe */ + tech_pvt->interface_state = SKYPIAX_STATE_DIALING ; + + globals.next_interface = interface_id + 1 < num_interfaces ? interface_id + 1 : 1; + switch_mutex_unlock(globals.mutex); + return tech_pvt; + } + } else { + DEBUGA_SKYPE("Skype interface: %d blank!! A hole here means we cannot hunt the last interface.\n", SKYPIAX_P_LOG, interface_id); + } + } + + switch_mutex_unlock(globals.mutex); + return NULL; +} SWITCH_STANDARD_API(sk_function) { @@ -1571,21 +1679,32 @@ SWITCH_STANDARD_API(sk_function) } if (!strcasecmp(argv[0], "list")) { - int i; + int i; + char next_flag_char = ' '; + for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) { + next_flag_char = i == globals.next_interface ? '*' : ' '; + if (strlen(globals.SKYPIAX_INTERFACES[i].name)) { if (strlen(globals.SKYPIAX_INTERFACES[i].session_uuid_str)) { stream->write_function(stream, - "globals.SKYPIAX_INTERFACES[%d].name=\t|||%s||| is \tBUSY, session_uuid_str=|||%s|||\n", + "%c\t%d\t[%s]\tBUSY, session_uuid_str=|||%s|||\n", + next_flag_char, i, globals.SKYPIAX_INTERFACES[i].name, globals.SKYPIAX_INTERFACES[i].session_uuid_str); } else { stream->write_function(stream, - "globals.SKYPIAX_INTERFACES[%d].name=\t|||%s||| is \tIDLE\n", + "%c\t%d\t[%s]\tIDLE\n", + next_flag_char, i, globals.SKYPIAX_INTERFACES[i].name); } - } + } else if(argc > 1 && !strcasecmp(argv[1], "full")) { + stream->write_function(stream, "%c\t%d\n", next_flag_char, i); + } + } + stream->write_function(stream, "\nTotal: %d\n", globals.real_interfaces - 1 ); + } else if (!strcasecmp(argv[0], "console")) { int i; int found = 0; diff --git a/src/mod/endpoints/mod_skypiax/skypiax.h b/src/mod/endpoints/mod_skypiax/skypiax.h index d50e3c9129..3971ca0143 100644 --- a/src/mod/endpoints/mod_skypiax/skypiax.h +++ b/src/mod/endpoints/mod_skypiax/skypiax.h @@ -238,6 +238,7 @@ struct private_object { struct timeval transfer_time; char transfer_callid_number[50]; char skype_transfer_call_id[512]; + int running; }; typedef struct private_object private_t; @@ -276,6 +277,7 @@ int skypiax_pipe_write(int pipe, short *buf, int howmany); #endif /* WIN32 */ int skypiax_close_socket(unsigned int fd); private_t *find_available_skypiax_interface(private_t * tech_pvt); +private_t *find_available_skypiax_interface_rr(void); int remote_party_is_ringing(private_t * tech_pvt); int remote_party_is_early_media(private_t * tech_pvt); int skypiax_answer(private_t * tech_pvt, char *id, char *value); diff --git a/src/mod/endpoints/mod_skypiax/skypiax_protocol.c b/src/mod/endpoints/mod_skypiax/skypiax_protocol.c index 07c0be6e0b..8ccc1d41ad 100644 --- a/src/mod/endpoints/mod_skypiax/skypiax_protocol.c +++ b/src/mod/endpoints/mod_skypiax/skypiax_protocol.c @@ -489,7 +489,7 @@ void *skypiax_do_tcp_srv_thread_func(void *obj) fd_set fsgio; struct timeval togio; - if (!running) + if (!(running && tech_pvt->running)) break; FD_ZERO(&fsgio); togio.tv_usec = 20000; //20msec @@ -506,7 +506,7 @@ void *skypiax_do_tcp_srv_thread_func(void *obj) while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) { DEBUGA_SKYPE("ACCEPTED here I send you %d\n", SKYPIAX_P_LOG, tech_pvt->tcp_srv_port); - if (!running) + if (!(running && tech_pvt->running)) break; while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS @@ -519,7 +519,7 @@ void *skypiax_do_tcp_srv_thread_func(void *obj) fd_set fs; struct timeval to; - if (!running) + if (!(running && tech_pvt->running)) break; //exit = 1; @@ -677,7 +677,7 @@ void *skypiax_do_tcp_cli_thread_func(void *obj) fd_set fsgio; struct timeval togio; - if (!running) + if (!(running && tech_pvt->running)) break; FD_ZERO(&fsgio); togio.tv_usec = 20000; //20msec @@ -698,7 +698,7 @@ void *skypiax_do_tcp_cli_thread_func(void *obj) fcntl(tech_pvt->audioskypepipe[0], F_SETFL, O_NONBLOCK); #endif //WIN32 - if (!running) + if (!(running && tech_pvt->running)) break; while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS @@ -710,7 +710,7 @@ void *skypiax_do_tcp_cli_thread_func(void *obj) fd_set fs; struct timeval to; - if (!running) + if (!(running && tech_pvt->running)) break; FD_ZERO(&fs); to.tv_usec = 120000; //120msec @@ -1238,9 +1238,9 @@ void *skypiax_do_skypeapi_thread_func(void *obj) (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0) != 0) { tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle; - while (running) { + while (running && tech_pvt->running) { MSG oMessage; - if (!running) + if (! (running && tech_pvt->running)) break; while (GetMessage(&oMessage, 0, 0, 0)) { TranslateMessage(&oMessage); @@ -1264,7 +1264,7 @@ int X11_errors_handler(Display * dpy, XErrorEvent * err) private_t *tech_pvt = NULL; xerror = err->error_code; - ERRORA("Received error code %d from X Server\n\n", SKYPIAX_P_LOG, xerror); + ERRORA("Received error code %d from X Server\n\n", SKYPIAX_P_LOG, xerror); ///FIXME why crash the entire skypiax? just crash the interface, instead running = 0; return 0; /* ignore the error */ } @@ -1489,7 +1489,7 @@ void *skypiax_do_skypeapi_thread_func(void *obj) while (1) { XNextEvent(disp, &an_event); - if (!running) + if (! (running && tech_pvt->running)) break; switch (an_event.type) { case ClientMessage: @@ -1557,7 +1557,7 @@ void *skypiax_do_skypeapi_thread_func(void *obj) running = 0; return NULL; } - running = 0; + //running = 0; return NULL; }