]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
skypiax: patch from Seven Du for hunting IDLE channels in a round-robin way (RR inter...
authorGiovanni Maruzzelli <gmaruzz@gmail.com>
Wed, 29 Jul 2009 09:08:31 +0000 (09:08 +0000)
committerGiovanni Maruzzelli <gmaruzz@gmail.com>
Wed, 29 Jul 2009 09:08:31 +0000 (09:08 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14410 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/endpoints/mod_skypiax/mod_skypiax.c
src/mod/endpoints/mod_skypiax/skypiax.h
src/mod/endpoints/mod_skypiax/skypiax_protocol.c

index bb888ccf915357ad2de832fdd52a67363d76eeb3..969b2a717bd8318d19cd386468f6af39f56dc2ed 100644 (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_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 <skypeusername | #interface_name | #interface_id> || 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;
index d50e3c91293337d65842992e16383d1da95b38b2..3971ca0143957036c21b0ae17f0833c5f1cec087 100644 (file)
@@ -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);
index 07c0be6e0b82e52ed08613de4d663f7ae0ca2ca4..8ccc1d41ad7d76c0abdc8bf08a3b8c7e216fd2a1 100644 (file)
@@ -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;
 
 }