]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
skypopen: CLOUDTREE patch with some modifications
authorGiovanni Maruzzelli <gmaruzz@gmail.com>
Mon, 25 Oct 2010 20:36:12 +0000 (15:36 -0500)
committerGiovanni Maruzzelli <gmaruzz@gmail.com>
Wed, 27 Oct 2010 14:44:50 +0000 (09:44 -0500)
src/mod/endpoints/mod_skypopen/mod_skypopen.c
src/mod/endpoints/mod_skypopen/skypopen.h
src/mod/endpoints/mod_skypopen/skypopen_protocol.c

index e83288770ba65bfab6c005785cb311417e2c8541..5837cbe1e4d8083ea6a51e0d40947e131ceeecd2 100644 (file)
@@ -159,12 +159,23 @@ static struct {
        switch_mutex_t *mutex;
        private_t *sk_console;
        int start_port;
+
+       // CLOUDTREE (THomas Hazel)
+       switch_mutex_t *list_mutex;
+
 } globals;
 
 switch_endpoint_interface_t *skypopen_endpoint_interface;
 switch_memory_pool_t *skypopen_module_pool = NULL;
 int running = 0;
 
+// CLOUDTREE (THomas Hazel)
+#ifndef WIN32
+struct SkypopenList global_handles_list;
+extern int xio_error_handler(Display *dpy);
+extern int X11_errors_handler(Display * dpy, XErrorEvent * err);
+#endif
+
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_context, globals.context);
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan);
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_destination, globals.destination);
@@ -175,7 +186,7 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_write_silence_when_idle, globals.wr
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_setsockopt, globals.setsockopt);
 
 static switch_status_t interface_exists(char *the_interface);
-static switch_status_t remove_interface(char *the_interface);
+/* CLOUDTREE (Thomas Hazel) static*/ switch_status_t remove_interface(char *the_interface, /* CLOUDTREE (Thomas Hazel */ switch_bool_t force);
 
 static switch_status_t channel_on_init(switch_core_session_t *session);
 static switch_status_t channel_on_hangup(switch_core_session_t *session);
@@ -298,7 +309,7 @@ static switch_status_t interface_exists(char *the_interface)
        return SWITCH_STATUS_FALSE;
 }
 
-static switch_status_t remove_interface(char *the_interface)
+/* CLOUDTREE (Thomas Hazel) static */ switch_status_t remove_interface(char *the_interface, /* CLOUDTREE (Thomas Hazel) */ switch_bool_t force)
 {
        int x = 10;
        unsigned int howmany = 8;
@@ -338,7 +349,7 @@ static switch_status_t remove_interface(char *the_interface)
                goto end;
        }
 
-       if (strlen(globals.SKYPOPEN_INTERFACES[interface_id].session_uuid_str)) {
+       if (/* CLOUDTREE (Thomas Hazel) */ (force == FALSE) && strlen(globals.SKYPOPEN_INTERFACES[interface_id].session_uuid_str)) {
                DEBUGA_SKYPE("interface '%s' is busy\n", SKYPOPEN_P_LOG, the_interface);
                goto end;
        }
@@ -743,7 +754,7 @@ read:
                                || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
                                || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPOPEN_STATE_UP)) {
                switch_mutex_lock(tech_pvt->mutex_audio_srv);
-               if (switch_buffer_inuse(tech_pvt->read_buffer)) {
+               if (tech_pvt->read_buffer && switch_buffer_inuse(tech_pvt->read_buffer)) {
                        bytes_read = switch_buffer_read(tech_pvt->read_buffer, tech_pvt->read_frame.data, 640);
                        tech_pvt->read_frame.datalen = bytes_read;
                }
@@ -1232,6 +1243,7 @@ static void *SWITCH_THREAD_FUNC skypopen_signaling_thread_func(switch_thread_t *
        private_t *tech_pvt = obj;
        int res;
        int forever = 1;
+       switch_event_t *event;
 
        if (!tech_pvt)
                return NULL;
@@ -1242,6 +1254,14 @@ static void *SWITCH_THREAD_FUNC skypopen_signaling_thread_func(switch_thread_t *
                if (!(running && tech_pvt->running))
                        break;
                res = skypopen_signaling_read(tech_pvt);
+
+               if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INCOMING_RAW) == SWITCH_STATUS_SUCCESS) {
+                       switch_event_add_header(event, SWITCH_STACK_BOTTOM, "X-Skype-Response-Code", "%d", res);
+                       switch_event_add_header(event, SWITCH_STACK_BOTTOM, "X-Skype-Interface", "%s", tech_pvt->interface_id);
+                       switch_event_add_body(event, "%s", tech_pvt->message);
+                       switch_event_fire(&event);
+               }
+
                if (res == CALLFLOW_INCOMING_HANGUP || tech_pvt->skype_callflow == CALLFLOW_INCOMING_HANGUP) {
                        switch_core_session_t *session = NULL;
                        switch_channel_t *channel = NULL;
@@ -1266,6 +1286,7 @@ static void *SWITCH_THREAD_FUNC skypopen_signaling_thread_func(switch_thread_t *
                                        DEBUGA_SKYPE("no session\n", SKYPOPEN_P_LOG);
                                }
                                switch_mutex_lock(globals.mutex);
+                               tech_pvt->ringing_state = SKYPOPEN_RINGING_INIT;
                                tech_pvt->interface_state = SKYPOPEN_STATE_DOWN;
                                *tech_pvt->session_uuid_str = '\0';
                                *tech_pvt->skype_call_id = '\0';
@@ -1299,6 +1320,9 @@ static switch_status_t load_config(int reload_type)
        switch_xml_t cfg, xml, global_settings, param, interfaces, myinterface;
        private_t *tech_pvt = NULL;
 
+       // CLOUDTREE (Thomas Hazel) - always try to load configuration
+       running = 1;
+
        switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, skypopen_module_pool);
        if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
                ERRORA("open of %s failed\n", SKYPOPEN_P_LOG, cf);
@@ -1769,18 +1793,36 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skypopen_load)
        skypopen_module_pool = pool;
        memset(&globals, '\0', sizeof(globals));
 
-       running = 1;
+       // CLOUDTREE (Thomas Hazel)
+       #ifndef WIN32
+       // XXX: these assumes no one will override
+       XSetErrorHandler(X11_errors_handler);
+       XSetIOErrorHandler(xio_error_handler);
+
+       memset(&global_handles_list, 0, sizeof(global_handles_list));
+       switch_mutex_init(&globals.list_mutex, SWITCH_MUTEX_NESTED, skypopen_module_pool);
+       #endif
 
-       if (load_config(FULL_RELOAD) != SWITCH_STATUS_SUCCESS) {
+       // CLOUDTREE (Thomas Hazel) - load_configs no longer locks things up, no need to fail load
+       /*if (*/ load_config(FULL_RELOAD); /* != SWITCH_STATUS_SUCCESS) {
                running = 0;
                return SWITCH_STATUS_FALSE;
        }
+       */
+
+       // CLOUDTREE (Thomas Hazel) - setting "running = 1;" use to be located before "load_config"
+       running = 1;
 
        if (switch_event_reserve_subclass(MY_EVENT_INCOMING_CHATMESSAGE) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n");
                return SWITCH_STATUS_GENERR;
        }
 
+       if (switch_event_reserve_subclass(MY_EVENT_INCOMING_RAW) != SWITCH_STATUS_SUCCESS) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n");
+               return SWITCH_STATUS_GENERR;
+       }
+
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
        skypopen_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
        skypopen_endpoint_interface->interface_name = "skypopen";
@@ -1794,7 +1836,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skypopen_load)
                SWITCH_ADD_API(commands_api_interface, "skypopen_chat", "Skypopen_chat interface remote_skypename TEXT", skypopen_chat_function, SKYPOPEN_CHAT_SYNTAX);
                SWITCH_ADD_CHAT(chat_interface, MDL_CHAT_PROTO, chat_send);
 
-
                /* indicate that the module should continue to be loaded */
                return SWITCH_STATUS_SUCCESS;
        } else
@@ -1814,6 +1855,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypopen_shutdown)
        for (interface_id = 0; interface_id < SKYPOPEN_MAX_INTERFACES; interface_id++) {
                tech_pvt = &globals.SKYPOPEN_INTERFACES[interface_id];
 
+
                if (strlen(globals.SKYPOPEN_INTERFACES[interface_id].name)) {
                        if (globals.SKYPOPEN_INTERFACES[interface_id].skypopen_signaling_thread) {
 #ifdef WIN32
@@ -1888,6 +1930,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypopen_shutdown)
 
        }
        switch_event_free_subclass(MY_EVENT_INCOMING_CHATMESSAGE);
+       switch_event_free_subclass(MY_EVENT_INCOMING_RAW);
 
        switch_safe_free(globals.context);
        switch_safe_free(globals.dialplan);
@@ -2058,14 +2101,14 @@ int remote_party_is_ringing(private_t * tech_pvt)
        if (!zstr(tech_pvt->session_uuid_str)) {
                session = switch_core_session_locate(tech_pvt->session_uuid_str);
        } else {
-               ERRORA("No session???\n", SKYPOPEN_P_LOG);
-               goto done;
+               ERRORA("No session_uuid_str???\n", SKYPOPEN_P_LOG);
+               goto bad;
        }
        if (session) {
                channel = switch_core_session_get_channel(session);
        } else {
                ERRORA("No session???\n", SKYPOPEN_P_LOG);
-               goto done;
+               goto bad;
        }
        if (channel) {
                switch_channel_mark_ring_ready(channel);
@@ -2076,7 +2119,8 @@ int remote_party_is_ringing(private_t * tech_pvt)
 
        switch_core_session_rwunlock(session);
 
-  done:
+       return 1;
+  bad:
        return 0;
 }
 
@@ -2088,7 +2132,7 @@ int remote_party_is_early_media(private_t * tech_pvt)
        if (!zstr(tech_pvt->session_uuid_str)) {
                session = switch_core_session_locate(tech_pvt->session_uuid_str);
        } else {
-               ERRORA("No session???\n\n\n", SKYPOPEN_P_LOG);
+               ERRORA("No session_uuid_str???\n\n\n", SKYPOPEN_P_LOG);
                goto done;
        }
        if (session) {
@@ -2276,7 +2320,7 @@ SWITCH_STANDARD_API(sk_function)
                }
        } else if (!strcasecmp(argv[0], "remove")) {
                if (argc == 2) {
-                       if (remove_interface(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                       if (remove_interface(argv[1], FALSE) == SWITCH_STATUS_SUCCESS) {
                                if (interface_exists(argv[1]) == SWITCH_STATUS_SUCCESS) {
                                        stream->write_function(stream, "sk remove '%s' failed\n", argv[1]);
                                } else {
@@ -2399,7 +2443,9 @@ int skypopen_partner_handle_ring(private_t * tech_pvt)
        }
        DEBUGA_SKYPE("NOT FOUND\n", SKYPOPEN_P_LOG);
 
-       if (tech_pvt && tech_pvt->skype_call_id && !strlen(tech_pvt->skype_call_id)) {
+       // CLOUDTREE (Thomas Hazel)
+       //if (tech_pvt && tech_pvt->skype_call_id && !strlen(tech_pvt->skype_call_id)) {
+       if (tech_pvt && tech_pvt->ringing_state == SKYPOPEN_RINGING_INIT) {
                /* we are not inside an active call */
 
                tech_pvt->interface_state = SKYPOPEN_STATE_PRERING;
@@ -2508,7 +2554,9 @@ int skypopen_answer(private_t * tech_pvt)
        }
        DEBUGA_SKYPE("NOT FOUND\n", SKYPOPEN_P_LOG);
 
-       if (tech_pvt && tech_pvt->skype_call_id && !strlen(tech_pvt->skype_call_id)) {
+       // CLOUDTREE (Thomas Hazel)
+       //if (tech_pvt && tech_pvt->skype_call_id && !strlen(tech_pvt->skype_call_id)) {
+       if (tech_pvt && tech_pvt->ringing_state == SKYPOPEN_RINGING_INIT) {
                /* we are not inside an active call */
 
                tech_pvt->ib_calls++;
@@ -2853,6 +2901,151 @@ int next_port(void)
        return (globals.start_port - 1);
 }
 
+#ifndef WIN32
+// CLOUDTREE (THomas Hazel) - is there a capable freeswitch list?
+struct SkypopenHandles* skypopen_list_add(struct SkypopenList* list, struct SkypopenHandles* handle)
+{
+       switch_mutex_lock(globals.list_mutex);
+
+       if (handle->managed == SWITCH_TRUE) {
+               // already added
+               switch_mutex_unlock(globals.list_mutex);
+               return 0;
+       }
+
+       if (list->head == 0) {
+               list->head = handle;
+               handle->prev = 0;
+
+       } else {
+               ((struct SkypopenHandles*) list->tail)->next = handle;
+               ((struct SkypopenHandles*) handle)->prev = list->tail;
+       }
+
+       list->tail = handle;
+       handle->next = 0;
+
+       handle->managed = SWITCH_TRUE;
+
+       list->entries++;
+
+       switch_mutex_unlock(globals.list_mutex);
+
+       return handle;
+}
+
+// CLOUDTREE (THomas Hazel) - is there a capable freeswitch list?
+struct SkypopenHandles* skypopen_list_remove_by_value(struct SkypopenList* list, Display* display)
+{
+       struct SkypopenHandles* iter;
+       struct SkypopenHandles* handle = 0;
+
+       switch_mutex_lock(globals.list_mutex);
+
+       iter = (struct SkypopenHandles*) list->head;
+       while (iter != 0) {
+               if (iter->disp == display) {
+                       handle = iter;
+                       break;
+               }
+
+               iter = (struct SkypopenHandles*) iter->next;
+       }
+
+       if ((handle != 0) && (handle->managed == SWITCH_TRUE)) {
+               if (handle->prev == 0) {
+                       list->head = ((struct SkypopenHandles*) handle)->next;
+
+               } else {
+                       ((struct SkypopenHandles*) handle->prev)->next = ((struct SkypopenHandles*) handle)->next;
+               }
+
+               if (handle->next == 0) {
+                       list->tail = ((struct SkypopenHandles*) handle)->prev;
+
+               } else {
+                       ((struct SkypopenHandles*) handle->next)->prev = ((struct SkypopenHandles*) handle)->prev;
+               }
+
+               handle->managed = SWITCH_FALSE;
+               handle->next = 0;
+               handle->prev = 0;
+
+               list->entries--;
+       }
+
+       switch_mutex_unlock(globals.list_mutex);
+
+       return handle;
+}
+
+// CLOUDTREE (THomas Hazel) - is there a capable freeswitch list?
+struct SkypopenHandles* skypopen_list_remove_by_reference(struct SkypopenList* list, struct SkypopenHandles* handle)
+{
+       switch_mutex_lock(globals.list_mutex);
+
+       if (handle->managed == SWITCH_FALSE) {
+               // already removed
+               switch_mutex_unlock(globals.list_mutex);
+               return 0;
+       }
+
+       if (handle->prev == 0) {
+               list->head = ((struct SkypopenHandles*) handle)->next;
+
+       } else {
+               ((struct SkypopenHandles*) handle->prev)->next = ((struct SkypopenHandles*) handle)->next;
+       }
+
+       if (handle->next == 0) {
+               list->tail = ((struct SkypopenHandles*) handle)->prev;
+
+       } else {
+               ((struct SkypopenHandles*) handle->next)->prev = ((struct SkypopenHandles*) handle)->prev;
+       }
+
+       handle->managed = SWITCH_FALSE;
+       handle->next = 0;
+       handle->prev = 0;
+
+       list->entries--;
+
+       switch_mutex_unlock(globals.list_mutex);
+
+       return handle;
+}
+
+// CLOUDTREE (THomas Hazel) - is there a capable freeswitch list?
+#ifdef XIO_ERROR_BY_UCONTEXT
+struct SkypopenHandles* skypopen_list_find(struct SkypopenList* list, struct SkypopenHandles* find)
+{
+       struct SkypopenHandles* iter;
+       struct SkypopenHandles* handle = NULL;
+
+       switch_mutex_lock(globals.list_mutex);
+
+       iter = (struct SkypopenHandles*) list->head;
+       while (iter != NULL) {
+               if (iter == find) {
+                       handle = iter;
+                       break;
+               }
+
+               iter = (struct SkypopenHandles*) iter->next;
+       }
+
+       switch_mutex_unlock(globals.list_mutex);
+
+       return handle;
+}
+#endif
+
+// CLOUDTREE (THomas Hazel) - is there a capable freeswitch list? 
+int skypopen_list_size(struct SkypopenList* list)
+{
+       return list->entries;
+}
+#endif /* NOT WIN32 */
 
 /* For Emacs:
  * Local Variables:
index 77e00dace55e4eb93917657253e54f7ceda6371e..d678ba23bf049397be04ba6e2fb3a049e4a7f88e 100644 (file)
 #include <X11/Xlib.h>
 #include <X11/Xlibint.h>
 #include <X11/Xatom.h>
+
+// CLOUDTREE (Thomas Hazel)
+#define XIO_ERROR_BY_SETJMP
+//#define XIO_ERROR_BY_UCONTEXT
+
+// CLOUDTREE (Thomas Hazel)
+#ifdef XIO_ERROR_BY_SETJMP
+       #include "setjmp.h"
+#endif
+// CLOUDTREE (Thomas Hazel)
+#ifdef XIO_ERROR_BY_UCONTEXT
+       #include "ucontext.h"
+#endif
+
 #endif //WIN32
 
 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
@@ -58,6 +72,7 @@
 #endif
 
 #define MY_EVENT_INCOMING_CHATMESSAGE "skypopen::incoming_chatmessage"
+#define MY_EVENT_INCOMING_RAW "skypopen::incoming_raw"
 
 #define SAMPLERATE_SKYPOPEN 16000
 #define SAMPLES_PER_FRAME SAMPLERATE_SKYPOPEN/50
@@ -99,6 +114,11 @@ typedef enum {
 #define SKYPOPEN_CONTROL_RINGING               1
 #define SKYPOPEN_CONTROL_ANSWER                2
 
+/*********************************/
+// CLOUDTREE (Thomas Hazel)
+#define SKYPOPEN_RINGING_INIT          0
+#define SKYPOPEN_RINGING_PRE           1
+
 /*********************************/
 #define                SKYPOPEN_STATE_IDLE                                     0
 #define                SKYPOPEN_STATE_DOWN                                     1
@@ -154,7 +174,35 @@ struct SkypopenHandles {
        int currentuserhandle;
        int api_connected;
        int fdesc[2];
+
+       // CLOUDTREE (Thomas Hazel)
+       #ifdef XIO_ERROR_BY_SETJMP
+               jmp_buf ioerror_context;
+       #endif
+       #ifdef XIO_ERROR_BY_UCONTEXT
+               ucontext_t ioerror_context;
+       #endif
+
+       // CLOUDTREE (Thomas Hazel) - is there a capable freeswitch list?
+       switch_bool_t managed;
+       void* prev;
+       void* next;
+};
+
+// CLOUDTREE (Thomas Hazel) - is there a capable freeswitch list?
+struct SkypopenList {
+       int entries;
+       void* head;
+       void* tail;
 };
+
+// CLOUDTREE (Thomas Hazel) - is there a capable freeswitch list?
+struct SkypopenHandles* skypopen_list_add(struct SkypopenList* list, struct SkypopenHandles* x);
+struct SkypopenHandles* skypopen_list_find(struct SkypopenList* list, struct SkypopenHandles* x);
+struct SkypopenHandles* skypopen_list_remove_by_value(struct SkypopenList* list, Display* display);
+struct SkypopenHandles* skypopen_list_remove_by_reference(struct SkypopenList* list, struct SkypopenHandles* x);
+int skypopen_list_size(struct SkypopenList* list);
+
 #else //WIN32
 
 struct SkypopenHandles {
@@ -218,6 +266,9 @@ struct private_object {
 #endif
        struct SkypopenHandles SkypopenHandles;
 
+       // CLOUDTREE (Thomas Hazel)
+       char ringing_state;
+
        int interface_state;
        char language[80];
        char exten[80];
@@ -294,6 +345,7 @@ struct private_object {
        char ring_id[256];
        char ring_value[256];
 
+       char message[4096];
 };
 
 typedef struct private_object private_t;
index ad699803880bd2d2323e7c3c4b06c710cd6f1c5c..3fc9aaa14cc869cd1c5f4ea31778fb322a500ade 100644 (file)
@@ -21,8 +21,12 @@ extern int running;
 #ifdef WIN32
 DWORD win32_dwThreadId;
 #else
-XErrorHandler old_handler = 0;
-int xerror = 0;
+
+// CLOUDTREE (Thomas Hazel)
+static int global_x_error = Success;
+extern struct SkypopenList global_handles_list;
+extern switch_status_t remove_interface(char *the_interface, switch_bool_t force);
+
 #endif /* WIN32 */
 /*************************************/
 #ifndef WIN32
@@ -174,6 +178,8 @@ int skypopen_signaling_read(private_t * tech_pvt)
 
                        //if (!strstr(message, "DURATION")) {
                        DEBUGA_SKYPE("READING: |||%s||| \n", SKYPOPEN_P_LOG, message);
+                       strncpy( tech_pvt->message, message, sizeof(tech_pvt->message) );
+
                        //}
                        if (!strcasecmp(message, "SILENT_MODE OFF")) {
                                if (tech_pvt->silent_mode) {
@@ -559,8 +565,10 @@ int skypopen_signaling_read(private_t * tech_pvt)
                                                char msg_to_skype[1024];
                                                if ((tech_pvt->interface_state != SKYPOPEN_STATE_SELECTED && tech_pvt->interface_state != SKYPOPEN_STATE_DIALING)
                                                        && (!strlen(tech_pvt->skype_call_id) || !strlen(tech_pvt->session_uuid_str))) {
-                                                       /* we are NOT inside an active call */
+                                                       // CLOUDTREE (Thomas Hazel)
+                                                       skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
 
+                                                       /* we are NOT inside an active call */
                                                        DEBUGA_SKYPE("NO ACTIVE calls in this moment, skype_call %s is RINGING, to ask PARTNER_DISPNAME and PARTNER_HANDLE\n", SKYPOPEN_P_LOG, id);
                                                        sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id);
                                                        skypopen_signaling_write(tech_pvt, msg_to_skype);
@@ -571,12 +579,28 @@ int skypopen_signaling_read(private_t * tech_pvt)
                                                } else {
                                                        /* we are inside an active call */
                                                        if (!strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                               // CLOUDTREE (Thomas Hazel)
+                                                               tech_pvt->ringing_state = SKYPOPEN_RINGING_PRE;
+
                                                                /* this is the call in which we are calling out */
                                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_RINGING;
                                                                tech_pvt->interface_state = SKYPOPEN_STATE_RINGING;
                                                                skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
                                                                DEBUGA_SKYPE("Our remote party in skype_call %s is RINGING\n", SKYPOPEN_P_LOG, id);
-                                                               remote_party_is_ringing(tech_pvt);
+                                                               if( !remote_party_is_ringing(tech_pvt)){
+
+                                                                       WARNINGA("We are getting the RINGING from a call we canceled, trying to get out hanging up call id: %s.\n", SKYPOPEN_P_LOG, id);
+                                                                       sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
+                                                                       skypopen_signaling_write(tech_pvt, msg_to_skype);
+                                                                       tech_pvt->skype_call_id[0] = '\0';
+                                                                       // CLOUDTREE (Thomas Hazel)
+                                                                       tech_pvt->ringing_state = SKYPOPEN_RINGING_INIT;
+                                                                       tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
+                                                                       tech_pvt->interface_state = SKYPOPEN_STATE_IDLE;
+                                                                       ERRORA("we're back to IDLE\n", SKYPOPEN_P_LOG, id);
+                                                                       skypopen_sleep(10000);
+
+                                                               }
                                                        } else {
                                                                DEBUGA_SKYPE
                                                                        ("We are in another call, but skype_call %s is RINGING on us, let's ask PARTNER_HANDLE, so maybe we'll TRANSFER\n",
@@ -606,9 +630,12 @@ int skypopen_signaling_read(private_t * tech_pvt)
                                                skypopen_signaling_write(tech_pvt, msg_to_skype);
 
                                                remote_party_is_early_media(tech_pvt);
+                                       /* CLOUDTREE (Thomas Hazel)
                                        } else if (!strcasecmp(value, "MISSED")) {
                                                DEBUGA_SKYPE("We missed skype_call %s\n", SKYPOPEN_P_LOG, id);
-                                       } else if (!strcasecmp(value, "FINISHED")) {
+                                       */
+                                       // CLOUDTREE (Thomas Hazel)
+                                       } else if (!strcasecmp(value, "MISSED") || !strcasecmp(value, "FINISHED")) {
                                                if (!strcasecmp(tech_pvt->skype_call_id, id)) {
                                                        DEBUGA_SKYPE("skype_call %s is MY call, now I'm going DOWN\n", SKYPOPEN_P_LOG, id);
                                                        if (tech_pvt->interface_state != SKYPOPEN_STATE_HANGUP_REQUESTED) {
@@ -1425,26 +1452,38 @@ void *skypopen_do_skypeapi_thread_func(void *obj)
 }
 
 #else /* NOT WIN32 */
-int X11_errors_handler(Display * dpy, XErrorEvent * err)
+
+// CLOUDTREE (Thomas Hazel)
+int xio_error_handler(Display *dpy)
 {
        private_t *tech_pvt = NULL;
-       (void) dpy;
+       struct SkypopenHandles* handle;
+
+       ERRORA("Fatal display error for %d, %s\n", SKYPOPEN_P_LOG, skypopen_list_size(&global_handles_list), dpy->display_name);
+
+       handle = skypopen_list_remove_by_value(&global_handles_list, dpy);
+       if (handle != NULL) {
+               #ifdef XIO_ERROR_BY_SETJMP
+                       siglongjmp(handle->ioerror_context, 1);
+               #endif
+               #ifdef XIO_ERROR_BY_UCONTEXT
+                       setcontext(&handle->ioerror_context);
+               #endif
+       }
 
-       xerror = err->error_code;
-       ERRORA("Received error code %d from X Server\n\n", SKYPOPEN_P_LOG, xerror);
-       return 0;                                       /*  ignore the error */
-}
+       ERRORA("Fatal display error for %p, %s - failed to siglongjmp\n", SKYPOPEN_P_LOG, (void*) handle, dpy->display_name);
 
-static void X11_errors_trap(void)
-{
-       xerror = 0;
-       old_handler = XSetErrorHandler(X11_errors_handler);
+       return 0;
 }
 
-static int X11_errors_untrap(void)
+int X11_errors_handler(Display * dpy, XErrorEvent * err)
 {
-       XSetErrorHandler(old_handler);
-       return (xerror != BadValue) && (xerror != BadWindow);
+       private_t *tech_pvt = NULL;
+       (void) dpy;
+
+       global_x_error = err->error_code;
+       ERRORA("Received error code %d from X Server\n\n", SKYPOPEN_P_LOG, global_x_error);
+       return 0;                                       /*  ignore the error */
 }
 
 int skypopen_send_message(private_t * tech_pvt, const char *message_P)
@@ -1453,7 +1492,6 @@ int skypopen_send_message(private_t * tech_pvt, const char *message_P)
        Window w_P = SkypopenHandles->skype_win;
        Display *disp = SkypopenHandles->disp;
        Window handle_P = SkypopenHandles->win;
-       int ok;
 
 
        Atom atom1 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
@@ -1472,7 +1510,9 @@ skypopen_sleep(1000);//giovanni
        e.xclient.window = handle_P;
        e.xclient.format = 8;
 
-       X11_errors_trap();
+       // CLOUDTREE (Thomas Hazel)
+       global_x_error = Success;
+
        do {
                unsigned int i;
                for (i = 0; i < 20 && i + pos <= len; ++i)
@@ -1485,10 +1525,10 @@ skypopen_sleep(1000);//giovanni
 
        //giovanni XSync(disp, False);
        XFlush(disp);
-       ok = X11_errors_untrap();
 
-       if (!ok) {
-               ERRORA("Sending message failed with status %d\n", SKYPOPEN_P_LOG, xerror);
+       // CLOUDTREE (Thomas Hazel)
+       if (global_x_error != Success) {
+               ERRORA("Sending message failed with status %d\n", SKYPOPEN_P_LOG, global_x_error);
                tech_pvt->running = 0;
                return 0;
        }
@@ -1525,11 +1565,9 @@ int skypopen_present(struct SkypopenHandles *SkypopenHandles)
        int status;
        private_t *tech_pvt = NULL;
 
-       X11_errors_trap();
        status =
                XGetWindowProperty(SkypopenHandles->disp, DefaultRootWindow(SkypopenHandles->disp),
                                                   skype_inst, 0, 1, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &bytes_after_ret, &prop);
-       X11_errors_untrap();
 
        /*  sanity check */
        if (status != Success || format_ret != 32 || nitems_ret != 1) {
@@ -1597,11 +1635,65 @@ void *skypopen_do_skypeapi_thread_func(void *obj)
        if (!disp) {
                ERRORA("Cannot open X Display '%s', exiting skype thread\n", SKYPOPEN_P_LOG, tech_pvt->X11_display);
                running = 0;
+
+               // CLOUDTREE (Thomas Hazel)
+               tech_pvt->skypopen_api_thread = NULL;
+               remove_interface(tech_pvt->skype_user, FALSE);
                return NULL;
        } else {
                DEBUGA_SKYPE("X Display '%s' opened\n", SKYPOPEN_P_LOG, tech_pvt->X11_display);
        }
 
+       // CLOUDTREE (Thomas Hazel)
+       #ifndef WIN32
+       {
+               skypopen_list_add(&global_handles_list, SkypopenHandles);
+
+               #ifdef XIO_ERROR_BY_SETJMP
+                       if (sigsetjmp(SkypopenHandles->ioerror_context, 1) != 0) {
+                               switch_core_session_t *session = NULL;
+                               ERRORA("Fatal display error for %s - successed to jump\n", SKYPOPEN_P_LOG, tech_pvt->X11_display);
+
+                               session = switch_core_session_locate(tech_pvt->session_uuid_str);
+                               if (session) {
+                                       switch_channel_t *channel = switch_core_session_get_channel(session);
+                                       WARNINGA("Closing session %s\n", SKYPOPEN_P_LOG, tech_pvt->skype_user);
+                                       switch_channel_hangup(channel, SWITCH_CAUSE_CRASH);
+                                       switch_core_session_rwunlock(session);
+                               }
+
+                               WARNINGA("Removing skype user %s\n", SKYPOPEN_P_LOG, tech_pvt->skype_user);
+                               tech_pvt->skypopen_api_thread = NULL;
+                               remove_interface(tech_pvt->skype_user, TRUE);
+                               XCloseDisplay(disp);
+                               return NULL;
+                       }
+               #endif
+               #ifdef XIO_ERROR_BY_UCONTEXT
+                       getcontext(&SkypopenHandles->ioerror_context);
+
+                       if (skypopen_list_find(&global_handles_list, SkypopenHandles) == NULL) {
+                               switch_core_session_t *session = NULL;
+                               ERRORA("Fatal display error for %s - successed to jump\n", SKYPOPEN_P_LOG, tech_pvt->X11_display);
+
+                               session = switch_core_session_locate(tech_pvt->session_uuid_str);
+                               if (session) {
+                                       switch_channel_t *channel = switch_core_session_get_channel(session);
+                                       WARNINGA("Closing session %s\n", SKYPOPEN_P_LOG, tech_pvt->skype_user);
+                                       switch_channel_hangup(channel, SWITCH_CAUSE_CRASH);
+                                       switch_core_session_rwunlock(session);
+                               }
+
+                               WARNINGA("Removing skype user %s\n", SKYPOPEN_P_LOG, tech_pvt->skype_user);
+                               tech_pvt->skypopen_api_thread = NULL;
+                               remove_interface(tech_pvt->skype_user, TRUE);
+                               XCloseDisplay(disp);
+                               return NULL;
+                       }
+               #endif
+       }
+       #endif /* NOT WIN32 */
+
        xfd = XConnectionNumber(disp);
        fcntl(xfd, F_SETFD, FD_CLOEXEC);
 
@@ -1617,6 +1709,13 @@ void *skypopen_do_skypeapi_thread_func(void *obj)
 
                if (!skypopen_send_message(tech_pvt, buf)) {
                        ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypopen again\n", SKYPOPEN_P_LOG);
+
+                       // CLOUDTREE (Thomas Hazel)
+                       #ifndef WIN32
+                       skypopen_list_remove_by_reference(&global_handles_list, SkypopenHandles);
+                       #endif
+
+                       XCloseDisplay(disp);
                        running = 0;
                        return NULL;
                }
@@ -1624,6 +1723,13 @@ void *skypopen_do_skypeapi_thread_func(void *obj)
                snprintf(buf, 512, "PROTOCOL 7");
                if (!skypopen_send_message(tech_pvt, buf)) {
                        ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypopen again\n", SKYPOPEN_P_LOG);
+
+                       // CLOUDTREE (Thomas Hazel)
+                       #ifndef WIN32
+                       skypopen_list_remove_by_reference(&global_handles_list, SkypopenHandles);
+                       #endif
+
+                       XCloseDisplay(disp);
                        running = 0;
                        return NULL;
                }
@@ -1750,8 +1856,16 @@ while(XPending(disp)){
                ERRORA("Skype is not running, maybe crashed. Please run/restart Skype and relaunch Skypopen\n", SKYPOPEN_P_LOG);
                running = 0;
        }
-       tech_pvt->skypopen_api_thread=NULL;
+
        NOTICA("EXITING\n", SKYPOPEN_P_LOG);
+
+       // CLOUDTREE (Thomas Hazel)
+       #ifndef WIN32
+       skypopen_list_remove_by_reference(&global_handles_list, SkypopenHandles);
+       #endif
+
+       tech_pvt->skypopen_api_thread=NULL;
+       XCloseDisplay(disp);
        return NULL;
 
 }