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
This commit is contained in:
Giovanni Maruzzelli 2009-07-29 09:08:31 +00:00
parent f4b2efba87
commit 506d3768a1
3 changed files with 155 additions and 34 deletions

View File

@ -86,7 +86,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown);
SWITCH_MODULE_DEFINITION(mod_skypiax, mod_skypiax_load, mod_skypiax_shutdown, NULL); SWITCH_MODULE_DEFINITION(mod_skypiax, mod_skypiax_load, mod_skypiax_shutdown, NULL);
SWITCH_STANDARD_API(sk_function); SWITCH_STANDARD_API(sk_function);
/* BEGIN: Changes here */ /* 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 <skypeusername | #interface_name | #interface_id> || reload"
/* END: Changes heres */ /* END: Changes heres */
SWITCH_STANDARD_API(skypiax_function); SWITCH_STANDARD_API(skypiax_function);
#define SKYPIAX_SYNTAX "interface_name skype_API_msg" #define SKYPIAX_SYNTAX "interface_name skype_API_msg"
@ -111,7 +111,9 @@ static struct {
int codec_rates_last; int codec_rates_last;
unsigned int flags; unsigned int flags;
int fd; int fd;
int calls; int calls;
int real_interfaces;
int next_interface;
char hold_music[256]; char hold_music[256];
private_t SKYPIAX_INTERFACES[SKYPIAX_MAX_INTERFACES]; private_t SKYPIAX_INTERFACES[SKYPIAX_MAX_INTERFACES];
switch_mutex_t *mutex; switch_mutex_t *mutex;
@ -211,20 +213,45 @@ void skypiax_tech_init(private_t * tech_pvt, switch_core_session_t * session)
} }
/* BEGIN: Changes here */ /* BEGIN: Changes here */
static switch_status_t interface_exists(char *skype_user) static switch_status_t interface_exists(char *interface)
{ {
int i; 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++) { for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) {
if (strlen(globals.SKYPIAX_INTERFACES[i].name)) { 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_SUCCESS;
} }
} }
} }
}
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
static switch_status_t remove_interface(char *skype_user) static switch_status_t remove_interface(char *interface)
{ {
int x = 100; int x = 100;
unsigned int howmany = 8; unsigned int howmany = 8;
@ -232,26 +259,48 @@ static switch_status_t remove_interface(char *skype_user)
private_t *tech_pvt = NULL; private_t *tech_pvt = NULL;
switch_status_t status; 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]; 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) { if (!tech_pvt) {
DEBUGA_SKYPE("interface for skype user '%s' does not exist\n", SKYPIAX_P_LOG, DEBUGA_SKYPE("interface '%s' does not exist\n", SKYPIAX_P_LOG,
skype_user); interface);
goto end; goto end;
} }
if (strlen(globals.SKYPIAX_INTERFACES[interface_id].session_uuid_str)) { 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; goto end;
} }
globals.SKYPIAX_INTERFACES[interface_id].running=0;
if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) { if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
#ifdef WIN32 #ifdef WIN32
switch_file_write(tech_pvt->SkypiaxHandles.fdesc[1], "sciutati", &howmany); // let's the controldev_thread die 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)); 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: end:
running = 1; //running = 1;
return SWITCH_STATUS_SUCCESS; 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_channel_set_state(channel, CS_ROUTING);
switch_mutex_lock(globals.mutex); switch_mutex_lock(globals.mutex);
globals.calls++; globals.calls++;
switch_mutex_unlock(globals.mutex); switch_mutex_unlock(globals.mutex);
DEBUGA_SKYPE("%s CHANNEL INIT\n", SKYPIAX_P_LOG, switch_channel_get_name(channel)); 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 */ /* 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); DEBUGA_SKYPE("Finding one available skype interface\n", SKYPIAX_P_LOG);
tech_pvt = find_available_skypiax_interface(NULL); tech_pvt = find_available_skypiax_interface(NULL);
if (tech_pvt) if (tech_pvt) found = 1;
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++) { 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 */ /* 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) 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); (void *) tech_pvt);
while (forever) { while (forever) {
if (!running) if (!(running && tech_pvt->running))
break; break;
res = skypiax_signaling_read(tech_pvt); res = skypiax_signaling_read(tech_pvt);
if (res == CALLFLOW_INCOMING_HANGUP) { if (res == CALLFLOW_INCOMING_HANGUP) {
@ -983,7 +1044,7 @@ static switch_status_t load_config(int reload_type)
/* BEGIN: Changes here */ /* BEGIN: Changes here */
if (reload_type == SOFT_RELOAD) { if (reload_type == SOFT_RELOAD) {
if (interface_exists(skype_user) == SWITCH_STATUS_SUCCESS) { if (interface_exists(name) == SWITCH_STATUS_SUCCESS) {
continue; continue;
} }
} }
@ -1049,6 +1110,8 @@ static switch_status_t load_config(int reload_type)
memset(&newconf, '\0', sizeof(newconf)); memset(&newconf, '\0', sizeof(newconf));
globals.SKYPIAX_INTERFACES[interface_id] = newconf; globals.SKYPIAX_INTERFACES[interface_id] = newconf;
globals.SKYPIAX_INTERFACES[interface_id].running = 1;
tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id]; 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++) { for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) {
if (strlen(globals.SKYPIAX_INTERFACES[i].name)) { if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
/* How many real intterfaces */
globals.real_interfaces = i + 1;
tech_pvt = &globals.SKYPIAX_INTERFACES[i]; tech_pvt = &globals.SKYPIAX_INTERFACES[i];
DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].interface_id=%s\n", 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 else
return NULL; 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) SWITCH_STANDARD_API(sk_function)
{ {
@ -1571,21 +1679,32 @@ SWITCH_STANDARD_API(sk_function)
} }
if (!strcasecmp(argv[0], "list")) { if (!strcasecmp(argv[0], "list")) {
int i; int i;
char next_flag_char = ' ';
for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) { 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].name)) {
if (strlen(globals.SKYPIAX_INTERFACES[i].session_uuid_str)) { if (strlen(globals.SKYPIAX_INTERFACES[i].session_uuid_str)) {
stream->write_function(stream, 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, i, globals.SKYPIAX_INTERFACES[i].name,
globals.SKYPIAX_INTERFACES[i].session_uuid_str); globals.SKYPIAX_INTERFACES[i].session_uuid_str);
} else { } else {
stream->write_function(stream, 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); 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")) { } else if (!strcasecmp(argv[0], "console")) {
int i; int i;
int found = 0; int found = 0;

View File

@ -238,6 +238,7 @@ struct private_object {
struct timeval transfer_time; struct timeval transfer_time;
char transfer_callid_number[50]; char transfer_callid_number[50];
char skype_transfer_call_id[512]; char skype_transfer_call_id[512];
int running;
}; };
typedef struct private_object private_t; typedef struct private_object private_t;
@ -276,6 +277,7 @@ int skypiax_pipe_write(int pipe, short *buf, int howmany);
#endif /* WIN32 */ #endif /* WIN32 */
int skypiax_close_socket(unsigned int fd); int skypiax_close_socket(unsigned int fd);
private_t *find_available_skypiax_interface(private_t * tech_pvt); 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_ringing(private_t * tech_pvt);
int remote_party_is_early_media(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); int skypiax_answer(private_t * tech_pvt, char *id, char *value);

View File

@ -489,7 +489,7 @@ void *skypiax_do_tcp_srv_thread_func(void *obj)
fd_set fsgio; fd_set fsgio;
struct timeval togio; struct timeval togio;
if (!running) if (!(running && tech_pvt->running))
break; break;
FD_ZERO(&fsgio); FD_ZERO(&fsgio);
togio.tv_usec = 20000; //20msec 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) { while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
DEBUGA_SKYPE("ACCEPTED here I send you %d\n", SKYPIAX_P_LOG, DEBUGA_SKYPE("ACCEPTED here I send you %d\n", SKYPIAX_P_LOG,
tech_pvt->tcp_srv_port); tech_pvt->tcp_srv_port);
if (!running) if (!(running && tech_pvt->running))
break; break;
while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
&& (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
@ -519,7 +519,7 @@ void *skypiax_do_tcp_srv_thread_func(void *obj)
fd_set fs; fd_set fs;
struct timeval to; struct timeval to;
if (!running) if (!(running && tech_pvt->running))
break; break;
//exit = 1; //exit = 1;
@ -677,7 +677,7 @@ void *skypiax_do_tcp_cli_thread_func(void *obj)
fd_set fsgio; fd_set fsgio;
struct timeval togio; struct timeval togio;
if (!running) if (!(running && tech_pvt->running))
break; break;
FD_ZERO(&fsgio); FD_ZERO(&fsgio);
togio.tv_usec = 20000; //20msec 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); fcntl(tech_pvt->audioskypepipe[0], F_SETFL, O_NONBLOCK);
#endif //WIN32 #endif //WIN32
if (!running) if (!(running && tech_pvt->running))
break; break;
while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
&& (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
@ -710,7 +710,7 @@ void *skypiax_do_tcp_cli_thread_func(void *obj)
fd_set fs; fd_set fs;
struct timeval to; struct timeval to;
if (!running) if (!(running && tech_pvt->running))
break; break;
FD_ZERO(&fs); FD_ZERO(&fs);
to.tv_usec = 120000; //120msec 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) { (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0) != 0) {
tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle =
tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle; tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle;
while (running) { while (running && tech_pvt->running) {
MSG oMessage; MSG oMessage;
if (!running) if (! (running && tech_pvt->running))
break; break;
while (GetMessage(&oMessage, 0, 0, 0)) { while (GetMessage(&oMessage, 0, 0, 0)) {
TranslateMessage(&oMessage); TranslateMessage(&oMessage);
@ -1264,7 +1264,7 @@ int X11_errors_handler(Display * dpy, XErrorEvent * err)
private_t *tech_pvt = NULL; private_t *tech_pvt = NULL;
xerror = err->error_code; 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; running = 0;
return 0; /* ignore the error */ return 0; /* ignore the error */
} }
@ -1489,7 +1489,7 @@ void *skypiax_do_skypeapi_thread_func(void *obj)
while (1) { while (1) {
XNextEvent(disp, &an_event); XNextEvent(disp, &an_event);
if (!running) if (! (running && tech_pvt->running))
break; break;
switch (an_event.type) { switch (an_event.type) {
case ClientMessage: case ClientMessage:
@ -1557,7 +1557,7 @@ void *skypiax_do_skypeapi_thread_func(void *obj)
running = 0; running = 0;
return NULL; return NULL;
} }
running = 0; //running = 0;
return NULL; return NULL;
} }