]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add switch_ivr_enterprise_originate optional new dimension to originate strings every...
authorAnthony Minessale <anthony.minessale@gmail.com>
Thu, 12 Nov 2009 22:21:30 +0000 (22:21 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Thu, 12 Nov 2009 22:21:30 +0000 (22:21 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15455 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_ivr.h
src/include/switch_utils.h
src/switch_ivr_originate.c
src/switch_utils.c

index c47e3d9b58c1615789bdb3ef9741fc21c7baa8ac..b8bdb15c97f2e5ce8432d2300e4f98dc90a4850e 100644 (file)
@@ -409,6 +409,19 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
                                                                                                         switch_originate_flag_t flags
                                                                                                         );
 
+SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_session_t *session,
+                                                                                                                               switch_core_session_t **bleg,
+                                                                                                                               switch_call_cause_t *cause,
+                                                                                                                               const char *bridgeto,
+                                                                                                                               uint32_t timelimit_sec,
+                                                                                                                               const switch_state_handler_table_t *table,
+                                                                                                                               const char *cid_name_override,
+                                                                                                                               const char *cid_num_override,
+                                                                                                                               switch_caller_profile_t *caller_profile_override, 
+                                                                                                                               switch_event_t *ovars,
+                                                                                                                               switch_originate_flag_t flags
+                                                                                                                               );
+
 SWITCH_DECLARE(void) switch_ivr_bridge_display(switch_core_session_t *session, switch_core_session_t *peer_session);
 
 /*!
index 40699ca8ee19295952a4ff3e37f7fa499a410f00..18bfbaf418cf35133e35950dcd386566263f4660 100644 (file)
@@ -517,6 +517,7 @@ SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in);
   \return the number of elements added to the array
 */
 SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, unsigned int arraylen);
+SWITCH_DECLARE(unsigned int) switch_separate_string_string(char *buf, char *delim, char **array, unsigned int arraylen);
 
 SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
 SWITCH_DECLARE(char *) switch_strip_spaces(const char *str);
index 6a4845e70debf784cc904348830508abd29d8a8f..0f1bbfb0a1451e39ee7359421e81c66ab29f50ea 100644 (file)
@@ -1134,6 +1134,180 @@ static switch_status_t setup_ringback(originate_global_t *oglobals,
  
 }
 
+#define OSEP ":_:"
+#define MAX_PEERS 128
+
+typedef struct {
+       switch_core_session_t *session;
+       switch_core_session_t *bleg;
+       switch_call_cause_t cause;
+       const char *bridgeto;
+       uint32_t timelimit_sec;
+       const switch_state_handler_table_t *table;
+       const char *cid_name_override;
+       const char *cid_num_override;
+       switch_caller_profile_t *caller_profile_override; 
+       switch_event_t *ovars;
+       switch_originate_flag_t flags;
+       switch_status_t status;
+       int done;
+       switch_thread_t *thread;
+} enterprise_originate_handle_t;
+
+
+static void *SWITCH_THREAD_FUNC enterprise_originate_thread(switch_thread_t *thread, void *obj)
+{
+       enterprise_originate_handle_t *handle = (enterprise_originate_handle_t *) obj;
+       
+       handle->done = 0;
+       handle->status = switch_ivr_originate(NULL, &handle->bleg, &handle->cause, 
+                                                                                 handle->bridgeto, handle->timelimit_sec,
+                                                                                 handle->table,
+                                                                                 handle->cid_name_override,
+                                                                                 handle->cid_num_override,
+                                                                                 handle->caller_profile_override,
+                                                                                 handle->ovars,
+                                                                                 handle->flags
+                                                                                 );
+
+
+       handle->done = 1;
+       
+       return NULL;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_session_t *session,
+                                                                                                                  switch_core_session_t **bleg,
+                                                                                                                  switch_call_cause_t *cause,
+                                                                                                                  const char *bridgeto,
+                                                                                                                  uint32_t timelimit_sec,
+                                                                                                                  const switch_state_handler_table_t *table,
+                                                                                                                  const char *cid_name_override,
+                                                                                                                  const char *cid_num_override,
+                                                                                                                  switch_caller_profile_t *caller_profile_override, 
+                                                                                                                  switch_event_t *ovars,
+                                                                                                                  switch_originate_flag_t flags
+                                                                                                                  )
+{
+       int x_argc;
+       char *x_argv[MAX_PEERS] = { 0 };
+       enterprise_originate_handle_t *hp = NULL, handles[MAX_PEERS] = { { 0 } };
+       int i;
+       switch_caller_profile_t *cp = NULL;
+       switch_channel_t *channel = NULL;
+       char *data;
+       switch_status_t status = SWITCH_STATUS_FALSE;
+       switch_threadattr_t *thd_attr = NULL;
+       int running = 0;
+       switch_status_t tstatus = SWITCH_STATUS_FALSE;
+       switch_memory_pool_t *pool;
+       switch_event_header_t *hi = NULL;
+
+       switch_core_new_memory_pool(&pool);
+
+       if (zstr(bridgeto)) {
+               *cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+               switch_goto_status(SWITCH_STATUS_FALSE, end);
+       }
+
+       data = switch_core_strdup(pool, bridgeto);
+
+       if (!(x_argc = switch_separate_string_string(data, OSEP, x_argv, MAX_PEERS))) {
+               *cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+               switch_goto_status(SWITCH_STATUS_FALSE, end);
+       }
+
+       if (session) {
+               channel = switch_core_session_get_channel(session);
+               cp = switch_channel_get_caller_profile(channel);
+       }
+
+       switch_threadattr_create(&thd_attr, pool);
+       switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+
+       for(i = 0; i < x_argc; i++) {
+               handles[i].session = session;
+               handles[i].bleg = NULL;
+               handles[i].cause = 0;
+               handles[i].bridgeto = x_argv[i];
+               handles[i].timelimit_sec = timelimit_sec;
+               handles[i].table = table;
+               handles[i].cid_name_override = cid_name_override;
+               handles[i].cid_num_override = cid_num_override;
+               handles[i].caller_profile_override = cp;
+
+               if (channel) {
+                       switch_channel_get_variables(channel, &handles[i].ovars);
+               } else {
+                       switch_event_create_plain(&handles[i].ovars, SWITCH_EVENT_CHANNEL_DATA);
+               }
+
+               if (ovars) {
+                       for (hi = ovars->headers; hi; hi = hi->next) {
+                               switch_event_add_header_string(handles[i].ovars, SWITCH_STACK_BOTTOM, hi->name, hi->value);
+                       }
+               }
+
+               handles[i].flags = flags;
+               switch_thread_create(&handles[i].thread, thd_attr, enterprise_originate_thread, &handles[i], pool);
+       }
+
+       for(;;) {
+               running = 0;
+
+               for(i = 0; i < x_argc; i++) {
+                       if (handles[i].done == 0) {
+                               running++;
+                       } else if (handles[i].done == 1) {
+                               if (handles[i].status == SWITCH_STATUS_SUCCESS) {
+                                       hp = &handles[i];
+                                       goto done;
+                               } else {
+                                       handles[i].done = 2;
+                               }
+                       }
+                       switch_cond_next();
+               }
+
+               if (!running) {
+                       break;
+               }
+       }
+
+ done:
+
+       for(i = 0; i < x_argc; i++) {
+               if (hp && hp == &handles[i]) {
+                       continue;
+               }
+               if (handles[i].bleg) {
+                       switch_channel_hangup(switch_core_session_get_channel(handles[i].bleg), SWITCH_CAUSE_LOSE_RACE);
+                       switch_core_session_rwunlock(handles[i].bleg);
+               }
+
+               handles[i].cause = SWITCH_CAUSE_LOSE_RACE;
+               switch_thread_join(&tstatus, handles[i].thread);
+               switch_event_destroy(&handles[i].ovars);
+       }
+       
+
+       if (hp) {
+               *cause = hp->cause;
+               status = hp->status;
+               *bleg = hp->bleg;
+               switch_thread_join(&tstatus, hp->thread);
+               switch_event_destroy(&hp->ovars);
+       }
+
+
+
+ end:
+
+       switch_core_destroy_memory_pool(&pool);
+
+       return status;
+
+}
 
 #define peer_eligible(_peer) (_peer && !(switch_channel_test_flag(_peer, CF_TRANSFER) || \
                                                                                 switch_channel_test_flag(_peer, CF_REDIRECT) || \
@@ -1141,7 +1315,7 @@ static switch_status_t setup_ringback(originate_global_t *oglobals,
                                                                                 switch_channel_get_state(_peer) == CS_RESET || \
                                                                                 !switch_channel_test_flag(_peer, CF_ORIGINATING)))
 
-#define MAX_PEERS 128
+
 SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *session,
                                                                                                         switch_core_session_t **bleg,
                                                                                                         switch_call_cause_t *cause,
@@ -1195,6 +1369,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
        const char *holding = NULL;
        const char *export_vars = NULL;
 
+
+       if (strstr(bridgeto, OSEP)) {
+               return switch_ivr_enterprise_originate(session, bleg, cause, bridgeto, timelimit_sec, table, cid_name_override, cid_num_override,
+                                                                                 caller_profile_override, ovars, flags);
+       }
+
+
        oglobals.ringback_ok = 1;
 
        if (session) {
@@ -1240,8 +1421,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
        oglobals.idx = IDX_NADA;
        oglobals.early_ok = 1;
 
-
-
        *bleg = NULL;
 
        switch_zmalloc(write_frame.data, SWITCH_RECOMMENDED_BUFFER_SIZE);
@@ -2088,7 +2267,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
                                oglobals.ringback_ok = 0;
                        }
                        
-                       while ((!caller_channel || switch_channel_ready(caller_channel) || switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) && 
+                       *cause = 0;
+                       while (*cause == 0 && ((!caller_channel || switch_channel_ready(caller_channel) || switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE))) && 
                                   check_channel_status(&oglobals, originate_status, and_argc)) {
                                time_t elapsed = switch_epoch_time_now(NULL) - start;
                                
@@ -2252,6 +2432,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
                                
                        }
 
+                       if (*cause) {
+                               force_reason = *cause;
+                       }
+
                  notready:
 
                        if (caller_channel) {
index 43a35bbfb002434c5173edd1457af3fb968a6145..f4be40350684baf07ab9c8b00a724f064249c512 100644 (file)
@@ -1589,6 +1589,25 @@ static char *cleanup_separated_string(char *str, char delim)
        return start;
 }
 
+SWITCH_DECLARE(unsigned int) switch_separate_string_string(char *buf, char *delim, char **array, unsigned int arraylen)
+{
+       unsigned int count = 0;
+       char *d;
+       size_t dlen = strlen(delim);
+       
+       array[count++] = buf;
+
+       while (count < arraylen && array[count-1]) {
+               if ((d = strstr(array[count-1], delim))) {
+                       *d = '\0';
+                       d += dlen;
+                       array[count++] = d;
+               } else break;
+       }
+
+       return count;
+}
+
 /* Separate a string using a delimiter that is not a space */
 static unsigned int separate_string_char_delim(char *buf, char delim, char **array, unsigned int arraylen)
 {