From: Giovanni Maruzzelli Date: Mon, 25 Oct 2010 20:36:12 +0000 (-0500) Subject: skypopen: CLOUDTREE patch with some modifications X-Git-Tag: v1.2-rc1~265^2~11^2~134 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f04322e9bb708fcc105c77e3e0cf699625a1597e;p=thirdparty%2Ffreeswitch.git skypopen: CLOUDTREE patch with some modifications --- diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index e83288770b..5837cbe1e4 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -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: diff --git a/src/mod/endpoints/mod_skypopen/skypopen.h b/src/mod/endpoints/mod_skypopen/skypopen.h index 77e00dace5..d678ba23bf 100644 --- a/src/mod/endpoints/mod_skypopen/skypopen.h +++ b/src/mod/endpoints/mod_skypopen/skypopen.h @@ -41,6 +41,20 @@ #include #include #include + +// 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; diff --git a/src/mod/endpoints/mod_skypopen/skypopen_protocol.c b/src/mod/endpoints/mod_skypopen/skypopen_protocol.c index ad69980388..3fc9aaa14c 100644 --- a/src/mod/endpoints/mod_skypopen/skypopen_protocol.c +++ b/src/mod/endpoints/mod_skypopen/skypopen_protocol.c @@ -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; }