<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][14544] </title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=14544">14544</a></dd>
<dt>Author</dt> <dd>gmaruzz</dd>
<dt>Date</dt> <dd>2009-08-17 04:17:09 -0500 (Mon, 17 Aug 2009)</dd>
</dl>
<h3>Log Message</h3>
<pre>celliax: added mod_celliax skeleton directory, with files from the celliax for asterisk distribution</pre>
<h3>Added Paths</h3>
<ul>
<li>freeswitch/branches/gmaruzz/mod_celliax/</li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxMakefile">freeswitch/branches/gmaruzz/mod_celliax/Makefile</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxREADME">freeswitch/branches/gmaruzz/mod_celliax/README</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxcelliaxh">freeswitch/branches/gmaruzz/mod_celliax/celliax.h</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxcelliax_protocolc">freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxmod_celliaxc">freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxmod_skypiax2008vcproj">freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.2008.vcproj</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxmod_skypiaxc">freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.c</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxmod_skypiaxso">freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.so</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxskypiaxh">freeswitch/branches/gmaruzz/mod_celliax/skypiax.h</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxskypiax_protocolc">freeswitch/branches/gmaruzz/mod_celliax/skypiax_protocol.c</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchbranchesgmaruzzmod_celliaxMakefile"></a>
<div class="addfile"><h4>Added: freeswitch/branches/gmaruzz/mod_celliax/Makefile (0 => 14544)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/Makefile         (rev 0)
+++ freeswitch/branches/gmaruzz/mod_celliax/Makefile        2009-08-17 09:17:09 UTC (rev 14544)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+MODNAME=mod_skypiax
+SVNDEF := -D'SKYPIAX_SVN_VERSION="$(shell svnversion -n .)"'
+LOCAL_CFLAGS += $(SVNDEF)
+LOCAL_LDFLAGS=-lX11
+LOCAL_OBJS=skypiax_protocol.o
+include ../../../../build/modmake.rules
</ins></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxREADME"></a>
<div class="addfile"><h4>Added: freeswitch/branches/gmaruzz/mod_celliax/README (0 => 14544)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/README         (rev 0)
+++ freeswitch/branches/gmaruzz/mod_celliax/README        2009-08-17 09:17:09 UTC (rev 14544)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+Skypiax, Skype Endpoint and Trunk
+
+All documentation on compiling, using, configuring,
+tricks and tweaks, possible problems at:
+
+http://wiki.freeswitch.org/wiki/Skypiax_Skype_Endpoint_and_Trunk
+
+< gmaruzz at gmail dot com >
+
</ins></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxcelliaxh"></a>
<div class="addfile"><h4>Added: freeswitch/branches/gmaruzz/mod_celliax/celliax.h (0 => 14544)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/celliax.h         (rev 0)
+++ freeswitch/branches/gmaruzz/mod_celliax/celliax.h        2009-08-17 09:17:09 UTC (rev 14544)
</span><span class="lines">@@ -0,0 +1,291 @@
</span><ins>+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * This module (mod_skypiax) has been contributed by:
+ *
+ * Giovanni Maruzzelli (gmaruzz@gmail.com)
+ *
+ *
+ * Further Contributors:
+ *
+ *
+ *
+ * mod_skypiax.c -- Skype compatible Endpoint Module
+ *
+ */
+
+#include <switch.h>
+#include <switch_version.h>
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#include <X11/Xatom.h>
+#endif //WIN32
+
+#ifdef _MSC_VER
+//Windows macro for FD_SET includes a warning C4127: conditional expression is constant
+#pragma warning(push)
+#pragma warning(disable:4127)
+#endif
+
+#define SAMPLERATE_SKYPIAX 16000
+#define SAMPLES_PER_FRAME SAMPLERATE_SKYPIAX/50
+
+#ifndef SKYPIAX_SVN_VERSION
+#define SKYPIAX_SVN_VERSION SWITCH_VERSION_REVISION
+#endif /* SKYPIAX_SVN_VERSION */
+
+typedef enum {
+        TFLAG_IO = (1 << 0),
+        TFLAG_INBOUND = (1 << 1),
+        TFLAG_OUTBOUND = (1 << 2),
+        TFLAG_DTMF = (1 << 3),
+        TFLAG_VOICE = (1 << 4),
+        TFLAG_HANGUP = (1 << 5),
+        TFLAG_LINEAR = (1 << 6),
+        TFLAG_CODEC = (1 << 7),
+        TFLAG_BREAK = (1 << 8)
+} TFLAGS;
+
+typedef enum {
+        GFLAG_MY_CODEC_PREFS = (1 << 0)
+} GFLAGS;
+
+#define DEBUGA_SKYPE(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_SKYPE %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_CALL(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_CALL %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_PBX(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_PBX %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define ERRORA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][ERRORA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define WARNINGA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][WARNINGA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define NOTICA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][NOTICA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+
+#define SKYPIAX_P_LOG NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt->name ? tech_pvt->name : "none" : "none", -1, tech_pvt ? tech_pvt->interface_state : -1, tech_pvt ? tech_pvt->skype_callflow : -1
+
+/*********************************/
+#define SKYPIAX_CAUSE_NORMAL                1
+/*********************************/
+#define SKYPIAX_FRAME_DTMF                        1
+/*********************************/
+#define SKYPIAX_CONTROL_RINGING                1
+#define SKYPIAX_CONTROL_ANSWER                2
+
+/*********************************/
+#define                SKYPIAX_STATE_IDLE                                        0
+#define                SKYPIAX_STATE_DOWN                                        1
+#define                SKYPIAX_STATE_RING                                        2
+#define                SKYPIAX_STATE_DIALING                                3
+#define                SKYPIAX_STATE_BUSY                                        4
+#define                SKYPIAX_STATE_UP                                        5
+#define                SKYPIAX_STATE_RINGING                                6
+#define                SKYPIAX_STATE_PRERING                                7
+#define                SKYPIAX_STATE_ERROR_DOUBLE_CALL                8
+#define                SKYPIAX_STATE_SELECTED                                9
+#define         SKYPIAX_STATE_HANGUP_REQUESTED                10
+#define                SKYPIAX_STATE_PREANSWER                                11
+/*********************************/
+/* call flow from the device */
+#define         CALLFLOW_CALL_IDLE                                        0
+#define         CALLFLOW_CALL_DOWN                                        1
+#define         CALLFLOW_INCOMING_RING                                2
+#define         CALLFLOW_CALL_DIALING                                3
+#define         CALLFLOW_CALL_LINEBUSY                                4
+#define         CALLFLOW_CALL_ACTIVE                                5
+#define         CALLFLOW_INCOMING_HANGUP                        6
+#define         CALLFLOW_CALL_RELEASED                                7
+#define         CALLFLOW_CALL_NOCARRIER                                8
+#define         CALLFLOW_CALL_INFLUX                                9
+#define         CALLFLOW_CALL_INCOMING                                10
+#define         CALLFLOW_CALL_FAILED                                11
+#define         CALLFLOW_CALL_NOSERVICE                                12
+#define         CALLFLOW_CALL_OUTGOINGRESTRICTED        13
+#define         CALLFLOW_CALL_SECURITYFAIL                        14
+#define         CALLFLOW_CALL_NOANSWER                                15
+#define         CALLFLOW_STATUS_FINISHED                        16
+#define         CALLFLOW_STATUS_CANCELLED                        17
+#define         CALLFLOW_STATUS_FAILED                                18
+#define         CALLFLOW_STATUS_REFUSED                                19
+#define         CALLFLOW_STATUS_RINGING                                20
+#define         CALLFLOW_STATUS_INPROGRESS                        21
+#define         CALLFLOW_STATUS_UNPLACED                        22
+#define         CALLFLOW_STATUS_ROUTING                                23
+#define         CALLFLOW_STATUS_EARLYMEDIA                        24
+#define         CALLFLOW_INCOMING_CALLID                        25
+#define         CALLFLOW_STATUS_REMOTEHOLD                        26
+
+/*********************************/
+
+#define SKYPIAX_MAX_INTERFACES 64
+
+#ifndef WIN32
+struct SkypiaxHandles {
+        Window skype_win;
+        Display *disp;
+        Window win;
+        int currentuserhandle;
+        int api_connected;
+        int fdesc[2];
+};
+#else //WIN32
+
+struct SkypiaxHandles {
+        HWND win32_hInit_MainWindowHandle;
+        HWND win32_hGlobal_SkypeAPIWindowHandle;
+        HINSTANCE win32_hInit_ProcessHandle;
+        char win32_acInit_WindowClassName[128];
+        UINT win32_uiGlobal_MsgID_SkypeControlAPIAttach;
+        UINT win32_uiGlobal_MsgID_SkypeControlAPIDiscover;
+        int currentuserhandle;
+        int api_connected;
+        switch_file_t *fdesc[2];
+};
+
+#endif //WIN32
+
+struct private_object {
+        unsigned int flags;
+        switch_codec_t read_codec;
+        switch_codec_t write_codec;
+        switch_frame_t read_frame;
+        unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+        char session_uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+        switch_caller_profile_t *caller_profile;
+        switch_mutex_t *mutex;
+        switch_mutex_t *flag_mutex;
+
+        char interface_id[80];
+        char name[80];
+        char dialplan[80];
+        char context[80];
+        char dial_regex[256];
+        char fail_dial_regex[256];
+        char hold_music[256];
+        char type[256];
+        char X11_display[256];
+#ifdef WIN32
+        unsigned short tcp_cli_port;
+        unsigned short tcp_srv_port;
+#else
+        int tcp_cli_port;
+        int tcp_srv_port;
+#endif
+        struct SkypiaxHandles SkypiaxHandles;
+
+        int interface_state;                /*!< \brief 'state' of the interface (channel) */
+        char language[80];                        /*!< \brief default Asterisk dialplan language for this interface */
+        char exten[80];                                /*!< \brief default Asterisk dialplan extension for this interface */
+        int skypiax_sound_rate;                /*!< \brief rate of the sound device, in Hz, eg: 8000 */
+        char callid_name[50];
+        char callid_number[50];
+        double playback_boost;
+        double capture_boost;
+        int stripmsd;
+        char skype_call_id[512];
+        int skype_call_ongoing;
+        char skype_friends[4096];
+        char skype_fullname[512];
+        char skype_displayname[512];
+        int skype_callflow;                        /*!< \brief 'callflow' of the skype interface (as opposed to phone interface) */
+        int skype;                                        /*!< \brief config flag, bool, Skype support on this interface (0 if false, -1 if true) */
+        int control_to_send;
+#ifdef WIN32
+        switch_file_t *audiopipe[2];
+        switch_file_t *audioskypepipe[2];
+        switch_file_t *skypiax_sound_capt_fd;        /*!< \brief file descriptor for sound capture dev */
+#else                                                        /* WIN32 */
+        int audiopipe[2];
+        int audioskypepipe[2];
+        int skypiax_sound_capt_fd;        /*!< \brief file descriptor for sound capture dev */
+#endif                                                        /* WIN32 */
+        switch_thread_t *tcp_srv_thread;
+        switch_thread_t *tcp_cli_thread;
+        switch_thread_t *skypiax_signaling_thread;
+        switch_thread_t *skypiax_api_thread;
+        short audiobuf[SAMPLES_PER_FRAME];
+        int audiobuf_is_loaded;
+
+        //int phonebook_listing;
+        //int phonebook_querying;
+        //int phonebook_listing_received_calls;
+
+        //int phonebook_first_entry;
+        //int phonebook_last_entry;
+        //int phonebook_number_lenght;
+        //int phonebook_text_lenght;
+        FILE *phonebook_writing_fp;
+        int skypiax_dir_entry_extension_prefix;
+        char skype_user[256];
+        char skype_password[256];
+        char destination[256];
+        struct timeval answer_time;
+
+        struct timeval transfer_time;
+        char transfer_callid_number[50];
+        char skype_transfer_call_id[512];
+        int running;
+        unsigned long ib_calls;
+        unsigned long ob_calls;
+        unsigned long ib_failed_calls;
+        unsigned long ob_failed_calls;
+};
+
+typedef struct private_object private_t;
+
+void *SWITCH_THREAD_FUNC skypiax_api_thread_func(switch_thread_t * thread, void *obj);
+int skypiax_audio_read(private_t * tech_pvt);
+int skypiax_audio_init(private_t * tech_pvt);
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype);
+int skypiax_signaling_read(private_t * tech_pvt);
+
+int skypiax_call(private_t * tech_pvt, char *idest, int timeout);
+int skypiax_senddigit(private_t * tech_pvt, char digit);
+
+void *skypiax_do_tcp_srv_thread_func(void *obj);
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_srv_thread(switch_thread_t * thread, void *obj);
+
+void *skypiax_do_tcp_cli_thread_func(void *obj);
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_cli_thread(switch_thread_t * thread, void *obj);
+
+void *skypiax_do_skypeapi_thread_func(void *obj);
+void *SWITCH_THREAD_FUNC skypiax_do_skypeapi_thread(switch_thread_t * thread, void *obj);
+int dtmf_received(private_t * tech_pvt, char *value);
+int start_audio_threads(private_t * tech_pvt);
+int new_inbound_channel(private_t * tech_pvt);
+int outbound_channel_answered(private_t * tech_pvt);
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype);
+#if defined(WIN32) && !defined(__CYGWIN__)
+int skypiax_pipe_read(switch_file_t * pipe, short *buf, int howmany);
+int skypiax_pipe_write(switch_file_t * pipe, short *buf, int howmany);
+/* Visual C do not have strsep ? */
+char *strsep(char **stringp, const char *delim);
+#else
+int skypiax_pipe_read(int pipe, short *buf, int howmany);
+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_rr(private_t * tech_pvt_calling);
+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);
+int skypiax_transfer(private_t * tech_pvt, char *id, char *value);
+int skypiax_socket_create_and_bind(private_t * tech_pvt, int *which_port);
</ins></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxcelliax_protocolc"></a>
<div class="addfile"><h4>Added: freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c (0 => 14544)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c         (rev 0)
+++ freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c        2009-08-17 09:17:09 UTC (rev 14544)
</span><span class="lines">@@ -0,0 +1,1548 @@
</span><ins>+#include "skypiax.h"
+
+#ifdef ASTERISK
+#define skypiax_sleep usleep
+#define skypiax_strncpy strncpy
+#define tech_pvt p
+extern int skypiax_debug;
+extern char *skypiax_console_active;
+#else /* FREESWITCH */
+#define skypiax_sleep switch_sleep
+#define skypiax_strncpy switch_copy_string
+extern switch_memory_pool_t *skypiax_module_pool;
+extern switch_endpoint_interface_t *skypiax_endpoint_interface;
+#endif /* ASTERISK */
+int samplerate_skypiax = SAMPLERATE_SKYPIAX;
+
+extern int running;
+
+/*************************************/
+/* suspicious globals FIXME */
+#ifdef WIN32
+DWORD win32_dwThreadId;
+#else
+XErrorHandler old_handler = 0;
+int xerror = 0;
+#endif /* WIN32 */
+/*************************************/
+
+int skypiax_socket_create_and_bind(private_t * tech_pvt, int *which_port)
+{
+        int s = -1;
+        struct sockaddr_in my_addr;
+        int start_port = 6001;
+
+        memset(&my_addr, 0, sizeof(my_addr));
+        my_addr.sin_family = AF_INET;
+        my_addr.sin_addr.s_addr = htonl(0x7f000001);        /* use the localhost */
+
+        if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+                ERRORA("socket Error\n", SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        if (*which_port != 0)
+                start_port = *which_port;
+
+        my_addr.sin_port = htons(start_port);
+        //tech_pvt->tcp_cli_port = start_port;
+        *which_port = start_port;
+        while (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) {
+                DEBUGA_SKYPE("*which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port,
+                                         tech_pvt->tcp_srv_port);
+                DEBUGA_SKYPE("bind errno=%d, error: %s\n", SKYPIAX_P_LOG, errno, strerror(errno));
+                start_port++;
+                my_addr.sin_port = htons(start_port);
+                *which_port = start_port;
+                DEBUGA_SKYPE("*which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port,
+                                         tech_pvt->tcp_srv_port);
+
+                if (start_port > 65000) {
+                        ERRORA("NO MORE PORTS! *which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port,
+                                 tech_pvt->tcp_cli_port, tech_pvt->tcp_srv_port);
+                        return -1;
+                }
+        }
+
+        DEBUGA_SKYPE("SUCCESS! *which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port,
+                                 tech_pvt->tcp_srv_port);
+        return s;
+}
+
+int skypiax_signaling_read(private_t * tech_pvt)
+{
+        char read_from_pipe[4096];
+        char message[4096];
+        char message_2[4096];
+        char *buf, obj[512] = "", id[512] = "", prop[512] = "", value[512] = "", *where;
+        char **stringp = NULL;
+        int a;
+        unsigned int howmany;
+        unsigned int i;
+
+        memset(read_from_pipe, 0, 4096);
+        memset(message, 0, 4096);
+        memset(message_2, 0, 4096);
+
+        howmany = skypiax_pipe_read(tech_pvt->SkypiaxHandles.fdesc[0], (short *) read_from_pipe, sizeof(read_from_pipe));
+
+        a = 0;
+        for (i = 0; i < howmany; i++) {
+                message[a] = read_from_pipe[i];
+                a++;
+
+                if (read_from_pipe[i] == '\0') {
+
+                        //if (!strstr(message, "DURATION")) {
+                        DEBUGA_SKYPE("READING: |||%s||| \n", SKYPIAX_P_LOG, message);
+                        //}
+
+                        if (!strcasecmp(message, "ERROR 68")) {
+                                DEBUGA_SKYPE
+                                        ("If I don't connect immediately, please give the Skype client authorization to be connected by Skypiax (and to not ask you again)\n",
+                                         SKYPIAX_P_LOG);
+                                skypiax_sleep(1000000);
+                                skypiax_signaling_write(tech_pvt, "PROTOCOL 7");
+                                skypiax_sleep(10000);
+                                return 0;
+                        }
+                        if (!strncasecmp(message, "ERROR 92 CALL", 12)) {
+                                ERRORA("Skype got ERROR: |||%s|||, the (skypeout) number we called was not recognized as valid\n", SKYPIAX_P_LOG, message);
+                                tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG);
+                                tech_pvt->skype_call_id[0] = '\0';
+
+                                if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                        return CALLFLOW_INCOMING_HANGUP;
+                                } else {
+                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                }
+                        }
+
+                        if (!strncasecmp(message, "ERROR", 4)) {
+                                if (!strncasecmp(message, "ERROR 96 CALL", 12)) {
+                                        DEBUGA_SKYPE
+                                                ("Skype got ERROR: |||%s|||, we are trying to use this interface to make or receive a call, but another call is half-active on this interface. Let's the previous one to continue.\n",
+                                                 SKYPIAX_P_LOG, message);
+                                } else if (!strncasecmp(message, "ERROR 99 CALL", 12)) {
+                                        ERRORA("Skype got ERROR: |||%s|||, another call is active on this interface\n\n\n", SKYPIAX_P_LOG, message);
+                                        tech_pvt->interface_state = SKYPIAX_STATE_ERROR_DOUBLE_CALL;
+                                } else if (!strncasecmp(message, "ERROR 592 ALTER CALL", 19)) {
+                                        ERRORA("Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n", SKYPIAX_P_LOG, message);
+                                } else if (!strncasecmp(message, "ERROR 559 CALL", 13)) {
+                                        DEBUGA_SKYPE("Skype got ERROR about a failed action (probably TRYING to HANGUP A CALL), no problem: |||%s|||\n", SKYPIAX_P_LOG,
+                                                                 message);
+                                } else {
+                                        ERRORA("Skype got ERROR: |||%s|||\n", SKYPIAX_P_LOG, message);
+                                        tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                        ERRORA("skype_call now is DOWN\n", SKYPIAX_P_LOG);
+                                        tech_pvt->skype_call_id[0] = '\0';
+
+                                        if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else {
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                        }
+                                }
+                        }
+
+
+
+
+                        skypiax_strncpy(message_2, message, sizeof(message) - 1);
+                        buf = message;
+                        stringp = &buf;
+                        where = strsep(stringp, " ");
+                        if (!where) {
+                                WARNINGA("Skype MSG without spaces: %s\n", SKYPIAX_P_LOG, message);
+                        }
+
+
+
+
+
+
+
+
+                        if (!strcasecmp(message, "CURRENTUSERHANDLE")) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                if (!strcasecmp(id, tech_pvt->skype_user)) {
+                                        tech_pvt->SkypiaxHandles.currentuserhandle = 1;
+                                        DEBUGA_SKYPE
+                                                ("Skype MSG: message: %s, currentuserhandle: %s, cuh: %s, skype_user: %s!\n",
+                                                 SKYPIAX_P_LOG, message, obj, id, tech_pvt->skype_user);
+                                }
+                        }
+                        if (!strcasecmp(message, "USER")) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                if (!strcasecmp(prop, "RECEIVEDAUTHREQUEST")) {
+                                        char msg_to_skype[256];
+                                        DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", SKYPIAX_P_LOG, message, obj, id, prop);
+                                        //TODO: allow authorization based on config param
+                                        sprintf(msg_to_skype, "SET USER %s ISAUTHORIZED TRUE", id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                }
+                        }
+                        if (!strcasecmp(message, "MESSAGE")) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                if (!strcasecmp(prop, "STATUS")) {
+                                        where = strsep(stringp, " ");
+                                        skypiax_strncpy(value, where, sizeof(value) - 1);
+                                        if (!strcasecmp(value, "RECEIVED")) {
+                                                char msg_to_skype[256];
+                                                DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s value: %s!\n", SKYPIAX_P_LOG, message, obj, id, prop, value);
+                                                //TODO: authomatically flag messages as read based on config param
+                                                sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                        }
+                                } else if (!strcasecmp(prop, "BODY")) {
+                                        char msg_to_skype[256];
+                                        DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", SKYPIAX_P_LOG, message, obj, id, prop);
+                                        //TODO: authomatically flag messages as read based on config param
+                                        sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                }
+                        }
+                        if (!strcasecmp(message, "CALL")) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(value, where, sizeof(value) - 1);
+                                where = strsep(stringp, " ");
+
+                                //DEBUGA_SKYPE
+                                //("Skype MSG: message: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n",
+                                //SKYPIAX_P_LOG, message, obj, id, prop, value, where ? where : "NULL");
+
+                                if (!strcasecmp(prop, "PARTNER_HANDLE")) {
+                                        if (tech_pvt->interface_state != SKYPIAX_STATE_SELECTED && (!strlen(tech_pvt->skype_call_id) || !strlen(tech_pvt->session_uuid_str))) {
+                                                //if (!strlen(tech_pvt->skype_call_id)) {
+                                                /* we are NOT inside an active call */
+                                                DEBUGA_SKYPE("Call %s TRY ANSWER\n", SKYPIAX_P_LOG, id);
+                                                skypiax_answer(tech_pvt, id, value);
+                                        } else {
+                                                /* we are inside an active call */
+                                                if (!strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                        /* this is the call in which we are calling out */
+                                                        DEBUGA_SKYPE("Call %s DO NOTHING\n", SKYPIAX_P_LOG, id);
+                                                } else {
+                                                        skypiax_sleep(400000);        //0.4 seconds
+                                                        DEBUGA_SKYPE("Call %s TRY TRANSFER\n", SKYPIAX_P_LOG, id);
+                                                        skypiax_transfer(tech_pvt, id, value);
+                                                }
+                                        }
+                                }
+                                if (!strcasecmp(prop, "PARTNER_DISPNAME")) {
+                                        snprintf(tech_pvt->callid_name, sizeof(tech_pvt->callid_name) - 1, "%s%s%s", value, where ? " " : "", where ? where : "");
+                                        //DEBUGA_SKYPE
+                                        //("the skype_call %s caller PARTNER_DISPNAME (tech_pvt->callid_name) is: %s\n",
+                                        //SKYPIAX_P_LOG, id, tech_pvt->callid_name);
+                                }
+                                if (!strcasecmp(prop, "CONF_ID") && !strcasecmp(value, "0")) {
+                                        //DEBUGA_SKYPE("the skype_call %s is NOT a conference call\n", SKYPIAX_P_LOG, id);
+                                        //if (tech_pvt->interface_state == SKYPIAX_STATE_DOWN)
+                                        //tech_pvt->interface_state = SKYPIAX_STATE_PRERING;
+                                }
+                                if (!strcasecmp(prop, "CONF_ID") && strcasecmp(value, "0")) {
+                                        DEBUGA_SKYPE("the skype_call %s is a conference call\n", SKYPIAX_P_LOG, id);
+                                        //if (tech_pvt->interface_state == SKYPIAX_STATE_DOWN)
+                                        //tech_pvt->interface_state = SKYPIAX_STATE_PRERING;
+                                }
+                                if (!strcasecmp(prop, "DTMF")) {
+                                        DEBUGA_SKYPE("Call %s received a DTMF: %s\n", SKYPIAX_P_LOG, id, value);
+                                        dtmf_received(tech_pvt, value);
+                                }
+                                if (!strcasecmp(prop, "FAILUREREASON")) {
+                                        DEBUGA_SKYPE("Skype FAILED on skype_call %s. Let's wait for the FAILED message.\n", SKYPIAX_P_LOG, id);
+                                }
+                                if (!strcasecmp(prop, "DURATION") && (!strcasecmp(value, "1"))) {
+                                        if (strcasecmp(id, tech_pvt->skype_call_id)) {
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                DEBUGA_SKYPE("We called a Skype contact and he answered us on skype_call: %s.\n", SKYPIAX_P_LOG, id);
+                                        }
+                                }
+
+                                if (!strcasecmp(prop, "DURATION") && (tech_pvt->interface_state == SKYPIAX_STATE_ERROR_DOUBLE_CALL)) {
+                                        char msg_to_skype[1024];
+                                        skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                        ERRORA("We are in a double call situation, trying to get out hanging up call id: %s.\n", SKYPIAX_P_LOG, id);
+                                        sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                        skypiax_sleep(10000);
+                                        //return CALLFLOW_INCOMING_HANGUP;
+                                }
+
+                                if (!strcasecmp(prop, "STATUS")) {
+
+                                        if (!strcasecmp(value, "RINGING")) {
+                                                char msg_to_skype[1024];
+                                                if ((tech_pvt->interface_state != SKYPIAX_STATE_SELECTED && tech_pvt->interface_state != SKYPIAX_STATE_DIALING)
+                                                        && (!strlen(tech_pvt->skype_call_id) || !strlen(tech_pvt->session_uuid_str))) {
+                                                        /* we are NOT inside an active call */
+
+                                                        DEBUGA_SKYPE("NO ACTIVE calls in this moment, skype_call %s is RINGING, to ask PARTNER_HANDLE\n", SKYPIAX_P_LOG, id);
+                                                        sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id);
+                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                        skypiax_sleep(10000);
+                                                } else {
+                                                        /* we are inside an active call */
+                                                        if (!strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                                /* this is the call in which we are calling out */
+                                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_RINGING;
+                                                                tech_pvt->interface_state = SKYPIAX_STATE_RINGING;
+                                                                skypiax_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", SKYPIAX_P_LOG, id);
+                                                                remote_party_is_ringing(tech_pvt);
+                                                        } 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",
+                                                                         SKYPIAX_P_LOG, id);
+                                                                sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id);
+                                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                skypiax_sleep(10000);
+                                                        }
+                                                }
+                                        } else if (!strcasecmp(value, "EARLYMEDIA")) {
+                                                char msg_to_skype[1024];
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_EARLYMEDIA;
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DIALING;
+                                                DEBUGA_SKYPE("Our remote party in skype_call %s is EARLYMEDIA\n", SKYPIAX_P_LOG, id);
+                                                if (start_audio_threads(tech_pvt)) {
+                                                        ERRORA("start_audio_threads FAILED\n", SKYPIAX_P_LOG);
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                }
+                                                skypiax_sleep(1000);
+                                                sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                sprintf(msg_to_skype, "#output ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+
+                                                remote_party_is_early_media(tech_pvt);
+                                        } else if (!strcasecmp(value, "MISSED")) {
+                                                DEBUGA_SKYPE("We missed skype_call %s\n", SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, "FINISHED")) {
+                                                //DEBUGA_SKYPE("skype_call %s now is DOWN\n", SKYPIAX_P_LOG, id);
+                                                if (!strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                        //tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                                        DEBUGA_SKYPE("skype_call %s is MY call, now I'm going DOWN\n", SKYPIAX_P_LOG, id);
+                                                        //tech_pvt->skype_call_id[0] = '\0';
+                                                        if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                                //tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                                return CALLFLOW_INCOMING_HANGUP;
+                                                        } else {
+                                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                        }
+                                                } else {
+                                                        DEBUGA_SKYPE("skype_call %s is NOT MY call, ignoring\n", SKYPIAX_P_LOG, id);
+                                                }
+
+                                        } else if (!strcasecmp(value, "CANCELLED")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_CANCELLED;
+                                                DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now CANCELLED\n", SKYPIAX_P_LOG, id);
+                                                tech_pvt->skype_call_id[0] = '\0';
+                                                if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                } else {
+                                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                }
+                                        } else if (!strcasecmp(value, "FAILED")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now FAILED\n", SKYPIAX_P_LOG, id);
+                                                tech_pvt->skype_call_id[0] = '\0';
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else if (!strcasecmp(value, "REFUSED")) {
+                                                if (!strcasecmp(id, tech_pvt->skype_call_id)) {
+                                                        /* this is the id of the call we are in, probably we generated it */
+                                                        tech_pvt->skype_callflow = CALLFLOW_STATUS_REFUSED;
+                                                        DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now REFUSED\n", SKYPIAX_P_LOG, id);
+                                                        skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                        tech_pvt->skype_call_id[0] = '\0';
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                } else {
+                                                        /* we're here because were us that refused an incoming call */
+                                                        DEBUGA_SKYPE("we REFUSED skype_call %s\n", SKYPIAX_P_LOG, id);
+                                                }
+                                        } else if (!strcasecmp(value, "TRANSFERRING")) {
+                                                DEBUGA_SKYPE("skype_call %s is transferring\n", SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, "TRANSFERRED")) {
+                                                DEBUGA_SKYPE("skype_call %s has been transferred\n", SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, "ROUTING")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_ROUTING;
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DIALING;
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                DEBUGA_SKYPE("skype_call: %s is now ROUTING\n", SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, "UNPLACED")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_UNPLACED;
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DIALING;
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                DEBUGA_SKYPE("skype_call: %s is now UNPLACED\n", SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, "INPROGRESS")) {
+                                                char msg_to_skype[1024];
+
+                                                if (!strlen(tech_pvt->session_uuid_str)) {
+                                                        DEBUGA_SKYPE("no tech_pvt->session_uuid_str\n", SKYPIAX_P_LOG);
+                                                }
+                                                if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                        if (!strlen(tech_pvt->session_uuid_str) || !strlen(tech_pvt->skype_call_id)
+                                                                || !strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                                DEBUGA_SKYPE("skype_call: %s is now active\n", SKYPIAX_P_LOG, id);
+
+                                                                if (tech_pvt->skype_callflow != CALLFLOW_STATUS_EARLYMEDIA) {
+                                                                        tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                                        tech_pvt->interface_state = SKYPIAX_STATE_UP;
+
+                                                                        if (start_audio_threads(tech_pvt)) {
+                                                                                ERRORA("start_audio_threads FAILED\n", SKYPIAX_P_LOG);
+                                                                                return CALLFLOW_INCOMING_HANGUP;
+                                                                        }
+                                                                        skypiax_sleep(1000);        //FIXME
+                                                                        sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port);
+                                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                        skypiax_sleep(1000);        //FIXME
+                                                                        sprintf(msg_to_skype, "#output ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port);
+                                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                }
+                                                                tech_pvt->skype_callflow = SKYPIAX_STATE_UP;
+                                                                if (!strlen(tech_pvt->session_uuid_str)) {
+                                                                        DEBUGA_SKYPE("New Inbound Channel!\n\n\n\n", SKYPIAX_P_LOG);
+                                                                        new_inbound_channel(tech_pvt);
+                                                                } else {
+                                                                        DEBUGA_SKYPE("Outbound Channel Answered! session_uuid_str=%s\n", SKYPIAX_P_LOG, tech_pvt->session_uuid_str);
+                                                                        outbound_channel_answered(tech_pvt);
+                                                                }
+                                                        } else {
+                                                                DEBUGA_SKYPE("I'm on %s, skype_call %s is NOT MY call, ignoring\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id, id);
+                                                        }
+                                                } else {
+                                                        tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                        DEBUGA_SKYPE("Back from REMOTEHOLD!\n", SKYPIAX_P_LOG);
+                                                }
+
+                                        } else if (!strcasecmp(value, "REMOTEHOLD")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_REMOTEHOLD;
+                                                DEBUGA_SKYPE("skype_call: %s is now REMOTEHOLD\n", SKYPIAX_P_LOG, id);
+
+                                        } else if (!strcasecmp(value, "BUSY")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE
+                                                        ("we tried to call Skype on skype_call %s and remote party (destination) was BUSY. Our outbound call has failed\n",
+                                                         SKYPIAX_P_LOG, id);
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                tech_pvt->skype_call_id[0] = '\0';
+                                                skypiax_sleep(1000);
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else if (!strcasecmp(value, "WAITING_REDIAL_COMMAND")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE
+                                                        ("we tried to call Skype on skype_call %s and remote party (destination) has rejected us (WAITING_REDIAL_COMMAND). Our outbound call has failed\n",
+                                                         SKYPIAX_P_LOG, id);
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                tech_pvt->skype_call_id[0] = '\0';
+                                                skypiax_sleep(1000);
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else {
+                                                WARNINGA("skype_call: %s, STATUS: %s is not recognized\n", SKYPIAX_P_LOG, id, value);
+                                        }
+                                }                                //STATUS
+                        }                                        //CALL
+                        /* the "numbered" messages that follows are used by the directory application, not yet ported */
+                        if (!strcasecmp(message, "#333")) {
+                                /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[11]: %s\n", SKYPIAX_P_LOG,
+                                 * message_2, &message_2[11]); */
+                                memset(tech_pvt->skype_friends, 0, 4096);
+                                skypiax_strncpy(tech_pvt->skype_friends, &message_2[11], 4095);
+                        }
+                        if (!strcasecmp(message, "#222")) {
+                                /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[10]: %s\n", SKYPIAX_P_LOG,
+                                 * message_2, &message_2[10]); */
+                                memset(tech_pvt->skype_fullname, 0, 512);
+                                skypiax_strncpy(tech_pvt->skype_fullname, &message_2[10], 511);
+                        }
+                        if (!strcasecmp(message, "#765")) {
+                                /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[10]: %s\n", SKYPIAX_P_LOG,
+                                 * message_2, &message_2[10]); */
+                                memset(tech_pvt->skype_displayname, 0, 512);
+                                skypiax_strncpy(tech_pvt->skype_displayname, &message_2[10], 511);
+                        }
+                        a = 0;
+                }                                                //message end
+        }                                                        //read_from_pipe
+        return 0;
+}
+
+void *skypiax_do_tcp_srv_thread_func(void *obj)
+{
+        private_t *tech_pvt = obj;
+        int s;
+        unsigned int len;
+        unsigned int i;
+        unsigned int a;
+#if defined(WIN32) && !defined(__CYGWIN__)
+        int sin_size;
+#else /* WIN32 */
+        unsigned int sin_size;
+#endif /* WIN32 */
+        unsigned int fd;
+        short srv_in[SAMPLES_PER_FRAME];
+        short srv_out[SAMPLES_PER_FRAME / 2];
+        //struct sockaddr_in my_addr;
+        struct sockaddr_in remote_addr;
+        //int exit = 0;
+        unsigned int kill_cli_size;
+        short kill_cli_buff[SAMPLES_PER_FRAME];
+        short totalbuf[SAMPLES_PER_FRAME];
+
+        s = skypiax_socket_create_and_bind(tech_pvt, &tech_pvt->tcp_srv_port);
+        if (s < 0) {
+                ERRORA("skypiax_socket_create_and_bind error!\n", SKYPIAX_P_LOG);
+                return NULL;
+        }
+        DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+
+        listen(s, 6);
+
+        sin_size = sizeof(remote_addr);
+
+ /****************************/
+        while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                 && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                         || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                         || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+
+                unsigned int fdselectgio;
+                int rtgio;
+                fd_set fsgio;
+                struct timeval togio;
+
+                if (!(running && tech_pvt->running))
+                        break;
+                FD_ZERO(&fsgio);
+                togio.tv_usec = 20000;        //20msec
+                togio.tv_sec = 0;
+                fdselectgio = s;
+                FD_SET(fdselectgio, &fsgio);
+
+                rtgio = select(fdselectgio + 1, &fsgio, NULL, NULL, &togio);
+
+                if (rtgio) {
+
+ /****************************/
+
+                        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 && tech_pvt->running))
+                                        break;
+                                while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                                         && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                                                 || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                                                 || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+
+                                        unsigned int fdselect;
+                                        int rt;
+                                        fd_set fs;
+                                        struct timeval to;
+
+                                        if (!(running && tech_pvt->running))
+                                                break;
+                                        //exit = 1;
+
+                                        fdselect = fd;
+                                        FD_ZERO(&fs);
+                                        FD_SET(fdselect, &fs);
+                                        //to.tv_usec = 2000000; //2000 msec
+                                        to.tv_usec = 60000;        //60 msec
+                                        to.tv_sec = 0;
+
+                                        rt = select(fdselect + 1, &fs, NULL, NULL, &to);
+                                        if (rt > 0) {
+
+                                                if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                        len = recv(fd, (char *) srv_in, 320, 0);        //seems that Skype only sends 320 bytes at time
+                                                } else {
+                                                        len = 0;
+                                                }
+
+                                                if (len == 320) {
+                                                        unsigned int howmany;
+
+                                                        if (samplerate_skypiax == 8000) {
+                                                                /* we're downsampling from 16khz to 8khz, srv_out will contain each other sample from srv_in */
+                                                                a = 0;
+                                                                for (i = 0; i < len / sizeof(short); i++) {
+                                                                        srv_out[a] = srv_in[i];
+                                                                        i++;
+                                                                        a++;
+                                                                }
+                                                        } else if (samplerate_skypiax == 16000) {
+                                                                /* we're NOT downsampling, srv_out will contain ALL samples from srv_in */
+                                                                for (i = 0; i < len / sizeof(short); i++) {
+                                                                        srv_out[i] = srv_in[i];
+                                                                }
+                                                        } else {
+                                                                ERRORA("SAMPLERATE_SKYPIAX can only be 8000 or 16000\n", SKYPIAX_P_LOG);
+                                                        }
+                                                        /* if not yet done, let's store the half incoming frame */
+                                                        if (!tech_pvt->audiobuf_is_loaded) {
+                                                                for (i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
+                                                                        tech_pvt->audiobuf[i] = srv_out[i];
+                                                                }
+                                                                tech_pvt->audiobuf_is_loaded = 1;
+                                                        } else {
+                                                                /* we got a stored half frame, build a complete frame in totalbuf using the stored half frame and the current half frame */
+                                                                for (i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
+                                                                        totalbuf[i] = tech_pvt->audiobuf[i];
+                                                                }
+                                                                for (a = 0; a < SAMPLES_PER_FRAME / 2; a++) {
+                                                                        totalbuf[i] = srv_out[a];
+                                                                        i++;
+                                                                }
+                                                                /* send the complete frame through the pipe to our code waiting for incoming audio */
+                                                                howmany = skypiax_pipe_write(tech_pvt->audiopipe[1], totalbuf, SAMPLES_PER_FRAME * sizeof(short));
+                                                                if (howmany != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                        ERRORA("howmany is %d, but was expected to be %d\n", SKYPIAX_P_LOG,
+                                                                                 howmany, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                                }
+                                                                /* done with the stored half frame */
+                                                                tech_pvt->audiobuf_is_loaded = 0;
+                                                        }
+
+                                                } else if (len == 0) {
+                                                        skypiax_sleep(1000);
+                                                } else {
+                                                        DEBUGA_SKYPE("len=%d, expected 320\n", SKYPIAX_P_LOG, len);
+                                                }
+
+                                        } else {
+                                                if (rt)
+                                                        ERRORA("SRV rt=%d\n", SKYPIAX_P_LOG, rt);
+                                                skypiax_sleep(10000);
+                                        }
+
+                                }
+
+                                /* let's send some frame in the pipes, so both tcp_cli and tcp_srv will have an occasion to die */
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt->audiopipe[1], kill_cli_buff, kill_cli_size);
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt->audioskypepipe[1], kill_cli_buff, kill_cli_size);
+                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt->audiopipe[1], kill_cli_buff, kill_cli_size);
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt->audioskypepipe[1], kill_cli_buff, kill_cli_size);
+
+                                DEBUGA_SKYPE("Skype incoming audio GONE\n", SKYPIAX_P_LOG);
+                                skypiax_close_socket(fd);
+                                //if (exit)
+                                break;
+                        }
+                }
+        }
+
+        DEBUGA_SKYPE("incoming audio server (I am it) EXITING\n", SKYPIAX_P_LOG);
+        skypiax_close_socket(s);
+        tech_pvt->tcp_srv_thread = NULL;
+        return NULL;
+}
+
+void *skypiax_do_tcp_cli_thread_func(void *obj)
+{
+        private_t *tech_pvt = obj;
+        int s;
+        //struct sockaddr_in my_addr;
+        struct sockaddr_in remote_addr;
+        unsigned int got;
+        unsigned int len;
+        unsigned int i;
+        unsigned int a;
+        unsigned int fd;
+        short cli_out[SAMPLES_PER_FRAME * 2];
+        short cli_in[SAMPLES_PER_FRAME];
+#ifdef WIN32
+        int sin_size;
+#else
+        unsigned int sin_size;
+#endif /* WIN32 */
+
+        s = skypiax_socket_create_and_bind(tech_pvt, &tech_pvt->tcp_cli_port);
+        if (s < 0) {
+                ERRORA("skypiax_socket_create_and_bind error!\n", SKYPIAX_P_LOG);
+                return NULL;
+        }
+
+
+
+        DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+
+        listen(s, 6);
+
+        sin_size = sizeof(remote_addr);
+
+ /****************************/
+        while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                 && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                         || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                         || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+
+                unsigned int fdselectgio;
+                int rtgio;
+                fd_set fsgio;
+                struct timeval togio;
+
+                if (!(running && tech_pvt->running))
+                        break;
+                FD_ZERO(&fsgio);
+                togio.tv_usec = 20000;        //20msec
+                togio.tv_sec = 0;
+                fdselectgio = s;
+                FD_SET(fdselectgio, &fsgio);
+
+                rtgio = select(fdselectgio + 1, &fsgio, NULL, NULL, &togio);
+
+                if (rtgio) {
+
+ /****************************/
+
+                        while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
+                                DEBUGA_SKYPE("ACCEPTED here you send me %d\n", SKYPIAX_P_LOG, tech_pvt->tcp_cli_port);
+#ifndef WIN32
+                                fcntl(tech_pvt->audioskypepipe[0], F_SETFL, O_NONBLOCK);
+                                fcntl(tech_pvt->audioskypepipe[1], F_SETFL, O_NONBLOCK);
+#endif //WIN32
+
+                                if (!(running && tech_pvt->running))
+                                        break;
+                                while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                                         && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                                                 || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                                                 || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+                                        unsigned int fdselect;
+                                        int rt;
+                                        fd_set fs;
+                                        struct timeval to;
+
+                                        if (!(running && tech_pvt->running))
+                                                break;
+                                        FD_ZERO(&fs);
+                                        to.tv_usec = 120000;        //120msec
+                                        to.tv_sec = 0;
+#if defined(WIN32) && !defined(__CYGWIN__)
+/* on win32 we cannot select from the apr "pipe", so we select on socket writability */
+                                        fdselect = fd;
+                                        FD_SET(fdselect, &fs);
+
+                                        rt = select(fdselect + 1, NULL, &fs, NULL, &to);
+#else
+/* on *unix and cygwin we select from the real pipe */
+                                        fdselect = tech_pvt->audioskypepipe[0];
+                                        FD_SET(fdselect, &fs);
+
+                                        rt = select(fdselect + 1, &fs, NULL, NULL, &to);
+#endif
+
+                                        if (rt > 0) {
+                                                int counter;
+
+                                                /* until we drained the pipe to empty */
+                                                for (counter = 0; counter < 10; counter++) {
+                                                        /* read from the pipe the audio frame we are supposed to send out */
+                                                        got = skypiax_pipe_read(tech_pvt->audioskypepipe[0], cli_in, SAMPLES_PER_FRAME * sizeof(short));
+                                                        if (got == -1)
+                                                                break;
+
+                                                        if (got != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                WARNINGA("got is %d, but was expected to be %d\n", SKYPIAX_P_LOG, got, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                        }
+
+                                                        if (got == SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                if (samplerate_skypiax == 8000) {
+
+                                                                        /* we're upsampling from 8khz to 16khz, cli_out will contain two times each sample from cli_in */
+                                                                        a = 0;
+                                                                        for (i = 0; i < got / sizeof(short); i++) {
+                                                                                cli_out[a] = cli_in[i];
+                                                                                a++;
+                                                                                cli_out[a] = cli_in[i];
+                                                                                a++;
+                                                                        }
+                                                                        got = got * 2;
+                                                                } else if (samplerate_skypiax == 16000) {
+                                                                        /* we're NOT upsampling, cli_out will contain just ALL samples from cli_in */
+                                                                        for (i = 0; i < got / sizeof(short); i++) {
+                                                                                cli_out[i] = cli_in[i];
+                                                                        }
+                                                                } else {
+                                                                        ERRORA("SAMPLERATE_SKYPIAX can only be 8000 or 16000\n", SKYPIAX_P_LOG);
+                                                                }
+
+                                                                /* send the 16khz frame to the Skype client waiting for incoming audio to be sent to the remote party */
+                                                                if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                                        len = send(fd, (char *) cli_out, got, 0);
+                                                                        skypiax_sleep(5000);        //5 msec
+
+                                                                        if (len == -1) {
+                                                                                break;
+                                                                        } else if (len != got) {
+                                                                                ERRORA("len=%d\n", SKYPIAX_P_LOG, len);
+                                                                                skypiax_sleep(1000);
+                                                                                break;
+                                                                        }
+                                                                }
+
+                                                        } else {
+
+                                                                WARNINGA("got is %d, but was expected to be %d\n", SKYPIAX_P_LOG, got, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                        }
+                                                }
+                                        } else {
+                                                if (rt)
+                                                        ERRORA("CLI rt=%d\n", SKYPIAX_P_LOG, rt);
+                                                memset(cli_out, 0, sizeof(cli_out));
+                                                if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                        len = send(fd, (char *) cli_out, sizeof(cli_out), 0);
+                                                        len = send(fd, (char *) cli_out, sizeof(cli_out) / 2, 0);
+                                                        //WARNINGA("sent %d of zeros to keep the Skype client socket busy\n", SKYPIAX_P_LOG, sizeof(cli_out) + sizeof(cli_out)/2);
+                                                } else {
+                                                        /*
+                                                         XXX do nothing
+                                                         */
+                                                        //WARNINGA("we don't send it\n", SKYPIAX_P_LOG);
+                                                }
+                                                skypiax_sleep(1000);
+                                        }
+
+                                }
+                                DEBUGA_SKYPE("Skype outbound audio GONE\n", SKYPIAX_P_LOG);
+                                skypiax_close_socket(fd);
+                                break;
+                        }
+                }
+        }
+
+        DEBUGA_SKYPE("outbound audio server (I am it) EXITING\n", SKYPIAX_P_LOG);
+        skypiax_close_socket(s);
+        tech_pvt->tcp_cli_thread = NULL;
+        return NULL;
+}
+
+int skypiax_audio_read(private_t * tech_pvt)
+{
+        unsigned int samples;
+
+        samples = skypiax_pipe_read(tech_pvt->audiopipe[0], tech_pvt->read_frame.data, SAMPLES_PER_FRAME * sizeof(short));
+
+        if (samples != SAMPLES_PER_FRAME * sizeof(short)) {
+                if (samples)
+                        WARNINGA("read samples=%u expected=%u\n", SKYPIAX_P_LOG, samples, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                return 0;
+        } else {
+                /* A real frame */
+                tech_pvt->read_frame.datalen = samples;
+        }
+        return 1;
+}
+
+int skypiax_senddigit(private_t * tech_pvt, char digit)
+{
+        char msg_to_skype[1024];
+
+        DEBUGA_SKYPE("DIGIT received: %c\n", SKYPIAX_P_LOG, digit);
+        sprintf(msg_to_skype, "SET CALL %s DTMF %c", tech_pvt->skype_call_id, digit);
+        skypiax_signaling_write(tech_pvt, msg_to_skype);
+
+        return 0;
+}
+
+int skypiax_call(private_t * tech_pvt, char *rdest, int timeout)
+{
+        char msg_to_skype[1024];
+
+        //skypiax_sleep(5000);
+        DEBUGA_SKYPE("Calling Skype, rdest is: %s\n", SKYPIAX_P_LOG, rdest);
+        //skypiax_signaling_write(tech_pvt, "SET AGC OFF");
+        //skypiax_sleep(10000);
+        //skypiax_signaling_write(tech_pvt, "SET AEC OFF");
+        //skypiax_sleep(10000);
+
+        sprintf(msg_to_skype, "CALL %s", rdest);
+        if (skypiax_signaling_write(tech_pvt, msg_to_skype) < 0) {
+                ERRORA("failed to communicate with Skype client, now exit\n", SKYPIAX_P_LOG);
+                return -1;
+        }
+        return 0;
+}
+
+/***************************/
+/* PLATFORM SPECIFIC */
+/***************************/
+#if defined(WIN32) && !defined(__CYGWIN__)
+int skypiax_pipe_read(switch_file_t * pipe, short *buf, int howmany)
+{
+        switch_size_t quantity;
+
+        quantity = howmany;
+
+        switch_file_read(pipe, buf, &quantity);
+
+        howmany = quantity;
+
+        return howmany;
+}
+
+int skypiax_pipe_write(switch_file_t * pipe, short *buf, int howmany)
+{
+        switch_size_t quantity;
+
+        quantity = howmany;
+
+        switch_file_write(pipe, buf, &quantity);
+
+        howmany = quantity;
+
+        return howmany;
+}
+
+int skypiax_close_socket(unsigned int fd)
+{
+        int res;
+
+        res = closesocket(fd);
+
+        return res;
+}
+
+int skypiax_audio_init(private_t * tech_pvt)
+{
+        switch_status_t rv;
+        rv = switch_file_pipe_create(&tech_pvt->audiopipe[0], &tech_pvt->audiopipe[1], skypiax_module_pool);
+        rv = switch_file_pipe_create(&tech_pvt->audioskypepipe[0], &tech_pvt->audioskypepipe[1], skypiax_module_pool);
+        return 0;
+}
+#else /* WIN32 */
+int skypiax_pipe_read(int pipe, short *buf, int howmany)
+{
+        howmany = read(pipe, buf, howmany);
+        return howmany;
+}
+
+int skypiax_pipe_write(int pipe, short *buf, int howmany)
+{
+        howmany = write(pipe, buf, howmany);
+        return howmany;
+}
+
+int skypiax_close_socket(unsigned int fd)
+{
+        int res;
+
+        res = close(fd);
+
+        return res;
+}
+
+int skypiax_audio_init(private_t * tech_pvt)
+{
+        if (pipe(tech_pvt->audiopipe)) {
+                fcntl(tech_pvt->audiopipe[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt->audiopipe[1], F_SETFL, O_NONBLOCK);
+        }
+        if (pipe(tech_pvt->audioskypepipe)) {
+                fcntl(tech_pvt->audioskypepipe[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt->audioskypepipe[1], F_SETFL, O_NONBLOCK);
+        }
+
+/* this pipe is the audio fd for asterisk to poll on during a call. FS do not use it */
+        tech_pvt->skypiax_sound_capt_fd = tech_pvt->audiopipe[0];
+
+        return 0;
+}
+#endif /* WIN32 */
+
+#ifdef WIN32
+
+enum {
+        SKYPECONTROLAPI_ATTACH_SUCCESS = 0,        /* Client is successfully
+                                                                                 attached and API window handle can be found
+                                                                                 in wParam parameter */
+        SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION = 1,        /* Skype has acknowledged
+                                                                                                                 connection request and is waiting
+                                                                                                                 for confirmation from the user. */
+        /* The client is not yet attached
+         * and should wait for SKYPECONTROLAPI_ATTACH_SUCCESS message */
+        SKYPECONTROLAPI_ATTACH_REFUSED = 2,        /* User has explicitly
+                                                                                 denied access to client */
+        SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE = 3,        /* API is not available
+                                                                                                 at the moment.
+                                                                                                 For example, this happens when no user
+                                                                                                 is currently logged in. */
+        /* Client should wait for
+         * SKYPECONTROLAPI_ATTACH_API_AVAILABLE
+         * broadcast before making any further */
+        /* connection attempts. */
+        SKYPECONTROLAPI_ATTACH_API_AVAILABLE = 0x8001
+};
+
+/* Visual C do not have strsep? */
+char
+ *strsep(char **stringp, const char *delim)
+{
+        char *res;
+
+        if (!stringp || !*stringp || !**stringp)
+                return (char *) 0;
+
+        res = *stringp;
+        while (**stringp && !strchr(delim, **stringp))
+                ++(*stringp);
+
+        if (**stringp) {
+                **stringp = '\0';
+                ++(*stringp);
+        }
+
+        return res;
+}
+
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype)
+{
+        static char acInputRow[1024];
+        COPYDATASTRUCT oCopyData;
+
+        DEBUGA_SKYPE("SENDING: |||%s||||\n", SKYPIAX_P_LOG, msg_to_skype);
+
+        sprintf(acInputRow, "%s", msg_to_skype);
+        DEBUGA_SKYPE("acInputRow: |||%s||||\n", SKYPIAX_P_LOG, acInputRow);
+        /* send command to skype */
+        oCopyData.dwData = 0;
+        oCopyData.lpData = acInputRow;
+        oCopyData.cbData = strlen(acInputRow) + 1;
+        if (oCopyData.cbData != 1) {
+                if (SendMessage
+                        (tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle, WM_COPYDATA,
+                         (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, (LPARAM) & oCopyData) == FALSE) {
+                        ERRORA("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax, then launch Skypiax and try again.\n", SKYPIAX_P_LOG);
+                        return -1;
+                }
+        }
+
+        return 0;
+
+}
+
+LRESULT APIENTRY skypiax_present(HWND hWindow, UINT uiMessage, WPARAM uiParam, LPARAM ulParam)
+{
+        LRESULT lReturnCode;
+        int fIssueDefProc;
+        private_t *tech_pvt = NULL;
+
+        lReturnCode = 0;
+        fIssueDefProc = 0;
+        tech_pvt = (private_t *) GetWindowLong(hWindow, GWL_USERDATA);
+        if (!running)
+                return lReturnCode;
+        switch (uiMessage) {
+        case WM_CREATE:
+                tech_pvt = (private_t *) ((LPCREATESTRUCT) ulParam)->lpCreateParams;
+                SetWindowLong(hWindow, GWL_USERDATA, (LONG) tech_pvt);
+                DEBUGA_SKYPE("got CREATE\n", SKYPIAX_P_LOG);
+                break;
+        case WM_DESTROY:
+                DEBUGA_SKYPE("got DESTROY\n", SKYPIAX_P_LOG);
+                tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = NULL;
+                PostQuitMessage(0);
+                break;
+        case WM_COPYDATA:
+                if (tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle == (HWND) uiParam) {
+                        unsigned int howmany;
+                        char msg_from_skype[2048];
+
+                        PCOPYDATASTRUCT poCopyData = (PCOPYDATASTRUCT) ulParam;
+
+                        memset(msg_from_skype, '\0', sizeof(msg_from_skype));
+                        skypiax_strncpy(msg_from_skype, (const char *) poCopyData->lpData, sizeof(msg_from_skype) - 2);
+
+                        howmany = strlen(msg_from_skype) + 1;
+                        howmany = skypiax_pipe_write(tech_pvt->SkypiaxHandles.fdesc[1], (short *) msg_from_skype, howmany);
+                        //DEBUGA_SKYPE("From Skype API: %s\n", SKYPIAX_P_LOG, msg_from_skype);
+                        lReturnCode = 1;
+                }
+                break;
+        default:
+                if (tech_pvt && tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+                        if (uiMessage == tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+                                switch (ulParam) {
+                                case SKYPECONTROLAPI_ATTACH_SUCCESS:
+                                        if (!tech_pvt->SkypiaxHandles.currentuserhandle) {
+                                                //DEBUGA_SKYPE("\n\n\tConnected to Skype API!\n", SKYPIAX_P_LOG);
+                                                tech_pvt->SkypiaxHandles.api_connected = 1;
+                                                tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle = (HWND) uiParam;
+                                                tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle = tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle;
+                                        }
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION:
+                                        //DEBUGA_SKYPE ("\n\n\tIf I do not (almost) immediately connect to Skype API,\n\tplease give the Skype client authorization to be connected \n\tby Asterisk and to not ask you again.\n\n", SKYPIAX_P_LOG);
+                                        skypiax_sleep(5000);
+#if 0
+                                        if (!tech_pvt->SkypiaxHandles.currentuserhandle) {
+                                                SendMessage(HWND_BROADCAST,
+                                                                        tech_pvt->SkypiaxHandles.
+                                                                        win32_uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0);
+                                        }
+#endif
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_REFUSED:
+                                        ERRORA("Skype client refused to be connected by Skypiax!\n", SKYPIAX_P_LOG);
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE:
+                                        ERRORA("Skype API not (yet?) available\n", SKYPIAX_P_LOG);
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_API_AVAILABLE:
+                                        DEBUGA_SKYPE("Skype API available\n", SKYPIAX_P_LOG);
+                                        skypiax_sleep(5000);
+#if 0
+                                        if (!tech_pvt->SkypiaxHandles.currentuserhandle) {
+                                                SendMessage(HWND_BROADCAST,
+                                                                        tech_pvt->SkypiaxHandles.
+                                                                        win32_uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0);
+                                        }
+#endif
+                                        break;
+                                default:
+                                        WARNINGA("GOT AN UNKNOWN SKYPE WINDOWS MSG\n", SKYPIAX_P_LOG);
+                                }
+                                lReturnCode = 1;
+                                break;
+                        }
+                }
+                fIssueDefProc = 1;
+                break;
+        }
+        if (fIssueDefProc)
+                lReturnCode = DefWindowProc(hWindow, uiMessage, uiParam, ulParam);
+        return (lReturnCode);
+}
+
+int win32_Initialize_CreateWindowClass(private_t * tech_pvt)
+{
+        unsigned char *paucUUIDString;
+        RPC_STATUS lUUIDResult;
+        int fReturnStatus;
+        UUID oUUID;
+
+        fReturnStatus = 0;
+        lUUIDResult = UuidCreate(&oUUID);
+        tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle = (HINSTANCE) OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
+        if (tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle != NULL && (lUUIDResult == RPC_S_OK || lUUIDResult == RPC_S_UUID_LOCAL_ONLY)) {
+                if (UuidToString(&oUUID, &paucUUIDString) == RPC_S_OK) {
+                        WNDCLASS oWindowClass;
+
+                        strcpy(tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, "Skype-API-Skypiax-");
+                        strcat(tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, (char *) paucUUIDString);
+
+                        oWindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+                        oWindowClass.lpfnWndProc = (WNDPROC) & skypiax_present;
+                        oWindowClass.cbClsExtra = 0;
+                        oWindowClass.cbWndExtra = 0;
+                        oWindowClass.hInstance = tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle;
+                        oWindowClass.hIcon = NULL;
+                        oWindowClass.hCursor = NULL;
+                        oWindowClass.hbrBackground = NULL;
+                        oWindowClass.lpszMenuName = NULL;
+                        oWindowClass.lpszClassName = tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName;
+
+                        if (RegisterClass(&oWindowClass) != 0)
+                                fReturnStatus = 1;
+
+                        RpcStringFree(&paucUUIDString);
+                }
+        }
+        if (fReturnStatus == 0)
+                CloseHandle(tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle);
+        tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle = NULL;
+        return (fReturnStatus);
+}
+
+void win32_DeInitialize_DestroyWindowClass(private_t * tech_pvt)
+{
+        UnregisterClass(tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle);
+        CloseHandle(tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle);
+        tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle = NULL;
+}
+
+int win32_Initialize_CreateMainWindow(private_t * tech_pvt)
+{
+        tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle =
+                CreateWindowEx(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,
+                                         tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, "",
+                                         WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT,
+                                         128, 128, NULL, 0, tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle, tech_pvt);
+        return (tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle != NULL ? 1 : 0);
+}
+
+void win32_DeInitialize_DestroyMainWindow(private_t * tech_pvt)
+{
+        if (tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle != NULL)
+                DestroyWindow(tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle), tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = NULL;
+}
+
+void *skypiax_do_skypeapi_thread_func(void *obj)
+{
+        private_t *tech_pvt = obj;
+#if defined(WIN32) && !defined(__CYGWIN__)
+        switch_status_t rv;
+
+        switch_file_pipe_create(&tech_pvt->SkypiaxHandles.fdesc[0], &tech_pvt->SkypiaxHandles.fdesc[1], skypiax_module_pool);
+        rv = switch_file_pipe_create(&tech_pvt->SkypiaxHandles.fdesc[0], &tech_pvt->SkypiaxHandles.fdesc[1], skypiax_module_pool);
+#else /* WIN32 */
+        if (pipe(tech_pvt->SkypiaxHandles.fdesc)) {
+                fcntl(tech_pvt->SkypiaxHandles.fdesc[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt->SkypiaxHandles.fdesc[1], F_SETFL, O_NONBLOCK);
+        }
+#endif /* WIN32 */
+
+        tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach = RegisterWindowMessage("SkypeControlAPIAttach");
+        tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover = RegisterWindowMessage("SkypeControlAPIDiscover");
+
+        skypiax_sleep(200000);                //0,2 sec
+
+        if (tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach != 0
+                && tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover != 0) {
+                if (win32_Initialize_CreateWindowClass(tech_pvt)) {
+                        if (win32_Initialize_CreateMainWindow(tech_pvt)) {
+                                if (SendMessage
+                                        (HWND_BROADCAST,
+                                         tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover,
+                                         (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0) != 0) {
+                                        tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle;
+                                        while (running && tech_pvt->running) {
+                                                MSG oMessage;
+                                                if (!(running && tech_pvt->running))
+                                                        break;
+                                                while (GetMessage(&oMessage, 0, 0, 0)) {
+                                                        TranslateMessage(&oMessage);
+                                                        DispatchMessage(&oMessage);
+                                                }
+                                        }
+                                }
+                                win32_DeInitialize_DestroyMainWindow(tech_pvt);
+                        }
+                        win32_DeInitialize_DestroyWindowClass(tech_pvt);
+                }
+        }
+
+        return NULL;
+}
+
+#else /* NOT WIN32 */
+int X11_errors_handler(Display * dpy, XErrorEvent * err)
+{
+        (void) dpy;
+        private_t *tech_pvt = NULL;
+
+        xerror = err->error_code;
+        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 */
+}
+
+static void X11_errors_trap(void)
+{
+        xerror = 0;
+        old_handler = XSetErrorHandler(X11_errors_handler);
+}
+
+static int X11_errors_untrap(void)
+{
+        XSetErrorHandler(old_handler);
+        return (xerror != BadValue) && (xerror != BadWindow);
+}
+
+int skypiax_send_message(struct SkypiaxHandles *SkypiaxHandles, const char *message_P)
+{
+
+        Window w_P;
+        Display *disp;
+        Window handle_P;
+        int ok;
+        private_t *tech_pvt = NULL;
+
+        w_P = SkypiaxHandles->skype_win;
+        disp = SkypiaxHandles->disp;
+        handle_P = SkypiaxHandles->win;
+
+        Atom atom1 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+        Atom atom2 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
+        unsigned int pos = 0;
+        unsigned int len = strlen(message_P);
+        XEvent e;
+
+        memset(&e, 0, sizeof(e));
+        e.xclient.type = ClientMessage;
+        e.xclient.message_type = atom1;        /* leading message */
+        e.xclient.display = disp;
+        e.xclient.window = handle_P;
+        e.xclient.format = 8;
+
+        X11_errors_trap();
+        //XLockDisplay(disp);
+        do {
+                unsigned int i;
+                for (i = 0; i < 20 && i + pos <= len; ++i)
+                        e.xclient.data.b[i] = message_P[i + pos];
+                XSendEvent(disp, w_P, False, 0, &e);
+
+                e.xclient.message_type = atom2;        /* following messages */
+                pos += i;
+        } while (pos <= len);
+
+        XSync(disp, False);
+        ok = X11_errors_untrap();
+
+        if (!ok)
+                ERRORA("Sending message failed with status %d\n", SKYPIAX_P_LOG, xerror);
+        //XUnlockDisplay(disp);
+
+        return 1;
+}
+
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype)
+{
+        struct SkypiaxHandles *SkypiaxHandles;
+
+        DEBUGA_SKYPE("SENDING: |||%s||||\n", SKYPIAX_P_LOG, msg_to_skype);
+
+        SkypiaxHandles = &tech_pvt->SkypiaxHandles;
+
+        if (!skypiax_send_message(SkypiaxHandles, msg_to_skype)) {
+                ERRORA
+                        ("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax, then restart Skype, then launch Skypiax and try again.\n",
+                         SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        return 0;
+
+}
+
+int skypiax_present(struct SkypiaxHandles *SkypiaxHandles)
+{
+        Atom skype_inst = XInternAtom(SkypiaxHandles->disp, "_SKYPE_INSTANCE", True);
+
+        Atom type_ret;
+        int format_ret;
+        unsigned long nitems_ret;
+        unsigned long bytes_after_ret;
+        unsigned char *prop;
+        int status;
+        private_t *tech_pvt = NULL;
+
+        X11_errors_trap();
+        //XLockDisplay(disp);
+        status =
+                XGetWindowProperty(SkypiaxHandles->disp, DefaultRootWindow(SkypiaxHandles->disp),
+                                                 skype_inst, 0, 1, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &bytes_after_ret, &prop);
+        //XUnlockDisplay(disp);
+        X11_errors_untrap();
+
+        /* sanity check */
+        if (status != Success || format_ret != 32 || nitems_ret != 1) {
+                SkypiaxHandles->skype_win = (Window) - 1;
+                DEBUGA_SKYPE("Skype instance not found\n", SKYPIAX_P_LOG);
+                running = 0;
+                SkypiaxHandles->api_connected = 0;
+                return 0;
+        }
+
+        SkypiaxHandles->skype_win = *(const unsigned long *) prop & 0xffffffff;
+        DEBUGA_SKYPE("Skype instance found with id #%d\n", SKYPIAX_P_LOG, (unsigned int) SkypiaxHandles->skype_win);
+        SkypiaxHandles->api_connected = 1;
+        return 1;
+}
+
+void skypiax_clean_disp(void *data)
+{
+
+        int *dispptr;
+        int disp;
+        private_t *tech_pvt = NULL;
+
+        dispptr = data;
+        disp = *dispptr;
+
+        if (disp) {
+                DEBUGA_SKYPE("to be destroyed disp %d\n", SKYPIAX_P_LOG, disp);
+                close(disp);
+                DEBUGA_SKYPE("destroyed disp\n", SKYPIAX_P_LOG);
+        } else {
+                DEBUGA_SKYPE("NOT destroyed disp\n", SKYPIAX_P_LOG);
+        }
+        DEBUGA_SKYPE("OUT destroyed disp\n", SKYPIAX_P_LOG);
+        skypiax_sleep(1000);
+}
+
+void *skypiax_do_skypeapi_thread_func(void *obj)
+{
+
+        private_t *tech_pvt = obj;
+        struct SkypiaxHandles *SkypiaxHandles;
+        char buf[512];
+        Display *disp = NULL;
+        Window root = -1;
+        Window win = -1;
+
+        if (!strlen(tech_pvt->X11_display))
+                strcpy(tech_pvt->X11_display, getenv("DISPLAY"));
+
+        if (!tech_pvt->tcp_srv_port)
+                tech_pvt->tcp_srv_port = 10160;
+
+        if (!tech_pvt->tcp_cli_port)
+                tech_pvt->tcp_cli_port = 10161;
+
+        if (pipe(tech_pvt->SkypiaxHandles.fdesc)) {
+                fcntl(tech_pvt->SkypiaxHandles.fdesc[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt->SkypiaxHandles.fdesc[1], F_SETFL, O_NONBLOCK);
+        }
+        SkypiaxHandles = &tech_pvt->SkypiaxHandles;
+        disp = XOpenDisplay(tech_pvt->X11_display);
+        if (!disp) {
+                ERRORA("Cannot open X Display '%s', exiting skype thread\n", SKYPIAX_P_LOG, tech_pvt->X11_display);
+                running = 0;
+                return NULL;
+        } else {
+                DEBUGA_SKYPE("X Display '%s' opened\n", SKYPIAX_P_LOG, tech_pvt->X11_display);
+        }
+
+        int xfd;
+        xfd = XConnectionNumber(disp);
+        fcntl(xfd, F_SETFD, FD_CLOEXEC);
+
+        SkypiaxHandles->disp = disp;
+
+        if (skypiax_present(SkypiaxHandles)) {
+                root = DefaultRootWindow(disp);
+                win = XCreateSimpleWindow(disp, root, 0, 0, 1, 1, 0, BlackPixel(disp, DefaultScreen(disp)), BlackPixel(disp, DefaultScreen(disp)));
+
+                SkypiaxHandles->win = win;
+
+                snprintf(buf, 512, "NAME skypiax");
+
+                if (!skypiax_send_message(SkypiaxHandles, buf)) {
+                        ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n", SKYPIAX_P_LOG);
+                        running = 0;
+                        return NULL;
+                }
+
+                snprintf(buf, 512, "PROTOCOL 7");
+                if (!skypiax_send_message(SkypiaxHandles, buf)) {
+                        ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n", SKYPIAX_P_LOG);
+                        running = 0;
+                        return NULL;
+                }
+
+                /* perform an events loop */
+                XEvent an_event;
+                char buf[21];                        /* can't be longer */
+                char buffer[17000];
+                char *b;
+                int i;
+                int continue_is_broken = 0;
+                Atom atom_begin = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+                Atom atom_continue = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
+
+                b = buffer;
+
+                while (1) {
+                        XNextEvent(disp, &an_event);
+                        if (!(running && tech_pvt->running))
+                                break;
+                        switch (an_event.type) {
+                        case ClientMessage:
+
+                                if (an_event.xclient.format != 8)
+                                        break;
+
+                                for (i = 0; i < 20 && an_event.xclient.data.b[i] != '\0'; ++i)
+                                        buf[i] = an_event.xclient.data.b[i];
+
+                                buf[i] = '\0';
+
+                                //DEBUGA_SKYPE ("BUF=|||%s|||\n", SKYPIAX_P_LOG, buf);
+
+                                if (an_event.xclient.message_type == atom_begin) {
+
+                                        if (strlen(buffer)) {
+                                                unsigned int howmany;
+                                                howmany = strlen(b) + 1;
+                                                howmany = write(SkypiaxHandles->fdesc[1], b, howmany);
+                                                DEBUGA_SKYPE("RECEIVED2=|||%s|||\n", SKYPIAX_P_LOG, buffer);
+                                                memset(buffer, '\0', 17000);
+                                        }
+                                }
+                                if (an_event.xclient.message_type == atom_continue) {
+
+                                        if (!strlen(buffer)) {
+                                                DEBUGA_SKYPE
+                                                        ("Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||\n", SKYPIAX_P_LOG, buf);
+                                                continue_is_broken = 1;
+                                                if (!strncmp(buf, "ognised identity", 15)) {
+                                                        WARNINGA
+                                                                ("Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||. Let's introduce a 1 second delay.\n",
+                                                                 SKYPIAX_P_LOG, buf);
+                                                        skypiax_sleep(1000000);        //1 sec
+                                                }
+                                                break;
+                                        }
+                                }
+
+                                strcat(buffer, buf);
+
+                                if (i < 20 || continue_is_broken) {        /* last fragment */
+                                        unsigned int howmany;
+
+                                        howmany = strlen(b) + 1;
+
+                                        howmany = write(SkypiaxHandles->fdesc[1], b, howmany);
+                                        //DEBUGA_SKYPE ("RECEIVED=|||%s|||\n", SKYPIAX_P_LOG, buffer);
+                                        memset(buffer, '\0', 17000);
+                                        XFlush(disp);
+                                        continue_is_broken = 0;
+                                }
+
+                                break;
+                        default:
+                                break;
+                        }
+                }
+        } else {
+                ERRORA("Skype is not running, maybe crashed. Please run/restart Skype and relaunch Skypiax\n", SKYPIAX_P_LOG);
+                running = 0;
+                return NULL;
+        }
+        //running = 0;
+        return NULL;
+
+}
+#endif // WIN32
</ins></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxmod_celliaxc"></a>
<div class="addfile"><h4>Added: freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c (0 => 14544)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c         (rev 0)
+++ freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c        2009-08-17 09:17:09 UTC (rev 14544)
</span><span class="lines">@@ -0,0 +1,2110 @@
</span><ins>+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * This module (mod_skypiax) has been contributed by:
+ *
+ * Giovanni Maruzzelli (gmaruzz@gmail.com)
+ *
+ *
+ * Further Contributors:
+ *
+ *
+ *
+ * mod_skypiax.c -- Skype compatible Endpoint Module
+ *
+ */
+
+#include "skypiax.h"
+
+#ifdef WIN32
+/***************/
+// from http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
+
+#include <time.h>
+
+#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
+#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+#else /* */
+#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
+#endif /* */
+struct sk_timezone {
+        int tz_minuteswest;                        /* minutes W of Greenwich */
+        int tz_dsttime;                                /* type of dst correction */
+};
+int gettimeofday(struct timeval *tv, struct sk_timezone *tz)
+{
+        FILETIME ft;
+        unsigned __int64 tmpres = 0;
+        static int tzflag;
+        if (NULL != tv) {
+                GetSystemTimeAsFileTime(&ft);
+                tmpres |= ft.dwHighDateTime;
+                tmpres <<= 32;
+                tmpres |= ft.dwLowDateTime;
+
+                /*converting file time to unix epoch */
+                tmpres /= 10;                        /*convert into microseconds */
+                tmpres -= DELTA_EPOCH_IN_MICROSECS;
+                tv->tv_sec = (long) (tmpres / 1000000UL);
+                tv->tv_usec = (long) (tmpres % 1000000UL);
+        }
+        if (NULL != tz) {
+                if (!tzflag) {
+                        _tzset();
+                        tzflag++;
+                }
+                tz->tz_minuteswest = _timezone / 60;
+                tz->tz_dsttime = _daylight;
+        }
+        return 0;
+}
+
+/***************/
+#endif /* WIN32 */
+SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load);
+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 [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"
+
+/* BEGIN: Changes here */
+#define FULL_RELOAD 0
+#define SOFT_RELOAD 1
+/* END: Changes heres */
+
+char *interface_status[] = {        /* should match SKYPIAX_STATE_xxx in skypiax.h */
+        "IDLE",
+        "DOWN",
+        "RING",
+        "DIALING",
+        "BUSY",
+        "UP",
+        "RINGING",
+        "PRERING",
+        "DOUBLE",
+        "SELECTD",
+        "HANG_RQ",
+        "PREANSW"
+};
+char *skype_callflow[] = {                /* should match CALLFLOW_XXX in skypiax.h */
+        "CALL_IDLE",
+        "CALL_DOWN",
+        "INCOMING_RNG",
+        "CALL_DIALING",
+        "CALL_LINEBUSY",
+        "CALL_ACTIVE",
+        "INCOMING_HNG",
+        "CALL_RLEASD",
+        "CALL_NOCARR",
+        "CALL_INFLUX",
+        "CALL_INCOMING",
+        "CALL_FAILED",
+        "CALL_NOSRVC",
+        "CALL_OUTRESTR",
+        "CALL_SECFAIL",
+        "CALL_NOANSWER",
+        "STATUS_FNSHED",
+        "STATUS_CANCLED",
+        "STATUS_FAILED",
+        "STATUS_REFUSED",
+        "STATUS_RINGING",
+        "STATUS_INPROGRS",
+        "STATUS_UNPLACD",
+        "STATUS_ROUTING",
+        "STATUS_EARLYMD",
+        "INCOMING_CLID",
+        "STATUS_RMTEHOLD"
+};
+
+
+static struct {
+        int debug;
+        char *ip;
+        int port;
+        char *dialplan;
+        char *destination;
+        char *context;
+        char *codec_string;
+        char *codec_order[SWITCH_MAX_CODECS];
+        int codec_order_last;
+        char *codec_rates_string;
+        char *codec_rates[SWITCH_MAX_CODECS];
+        int codec_rates_last;
+        unsigned int flags;
+        int fd;
+        int calls;
+        int real_interfaces;
+        int next_interface;
+        char hold_music[256];
+        private_t SKYPIAX_INTERFACES[SKYPIAX_MAX_INTERFACES];
+        switch_mutex_t *mutex;
+        private_t *sk_console;
+} globals;
+
+switch_endpoint_interface_t *skypiax_endpoint_interface;
+switch_memory_pool_t *skypiax_module_pool = NULL;
+int running = 0;
+
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_context, globals.context);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_destination, globals.destination);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string);
+
+/* BEGIN: Changes here */
+static switch_status_t interface_exists(char *the_interface);
+static switch_status_t remove_interface(char *the_interface);
+/* END: Changes here */
+
+static switch_status_t channel_on_init(switch_core_session_t *session);
+static switch_status_t channel_on_hangup(switch_core_session_t *session);
+static switch_status_t channel_on_destroy(switch_core_session_t *session);
+static switch_status_t channel_on_routing(switch_core_session_t *session);
+static switch_status_t channel_on_exchange_media(switch_core_session_t *session);
+static switch_status_t channel_on_consume_media(switch_core_session_t *session);
+static switch_status_t channel_on_soft_execute(switch_core_session_t *session);
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
+                                                                                                        switch_event_t *var_event,
+                                                                                                        switch_caller_profile_t *outbound_profile,
+                                                                                                        switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags);
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
+static switch_status_t skypiax_tech_init(private_t * tech_pvt, switch_core_session_t *session);
+
+static switch_status_t skypiax_codec(private_t * tech_pvt, int sample_rate, int codec_ms)
+{
+        switch_core_session_t *session = NULL;
+
+        if (switch_core_codec_init
+                (&tech_pvt->read_codec, "L16", NULL, sample_rate, codec_ms, 1,
+                 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+                ERRORA("Can't load codec?\n", SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+
+        if (switch_core_codec_init
+                (&tech_pvt->write_codec, "L16", NULL, sample_rate, codec_ms, 1,
+                 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+                ERRORA("Can't load codec?\n", SKYPIAX_P_LOG);
+                switch_core_codec_destroy(&tech_pvt->read_codec);
+                return SWITCH_STATUS_FALSE;
+        }
+
+        tech_pvt->read_frame.rate = sample_rate;
+        tech_pvt->read_frame.codec = &tech_pvt->read_codec;
+
+        session = switch_core_session_locate(tech_pvt->session_uuid_str);
+
+        if (session) {
+                switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
+                switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
+                switch_core_session_rwunlock(session);
+        } else {
+                ERRORA("no session\n", SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+
+}
+
+switch_status_t skypiax_tech_init(private_t * tech_pvt, switch_core_session_t *session)
+{
+
+        switch_assert(tech_pvt != NULL);
+        switch_assert(session != NULL);
+        tech_pvt->read_frame.data = tech_pvt->databuf;
+        tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
+        switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+        switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+        switch_core_session_set_private(session, tech_pvt);
+        switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
+        if (!strlen(tech_pvt->session_uuid_str)) {
+                ERRORA("no tech_pvt->session_uuid_str\n", SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+        if (skypiax_codec(tech_pvt, SAMPLERATE_SKYPIAX, 20) != SWITCH_STATUS_SUCCESS) {
+                ERRORA("skypiax_codec FAILED\n", SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+        DEBUGA_SKYPE("skypiax_codec SUCCESS\n", SKYPIAX_P_LOG);
+        return SWITCH_STATUS_SUCCESS;
+}
+
+/* BEGIN: Changes here */
+static switch_status_t interface_exists(char *the_interface)
+{
+        int i;
+        int interface_id;
+
+        if (*the_interface == '#') {        /* look by interface id or interface name */
+                the_interface++;
+                switch_assert(the_interface);
+                interface_id = atoi(the_interface);
+
+                /* take a number as interface id */
+                if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) {
+                        if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                                return SWITCH_STATUS_SUCCESS;
+                        }
+                } else {
+                        /* interface name */
+                        for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) {
+                                if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].name, the_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].skype_user)) {
+                                if (strcmp(globals.SKYPIAX_INTERFACES[i].skype_user, the_interface) == 0) {
+                                        return SWITCH_STATUS_SUCCESS;
+                                }
+                        }
+                }
+        }
+        return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t remove_interface(char *the_interface)
+{
+        int x = 10;
+        unsigned int howmany = 8;
+        int interface_id = -1;
+        private_t *tech_pvt = NULL;
+        switch_status_t status;
+
+        //running = 0;
+
+
+        if (*the_interface == '#') {        /* remove by interface id or interface name */
+                the_interface++;
+                switch_assert(the_interface);
+                interface_id = atoi(the_interface);
+
+                if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) {
+                        /* take a number as interface id */
+                        tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+                } else {
+
+                        for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) {
+                                if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].name, the_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, the_interface) == 0) {
+                                tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+                                break;
+                        }
+                }
+        }
+
+        if (!tech_pvt) {
+                DEBUGA_SKYPE("interface '%s' does not exist\n", SKYPIAX_P_LOG, the_interface);
+                goto end;
+        }
+
+        if (strlen(globals.SKYPIAX_INTERFACES[interface_id].session_uuid_str)) {
+                DEBUGA_SKYPE("interface '%s' is busy\n", SKYPIAX_P_LOG, the_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
+#else /* WIN32 */
+                howmany = write(tech_pvt->SkypiaxHandles.fdesc[1], "sciutati", howmany);
+#endif /* WIN32 */
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+#ifdef WIN32
+                if (SendMessage(tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {        // let's the skypiax_api_thread_func die
+                        DEBUGA_SKYPE("got FALSE here, thread probably was already dead. GetLastError returned: %d\n", SKYPIAX_P_LOG, GetLastError());
+                        globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread = NULL;
+                }
+#else
+                XEvent e;
+                Atom atom1 = XInternAtom(tech_pvt->SkypiaxHandles.disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+                memset(&e, 0, sizeof(e));
+                e.xclient.type = ClientMessage;
+                e.xclient.message_type = atom1;        /* leading message */
+                e.xclient.display = tech_pvt->SkypiaxHandles.disp;
+                e.xclient.window = tech_pvt->SkypiaxHandles.skype_win;
+                e.xclient.format = 8;
+
+                XSendEvent(tech_pvt->SkypiaxHandles.disp, tech_pvt->SkypiaxHandles.win, False, 0, &e);
+                XSync(tech_pvt->SkypiaxHandles.disp, False);
+#endif
+        }
+
+        while (x) {
+                x--;
+                switch_yield(50000);
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
+                switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread);
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+                switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread);
+        }
+
+        switch_mutex_lock(globals.mutex);
+        if (globals.sk_console == &globals.SKYPIAX_INTERFACES[interface_id]) {
+                DEBUGA_SKYPE("interface '%s' no more console\n", SKYPIAX_P_LOG, the_interface);
+                globals.sk_console = NULL;
+        } else {
+                DEBUGA_SKYPE("interface '%s' STILL console\n", SKYPIAX_P_LOG, the_interface);
+        }
+        memset(&globals.SKYPIAX_INTERFACES[interface_id], '\0', sizeof(private_t));
+        globals.real_interfaces--;
+        switch_mutex_unlock(globals.mutex);
+
+        DEBUGA_SKYPE("interface '%s' deleted successfully\n", SKYPIAX_P_LOG, the_interface);
+        globals.SKYPIAX_INTERFACES[interface_id].running = 1;
+ end:
+        //running = 1;
+        return SWITCH_STATUS_SUCCESS;
+}
+
+/* END: Changes here */
+
+/*
+ State methods they get called when the state changes to the specific state
+ returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
+ so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
+*/
+static switch_status_t channel_on_init(switch_core_session_t *session)
+{
+        switch_channel_t *channel;
+        private_t *tech_pvt = NULL;
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+        //ERRORA("%s CHANNEL INIT\n", SKYPIAX_P_LOG, tech_pvt->name);
+        switch_set_flag(tech_pvt, TFLAG_IO);
+
+        /* Move channel's state machine to ROUTING. This means the call is trying
+         to get from the initial start where the call because, to the point
+         where a destination has been identified. If the channel is simply
+         left in the initial state, nothing will happen. */
+        switch_channel_set_state(channel, CS_ROUTING);
+        switch_mutex_lock(globals.mutex);
+        globals.calls++;
+
+        switch_mutex_unlock(globals.mutex);
+        DEBUGA_SKYPE("%s CHANNEL INIT %s\n", SKYPIAX_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_destroy(switch_core_session_t *session)
+{
+        private_t *tech_pvt = NULL;
+
+        tech_pvt = switch_core_session_get_private(session);
+
+
+        if (tech_pvt) {
+                DEBUGA_SKYPE("%s CHANNEL DESTROY %s\n", SKYPIAX_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
+
+                if (switch_core_codec_ready(&tech_pvt->read_codec)) {
+                        switch_core_codec_destroy(&tech_pvt->read_codec);
+                }
+
+                if (switch_core_codec_ready(&tech_pvt->write_codec)) {
+                        switch_core_codec_destroy(&tech_pvt->write_codec);
+                }
+                *tech_pvt->session_uuid_str = '\0';
+                tech_pvt->interface_state = SKYPIAX_STATE_IDLE;
+                if (tech_pvt->skype_callflow == CALLFLOW_STATUS_FINISHED) {
+                        tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
+                }
+                switch_core_session_set_private(session, NULL);
+        } else {
+                DEBUGA_SKYPE("!!!!!!NO tech_pvt!!!! CHANNEL DESTROY %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(session));
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_hangup(switch_core_session_t *session)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+        char msg_to_skype[256];
+
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
+                if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+                        tech_pvt->ob_failed_calls++;
+                } else {
+                        tech_pvt->ib_failed_calls++;
+                }
+        }
+
+        switch_clear_flag(tech_pvt, TFLAG_IO);
+        switch_clear_flag(tech_pvt, TFLAG_VOICE);
+        //switch_set_flag(tech_pvt, TFLAG_HANGUP);
+
+        if (strlen(tech_pvt->skype_call_id)) {
+                //switch_thread_cond_signal(tech_pvt->cond);
+                DEBUGA_SKYPE("hanging up skype call: %s\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id);
+                sprintf(msg_to_skype, "ALTER CALL %s HANGUP", tech_pvt->skype_call_id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+        }
+        //memset(tech_pvt->session_uuid_str, '\0', sizeof(tech_pvt->session_uuid_str));
+        //*tech_pvt->session_uuid_str = '\0';
+        DEBUGA_SKYPE("%s CHANNEL HANGUP\n", SKYPIAX_P_LOG, tech_pvt->name);
+        switch_mutex_lock(globals.mutex);
+        globals.calls--;
+        if (globals.calls < 0) {
+                globals.calls = 0;
+        }
+
+        tech_pvt->interface_state = SKYPIAX_STATE_IDLE;
+        if (tech_pvt->skype_callflow == CALLFLOW_STATUS_FINISHED) {
+                tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
+        }
+        switch_mutex_unlock(globals.mutex);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_routing(switch_core_session_t *session)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        DEBUGA_SKYPE("%s CHANNEL ROUTING\n", SKYPIAX_P_LOG, tech_pvt->name);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_execute(switch_core_session_t *session)
+{
+
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        DEBUGA_SKYPE("%s CHANNEL EXECUTE\n", SKYPIAX_P_LOG, tech_pvt->name);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        DEBUGA_SKYPE("%s CHANNEL KILL_CHANNEL\n", SKYPIAX_P_LOG, tech_pvt->name);
+        switch (sig) {
+        case SWITCH_SIG_KILL:
+                DEBUGA_SKYPE("%s CHANNEL got SWITCH_SIG_KILL\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                //switch_mutex_lock(tech_pvt->flag_mutex);
+                switch_clear_flag(tech_pvt, TFLAG_IO);
+                switch_clear_flag(tech_pvt, TFLAG_VOICE);
+                switch_set_flag(tech_pvt, TFLAG_HANGUP);
+                //switch_mutex_unlock(tech_pvt->flag_mutex);
+                break;
+        case SWITCH_SIG_BREAK:
+                DEBUGA_SKYPE("%s CHANNEL got SWITCH_SIG_BREAK\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                //switch_set_flag(tech_pvt, TFLAG_BREAK);
+                //switch_mutex_lock(tech_pvt->flag_mutex);
+                switch_set_flag(tech_pvt, TFLAG_BREAK);
+                //switch_mutex_unlock(tech_pvt->flag_mutex);
+                break;
+        default:
+                break;
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+}
+static switch_status_t channel_on_consume_media(switch_core_session_t *session)
+{
+        private_t *tech_pvt = NULL;
+
+        tech_pvt = switch_core_session_get_private(session);
+
+        DEBUGA_SKYPE("%s CHANNEL CONSUME_MEDIA\n", SKYPIAX_P_LOG, tech_pvt->name);
+        return SWITCH_STATUS_SUCCESS;
+}
+
+
+static switch_status_t channel_on_exchange_media(switch_core_session_t *session)
+{
+        private_t *tech_pvt = NULL;
+        tech_pvt = switch_core_session_get_private(session);
+        DEBUGA_SKYPE("%s CHANNEL EXCHANGE_MEDIA\n", SKYPIAX_P_LOG, tech_pvt->name);
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_soft_execute(switch_core_session_t *session)
+{
+        private_t *tech_pvt = NULL;
+        tech_pvt = switch_core_session_get_private(session);
+        DEBUGA_SKYPE("%s CHANNEL SOFT_EXECUTE\n", SKYPIAX_P_LOG, tech_pvt->name);
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
+{
+        private_t *tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        DEBUGA_SKYPE("%s CHANNEL SEND_DTMF\n", SKYPIAX_P_LOG, tech_pvt->name);
+        DEBUGA_SKYPE("DTMF: %c\n", SKYPIAX_P_LOG, dtmf->digit);
+
+        skypiax_senddigit(tech_pvt, dtmf->digit);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+        switch_byte_t *data;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) {
+                ERRORA("channel not ready \n", SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                return SWITCH_STATUS_FALSE;
+        }
+
+        tech_pvt->read_frame.flags = SFF_NONE;
+        *frame = NULL;
+
+        if (!skypiax_audio_read(tech_pvt)) {
+
+                ERRORA("skypiax_audio_read ERROR\n", SKYPIAX_P_LOG);
+
+        } else {
+                switch_set_flag(tech_pvt, TFLAG_VOICE);
+        }
+
+        while (switch_test_flag(tech_pvt, TFLAG_IO)) {
+                if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
+                        switch_clear_flag(tech_pvt, TFLAG_BREAK);
+                        DEBUGA_SKYPE("CHANNEL READ FRAME goto CNG\n", SKYPIAX_P_LOG);
+                        goto cng;
+                }
+
+                if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
+                        DEBUGA_SKYPE("CHANNEL READ FRAME not IO\n", SKYPIAX_P_LOG);
+                        return SWITCH_STATUS_FALSE;
+                }
+
+                if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
+                        switch_clear_flag(tech_pvt, TFLAG_VOICE);
+                        if (!tech_pvt->read_frame.datalen) {
+                                DEBUGA_SKYPE("CHANNEL READ CONTINUE\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        *frame = &tech_pvt->read_frame;
+#ifdef BIGENDIAN
+                        if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+                                switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2);
+                        }
+#endif
+                        return SWITCH_STATUS_SUCCESS;
+                }
+
+                DEBUGA_SKYPE("CHANNEL READ no TFLAG_IO\n", SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+
+        }
+
+        DEBUGA_SKYPE("CHANNEL READ FALSE\n", SKYPIAX_P_LOG);
+        return SWITCH_STATUS_FALSE;
+
+ cng:
+        data = (switch_byte_t *) tech_pvt->read_frame.data;
+        data[0] = 65;
+        data[1] = 0;
+        tech_pvt->read_frame.datalen = 2;
+        tech_pvt->read_frame.flags = SFF_CNG;
+        *frame = &tech_pvt->read_frame;
+        return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+        unsigned int sent;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) {
+                ERRORA("channel not ready \n", SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                return SWITCH_STATUS_FALSE;
+        }
+#ifdef BIGENDIAN
+        if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+                switch_swap_linear(frame->data, (int) frame->datalen / 2);
+        }
+#endif
+
+        sent = frame->datalen;
+#ifdef WIN32
+        switch_file_write(tech_pvt->audioskypepipe[1], frame->data, &sent);
+#else /* WIN32 */
+        sent = write(tech_pvt->audioskypepipe[1], frame->data, sent);
+#endif /* WIN32 */
+        if (sent != frame->datalen && sent != -1) {
+                DEBUGA_SKYPE("CLI PIPE write %d\n", SKYPIAX_P_LOG, sent);
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_answer_channel(switch_core_session_t *session)
+{
+        private_t *tech_pvt;
+        switch_channel_t *channel = NULL;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        DEBUGA_SKYPE("ANSWERED! \n", SKYPIAX_P_LOG);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
+{
+        switch_channel_t *channel;
+        private_t *tech_pvt;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = (private_t *) switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        switch (msg->message_id) {
+        case SWITCH_MESSAGE_INDICATE_ANSWER:
+                {
+                        DEBUGA_SKYPE("MSG_ID=%d, TO BE ANSWERED!\n", SKYPIAX_P_LOG, msg->message_id);
+                        channel_answer_channel(session);
+                }
+                break;
+        default:
+                {
+                        DEBUGA_SKYPE("MSG_ID=%d\n", SKYPIAX_P_LOG, msg->message_id);
+                }
+                break;
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
+{
+        struct private_object *tech_pvt = switch_core_session_get_private(session);
+        char *body = switch_event_get_body(event);
+        switch_assert(tech_pvt != NULL);
+
+        if (!body) {
+                body = "";
+        }
+
+        WARNINGA("event: |||%s|||\n", SKYPIAX_P_LOG, body);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+switch_state_handler_table_t skypiax_state_handlers = {
+        /*.on_init */ channel_on_init,
+        /*.on_routing */ channel_on_routing,
+        /*.on_execute */ channel_on_execute,
+        /*.on_hangup */ channel_on_hangup,
+        /*.on_exchange_media */ channel_on_exchange_media,
+        /*.on_soft_execute */ channel_on_soft_execute,
+        /*.on_consume_media */ channel_on_consume_media,
+        /*.on_hibernate */ NULL,
+        /*.on_reset */ NULL,
+        /*.on_park */ NULL,
+        /*.on_reporting */ NULL,
+        /*.on_destroy */ channel_on_destroy
+};
+
+switch_io_routines_t skypiax_io_routines = {
+        /*.outgoing_channel */ channel_outgoing_channel,
+        /*.read_frame */ channel_read_frame,
+        /*.write_frame */ channel_write_frame,
+        /*.kill_channel */ channel_kill_channel,
+        /*.send_dtmf */ channel_send_dtmf,
+        /*.receive_message */ channel_receive_message,
+        /*.receive_event */ channel_receive_event
+};
+
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
+                                                                                                        switch_event_t *var_event,
+                                                                                                        switch_caller_profile_t *outbound_profile,
+                                                                                                        switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags)
+{
+        private_t *tech_pvt = NULL;
+        if ((*new_session = switch_core_session_request(skypiax_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) {
+                switch_channel_t *channel = NULL;
+                switch_caller_profile_t *caller_profile;
+                char *rdest;
+                int found = 0;
+                char interface_name[256];
+
+                DEBUGA_SKYPE("1 SESSION_REQUEST %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+                switch_core_session_add_stream(*new_session, NULL);
+
+
+                if (!switch_strlen_zero(outbound_profile->destination_number)) {
+                        int i;
+                        char *slash;
+
+                        switch_copy_string(interface_name, outbound_profile->destination_number, 255);
+                        slash = strrchr(interface_name, '/');
+                        *slash = '\0';
+
+                        switch_mutex_lock(globals.mutex);
+                        if (strncmp("ANY", interface_name, strlen(interface_name)) == 0 || strncmp("RR", interface_name, strlen(interface_name)) == 0) {
+                                /* 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;
+                                //} 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(NULL);
+                                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)
+                                        && (strncmp(globals.SKYPIAX_INTERFACES[i].name, interface_name, strlen(interface_name)) == 0)) {
+                                        if (strlen(globals.SKYPIAX_INTERFACES[i].session_uuid_str)) {
+                                                DEBUGA_SKYPE
+                                                        ("globals.SKYPIAX_INTERFACES[%d].name=|||%s||| session_uuid_str=|||%s||| is BUSY\n",
+                                                         SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name, globals.SKYPIAX_INTERFACES[i].session_uuid_str);
+                                                DEBUGA_SKYPE("1 SESSION_DESTROY %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+                                                switch_core_session_destroy(new_session);
+                                                switch_mutex_unlock(globals.mutex);
+                                                return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                                        }
+
+                                        DEBUGA_SKYPE("globals.SKYPIAX_INTERFACES[%d].name=|||%s|||?\n", SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name);
+                                        tech_pvt = &globals.SKYPIAX_INTERFACES[i];
+                                        found = 1;
+                                        break;
+                                }
+
+                        }
+
+                } else {
+                        ERRORA("Doh! no destination number?\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+
+                if (!found) {
+                        DEBUGA_SKYPE("Doh! no available interface for |||%s|||?\n", SKYPIAX_P_LOG, interface_name);
+                        DEBUGA_SKYPE("2 SESSION_DESTROY %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+                        switch_core_session_destroy(new_session);
+                        switch_mutex_unlock(globals.mutex);
+                        //return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                        return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
+                }
+
+                channel = switch_core_session_get_channel(*new_session);
+                if (!channel) {
+                        ERRORA("Doh! no channel?\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        switch_mutex_unlock(globals.mutex);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+                if (skypiax_tech_init(tech_pvt, *new_session) != SWITCH_STATUS_SUCCESS) {
+                        ERRORA("Doh! no tech_init?\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        switch_mutex_unlock(globals.mutex);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+
+
+                if (outbound_profile) {
+                        char name[128];
+
+                        snprintf(name, sizeof(name), "skypiax/%s", outbound_profile->destination_number);
+                        //snprintf(name, sizeof(name), "skypiax/%s", tech_pvt->name);
+                        switch_channel_set_name(channel, name);
+                        caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+                        switch_channel_set_caller_profile(channel, caller_profile);
+                        tech_pvt->caller_profile = caller_profile;
+                } else {
+                        ERRORA("Doh! no caller profile\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        switch_mutex_unlock(globals.mutex);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+
+                tech_pvt->ob_calls++;
+
+                rdest = strchr(caller_profile->destination_number, '/');
+                *rdest++ = '\0';
+
+                //skypiax_call(tech_pvt, rdest, 30);
+
+                switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(*new_session), sizeof(tech_pvt->session_uuid_str));
+                caller_profile = tech_pvt->caller_profile;
+                caller_profile->destination_number = rdest;
+
+                switch_channel_set_flag(channel, CF_OUTBOUND);
+                switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
+                switch_channel_set_state(channel, CS_INIT);
+                skypiax_call(tech_pvt, rdest, 30);
+                switch_mutex_unlock(globals.mutex);
+                return SWITCH_CAUSE_SUCCESS;
+        }
+
+        ERRORA("Doh! no new_session\n", SKYPIAX_P_LOG);
+        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+}
+
+/*!
+ * \brief This thread runs during a call, and monitor the interface for signaling, like hangup, caller id, etc most of signaling is handled inside the skypiax_signaling_read function
+ *
+ */
+static void *SWITCH_THREAD_FUNC skypiax_signaling_thread_func(switch_thread_t * thread, void *obj)
+{
+        private_t *tech_pvt = obj;
+        int res;
+        int forever = 1;
+
+        if (!tech_pvt)
+                return NULL;
+
+        DEBUGA_SKYPE("In skypiax_signaling_thread_func: started, p=%p\n", SKYPIAX_P_LOG, (void *) tech_pvt);
+
+        while (forever) {
+                if (!(running && tech_pvt->running))
+                        break;
+                res = skypiax_signaling_read(tech_pvt);
+                if (res == CALLFLOW_INCOMING_HANGUP) {
+                        switch_core_session_t *session = NULL;
+                        switch_channel_t *channel = NULL;
+                        //private_t *tech_pvt = NULL;
+                        DEBUGA_SKYPE("skype call ended\n", SKYPIAX_P_LOG);
+
+                        if (tech_pvt) {
+                                session = switch_core_session_locate(tech_pvt->session_uuid_str);
+                                if (session) {
+                                        channel = switch_core_session_get_channel(session);
+                                        if (channel) {
+                                                switch_channel_state_t state = switch_channel_get_state(channel);
+                                                if (state < CS_EXECUTE) {
+                                                        switch_sleep(10000);        //10 msec, let the state evolve from CS_NEW
+                                                }
+                                                switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+                                        } else {
+                                                ERRORA("no channel?\n", SKYPIAX_P_LOG);
+                                        }
+                                        switch_core_session_rwunlock(session);
+                                } else {
+                                        DEBUGA_SKYPE("no session\n", SKYPIAX_P_LOG);
+                                }
+                                switch_mutex_lock(globals.mutex);
+                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                *tech_pvt->session_uuid_str = '\0';
+                                *tech_pvt->skype_call_id = '\0';
+                                switch_mutex_unlock(globals.mutex);
+
+                                //ERRORA("LET'S WAIT\n", SKYPIAX_P_LOG);
+                                switch_sleep(300000);        //0.3 sec
+                                //ERRORA("WAIT'S OVER\n", SKYPIAX_P_LOG);
+                                //tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                //usleep(30000); //0.03 sec
+                                switch_mutex_lock(globals.mutex);
+                                tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
+                                tech_pvt->interface_state = SKYPIAX_STATE_IDLE;
+                                switch_mutex_unlock(globals.mutex);
+                        } else {
+                                ERRORA("no tech_pvt?\n", SKYPIAX_P_LOG);
+                        }
+                }
+        }
+        return NULL;
+}
+
+/* BEGIN: Changes heres */
+static switch_status_t load_config(int reload_type)
+/* END: Changes heres */
+{
+        char *cf = "skypiax.conf";
+        switch_xml_t cfg, xml, global_settings, param, interfaces, myinterface;
+        private_t *tech_pvt = NULL;
+
+        switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, skypiax_module_pool);
+        if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+                ERRORA("open of %s failed\n", SKYPIAX_P_LOG, cf);
+                running = 0;
+                switch_xml_free(xml);
+                return SWITCH_STATUS_TERM;
+        }
+
+        switch_mutex_lock(globals.mutex);
+        if ((global_settings = switch_xml_child(cfg, "global_settings"))) {
+                for (param = switch_xml_child(global_settings, "param"); param; param = param->next) {
+                        char *var = (char *) switch_xml_attr_soft(param, "name");
+                        char *val = (char *) switch_xml_attr_soft(param, "value");
+
+                        if (!strcasecmp(var, "debug")) {
+                                DEBUGA_SKYPE("globals.debug=%d\n", SKYPIAX_P_LOG, globals.debug);
+                                globals.debug = atoi(val);
+                                DEBUGA_SKYPE("globals.debug=%d\n", SKYPIAX_P_LOG, globals.debug);
+                        } else if (!strcasecmp(var, "hold-music")) {
+                                switch_set_string(globals.hold_music, val);
+                                DEBUGA_SKYPE("globals.hold_music=%s\n", SKYPIAX_P_LOG, globals.hold_music);
+                        } else if (!strcmp(var, "port")) {
+                                globals.port = atoi(val);
+                                DEBUGA_SKYPE("globals.port=%d\n", SKYPIAX_P_LOG, globals.port);
+                        } else if (!strcmp(var, "codec-master")) {
+                                if (!strcasecmp(val, "us")) {
+                                        switch_set_flag(&globals, GFLAG_MY_CODEC_PREFS);
+                                }
+                                DEBUGA_SKYPE("codec-master globals.debug=%d\n", SKYPIAX_P_LOG, globals.debug);
+                        } else if (!strcmp(var, "dialplan")) {
+                                set_global_dialplan(val);
+                                DEBUGA_SKYPE("globals.dialplan=%s\n", SKYPIAX_P_LOG, globals.dialplan);
+                        } else if (!strcmp(var, "destination")) {
+                                set_global_destination(val);
+                                DEBUGA_SKYPE("globals.destination=%s\n", SKYPIAX_P_LOG, globals.destination);
+                        } else if (!strcmp(var, "context")) {
+                                set_global_context(val);
+                                DEBUGA_SKYPE("globals.context=%s\n", SKYPIAX_P_LOG, globals.context);
+                        } else if (!strcmp(var, "codec-prefs")) {
+                                set_global_codec_string(val);
+                                DEBUGA_SKYPE("globals.codec_string=%s\n", SKYPIAX_P_LOG, globals.codec_string);
+                                globals.codec_order_last = switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS);
+                        } else if (!strcmp(var, "codec-rates")) {
+                                set_global_codec_rates_string(val);
+                                DEBUGA_SKYPE("globals.codec_rates_string=%s\n", SKYPIAX_P_LOG, globals.codec_rates_string);
+                                globals.codec_rates_last = switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS);
+                        }
+
+                }
+        }
+
+        if ((interfaces = switch_xml_child(cfg, "per_interface_settings"))) {
+                int i = 0;
+
+                for (myinterface = switch_xml_child(interfaces, "interface"); myinterface; myinterface = myinterface->next) {
+                        char *id = (char *) switch_xml_attr(myinterface, "id");
+                        char *name = (char *) switch_xml_attr(myinterface, "name");
+                        char *context = "default";
+                        char *dialplan = "XML";
+                        char *destination = "5000";
+                        char *tonegroup = NULL;
+                        char *digit_timeout = NULL;
+                        char *max_digits = NULL;
+                        char *hotline = NULL;
+                        char *dial_regex = NULL;
+                        char *hold_music = NULL;
+                        char *fail_dial_regex = NULL;
+                        char *enable_callerid = "true";
+                        char *X11_display = NULL;
+                        char *tcp_cli_port = NULL;
+                        char *tcp_srv_port = NULL;
+                        char *skype_user = NULL;
+
+                        uint32_t interface_id = 0, to = 0, max = 0;
+
+                        tech_pvt = NULL;
+
+                        for (param = switch_xml_child(myinterface, "param"); param; param = param->next) {
+                                char *var = (char *) switch_xml_attr_soft(param, "name");
+                                char *val = (char *) switch_xml_attr_soft(param, "value");
+
+                                if (!strcasecmp(var, "tonegroup")) {
+                                        tonegroup = val;
+                                } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) {
+                                        digit_timeout = val;
+                                } else if (!strcasecmp(var, "context")) {
+                                        context = val;
+                                } else if (!strcasecmp(var, "dialplan")) {
+                                        dialplan = val;
+                                } else if (!strcasecmp(var, "destination")) {
+                                        destination = val;
+                                } else if (!strcasecmp(var, "dial-regex")) {
+                                        dial_regex = val;
+                                } else if (!strcasecmp(var, "enable-callerid")) {
+                                        enable_callerid = val;
+                                } else if (!strcasecmp(var, "fail-dial-regex")) {
+                                        fail_dial_regex = val;
+                                } else if (!strcasecmp(var, "hold-music")) {
+                                        hold_music = val;
+                                } else if (!strcasecmp(var, "skype_user")) {
+                                        skype_user = val;
+                                } else if (!strcasecmp(var, "tcp_cli_port")) {
+                                        tcp_cli_port = val;
+                                } else if (!strcasecmp(var, "tcp_srv_port")) {
+                                        tcp_srv_port = val;
+                                } else if (!strcasecmp(var, "X11-display") || !strcasecmp(var, "X11_display")) {
+                                        X11_display = val;
+                                } else if (!strcasecmp(var, "max_digits") || !strcasecmp(var, "max-digits")) {
+                                        max_digits = val;
+                                } else if (!strcasecmp(var, "hotline")) {
+                                        hotline = val;
+                                }
+
+                        }
+                        if (!skype_user) {
+                                ERRORA("interface missing REQUIRED param 'skype_user'\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+
+                        /* BEGIN: Changes here */
+                        if (reload_type == SOFT_RELOAD) {
+                                char the_interface[256];
+                                sprintf(the_interface, "#%s", name);
+
+                                if (interface_exists(the_interface) == SWITCH_STATUS_SUCCESS) {
+                                        continue;
+                                }
+                        }
+                        /* END: Changes here */
+
+                        if (!X11_display) {
+                                ERRORA("interface missing REQUIRED param 'X11_display'\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (!tcp_cli_port) {
+                                ERRORA("interface missing REQUIRED param 'tcp_cli_port'\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+
+                        if (!tcp_srv_port) {
+                                ERRORA("interface missing REQUIRED param 'tcp_srv_port'\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (!id) {
+                                ERRORA("interface missing REQUIRED param 'id'\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (switch_is_number(id)) {
+                                interface_id = atoi(id);
+                                DEBUGA_SKYPE("interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+                        } else {
+                                ERRORA("interface param 'id' MUST be a number, now id='%s'\n", SKYPIAX_P_LOG, id);
+                                continue;
+                        }
+
+                        if (!name) {
+                                WARNINGA("interface missing param 'name', not nice, but works\n", SKYPIAX_P_LOG);
+                        }
+
+                        if (!tonegroup) {
+                                tonegroup = "us";
+                        }
+
+                        if (digit_timeout) {
+                                to = atoi(digit_timeout);
+                        }
+
+                        if (max_digits) {
+                                max = atoi(max_digits);
+                        }
+
+                        if (name) {
+                                DEBUGA_SKYPE("name=%s\n", SKYPIAX_P_LOG, name);
+                        }
+#ifndef WIN32
+                        if (!XInitThreads()) {
+                                ERRORA("Not initialized XInitThreads!\n", SKYPIAX_P_LOG);
+                        } else {
+                                DEBUGA_SKYPE("Initialized XInitThreads!\n", SKYPIAX_P_LOG);
+                        }
+                        switch_sleep(100);
+#endif /* WIN32 */
+
+                        if (interface_id && interface_id < SKYPIAX_MAX_INTERFACES) {
+                                private_t newconf;
+                                switch_threadattr_t *skypiax_api_thread_attr = NULL;
+                                switch_threadattr_t *skypiax_signaling_thread_attr = NULL;
+
+                                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];
+
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].interface_id, id);
+                                if (name) {
+                                        switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].name, name);
+                                } else {
+                                        switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].name, "N/A");
+                                }
+                                DEBUGA_SKYPE("CONFIGURING interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+#ifdef WIN32
+                                globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port = (unsigned short) atoi(tcp_cli_port);
+                                globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port = (unsigned short) atoi(tcp_srv_port);
+#else /* WIN32 */
+                                globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port = atoi(tcp_cli_port);
+                                globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port = atoi(tcp_srv_port);
+#endif /* WIN32 */
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].X11_display, X11_display);
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].skype_user, skype_user);
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].context, context);
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].dialplan, dialplan);
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].destination, destination);
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].context, context);
+
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].X11_display=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].X11_display);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].skype_user=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port=%d\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port=%d\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port);
+                                DEBUGA_SKYPE("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].name=%s\n",
+                                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].name);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].dialplan=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].dialplan);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].destination=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].destination);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
+                                WARNINGA("STARTING interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+
+                                switch_threadattr_create(&skypiax_api_thread_attr, skypiax_module_pool);
+                                switch_threadattr_stacksize_set(skypiax_api_thread_attr, SWITCH_THREAD_STACKSIZE);
+                                switch_thread_create(&globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread,
+                                                                         skypiax_api_thread_attr, skypiax_do_skypeapi_thread, &globals.SKYPIAX_INTERFACES[interface_id], skypiax_module_pool);
+
+                                switch_sleep(100000);
+
+                                switch_threadattr_create(&skypiax_signaling_thread_attr, skypiax_module_pool);
+                                switch_threadattr_stacksize_set(skypiax_signaling_thread_attr, SWITCH_THREAD_STACKSIZE);
+                                switch_thread_create(&globals.SKYPIAX_INTERFACES[interface_id].
+                                                                         skypiax_signaling_thread, skypiax_signaling_thread_attr,
+                                                                         skypiax_signaling_thread_func, &globals.SKYPIAX_INTERFACES[interface_id], skypiax_module_pool);
+
+                                switch_sleep(100000);
+
+                                skypiax_audio_init(&globals.SKYPIAX_INTERFACES[interface_id]);
+
+                                NOTICA
+                                        ("WAITING roughly 10 seconds to find a running Skype client and connect to its SKYPE API for interface_id=%d\n",
+                                         SKYPIAX_P_LOG, interface_id);
+                                i = 0;
+                                while (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.api_connected == 0 && running && i < 200) {        // 10 seconds! thanks Jeff Lenk
+                                        switch_sleep(50000);
+                                        i++;
+                                }
+                                if (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.api_connected) {
+                                        NOTICA
+                                                ("Found a running Skype client, connected to its SKYPE API for interface_id=%d, waiting 60 seconds for CURRENTUSERHANDLE==%s\n",
+                                                 SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                } else {
+                                        ERRORA
+                                                ("Failed to connect to a SKYPE API for interface_id=%d, no SKYPE client running, please (re)start Skype client. Skypiax exiting\n",
+                                                 SKYPIAX_P_LOG, interface_id);
+                                        running = 0;
+                                        switch_mutex_unlock(globals.mutex);
+                                        switch_xml_free(xml);
+                                        return SWITCH_STATUS_FALSE;
+                                }
+
+                                i = 0;
+                                while (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.currentuserhandle == 0 && running && i < 1200) {        // 60 seconds! thanks Jeff Lenk
+                                        switch_sleep(50000);
+                                        i++;
+                                }
+                                if (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.currentuserhandle) {
+                                        WARNINGA
+                                                ("Interface_id=%d is now STARTED, the Skype client to which we are connected gave us the correct CURRENTUSERHANDLE (%s)\n",
+                                                 SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+
+                                        skypiax_signaling_write(&globals.SKYPIAX_INTERFACES[interface_id], "SET AUTOAWAY OFF");
+                                } else {
+                                        ERRORA
+                                                ("The Skype client to which we are connected FAILED to gave us CURRENTUSERHANDLE=%s, interface_id=%d FAILED to start. No Skype client logged in as '%s' has been found. Please (re)launch a Skype client logged in as '%s'. Skypiax exiting now\n",
+                                                 SKYPIAX_P_LOG, globals.SKYPIAX_INTERFACES[interface_id].skype_user,
+                                                 interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                        running = 0;
+                                        switch_mutex_unlock(globals.mutex);
+                                        switch_xml_free(xml);
+                                        return SWITCH_STATUS_FALSE;
+                                }
+
+                        } else {
+                                ERRORA("interface id %d is higher than SKYPIAX_MAX_INTERFACES (%d)\n", SKYPIAX_P_LOG, interface_id, SKYPIAX_MAX_INTERFACES);
+                                continue;
+                        }
+
+                }
+
+                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", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].interface_id);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].X11_display=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].X11_display);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].name=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].name);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].context);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].dialplan=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].dialplan);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].destination=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].destination);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].context);
+                        }
+                }
+        }
+
+        switch_mutex_unlock(globals.mutex);
+        switch_xml_free(xml);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load)
+{
+        switch_api_interface_t *commands_api_interface;
+
+        skypiax_module_pool = pool;
+        memset(&globals, '\0', sizeof(globals));
+
+        running = 1;
+
+        if (load_config(FULL_RELOAD) != SWITCH_STATUS_SUCCESS) {
+                running = 0;
+                return SWITCH_STATUS_FALSE;
+        }
+
+        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+        skypiax_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
+        skypiax_endpoint_interface->interface_name = "skypiax";
+        skypiax_endpoint_interface->io_routines = &skypiax_io_routines;
+        skypiax_endpoint_interface->state_handler = &skypiax_state_handlers;
+
+        if (running) {
+
+                SWITCH_ADD_API(commands_api_interface, "sk", "Skypiax console commands", sk_function, SK_SYNTAX);
+                SWITCH_ADD_API(commands_api_interface, "skypiax", "Skypiax interface commands", skypiax_function, SKYPIAX_SYNTAX);
+
+                /* indicate that the module should continue to be loaded */
+                return SWITCH_STATUS_SUCCESS;
+        } else
+                return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown)
+{
+        int x;
+        private_t *tech_pvt = NULL;
+        switch_status_t status;
+        unsigned int howmany = 8;
+        int interface_id;
+
+        running = 0;
+
+        for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) {
+                tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+
+                if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                        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
+#else /* WIN32 */
+                                howmany = write(tech_pvt->SkypiaxHandles.fdesc[1], "sciutati", howmany);
+#endif /* WIN32 */
+                        }
+
+                        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+#ifdef WIN32
+                                if (SendMessage(tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {        // let's the skypiax_api_thread_func die
+                                        DEBUGA_SKYPE("got FALSE here, thread probably was already dead. GetLastError returned: %d\n", SKYPIAX_P_LOG, GetLastError());
+                                        globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread = NULL;
+                                }
+#else
+                                XEvent e;
+                                Atom atom1 = XInternAtom(tech_pvt->SkypiaxHandles.disp, "SKYPECONTROLAPI_MESSAGE_BEGIN",
+                                                                                 False);
+                                memset(&e, 0, sizeof(e));
+                                e.xclient.type = ClientMessage;
+                                e.xclient.message_type = atom1;        /* leading message */
+                                e.xclient.display = tech_pvt->SkypiaxHandles.disp;
+                                e.xclient.window = tech_pvt->SkypiaxHandles.skype_win;
+                                e.xclient.format = 8;
+
+                                XSendEvent(tech_pvt->SkypiaxHandles.disp, tech_pvt->SkypiaxHandles.win, False, 0, &e);
+                                XSync(tech_pvt->SkypiaxHandles.disp, False);
+#endif
+                        }
+                        x = 10;
+                        while (x) {                        //FIXME 0.5 seconds?
+                                x--;
+                                switch_yield(50000);
+                        }
+                        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
+                                switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread);
+                        }
+                        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+                                switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread);
+                        }
+#ifndef WIN32
+                        WARNINGA("SHUTDOWN interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+                        shutdown(tech_pvt->audioskypepipe[0], 2);
+                        close(tech_pvt->audioskypepipe[0]);
+                        shutdown(tech_pvt->audioskypepipe[1], 2);
+                        close(tech_pvt->audioskypepipe[1]);
+                        shutdown(tech_pvt->audiopipe[0], 2);
+                        close(tech_pvt->audiopipe[0]);
+                        shutdown(tech_pvt->audiopipe[1], 2);
+                        close(tech_pvt->audiopipe[1]);
+                        shutdown(tech_pvt->SkypiaxHandles.fdesc[0], 2);
+                        close(tech_pvt->SkypiaxHandles.fdesc[0]);
+                        shutdown(tech_pvt->SkypiaxHandles.fdesc[1], 2);
+                        close(tech_pvt->SkypiaxHandles.fdesc[1]);
+#endif /* WIN32 */
+                }
+
+        }
+        switch_safe_free(globals.dialplan);
+        switch_safe_free(globals.context);
+        switch_safe_free(globals.destination);
+        switch_safe_free(globals.codec_string);
+        switch_safe_free(globals.codec_rates_string);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_srv_thread(switch_thread_t * thread, void *obj)
+{
+        return skypiax_do_tcp_srv_thread_func(obj);
+}
+
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_cli_thread(switch_thread_t * thread, void *obj)
+{
+        return skypiax_do_tcp_cli_thread_func(obj);
+}
+
+void *SWITCH_THREAD_FUNC skypiax_do_skypeapi_thread(switch_thread_t * thread, void *obj)
+{
+        return skypiax_do_skypeapi_thread_func(obj);
+}
+
+int dtmf_received(private_t * tech_pvt, char *value)
+{
+        switch_core_session_t *session = NULL;
+        switch_channel_t *channel = NULL;
+
+        session = switch_core_session_locate(tech_pvt->session_uuid_str);
+        channel = switch_core_session_get_channel(session);
+
+        if (channel) {
+
+                if (!switch_channel_test_flag(channel, CF_BRIDGED)) {
+
+                        switch_dtmf_t dtmf = { (char) value[0], switch_core_default_dtmf_duration(0) };
+                        DEBUGA_SKYPE("received DTMF %c on channel %s\n", SKYPIAX_P_LOG, dtmf.digit, switch_channel_get_name(channel));
+                        switch_mutex_lock(tech_pvt->flag_mutex);
+                        //FIXME: why sometimes DTMFs from here do not seems to be get by FS?
+                        switch_channel_queue_dtmf(channel, &dtmf);
+                        switch_set_flag(tech_pvt, TFLAG_DTMF);
+                        switch_mutex_unlock(tech_pvt->flag_mutex);
+                } else {
+                        DEBUGA_SKYPE
+                                ("received a DTMF on channel %s, but we're BRIDGED, so let's NOT relay it out of band\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                }
+        } else {
+                WARNINGA("received %c DTMF, but no channel?\n", SKYPIAX_P_LOG, value[0]);
+        }
+        switch_core_session_rwunlock(session);
+
+        return 0;
+}
+
+int start_audio_threads(private_t * tech_pvt)
+{
+        switch_threadattr_t *thd_attr = NULL;
+
+        switch_threadattr_create(&thd_attr, skypiax_module_pool);
+        switch_threadattr_detach_set(thd_attr, 1);
+        switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+        if (switch_thread_create(&tech_pvt->tcp_srv_thread, thd_attr, skypiax_do_tcp_srv_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) {
+                DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+        } else {
+                ERRORA("failed to start tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        switch_threadattr_create(&thd_attr, skypiax_module_pool);
+        switch_threadattr_detach_set(thd_attr, 1);
+        switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+        if (switch_thread_create(&tech_pvt->tcp_cli_thread, thd_attr, skypiax_do_tcp_cli_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) {
+                DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+        } else {
+                ERRORA("failed to start tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+                return -1;
+        }
+        switch_sleep(100000);
+
+        if (tech_pvt->tcp_cli_thread == NULL || tech_pvt->tcp_srv_thread == NULL) {
+                ERRORA("tcp_cli_thread or tcp_srv_thread exited\n", SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        return 0;
+}
+
+int new_inbound_channel(private_t * tech_pvt)
+{
+        switch_core_session_t *session = NULL;
+        switch_channel_t *channel = NULL;
+
+        if ((session = switch_core_session_request(skypiax_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL)) != 0) {
+                DEBUGA_SKYPE("2 SESSION_REQUEST %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(session));
+                switch_core_session_add_stream(session, NULL);
+                channel = switch_core_session_get_channel(session);
+                if (!channel) {
+                        ERRORA("Doh! no channel?\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&session);
+                        return 0;
+                }
+                if (skypiax_tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS) {
+                        ERRORA("Doh! no tech_init?\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&session);
+                        return 0;
+                }
+
+                if ((tech_pvt->caller_profile =
+                         switch_caller_profile_new(switch_core_session_get_pool(session), "skypiax",
+                                                                         tech_pvt->dialplan, tech_pvt->callid_name,
+                                                                         tech_pvt->callid_number, NULL, NULL, NULL, NULL, "mod_skypiax", tech_pvt->context, tech_pvt->destination)) != 0) {
+                        char name[128];
+                        //switch_snprintf(name, sizeof(name), "skypiax/%s/%s", tech_pvt->name, tech_pvt->caller_profile->destination_number);
+                        switch_snprintf(name, sizeof(name), "skypiax/%s", tech_pvt->name);
+                        switch_channel_set_name(channel, name);
+                        switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+                }
+                switch_channel_set_state(channel, CS_INIT);
+                if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
+                        ERRORA("Error spawning thread\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&session);
+                        return 0;
+                }
+        }
+        if (channel) {
+                switch_channel_mark_answered(channel);
+        }
+
+        DEBUGA_SKYPE("new_inbound_channel\n", SKYPIAX_P_LOG);
+
+        return 0;
+}
+
+int remote_party_is_ringing(private_t * tech_pvt)
+{
+        switch_core_session_t *session = NULL;
+        switch_channel_t *channel = NULL;
+
+        if (!switch_strlen_zero(tech_pvt->session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt->session_uuid_str);
+        } else {
+                ERRORA("No session???\n", SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (session) {
+                channel = switch_core_session_get_channel(session);
+        } else {
+                ERRORA("No session???\n", SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_ring_ready(channel);
+                DEBUGA_SKYPE("skype_call: REMOTE PARTY RINGING\n", SKYPIAX_P_LOG);
+        } else {
+                ERRORA("No channel???\n", SKYPIAX_P_LOG);
+        }
+
+        switch_core_session_rwunlock(session);
+
+ done:
+        return 0;
+}
+
+int remote_party_is_early_media(private_t * tech_pvt)
+{
+        switch_core_session_t *session = NULL;
+        switch_channel_t *channel = NULL;
+
+        if (!switch_strlen_zero(tech_pvt->session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt->session_uuid_str);
+        } else {
+                ERRORA("No session???\n\n\n", SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                goto done;
+        }
+        if (session) {
+                channel = switch_core_session_get_channel(session);
+                switch_core_session_add_stream(session, NULL);
+        } else {
+                ERRORA("No session???\n", SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_pre_answered(channel);
+                DEBUGA_SKYPE("skype_call: REMOTE PARTY EARLY MEDIA\n", SKYPIAX_P_LOG);
+        } else {
+                ERRORA("No channel???\n", SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+        }
+
+        switch_core_session_rwunlock(session);
+
+ done:
+        return 0;
+}
+
+int outbound_channel_answered(private_t * tech_pvt)
+{
+        switch_core_session_t *session = NULL;
+        switch_channel_t *channel = NULL;
+
+        if (!switch_strlen_zero(tech_pvt->session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt->session_uuid_str);
+        } else {
+                ERRORA("No session???\n", SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (session) {
+                channel = switch_core_session_get_channel(session);
+        } else {
+                ERRORA("No channel???\n", SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_answered(channel);
+                //DEBUGA_SKYPE("skype_call: %s, answered\n", SKYPIAX_P_LOG, id);
+        } else {
+                ERRORA("No channel???\n", SKYPIAX_P_LOG);
+        }
+
+        switch_core_session_rwunlock(session);
+
+ done:
+        DEBUGA_SKYPE("outbound_channel_answered!\n", SKYPIAX_P_LOG);
+
+        return 0;
+}
+
+private_t *find_available_skypiax_interface_rr(private_t * tech_pvt_calling)
+{
+        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 */
+        //XXX no, is just a convention, but you can have it start from 0. I do not, for aestetic reasons :-)
+        //if (globals.next_interface == 0) globals.next_interface = 1;
+
+        for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) {
+                int interface_id;
+
+                interface_id = globals.next_interface;
+                //interface_id = interface_id < SKYPIAX_MAX_INTERFACES ? interface_id : interface_id - SKYPIAX_MAX_INTERFACES + 1;
+                globals.next_interface = interface_id + 1 < SKYPIAX_MAX_INTERFACES ? interface_id + 1 : 0;
+
+                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 ((tech_pvt_calling ? strcmp(tech_pvt->skype_user, tech_pvt_calling->skype_user) : 1)
+                                && (SKYPIAX_STATE_DOWN == skype_state || 0 == skype_state) && (tech_pvt->skype_callflow == CALLFLOW_STATUS_FINISHED
+                                                                                                                                                         || 0 == tech_pvt->skype_callflow)) {
+                                DEBUGA_SKYPE("returning as available skype interface name: %s, state: %d callflow: %d\n", SKYPIAX_P_LOG, tech_pvt->name, skype_state,
+                                                         tech_pvt->skype_callflow);
+                                /*set to Dialing state to avoid other thread fint it, don't know if it is safe */
+                                //XXX no, it's not safe
+                                if (tech_pvt_calling == NULL) {
+                                        tech_pvt->interface_state = SKYPIAX_STATE_SELECTED;
+                                }
+
+                                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)
+{
+        char *mycmd = NULL, *argv[10] = { 0 };
+        int argc = 0;
+
+        if (globals.sk_console)
+                stream->write_function(stream, "sk console is: |||%s|||\n", globals.sk_console->name);
+        else
+                stream->write_function(stream, "sk console is NOT yet assigned\n");
+
+        if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+                argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+        }
+
+        if (!argc || !argv[0]) {
+                stream->write_function(stream, "%s", SK_SYNTAX);
+                goto end;
+        }
+
+        if (!strcasecmp(argv[0], "list")) {
+                int i;
+                char next_flag_char = ' ';
+
+                stream->write_function(stream, "F ID\t Name \tIB (F/T) OB (F/T)\tState\tCallFlw\t\tUUID\n");
+                stream->write_function(stream, "= ====\t ======== \t======= =======\t======\t============\t======\n");
+
+                for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) {
+                        next_flag_char = i == globals.next_interface ? '*' : ' ';
+
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+                                stream->write_function(stream,
+                                                                         "%c %d\t[%s]\t%3ld/%ld\t%6ld/%ld\t%s\t%s\t%s\n",
+                                                                         next_flag_char,
+                                                                         i, globals.SKYPIAX_INTERFACES[i].name,
+                                                                         globals.SKYPIAX_INTERFACES[i].ib_failed_calls,
+                                                                         globals.SKYPIAX_INTERFACES[i].ib_calls,
+                                                                         globals.SKYPIAX_INTERFACES[i].ob_failed_calls,
+                                                                         globals.SKYPIAX_INTERFACES[i].ob_calls,
+                                                                         interface_status[globals.SKYPIAX_INTERFACES[i].interface_state],
+                                                                         skype_callflow[globals.SKYPIAX_INTERFACES[i].skype_callflow], globals.SKYPIAX_INTERFACES[i].session_uuid_str);
+                        } 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;
+
+                if (argc == 2) {
+                        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)
+                                        && (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[1], strlen(argv[1])) == 0)) {
+                                        globals.sk_console = &globals.SKYPIAX_INTERFACES[i];
+                                        stream->write_function(stream,
+                                                                                 "sk console is now: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n", i, globals.SKYPIAX_INTERFACES[i].name);
+                                        stream->write_function(stream, "sk console is: |||%s|||\n", globals.sk_console->name);
+                                        found = 1;
+                                        break;
+                                }
+
+                        }
+                        if (!found)
+                                stream->write_function(stream, "ERROR: A Skypiax interface with name='%s' was not found\n", argv[1]);
+                } else {
+
+                        stream->write_function(stream, "-ERR Usage: sk console interface_name\n");
+                        goto end;
+                }
+
+        } else if (!strcasecmp(argv[0], "ciapalino")) {
+
+/* BEGIN: Changes heres */
+        } else if (!strcasecmp(argv[0], "reload")) {
+                if (load_config(SOFT_RELOAD) != SWITCH_STATUS_SUCCESS) {
+                        stream->write_function(stream, "sk reload failed\n");
+                } else {
+                        stream->write_function(stream, "sk reload success\n");
+                }
+        } else if (!strcasecmp(argv[0], "remove")) {
+                if (argc == 2) {
+                        if (remove_interface(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                                if (interface_exists(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                                        stream->write_function(stream, "sk remove '%s' failed\n", argv[1]);
+                                } else {
+                                        stream->write_function(stream, "sk remove '%s' success\n", argv[1]);
+                                }
+                        }
+                } else {
+                        stream->write_function(stream, "-ERR Usage: sk remove interface_name\n");
+                        goto end;
+                }
+/* END: Changes heres */
+
+        } else {
+                if (globals.sk_console)
+                        skypiax_signaling_write(globals.sk_console, (char *) cmd);
+                else
+                        stream->write_function(stream, "sk console is NOT yet assigned\n");
+        }
+ end:
+        switch_safe_free(mycmd);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_API(skypiax_function)
+{
+        char *mycmd = NULL, *argv[10] = { 0 };
+        int argc = 0;
+        private_t *tech_pvt = NULL;
+
+        if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+                argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+        }
+
+        if (!argc) {
+                stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_SYNTAX);
+                goto end;
+        }
+
+        if (argc < 2) {
+                stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_SYNTAX);
+                goto end;
+        }
+
+        if (argv[0]) {
+                int i;
+                int found = 0;
+
+                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)
+                                && (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
+                                tech_pvt = &globals.SKYPIAX_INTERFACES[i];
+                                stream->write_function(stream, "Using interface: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n", i, globals.SKYPIAX_INTERFACES[i].name);
+                                found = 1;
+                                break;
+                        }
+
+                }
+                if (!found) {
+                        stream->write_function(stream, "ERROR: A Skypiax interface with name='%s' was not found\n", argv[0]);
+                        switch_safe_free(mycmd);
+
+                        return SWITCH_STATUS_SUCCESS;
+                } else {
+                        skypiax_signaling_write(tech_pvt, (char *) &cmd[strlen(argv[0]) + 1]);
+                }
+        } else {
+                stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_SYNTAX);
+        }
+ end:
+        switch_safe_free(mycmd);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+int skypiax_answer(private_t * tech_pvt, char *id, char *value)
+{
+        char msg_to_skype[1024];
+        int i;
+        int found = 0;
+        private_t *giovatech;
+        struct timeval timenow;
+
+        switch_mutex_lock(globals.mutex);
+
+        gettimeofday(&timenow, NULL);
+        for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                        giovatech = &globals.SKYPIAX_INTERFACES[i];
+                        //NOTICA("skype interface: %d, name: %s, state: %d, value=%s, giovatech->callid_number=%s, giovatech->skype_user=%s\n", SKYPIAX_P_LOG, i, giovatech->name, giovatech->interface_state, value, giovatech->callid_number, giovatech->skype_user);
+                        //FIXME check a timestamp here
+                        if (strlen(giovatech->skype_call_id) && (giovatech->interface_state != SKYPIAX_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->callid_number, value)) && ((((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) < 500000)) {        //0.5sec
+                                found = 1;
+                                DEBUGA_SKYPE
+                                        ("FOUND (name=%s, giovatech->interface_state=%d != SKYPIAX_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
+                                         SKYPIAX_P_LOG, giovatech->name, giovatech->interface_state,
+                                         giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number, value)
+                                        if (tech_pvt->interface_state == SKYPIAX_STATE_PRERING) {
+                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                } else if (tech_pvt->interface_state != 0 && tech_pvt->interface_state != SKYPIAX_STATE_DOWN) {
+                                        WARNINGA("Why an interface_state %d HERE?\n", SKYPIAX_P_LOG, tech_pvt->interface_state);
+                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                }
+
+                                break;
+                        }
+                }
+        }
+
+        if (found) {
+                //tech_pvt->callid_number[0]='\0';
+                //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_mutex_unlock(globals.mutex);
+                return 0;
+        }
+        DEBUGA_SKYPE("NOT FOUND\n", SKYPIAX_P_LOG);
+
+        if (tech_pvt && tech_pvt->skype_call_id && !strlen(tech_pvt->skype_call_id)) {
+                /* we are not inside an active call */
+
+                tech_pvt->ib_calls++;
+
+                sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_sleep(10000);
+                tech_pvt->interface_state = SKYPIAX_STATE_PREANSWER;
+                sprintf(msg_to_skype, "ALTER CALL %s ANSWER", id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                DEBUGA_SKYPE("We answered a Skype RING on skype_call %s\n", SKYPIAX_P_LOG, id);
+                //FIXME write a timestamp here
+                gettimeofday(&tech_pvt->answer_time, NULL);
+                switch_copy_string(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+
+                switch_copy_string(tech_pvt->callid_number, value, sizeof(tech_pvt->callid_number) - 1);
+
+                DEBUGA_SKYPE
+                        ("NEW! name: %s, state: %d, value=%s, tech_pvt->callid_number=%s, tech_pvt->skype_user=%s\n",
+                         SKYPIAX_P_LOG, tech_pvt->name, tech_pvt->interface_state, value, tech_pvt->callid_number, tech_pvt->skype_user);
+        } else if (!tech_pvt || !tech_pvt->skype_call_id) {
+                ERRORA("No Call ID?\n", SKYPIAX_P_LOG);
+        } else {
+                DEBUGA_SKYPE("We're in a call now (%s), let's refuse this one (%s)\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id, id);
+                sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+        }
+
+        switch_mutex_unlock(globals.mutex);
+        return 0;
+}
+int skypiax_transfer(private_t * tech_pvt, char *id, char *value)
+{
+        char msg_to_skype[1024];
+        int i;
+        int found = 0;
+        private_t *giovatech;
+        struct timeval timenow;
+
+        switch_mutex_lock(globals.mutex);
+
+        gettimeofday(&timenow, NULL);
+        for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                        giovatech = &globals.SKYPIAX_INTERFACES[i];
+                        //NOTICA("skype interface: %d, name: %s, state: %d, value=%s, giovatech->callid_number=%s, giovatech->skype_user=%s\n", SKYPIAX_P_LOG, i, giovatech->name, giovatech->interface_state, value, giovatech->callid_number, giovatech->skype_user);
+                        //FIXME check a timestamp here
+                        if (strlen(giovatech->skype_call_id) && (giovatech->interface_state != SKYPIAX_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->callid_number, value)) && ((((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) < 500000)) {        //0.5sec
+                                found = 1;
+                                DEBUGA_SKYPE
+                                        ("FOUND (name=%s, giovatech->interface_state=%d != SKYPIAX_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
+                                         SKYPIAX_P_LOG, giovatech->name, giovatech->interface_state,
+                                         giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number, value)
+                                        break;
+                        }
+                }
+        }
+
+        if (found) {
+                //tech_pvt->callid_number[0]='\0';
+                //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_mutex_unlock(globals.mutex);
+                return 0;
+        }
+        DEBUGA_SKYPE("NOT FOUND\n", SKYPIAX_P_LOG);
+
+        if (!tech_pvt || !tech_pvt->skype_call_id || !strlen(tech_pvt->skype_call_id)) {
+                /* we are not inside an active call */
+                DEBUGA_SKYPE("We're NO MORE in a call now %s\n", SKYPIAX_P_LOG, (tech_pvt && tech_pvt->skype_call_id) ? tech_pvt->skype_call_id : "");
+                switch_mutex_unlock(globals.mutex);
+
+        } else {
+
+                /* we're owned, we're in a call, let's try to transfer */
+                /************************** TODO
+                 Checking here if it is possible to transfer this call to Test2
+                 -> GET CALL 288 CAN_TRANSFER Test2
+                 <- CALL 288 CAN_TRANSFER test2 TRUE
+                 **********************************/
+
+                private_t *available_skypiax_interface = NULL;
+
+                gettimeofday(&timenow, NULL);
+                for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                                giovatech = &globals.SKYPIAX_INTERFACES[i];
+                                //NOTICA("skype interface: %d, name: %s, state: %d, value=%s, giovatech->callid_number=%s, giovatech->skype_user=%s\n", SKYPIAX_P_LOG, i, giovatech->name, giovatech->interface_state, value, giovatech->callid_number, giovatech->skype_user);
+                                //FIXME check a timestamp here
+                                if (strlen(giovatech->skype_transfer_call_id) && (giovatech->interface_state != SKYPIAX_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->transfer_callid_number, value)) && ((((timenow.tv_sec - giovatech->transfer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->transfer_time.tv_usec)) < 1000000)) {        //1.0 sec
+                                        found = 1;
+                                        DEBUGA_SKYPE
+                                                ("FOUND (name=%s, giovatech->interface_state=%d != SKYPIAX_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->transfer_callid_number=%s == value=%s)\n",
+                                                 SKYPIAX_P_LOG, giovatech->name, giovatech->interface_state,
+                                                 giovatech->skype_user, tech_pvt->skype_user, giovatech->transfer_callid_number, value)
+                                                break;
+                                }
+                        }
+                }
+
+                if (found) {
+                        //tech_pvt->callid_number[0]='\0';
+                        //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                        //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                        switch_mutex_unlock(globals.mutex);
+                        return 0;
+                }
+                DEBUGA_SKYPE("NOT FOUND\n", SKYPIAX_P_LOG);
+
+                available_skypiax_interface = find_available_skypiax_interface_rr(tech_pvt);
+                if (available_skypiax_interface) {
+                        /* there is a skypiax interface idle, let's transfer the call to it */
+
+                        //FIXME write a timestamp here
+                        gettimeofday(&tech_pvt->transfer_time, NULL);
+                        switch_copy_string(tech_pvt->skype_transfer_call_id, id, sizeof(tech_pvt->skype_transfer_call_id) - 1);
+
+                        switch_copy_string(tech_pvt->transfer_callid_number, value, sizeof(tech_pvt->transfer_callid_number) - 1);
+
+                        DEBUGA_SKYPE
+                                ("Let's transfer the skype_call %s to %s interface (with skype_user: %s), because we are already in a skypiax call(%s)\n",
+                                 SKYPIAX_P_LOG, tech_pvt->skype_call_id, available_skypiax_interface->name, available_skypiax_interface->skype_user, id);
+
+                        //FIXME why this? the inbound call will come, eventually, on that other interface
+                        //available_skypiax_interface->ib_calls++;
+
+                        sprintf(msg_to_skype, "ALTER CALL %s TRANSFER %s", id, available_skypiax_interface->skype_user);
+                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                        if (tech_pvt->interface_state == SKYPIAX_STATE_SELECTED) {
+                                tech_pvt->interface_state = SKYPIAX_STATE_IDLE;        //we marked it SKYPIAX_STATE_SELECTED just in case it has to make an outbound call
+                        }
+                } else {
+                        /* no skypiax interfaces idle, do nothing */
+                        DEBUGA_SKYPE
+                                ("Not answering the skype_call %s, because we are already in a skypiax call(%s) and not transferring, because no other skypiax interfaces are available\n",
+                                 SKYPIAX_P_LOG, id, tech_pvt->skype_call_id);
+                        sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                }
+                switch_sleep(10000);
+                DEBUGA_SKYPE
+                        ("We have NOT answered a Skype RING from skype_call %s, because we are already in a skypiax call (%s)\n",
+                         SKYPIAX_P_LOG, id, tech_pvt->skype_call_id);
+
+                switch_mutex_unlock(globals.mutex);
+        }
+        return 0;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
</ins></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxmod_skypiax2008vcproj"></a>
<div class="addfile"><h4>Added: freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.2008.vcproj (0 => 14544)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.2008.vcproj         (rev 0)
+++ freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.2008.vcproj        2009-08-17 09:17:09 UTC (rev 14544)
</span><span class="lines">@@ -0,0 +1,164 @@
</span><ins>+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+        ProjectType="Visual C++"
+        Version="9.00"
+        Name="mod_skypiax"
+        ProjectGUID="{C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}"
+        RootNamespace="mod_skypiax"
+        Keyword="Win32Proj"
+        TargetFrameworkVersion="131072"
+        >
+        <Platforms>
+                <Platform
+                        Name="Win32"
+                />
+        </Platforms>
+        <ToolFiles>
+        </ToolFiles>
+        <Configurations>
+                <Configuration
+                        Name="Debug|Win32"
+                        ConfigurationType="2"
+                        InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"
+                        CharacterSet="2"
+                        >
+                        <Tool
+                                Name="VCPreBuildEventTool"
+                        />
+                        <Tool
+                                Name="VCCustomBuildTool"
+                        />
+                        <Tool
+                                Name="VCXMLDataGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCWebServiceProxyGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCMIDLTool"
+                        />
+                        <Tool
+                                Name="VCCLCompilerTool"
+                                UsePrecompiledHeader="0"
+                                WarningLevel="4"
+                                WarnAsError="false"
+                        />
+                        <Tool
+                                Name="VCManagedResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCPreLinkEventTool"
+                        />
+                        <Tool
+                                Name="VCLinkerTool"
+                                AdditionalOptions="rpcrt4.lib "
+                                RandomizedBaseAddress="1"
+                                DataExecutionPrevention="0"
+                        />
+                        <Tool
+                                Name="VCALinkTool"
+                        />
+                        <Tool
+                                Name="VCManifestTool"
+                        />
+                        <Tool
+                                Name="VCXDCMakeTool"
+                        />
+                        <Tool
+                                Name="VCBscMakeTool"
+                        />
+                        <Tool
+                                Name="VCFxCopTool"
+                        />
+                        <Tool
+                                Name="VCAppVerifierTool"
+                        />
+                        <Tool
+                                Name="VCPostBuildEventTool"
+                        />
+                </Configuration>
+                <Configuration
+                        Name="Release|Win32"
+                        ConfigurationType="2"
+                        InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"
+                        CharacterSet="2"
+                        >
+                        <Tool
+                                Name="VCPreBuildEventTool"
+                        />
+                        <Tool
+                                Name="VCCustomBuildTool"
+                        />
+                        <Tool
+                                Name="VCXMLDataGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCWebServiceProxyGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCMIDLTool"
+                        />
+                        <Tool
+                                Name="VCCLCompilerTool"
+                                UsePrecompiledHeader="0"
+                        />
+                        <Tool
+                                Name="VCManagedResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCPreLinkEventTool"
+                        />
+                        <Tool
+                                Name="VCLinkerTool"
+                                AdditionalOptions="rpcrt4.lib "
+                                RandomizedBaseAddress="1"
+                                DataExecutionPrevention="0"
+                        />
+                        <Tool
+                                Name="VCALinkTool"
+                        />
+                        <Tool
+                                Name="VCManifestTool"
+                        />
+                        <Tool
+                                Name="VCXDCMakeTool"
+                        />
+                        <Tool
+                                Name="VCBscMakeTool"
+                        />
+                        <Tool
+                                Name="VCFxCopTool"
+                        />
+                        <Tool
+                                Name="VCAppVerifierTool"
+                        />
+                        <Tool
+                                Name="VCPostBuildEventTool"
+                        />
+                </Configuration>
+        </Configurations>
+        <References>
+        </References>
+        <Files>
+                <File
+                        RelativePath="..\mod_skypiax\mod_skypiax.c"
+                        >
+                </File>
+                <File
+                        RelativePath=".\skypiax.h"
+                        >
+                </File>
+                <File
+                        RelativePath=".\skypiax_protocol.c"
+                        >
+                </File>
+        </Files>
+        <Globals>
+        </Globals>
+</VisualStudioProject>
</ins></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxmod_skypiaxc"></a>
<div class="addfile"><h4>Added: freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.c (0 => 14544)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.c         (rev 0)
+++ freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.c        2009-08-17 09:17:09 UTC (rev 14544)
</span><span class="lines">@@ -0,0 +1,2110 @@
</span><ins>+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * This module (mod_skypiax) has been contributed by:
+ *
+ * Giovanni Maruzzelli (gmaruzz@gmail.com)
+ *
+ *
+ * Further Contributors:
+ *
+ *
+ *
+ * mod_skypiax.c -- Skype compatible Endpoint Module
+ *
+ */
+
+#include "skypiax.h"
+
+#ifdef WIN32
+/***************/
+// from http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
+
+#include <time.h>
+
+#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
+#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+#else /* */
+#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
+#endif /* */
+struct sk_timezone {
+        int tz_minuteswest;                        /* minutes W of Greenwich */
+        int tz_dsttime;                                /* type of dst correction */
+};
+int gettimeofday(struct timeval *tv, struct sk_timezone *tz)
+{
+        FILETIME ft;
+        unsigned __int64 tmpres = 0;
+        static int tzflag;
+        if (NULL != tv) {
+                GetSystemTimeAsFileTime(&ft);
+                tmpres |= ft.dwHighDateTime;
+                tmpres <<= 32;
+                tmpres |= ft.dwLowDateTime;
+
+                /*converting file time to unix epoch */
+                tmpres /= 10;                        /*convert into microseconds */
+                tmpres -= DELTA_EPOCH_IN_MICROSECS;
+                tv->tv_sec = (long) (tmpres / 1000000UL);
+                tv->tv_usec = (long) (tmpres % 1000000UL);
+        }
+        if (NULL != tz) {
+                if (!tzflag) {
+                        _tzset();
+                        tzflag++;
+                }
+                tz->tz_minuteswest = _timezone / 60;
+                tz->tz_dsttime = _daylight;
+        }
+        return 0;
+}
+
+/***************/
+#endif /* WIN32 */
+SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load);
+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 [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"
+
+/* BEGIN: Changes here */
+#define FULL_RELOAD 0
+#define SOFT_RELOAD 1
+/* END: Changes heres */
+
+char *interface_status[] = {        /* should match SKYPIAX_STATE_xxx in skypiax.h */
+        "IDLE",
+        "DOWN",
+        "RING",
+        "DIALING",
+        "BUSY",
+        "UP",
+        "RINGING",
+        "PRERING",
+        "DOUBLE",
+        "SELECTD",
+        "HANG_RQ",
+        "PREANSW"
+};
+char *skype_callflow[] = {                /* should match CALLFLOW_XXX in skypiax.h */
+        "CALL_IDLE",
+        "CALL_DOWN",
+        "INCOMING_RNG",
+        "CALL_DIALING",
+        "CALL_LINEBUSY",
+        "CALL_ACTIVE",
+        "INCOMING_HNG",
+        "CALL_RLEASD",
+        "CALL_NOCARR",
+        "CALL_INFLUX",
+        "CALL_INCOMING",
+        "CALL_FAILED",
+        "CALL_NOSRVC",
+        "CALL_OUTRESTR",
+        "CALL_SECFAIL",
+        "CALL_NOANSWER",
+        "STATUS_FNSHED",
+        "STATUS_CANCLED",
+        "STATUS_FAILED",
+        "STATUS_REFUSED",
+        "STATUS_RINGING",
+        "STATUS_INPROGRS",
+        "STATUS_UNPLACD",
+        "STATUS_ROUTING",
+        "STATUS_EARLYMD",
+        "INCOMING_CLID",
+        "STATUS_RMTEHOLD"
+};
+
+
+static struct {
+        int debug;
+        char *ip;
+        int port;
+        char *dialplan;
+        char *destination;
+        char *context;
+        char *codec_string;
+        char *codec_order[SWITCH_MAX_CODECS];
+        int codec_order_last;
+        char *codec_rates_string;
+        char *codec_rates[SWITCH_MAX_CODECS];
+        int codec_rates_last;
+        unsigned int flags;
+        int fd;
+        int calls;
+        int real_interfaces;
+        int next_interface;
+        char hold_music[256];
+        private_t SKYPIAX_INTERFACES[SKYPIAX_MAX_INTERFACES];
+        switch_mutex_t *mutex;
+        private_t *sk_console;
+} globals;
+
+switch_endpoint_interface_t *skypiax_endpoint_interface;
+switch_memory_pool_t *skypiax_module_pool = NULL;
+int running = 0;
+
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_context, globals.context);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_destination, globals.destination);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string);
+
+/* BEGIN: Changes here */
+static switch_status_t interface_exists(char *the_interface);
+static switch_status_t remove_interface(char *the_interface);
+/* END: Changes here */
+
+static switch_status_t channel_on_init(switch_core_session_t *session);
+static switch_status_t channel_on_hangup(switch_core_session_t *session);
+static switch_status_t channel_on_destroy(switch_core_session_t *session);
+static switch_status_t channel_on_routing(switch_core_session_t *session);
+static switch_status_t channel_on_exchange_media(switch_core_session_t *session);
+static switch_status_t channel_on_consume_media(switch_core_session_t *session);
+static switch_status_t channel_on_soft_execute(switch_core_session_t *session);
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
+                                                                                                        switch_event_t *var_event,
+                                                                                                        switch_caller_profile_t *outbound_profile,
+                                                                                                        switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags);
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
+static switch_status_t skypiax_tech_init(private_t * tech_pvt, switch_core_session_t *session);
+
+static switch_status_t skypiax_codec(private_t * tech_pvt, int sample_rate, int codec_ms)
+{
+        switch_core_session_t *session = NULL;
+
+        if (switch_core_codec_init
+                (&tech_pvt->read_codec, "L16", NULL, sample_rate, codec_ms, 1,
+                 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+                ERRORA("Can't load codec?\n", SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+
+        if (switch_core_codec_init
+                (&tech_pvt->write_codec, "L16", NULL, sample_rate, codec_ms, 1,
+                 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+                ERRORA("Can't load codec?\n", SKYPIAX_P_LOG);
+                switch_core_codec_destroy(&tech_pvt->read_codec);
+                return SWITCH_STATUS_FALSE;
+        }
+
+        tech_pvt->read_frame.rate = sample_rate;
+        tech_pvt->read_frame.codec = &tech_pvt->read_codec;
+
+        session = switch_core_session_locate(tech_pvt->session_uuid_str);
+
+        if (session) {
+                switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
+                switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
+                switch_core_session_rwunlock(session);
+        } else {
+                ERRORA("no session\n", SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+
+}
+
+switch_status_t skypiax_tech_init(private_t * tech_pvt, switch_core_session_t *session)
+{
+
+        switch_assert(tech_pvt != NULL);
+        switch_assert(session != NULL);
+        tech_pvt->read_frame.data = tech_pvt->databuf;
+        tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
+        switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+        switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+        switch_core_session_set_private(session, tech_pvt);
+        switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
+        if (!strlen(tech_pvt->session_uuid_str)) {
+                ERRORA("no tech_pvt->session_uuid_str\n", SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+        if (skypiax_codec(tech_pvt, SAMPLERATE_SKYPIAX, 20) != SWITCH_STATUS_SUCCESS) {
+                ERRORA("skypiax_codec FAILED\n", SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+        DEBUGA_SKYPE("skypiax_codec SUCCESS\n", SKYPIAX_P_LOG);
+        return SWITCH_STATUS_SUCCESS;
+}
+
+/* BEGIN: Changes here */
+static switch_status_t interface_exists(char *the_interface)
+{
+        int i;
+        int interface_id;
+
+        if (*the_interface == '#') {        /* look by interface id or interface name */
+                the_interface++;
+                switch_assert(the_interface);
+                interface_id = atoi(the_interface);
+
+                /* take a number as interface id */
+                if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) {
+                        if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                                return SWITCH_STATUS_SUCCESS;
+                        }
+                } else {
+                        /* interface name */
+                        for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) {
+                                if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].name, the_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].skype_user)) {
+                                if (strcmp(globals.SKYPIAX_INTERFACES[i].skype_user, the_interface) == 0) {
+                                        return SWITCH_STATUS_SUCCESS;
+                                }
+                        }
+                }
+        }
+        return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t remove_interface(char *the_interface)
+{
+        int x = 10;
+        unsigned int howmany = 8;
+        int interface_id = -1;
+        private_t *tech_pvt = NULL;
+        switch_status_t status;
+
+        //running = 0;
+
+
+        if (*the_interface == '#') {        /* remove by interface id or interface name */
+                the_interface++;
+                switch_assert(the_interface);
+                interface_id = atoi(the_interface);
+
+                if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) {
+                        /* take a number as interface id */
+                        tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+                } else {
+
+                        for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) {
+                                if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].name, the_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, the_interface) == 0) {
+                                tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+                                break;
+                        }
+                }
+        }
+
+        if (!tech_pvt) {
+                DEBUGA_SKYPE("interface '%s' does not exist\n", SKYPIAX_P_LOG, the_interface);
+                goto end;
+        }
+
+        if (strlen(globals.SKYPIAX_INTERFACES[interface_id].session_uuid_str)) {
+                DEBUGA_SKYPE("interface '%s' is busy\n", SKYPIAX_P_LOG, the_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
+#else /* WIN32 */
+                howmany = write(tech_pvt->SkypiaxHandles.fdesc[1], "sciutati", howmany);
+#endif /* WIN32 */
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+#ifdef WIN32
+                if (SendMessage(tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {        // let's the skypiax_api_thread_func die
+                        DEBUGA_SKYPE("got FALSE here, thread probably was already dead. GetLastError returned: %d\n", SKYPIAX_P_LOG, GetLastError());
+                        globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread = NULL;
+                }
+#else
+                XEvent e;
+                Atom atom1 = XInternAtom(tech_pvt->SkypiaxHandles.disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+                memset(&e, 0, sizeof(e));
+                e.xclient.type = ClientMessage;
+                e.xclient.message_type = atom1;        /* leading message */
+                e.xclient.display = tech_pvt->SkypiaxHandles.disp;
+                e.xclient.window = tech_pvt->SkypiaxHandles.skype_win;
+                e.xclient.format = 8;
+
+                XSendEvent(tech_pvt->SkypiaxHandles.disp, tech_pvt->SkypiaxHandles.win, False, 0, &e);
+                XSync(tech_pvt->SkypiaxHandles.disp, False);
+#endif
+        }
+
+        while (x) {
+                x--;
+                switch_yield(50000);
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
+                switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread);
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+                switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread);
+        }
+
+        switch_mutex_lock(globals.mutex);
+        if (globals.sk_console == &globals.SKYPIAX_INTERFACES[interface_id]) {
+                DEBUGA_SKYPE("interface '%s' no more console\n", SKYPIAX_P_LOG, the_interface);
+                globals.sk_console = NULL;
+        } else {
+                DEBUGA_SKYPE("interface '%s' STILL console\n", SKYPIAX_P_LOG, the_interface);
+        }
+        memset(&globals.SKYPIAX_INTERFACES[interface_id], '\0', sizeof(private_t));
+        globals.real_interfaces--;
+        switch_mutex_unlock(globals.mutex);
+
+        DEBUGA_SKYPE("interface '%s' deleted successfully\n", SKYPIAX_P_LOG, the_interface);
+        globals.SKYPIAX_INTERFACES[interface_id].running = 1;
+ end:
+        //running = 1;
+        return SWITCH_STATUS_SUCCESS;
+}
+
+/* END: Changes here */
+
+/*
+ State methods they get called when the state changes to the specific state
+ returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
+ so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
+*/
+static switch_status_t channel_on_init(switch_core_session_t *session)
+{
+        switch_channel_t *channel;
+        private_t *tech_pvt = NULL;
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+        //ERRORA("%s CHANNEL INIT\n", SKYPIAX_P_LOG, tech_pvt->name);
+        switch_set_flag(tech_pvt, TFLAG_IO);
+
+        /* Move channel's state machine to ROUTING. This means the call is trying
+         to get from the initial start where the call because, to the point
+         where a destination has been identified. If the channel is simply
+         left in the initial state, nothing will happen. */
+        switch_channel_set_state(channel, CS_ROUTING);
+        switch_mutex_lock(globals.mutex);
+        globals.calls++;
+
+        switch_mutex_unlock(globals.mutex);
+        DEBUGA_SKYPE("%s CHANNEL INIT %s\n", SKYPIAX_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_destroy(switch_core_session_t *session)
+{
+        private_t *tech_pvt = NULL;
+
+        tech_pvt = switch_core_session_get_private(session);
+
+
+        if (tech_pvt) {
+                DEBUGA_SKYPE("%s CHANNEL DESTROY %s\n", SKYPIAX_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
+
+                if (switch_core_codec_ready(&tech_pvt->read_codec)) {
+                        switch_core_codec_destroy(&tech_pvt->read_codec);
+                }
+
+                if (switch_core_codec_ready(&tech_pvt->write_codec)) {
+                        switch_core_codec_destroy(&tech_pvt->write_codec);
+                }
+                *tech_pvt->session_uuid_str = '\0';
+                tech_pvt->interface_state = SKYPIAX_STATE_IDLE;
+                if (tech_pvt->skype_callflow == CALLFLOW_STATUS_FINISHED) {
+                        tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
+                }
+                switch_core_session_set_private(session, NULL);
+        } else {
+                DEBUGA_SKYPE("!!!!!!NO tech_pvt!!!! CHANNEL DESTROY %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(session));
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_hangup(switch_core_session_t *session)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+        char msg_to_skype[256];
+
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
+                if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+                        tech_pvt->ob_failed_calls++;
+                } else {
+                        tech_pvt->ib_failed_calls++;
+                }
+        }
+
+        switch_clear_flag(tech_pvt, TFLAG_IO);
+        switch_clear_flag(tech_pvt, TFLAG_VOICE);
+        //switch_set_flag(tech_pvt, TFLAG_HANGUP);
+
+        if (strlen(tech_pvt->skype_call_id)) {
+                //switch_thread_cond_signal(tech_pvt->cond);
+                DEBUGA_SKYPE("hanging up skype call: %s\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id);
+                sprintf(msg_to_skype, "ALTER CALL %s HANGUP", tech_pvt->skype_call_id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+        }
+        //memset(tech_pvt->session_uuid_str, '\0', sizeof(tech_pvt->session_uuid_str));
+        //*tech_pvt->session_uuid_str = '\0';
+        DEBUGA_SKYPE("%s CHANNEL HANGUP\n", SKYPIAX_P_LOG, tech_pvt->name);
+        switch_mutex_lock(globals.mutex);
+        globals.calls--;
+        if (globals.calls < 0) {
+                globals.calls = 0;
+        }
+
+        tech_pvt->interface_state = SKYPIAX_STATE_IDLE;
+        if (tech_pvt->skype_callflow == CALLFLOW_STATUS_FINISHED) {
+                tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
+        }
+        switch_mutex_unlock(globals.mutex);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_routing(switch_core_session_t *session)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        DEBUGA_SKYPE("%s CHANNEL ROUTING\n", SKYPIAX_P_LOG, tech_pvt->name);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_execute(switch_core_session_t *session)
+{
+
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        DEBUGA_SKYPE("%s CHANNEL EXECUTE\n", SKYPIAX_P_LOG, tech_pvt->name);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        DEBUGA_SKYPE("%s CHANNEL KILL_CHANNEL\n", SKYPIAX_P_LOG, tech_pvt->name);
+        switch (sig) {
+        case SWITCH_SIG_KILL:
+                DEBUGA_SKYPE("%s CHANNEL got SWITCH_SIG_KILL\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                //switch_mutex_lock(tech_pvt->flag_mutex);
+                switch_clear_flag(tech_pvt, TFLAG_IO);
+                switch_clear_flag(tech_pvt, TFLAG_VOICE);
+                switch_set_flag(tech_pvt, TFLAG_HANGUP);
+                //switch_mutex_unlock(tech_pvt->flag_mutex);
+                break;
+        case SWITCH_SIG_BREAK:
+                DEBUGA_SKYPE("%s CHANNEL got SWITCH_SIG_BREAK\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                //switch_set_flag(tech_pvt, TFLAG_BREAK);
+                //switch_mutex_lock(tech_pvt->flag_mutex);
+                switch_set_flag(tech_pvt, TFLAG_BREAK);
+                //switch_mutex_unlock(tech_pvt->flag_mutex);
+                break;
+        default:
+                break;
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+}
+static switch_status_t channel_on_consume_media(switch_core_session_t *session)
+{
+        private_t *tech_pvt = NULL;
+
+        tech_pvt = switch_core_session_get_private(session);
+
+        DEBUGA_SKYPE("%s CHANNEL CONSUME_MEDIA\n", SKYPIAX_P_LOG, tech_pvt->name);
+        return SWITCH_STATUS_SUCCESS;
+}
+
+
+static switch_status_t channel_on_exchange_media(switch_core_session_t *session)
+{
+        private_t *tech_pvt = NULL;
+        tech_pvt = switch_core_session_get_private(session);
+        DEBUGA_SKYPE("%s CHANNEL EXCHANGE_MEDIA\n", SKYPIAX_P_LOG, tech_pvt->name);
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_soft_execute(switch_core_session_t *session)
+{
+        private_t *tech_pvt = NULL;
+        tech_pvt = switch_core_session_get_private(session);
+        DEBUGA_SKYPE("%s CHANNEL SOFT_EXECUTE\n", SKYPIAX_P_LOG, tech_pvt->name);
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
+{
+        private_t *tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        DEBUGA_SKYPE("%s CHANNEL SEND_DTMF\n", SKYPIAX_P_LOG, tech_pvt->name);
+        DEBUGA_SKYPE("DTMF: %c\n", SKYPIAX_P_LOG, dtmf->digit);
+
+        skypiax_senddigit(tech_pvt, dtmf->digit);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+        switch_byte_t *data;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) {
+                ERRORA("channel not ready \n", SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                return SWITCH_STATUS_FALSE;
+        }
+
+        tech_pvt->read_frame.flags = SFF_NONE;
+        *frame = NULL;
+
+        if (!skypiax_audio_read(tech_pvt)) {
+
+                ERRORA("skypiax_audio_read ERROR\n", SKYPIAX_P_LOG);
+
+        } else {
+                switch_set_flag(tech_pvt, TFLAG_VOICE);
+        }
+
+        while (switch_test_flag(tech_pvt, TFLAG_IO)) {
+                if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
+                        switch_clear_flag(tech_pvt, TFLAG_BREAK);
+                        DEBUGA_SKYPE("CHANNEL READ FRAME goto CNG\n", SKYPIAX_P_LOG);
+                        goto cng;
+                }
+
+                if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
+                        DEBUGA_SKYPE("CHANNEL READ FRAME not IO\n", SKYPIAX_P_LOG);
+                        return SWITCH_STATUS_FALSE;
+                }
+
+                if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
+                        switch_clear_flag(tech_pvt, TFLAG_VOICE);
+                        if (!tech_pvt->read_frame.datalen) {
+                                DEBUGA_SKYPE("CHANNEL READ CONTINUE\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        *frame = &tech_pvt->read_frame;
+#ifdef BIGENDIAN
+                        if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+                                switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2);
+                        }
+#endif
+                        return SWITCH_STATUS_SUCCESS;
+                }
+
+                DEBUGA_SKYPE("CHANNEL READ no TFLAG_IO\n", SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+
+        }
+
+        DEBUGA_SKYPE("CHANNEL READ FALSE\n", SKYPIAX_P_LOG);
+        return SWITCH_STATUS_FALSE;
+
+ cng:
+        data = (switch_byte_t *) tech_pvt->read_frame.data;
+        data[0] = 65;
+        data[1] = 0;
+        tech_pvt->read_frame.datalen = 2;
+        tech_pvt->read_frame.flags = SFF_CNG;
+        *frame = &tech_pvt->read_frame;
+        return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+        unsigned int sent;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) {
+                ERRORA("channel not ready \n", SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                return SWITCH_STATUS_FALSE;
+        }
+#ifdef BIGENDIAN
+        if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+                switch_swap_linear(frame->data, (int) frame->datalen / 2);
+        }
+#endif
+
+        sent = frame->datalen;
+#ifdef WIN32
+        switch_file_write(tech_pvt->audioskypepipe[1], frame->data, &sent);
+#else /* WIN32 */
+        sent = write(tech_pvt->audioskypepipe[1], frame->data, sent);
+#endif /* WIN32 */
+        if (sent != frame->datalen && sent != -1) {
+                DEBUGA_SKYPE("CLI PIPE write %d\n", SKYPIAX_P_LOG, sent);
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_answer_channel(switch_core_session_t *session)
+{
+        private_t *tech_pvt;
+        switch_channel_t *channel = NULL;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        DEBUGA_SKYPE("ANSWERED! \n", SKYPIAX_P_LOG);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
+{
+        switch_channel_t *channel;
+        private_t *tech_pvt;
+
+        channel = switch_core_session_get_channel(session);
+        switch_assert(channel != NULL);
+
+        tech_pvt = (private_t *) switch_core_session_get_private(session);
+        switch_assert(tech_pvt != NULL);
+
+        switch (msg->message_id) {
+        case SWITCH_MESSAGE_INDICATE_ANSWER:
+                {
+                        DEBUGA_SKYPE("MSG_ID=%d, TO BE ANSWERED!\n", SKYPIAX_P_LOG, msg->message_id);
+                        channel_answer_channel(session);
+                }
+                break;
+        default:
+                {
+                        DEBUGA_SKYPE("MSG_ID=%d\n", SKYPIAX_P_LOG, msg->message_id);
+                }
+                break;
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
+{
+        struct private_object *tech_pvt = switch_core_session_get_private(session);
+        char *body = switch_event_get_body(event);
+        switch_assert(tech_pvt != NULL);
+
+        if (!body) {
+                body = "";
+        }
+
+        WARNINGA("event: |||%s|||\n", SKYPIAX_P_LOG, body);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+switch_state_handler_table_t skypiax_state_handlers = {
+        /*.on_init */ channel_on_init,
+        /*.on_routing */ channel_on_routing,
+        /*.on_execute */ channel_on_execute,
+        /*.on_hangup */ channel_on_hangup,
+        /*.on_exchange_media */ channel_on_exchange_media,
+        /*.on_soft_execute */ channel_on_soft_execute,
+        /*.on_consume_media */ channel_on_consume_media,
+        /*.on_hibernate */ NULL,
+        /*.on_reset */ NULL,
+        /*.on_park */ NULL,
+        /*.on_reporting */ NULL,
+        /*.on_destroy */ channel_on_destroy
+};
+
+switch_io_routines_t skypiax_io_routines = {
+        /*.outgoing_channel */ channel_outgoing_channel,
+        /*.read_frame */ channel_read_frame,
+        /*.write_frame */ channel_write_frame,
+        /*.kill_channel */ channel_kill_channel,
+        /*.send_dtmf */ channel_send_dtmf,
+        /*.receive_message */ channel_receive_message,
+        /*.receive_event */ channel_receive_event
+};
+
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
+                                                                                                        switch_event_t *var_event,
+                                                                                                        switch_caller_profile_t *outbound_profile,
+                                                                                                        switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags)
+{
+        private_t *tech_pvt = NULL;
+        if ((*new_session = switch_core_session_request(skypiax_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) {
+                switch_channel_t *channel = NULL;
+                switch_caller_profile_t *caller_profile;
+                char *rdest;
+                int found = 0;
+                char interface_name[256];
+
+                DEBUGA_SKYPE("1 SESSION_REQUEST %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+                switch_core_session_add_stream(*new_session, NULL);
+
+
+                if (!switch_strlen_zero(outbound_profile->destination_number)) {
+                        int i;
+                        char *slash;
+
+                        switch_copy_string(interface_name, outbound_profile->destination_number, 255);
+                        slash = strrchr(interface_name, '/');
+                        *slash = '\0';
+
+                        switch_mutex_lock(globals.mutex);
+                        if (strncmp("ANY", interface_name, strlen(interface_name)) == 0 || strncmp("RR", interface_name, strlen(interface_name)) == 0) {
+                                /* 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;
+                                //} 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(NULL);
+                                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)
+                                        && (strncmp(globals.SKYPIAX_INTERFACES[i].name, interface_name, strlen(interface_name)) == 0)) {
+                                        if (strlen(globals.SKYPIAX_INTERFACES[i].session_uuid_str)) {
+                                                DEBUGA_SKYPE
+                                                        ("globals.SKYPIAX_INTERFACES[%d].name=|||%s||| session_uuid_str=|||%s||| is BUSY\n",
+                                                         SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name, globals.SKYPIAX_INTERFACES[i].session_uuid_str);
+                                                DEBUGA_SKYPE("1 SESSION_DESTROY %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+                                                switch_core_session_destroy(new_session);
+                                                switch_mutex_unlock(globals.mutex);
+                                                return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                                        }
+
+                                        DEBUGA_SKYPE("globals.SKYPIAX_INTERFACES[%d].name=|||%s|||?\n", SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name);
+                                        tech_pvt = &globals.SKYPIAX_INTERFACES[i];
+                                        found = 1;
+                                        break;
+                                }
+
+                        }
+
+                } else {
+                        ERRORA("Doh! no destination number?\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+
+                if (!found) {
+                        DEBUGA_SKYPE("Doh! no available interface for |||%s|||?\n", SKYPIAX_P_LOG, interface_name);
+                        DEBUGA_SKYPE("2 SESSION_DESTROY %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+                        switch_core_session_destroy(new_session);
+                        switch_mutex_unlock(globals.mutex);
+                        //return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                        return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
+                }
+
+                channel = switch_core_session_get_channel(*new_session);
+                if (!channel) {
+                        ERRORA("Doh! no channel?\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        switch_mutex_unlock(globals.mutex);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+                if (skypiax_tech_init(tech_pvt, *new_session) != SWITCH_STATUS_SUCCESS) {
+                        ERRORA("Doh! no tech_init?\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        switch_mutex_unlock(globals.mutex);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+
+
+                if (outbound_profile) {
+                        char name[128];
+
+                        snprintf(name, sizeof(name), "skypiax/%s", outbound_profile->destination_number);
+                        //snprintf(name, sizeof(name), "skypiax/%s", tech_pvt->name);
+                        switch_channel_set_name(channel, name);
+                        caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+                        switch_channel_set_caller_profile(channel, caller_profile);
+                        tech_pvt->caller_profile = caller_profile;
+                } else {
+                        ERRORA("Doh! no caller profile\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        switch_mutex_unlock(globals.mutex);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+
+                tech_pvt->ob_calls++;
+
+                rdest = strchr(caller_profile->destination_number, '/');
+                *rdest++ = '\0';
+
+                //skypiax_call(tech_pvt, rdest, 30);
+
+                switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(*new_session), sizeof(tech_pvt->session_uuid_str));
+                caller_profile = tech_pvt->caller_profile;
+                caller_profile->destination_number = rdest;
+
+                switch_channel_set_flag(channel, CF_OUTBOUND);
+                switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
+                switch_channel_set_state(channel, CS_INIT);
+                skypiax_call(tech_pvt, rdest, 30);
+                switch_mutex_unlock(globals.mutex);
+                return SWITCH_CAUSE_SUCCESS;
+        }
+
+        ERRORA("Doh! no new_session\n", SKYPIAX_P_LOG);
+        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+}
+
+/*!
+ * \brief This thread runs during a call, and monitor the interface for signaling, like hangup, caller id, etc most of signaling is handled inside the skypiax_signaling_read function
+ *
+ */
+static void *SWITCH_THREAD_FUNC skypiax_signaling_thread_func(switch_thread_t * thread, void *obj)
+{
+        private_t *tech_pvt = obj;
+        int res;
+        int forever = 1;
+
+        if (!tech_pvt)
+                return NULL;
+
+        DEBUGA_SKYPE("In skypiax_signaling_thread_func: started, p=%p\n", SKYPIAX_P_LOG, (void *) tech_pvt);
+
+        while (forever) {
+                if (!(running && tech_pvt->running))
+                        break;
+                res = skypiax_signaling_read(tech_pvt);
+                if (res == CALLFLOW_INCOMING_HANGUP) {
+                        switch_core_session_t *session = NULL;
+                        switch_channel_t *channel = NULL;
+                        //private_t *tech_pvt = NULL;
+                        DEBUGA_SKYPE("skype call ended\n", SKYPIAX_P_LOG);
+
+                        if (tech_pvt) {
+                                session = switch_core_session_locate(tech_pvt->session_uuid_str);
+                                if (session) {
+                                        channel = switch_core_session_get_channel(session);
+                                        if (channel) {
+                                                switch_channel_state_t state = switch_channel_get_state(channel);
+                                                if (state < CS_EXECUTE) {
+                                                        switch_sleep(10000);        //10 msec, let the state evolve from CS_NEW
+                                                }
+                                                switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+                                        } else {
+                                                ERRORA("no channel?\n", SKYPIAX_P_LOG);
+                                        }
+                                        switch_core_session_rwunlock(session);
+                                } else {
+                                        DEBUGA_SKYPE("no session\n", SKYPIAX_P_LOG);
+                                }
+                                switch_mutex_lock(globals.mutex);
+                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                *tech_pvt->session_uuid_str = '\0';
+                                *tech_pvt->skype_call_id = '\0';
+                                switch_mutex_unlock(globals.mutex);
+
+                                //ERRORA("LET'S WAIT\n", SKYPIAX_P_LOG);
+                                switch_sleep(300000);        //0.3 sec
+                                //ERRORA("WAIT'S OVER\n", SKYPIAX_P_LOG);
+                                //tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                //usleep(30000); //0.03 sec
+                                switch_mutex_lock(globals.mutex);
+                                tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
+                                tech_pvt->interface_state = SKYPIAX_STATE_IDLE;
+                                switch_mutex_unlock(globals.mutex);
+                        } else {
+                                ERRORA("no tech_pvt?\n", SKYPIAX_P_LOG);
+                        }
+                }
+        }
+        return NULL;
+}
+
+/* BEGIN: Changes heres */
+static switch_status_t load_config(int reload_type)
+/* END: Changes heres */
+{
+        char *cf = "skypiax.conf";
+        switch_xml_t cfg, xml, global_settings, param, interfaces, myinterface;
+        private_t *tech_pvt = NULL;
+
+        switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, skypiax_module_pool);
+        if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+                ERRORA("open of %s failed\n", SKYPIAX_P_LOG, cf);
+                running = 0;
+                switch_xml_free(xml);
+                return SWITCH_STATUS_TERM;
+        }
+
+        switch_mutex_lock(globals.mutex);
+        if ((global_settings = switch_xml_child(cfg, "global_settings"))) {
+                for (param = switch_xml_child(global_settings, "param"); param; param = param->next) {
+                        char *var = (char *) switch_xml_attr_soft(param, "name");
+                        char *val = (char *) switch_xml_attr_soft(param, "value");
+
+                        if (!strcasecmp(var, "debug")) {
+                                DEBUGA_SKYPE("globals.debug=%d\n", SKYPIAX_P_LOG, globals.debug);
+                                globals.debug = atoi(val);
+                                DEBUGA_SKYPE("globals.debug=%d\n", SKYPIAX_P_LOG, globals.debug);
+                        } else if (!strcasecmp(var, "hold-music")) {
+                                switch_set_string(globals.hold_music, val);
+                                DEBUGA_SKYPE("globals.hold_music=%s\n", SKYPIAX_P_LOG, globals.hold_music);
+                        } else if (!strcmp(var, "port")) {
+                                globals.port = atoi(val);
+                                DEBUGA_SKYPE("globals.port=%d\n", SKYPIAX_P_LOG, globals.port);
+                        } else if (!strcmp(var, "codec-master")) {
+                                if (!strcasecmp(val, "us")) {
+                                        switch_set_flag(&globals, GFLAG_MY_CODEC_PREFS);
+                                }
+                                DEBUGA_SKYPE("codec-master globals.debug=%d\n", SKYPIAX_P_LOG, globals.debug);
+                        } else if (!strcmp(var, "dialplan")) {
+                                set_global_dialplan(val);
+                                DEBUGA_SKYPE("globals.dialplan=%s\n", SKYPIAX_P_LOG, globals.dialplan);
+                        } else if (!strcmp(var, "destination")) {
+                                set_global_destination(val);
+                                DEBUGA_SKYPE("globals.destination=%s\n", SKYPIAX_P_LOG, globals.destination);
+                        } else if (!strcmp(var, "context")) {
+                                set_global_context(val);
+                                DEBUGA_SKYPE("globals.context=%s\n", SKYPIAX_P_LOG, globals.context);
+                        } else if (!strcmp(var, "codec-prefs")) {
+                                set_global_codec_string(val);
+                                DEBUGA_SKYPE("globals.codec_string=%s\n", SKYPIAX_P_LOG, globals.codec_string);
+                                globals.codec_order_last = switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS);
+                        } else if (!strcmp(var, "codec-rates")) {
+                                set_global_codec_rates_string(val);
+                                DEBUGA_SKYPE("globals.codec_rates_string=%s\n", SKYPIAX_P_LOG, globals.codec_rates_string);
+                                globals.codec_rates_last = switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS);
+                        }
+
+                }
+        }
+
+        if ((interfaces = switch_xml_child(cfg, "per_interface_settings"))) {
+                int i = 0;
+
+                for (myinterface = switch_xml_child(interfaces, "interface"); myinterface; myinterface = myinterface->next) {
+                        char *id = (char *) switch_xml_attr(myinterface, "id");
+                        char *name = (char *) switch_xml_attr(myinterface, "name");
+                        char *context = "default";
+                        char *dialplan = "XML";
+                        char *destination = "5000";
+                        char *tonegroup = NULL;
+                        char *digit_timeout = NULL;
+                        char *max_digits = NULL;
+                        char *hotline = NULL;
+                        char *dial_regex = NULL;
+                        char *hold_music = NULL;
+                        char *fail_dial_regex = NULL;
+                        char *enable_callerid = "true";
+                        char *X11_display = NULL;
+                        char *tcp_cli_port = NULL;
+                        char *tcp_srv_port = NULL;
+                        char *skype_user = NULL;
+
+                        uint32_t interface_id = 0, to = 0, max = 0;
+
+                        tech_pvt = NULL;
+
+                        for (param = switch_xml_child(myinterface, "param"); param; param = param->next) {
+                                char *var = (char *) switch_xml_attr_soft(param, "name");
+                                char *val = (char *) switch_xml_attr_soft(param, "value");
+
+                                if (!strcasecmp(var, "tonegroup")) {
+                                        tonegroup = val;
+                                } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) {
+                                        digit_timeout = val;
+                                } else if (!strcasecmp(var, "context")) {
+                                        context = val;
+                                } else if (!strcasecmp(var, "dialplan")) {
+                                        dialplan = val;
+                                } else if (!strcasecmp(var, "destination")) {
+                                        destination = val;
+                                } else if (!strcasecmp(var, "dial-regex")) {
+                                        dial_regex = val;
+                                } else if (!strcasecmp(var, "enable-callerid")) {
+                                        enable_callerid = val;
+                                } else if (!strcasecmp(var, "fail-dial-regex")) {
+                                        fail_dial_regex = val;
+                                } else if (!strcasecmp(var, "hold-music")) {
+                                        hold_music = val;
+                                } else if (!strcasecmp(var, "skype_user")) {
+                                        skype_user = val;
+                                } else if (!strcasecmp(var, "tcp_cli_port")) {
+                                        tcp_cli_port = val;
+                                } else if (!strcasecmp(var, "tcp_srv_port")) {
+                                        tcp_srv_port = val;
+                                } else if (!strcasecmp(var, "X11-display") || !strcasecmp(var, "X11_display")) {
+                                        X11_display = val;
+                                } else if (!strcasecmp(var, "max_digits") || !strcasecmp(var, "max-digits")) {
+                                        max_digits = val;
+                                } else if (!strcasecmp(var, "hotline")) {
+                                        hotline = val;
+                                }
+
+                        }
+                        if (!skype_user) {
+                                ERRORA("interface missing REQUIRED param 'skype_user'\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+
+                        /* BEGIN: Changes here */
+                        if (reload_type == SOFT_RELOAD) {
+                                char the_interface[256];
+                                sprintf(the_interface, "#%s", name);
+
+                                if (interface_exists(the_interface) == SWITCH_STATUS_SUCCESS) {
+                                        continue;
+                                }
+                        }
+                        /* END: Changes here */
+
+                        if (!X11_display) {
+                                ERRORA("interface missing REQUIRED param 'X11_display'\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (!tcp_cli_port) {
+                                ERRORA("interface missing REQUIRED param 'tcp_cli_port'\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+
+                        if (!tcp_srv_port) {
+                                ERRORA("interface missing REQUIRED param 'tcp_srv_port'\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (!id) {
+                                ERRORA("interface missing REQUIRED param 'id'\n", SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (switch_is_number(id)) {
+                                interface_id = atoi(id);
+                                DEBUGA_SKYPE("interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+                        } else {
+                                ERRORA("interface param 'id' MUST be a number, now id='%s'\n", SKYPIAX_P_LOG, id);
+                                continue;
+                        }
+
+                        if (!name) {
+                                WARNINGA("interface missing param 'name', not nice, but works\n", SKYPIAX_P_LOG);
+                        }
+
+                        if (!tonegroup) {
+                                tonegroup = "us";
+                        }
+
+                        if (digit_timeout) {
+                                to = atoi(digit_timeout);
+                        }
+
+                        if (max_digits) {
+                                max = atoi(max_digits);
+                        }
+
+                        if (name) {
+                                DEBUGA_SKYPE("name=%s\n", SKYPIAX_P_LOG, name);
+                        }
+#ifndef WIN32
+                        if (!XInitThreads()) {
+                                ERRORA("Not initialized XInitThreads!\n", SKYPIAX_P_LOG);
+                        } else {
+                                DEBUGA_SKYPE("Initialized XInitThreads!\n", SKYPIAX_P_LOG);
+                        }
+                        switch_sleep(100);
+#endif /* WIN32 */
+
+                        if (interface_id && interface_id < SKYPIAX_MAX_INTERFACES) {
+                                private_t newconf;
+                                switch_threadattr_t *skypiax_api_thread_attr = NULL;
+                                switch_threadattr_t *skypiax_signaling_thread_attr = NULL;
+
+                                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];
+
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].interface_id, id);
+                                if (name) {
+                                        switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].name, name);
+                                } else {
+                                        switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].name, "N/A");
+                                }
+                                DEBUGA_SKYPE("CONFIGURING interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+#ifdef WIN32
+                                globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port = (unsigned short) atoi(tcp_cli_port);
+                                globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port = (unsigned short) atoi(tcp_srv_port);
+#else /* WIN32 */
+                                globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port = atoi(tcp_cli_port);
+                                globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port = atoi(tcp_srv_port);
+#endif /* WIN32 */
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].X11_display, X11_display);
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].skype_user, skype_user);
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].context, context);
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].dialplan, dialplan);
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].destination, destination);
+                                switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].context, context);
+
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].X11_display=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].X11_display);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].skype_user=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port=%d\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port=%d\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port);
+                                DEBUGA_SKYPE("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].name=%s\n",
+                                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].name);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].dialplan=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].dialplan);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].destination=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].destination);
+                                DEBUGA_SKYPE
+                                        ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n",
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
+                                WARNINGA("STARTING interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+
+                                switch_threadattr_create(&skypiax_api_thread_attr, skypiax_module_pool);
+                                switch_threadattr_stacksize_set(skypiax_api_thread_attr, SWITCH_THREAD_STACKSIZE);
+                                switch_thread_create(&globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread,
+                                                                         skypiax_api_thread_attr, skypiax_do_skypeapi_thread, &globals.SKYPIAX_INTERFACES[interface_id], skypiax_module_pool);
+
+                                switch_sleep(100000);
+
+                                switch_threadattr_create(&skypiax_signaling_thread_attr, skypiax_module_pool);
+                                switch_threadattr_stacksize_set(skypiax_signaling_thread_attr, SWITCH_THREAD_STACKSIZE);
+                                switch_thread_create(&globals.SKYPIAX_INTERFACES[interface_id].
+                                                                         skypiax_signaling_thread, skypiax_signaling_thread_attr,
+                                                                         skypiax_signaling_thread_func, &globals.SKYPIAX_INTERFACES[interface_id], skypiax_module_pool);
+
+                                switch_sleep(100000);
+
+                                skypiax_audio_init(&globals.SKYPIAX_INTERFACES[interface_id]);
+
+                                NOTICA
+                                        ("WAITING roughly 10 seconds to find a running Skype client and connect to its SKYPE API for interface_id=%d\n",
+                                         SKYPIAX_P_LOG, interface_id);
+                                i = 0;
+                                while (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.api_connected == 0 && running && i < 200) {        // 10 seconds! thanks Jeff Lenk
+                                        switch_sleep(50000);
+                                        i++;
+                                }
+                                if (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.api_connected) {
+                                        NOTICA
+                                                ("Found a running Skype client, connected to its SKYPE API for interface_id=%d, waiting 60 seconds for CURRENTUSERHANDLE==%s\n",
+                                                 SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                } else {
+                                        ERRORA
+                                                ("Failed to connect to a SKYPE API for interface_id=%d, no SKYPE client running, please (re)start Skype client. Skypiax exiting\n",
+                                                 SKYPIAX_P_LOG, interface_id);
+                                        running = 0;
+                                        switch_mutex_unlock(globals.mutex);
+                                        switch_xml_free(xml);
+                                        return SWITCH_STATUS_FALSE;
+                                }
+
+                                i = 0;
+                                while (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.currentuserhandle == 0 && running && i < 1200) {        // 60 seconds! thanks Jeff Lenk
+                                        switch_sleep(50000);
+                                        i++;
+                                }
+                                if (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.currentuserhandle) {
+                                        WARNINGA
+                                                ("Interface_id=%d is now STARTED, the Skype client to which we are connected gave us the correct CURRENTUSERHANDLE (%s)\n",
+                                                 SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+
+                                        skypiax_signaling_write(&globals.SKYPIAX_INTERFACES[interface_id], "SET AUTOAWAY OFF");
+                                } else {
+                                        ERRORA
+                                                ("The Skype client to which we are connected FAILED to gave us CURRENTUSERHANDLE=%s, interface_id=%d FAILED to start. No Skype client logged in as '%s' has been found. Please (re)launch a Skype client logged in as '%s'. Skypiax exiting now\n",
+                                                 SKYPIAX_P_LOG, globals.SKYPIAX_INTERFACES[interface_id].skype_user,
+                                                 interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                        running = 0;
+                                        switch_mutex_unlock(globals.mutex);
+                                        switch_xml_free(xml);
+                                        return SWITCH_STATUS_FALSE;
+                                }
+
+                        } else {
+                                ERRORA("interface id %d is higher than SKYPIAX_MAX_INTERFACES (%d)\n", SKYPIAX_P_LOG, interface_id, SKYPIAX_MAX_INTERFACES);
+                                continue;
+                        }
+
+                }
+
+                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", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].interface_id);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].X11_display=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].X11_display);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].name=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].name);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].context);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].dialplan=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].dialplan);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].destination=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].destination);
+                                DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].context);
+                        }
+                }
+        }
+
+        switch_mutex_unlock(globals.mutex);
+        switch_xml_free(xml);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load)
+{
+        switch_api_interface_t *commands_api_interface;
+
+        skypiax_module_pool = pool;
+        memset(&globals, '\0', sizeof(globals));
+
+        running = 1;
+
+        if (load_config(FULL_RELOAD) != SWITCH_STATUS_SUCCESS) {
+                running = 0;
+                return SWITCH_STATUS_FALSE;
+        }
+
+        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+        skypiax_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
+        skypiax_endpoint_interface->interface_name = "skypiax";
+        skypiax_endpoint_interface->io_routines = &skypiax_io_routines;
+        skypiax_endpoint_interface->state_handler = &skypiax_state_handlers;
+
+        if (running) {
+
+                SWITCH_ADD_API(commands_api_interface, "sk", "Skypiax console commands", sk_function, SK_SYNTAX);
+                SWITCH_ADD_API(commands_api_interface, "skypiax", "Skypiax interface commands", skypiax_function, SKYPIAX_SYNTAX);
+
+                /* indicate that the module should continue to be loaded */
+                return SWITCH_STATUS_SUCCESS;
+        } else
+                return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown)
+{
+        int x;
+        private_t *tech_pvt = NULL;
+        switch_status_t status;
+        unsigned int howmany = 8;
+        int interface_id;
+
+        running = 0;
+
+        for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) {
+                tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+
+                if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                        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
+#else /* WIN32 */
+                                howmany = write(tech_pvt->SkypiaxHandles.fdesc[1], "sciutati", howmany);
+#endif /* WIN32 */
+                        }
+
+                        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+#ifdef WIN32
+                                if (SendMessage(tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {        // let's the skypiax_api_thread_func die
+                                        DEBUGA_SKYPE("got FALSE here, thread probably was already dead. GetLastError returned: %d\n", SKYPIAX_P_LOG, GetLastError());
+                                        globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread = NULL;
+                                }
+#else
+                                XEvent e;
+                                Atom atom1 = XInternAtom(tech_pvt->SkypiaxHandles.disp, "SKYPECONTROLAPI_MESSAGE_BEGIN",
+                                                                                 False);
+                                memset(&e, 0, sizeof(e));
+                                e.xclient.type = ClientMessage;
+                                e.xclient.message_type = atom1;        /* leading message */
+                                e.xclient.display = tech_pvt->SkypiaxHandles.disp;
+                                e.xclient.window = tech_pvt->SkypiaxHandles.skype_win;
+                                e.xclient.format = 8;
+
+                                XSendEvent(tech_pvt->SkypiaxHandles.disp, tech_pvt->SkypiaxHandles.win, False, 0, &e);
+                                XSync(tech_pvt->SkypiaxHandles.disp, False);
+#endif
+                        }
+                        x = 10;
+                        while (x) {                        //FIXME 0.5 seconds?
+                                x--;
+                                switch_yield(50000);
+                        }
+                        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
+                                switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread);
+                        }
+                        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+                                switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread);
+                        }
+#ifndef WIN32
+                        WARNINGA("SHUTDOWN interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+                        shutdown(tech_pvt->audioskypepipe[0], 2);
+                        close(tech_pvt->audioskypepipe[0]);
+                        shutdown(tech_pvt->audioskypepipe[1], 2);
+                        close(tech_pvt->audioskypepipe[1]);
+                        shutdown(tech_pvt->audiopipe[0], 2);
+                        close(tech_pvt->audiopipe[0]);
+                        shutdown(tech_pvt->audiopipe[1], 2);
+                        close(tech_pvt->audiopipe[1]);
+                        shutdown(tech_pvt->SkypiaxHandles.fdesc[0], 2);
+                        close(tech_pvt->SkypiaxHandles.fdesc[0]);
+                        shutdown(tech_pvt->SkypiaxHandles.fdesc[1], 2);
+                        close(tech_pvt->SkypiaxHandles.fdesc[1]);
+#endif /* WIN32 */
+                }
+
+        }
+        switch_safe_free(globals.dialplan);
+        switch_safe_free(globals.context);
+        switch_safe_free(globals.destination);
+        switch_safe_free(globals.codec_string);
+        switch_safe_free(globals.codec_rates_string);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_srv_thread(switch_thread_t * thread, void *obj)
+{
+        return skypiax_do_tcp_srv_thread_func(obj);
+}
+
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_cli_thread(switch_thread_t * thread, void *obj)
+{
+        return skypiax_do_tcp_cli_thread_func(obj);
+}
+
+void *SWITCH_THREAD_FUNC skypiax_do_skypeapi_thread(switch_thread_t * thread, void *obj)
+{
+        return skypiax_do_skypeapi_thread_func(obj);
+}
+
+int dtmf_received(private_t * tech_pvt, char *value)
+{
+        switch_core_session_t *session = NULL;
+        switch_channel_t *channel = NULL;
+
+        session = switch_core_session_locate(tech_pvt->session_uuid_str);
+        channel = switch_core_session_get_channel(session);
+
+        if (channel) {
+
+                if (!switch_channel_test_flag(channel, CF_BRIDGED)) {
+
+                        switch_dtmf_t dtmf = { (char) value[0], switch_core_default_dtmf_duration(0) };
+                        DEBUGA_SKYPE("received DTMF %c on channel %s\n", SKYPIAX_P_LOG, dtmf.digit, switch_channel_get_name(channel));
+                        switch_mutex_lock(tech_pvt->flag_mutex);
+                        //FIXME: why sometimes DTMFs from here do not seems to be get by FS?
+                        switch_channel_queue_dtmf(channel, &dtmf);
+                        switch_set_flag(tech_pvt, TFLAG_DTMF);
+                        switch_mutex_unlock(tech_pvt->flag_mutex);
+                } else {
+                        DEBUGA_SKYPE
+                                ("received a DTMF on channel %s, but we're BRIDGED, so let's NOT relay it out of band\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                }
+        } else {
+                WARNINGA("received %c DTMF, but no channel?\n", SKYPIAX_P_LOG, value[0]);
+        }
+        switch_core_session_rwunlock(session);
+
+        return 0;
+}
+
+int start_audio_threads(private_t * tech_pvt)
+{
+        switch_threadattr_t *thd_attr = NULL;
+
+        switch_threadattr_create(&thd_attr, skypiax_module_pool);
+        switch_threadattr_detach_set(thd_attr, 1);
+        switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+        if (switch_thread_create(&tech_pvt->tcp_srv_thread, thd_attr, skypiax_do_tcp_srv_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) {
+                DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+        } else {
+                ERRORA("failed to start tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        switch_threadattr_create(&thd_attr, skypiax_module_pool);
+        switch_threadattr_detach_set(thd_attr, 1);
+        switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+        if (switch_thread_create(&tech_pvt->tcp_cli_thread, thd_attr, skypiax_do_tcp_cli_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) {
+                DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+        } else {
+                ERRORA("failed to start tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+                return -1;
+        }
+        switch_sleep(100000);
+
+        if (tech_pvt->tcp_cli_thread == NULL || tech_pvt->tcp_srv_thread == NULL) {
+                ERRORA("tcp_cli_thread or tcp_srv_thread exited\n", SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        return 0;
+}
+
+int new_inbound_channel(private_t * tech_pvt)
+{
+        switch_core_session_t *session = NULL;
+        switch_channel_t *channel = NULL;
+
+        if ((session = switch_core_session_request(skypiax_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL)) != 0) {
+                DEBUGA_SKYPE("2 SESSION_REQUEST %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(session));
+                switch_core_session_add_stream(session, NULL);
+                channel = switch_core_session_get_channel(session);
+                if (!channel) {
+                        ERRORA("Doh! no channel?\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&session);
+                        return 0;
+                }
+                if (skypiax_tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS) {
+                        ERRORA("Doh! no tech_init?\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&session);
+                        return 0;
+                }
+
+                if ((tech_pvt->caller_profile =
+                         switch_caller_profile_new(switch_core_session_get_pool(session), "skypiax",
+                                                                         tech_pvt->dialplan, tech_pvt->callid_name,
+                                                                         tech_pvt->callid_number, NULL, NULL, NULL, NULL, "mod_skypiax", tech_pvt->context, tech_pvt->destination)) != 0) {
+                        char name[128];
+                        //switch_snprintf(name, sizeof(name), "skypiax/%s/%s", tech_pvt->name, tech_pvt->caller_profile->destination_number);
+                        switch_snprintf(name, sizeof(name), "skypiax/%s", tech_pvt->name);
+                        switch_channel_set_name(channel, name);
+                        switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+                }
+                switch_channel_set_state(channel, CS_INIT);
+                if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
+                        ERRORA("Error spawning thread\n", SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&session);
+                        return 0;
+                }
+        }
+        if (channel) {
+                switch_channel_mark_answered(channel);
+        }
+
+        DEBUGA_SKYPE("new_inbound_channel\n", SKYPIAX_P_LOG);
+
+        return 0;
+}
+
+int remote_party_is_ringing(private_t * tech_pvt)
+{
+        switch_core_session_t *session = NULL;
+        switch_channel_t *channel = NULL;
+
+        if (!switch_strlen_zero(tech_pvt->session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt->session_uuid_str);
+        } else {
+                ERRORA("No session???\n", SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (session) {
+                channel = switch_core_session_get_channel(session);
+        } else {
+                ERRORA("No session???\n", SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_ring_ready(channel);
+                DEBUGA_SKYPE("skype_call: REMOTE PARTY RINGING\n", SKYPIAX_P_LOG);
+        } else {
+                ERRORA("No channel???\n", SKYPIAX_P_LOG);
+        }
+
+        switch_core_session_rwunlock(session);
+
+ done:
+        return 0;
+}
+
+int remote_party_is_early_media(private_t * tech_pvt)
+{
+        switch_core_session_t *session = NULL;
+        switch_channel_t *channel = NULL;
+
+        if (!switch_strlen_zero(tech_pvt->session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt->session_uuid_str);
+        } else {
+                ERRORA("No session???\n\n\n", SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                goto done;
+        }
+        if (session) {
+                channel = switch_core_session_get_channel(session);
+                switch_core_session_add_stream(session, NULL);
+        } else {
+                ERRORA("No session???\n", SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_pre_answered(channel);
+                DEBUGA_SKYPE("skype_call: REMOTE PARTY EARLY MEDIA\n", SKYPIAX_P_LOG);
+        } else {
+                ERRORA("No channel???\n", SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+        }
+
+        switch_core_session_rwunlock(session);
+
+ done:
+        return 0;
+}
+
+int outbound_channel_answered(private_t * tech_pvt)
+{
+        switch_core_session_t *session = NULL;
+        switch_channel_t *channel = NULL;
+
+        if (!switch_strlen_zero(tech_pvt->session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt->session_uuid_str);
+        } else {
+                ERRORA("No session???\n", SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (session) {
+                channel = switch_core_session_get_channel(session);
+        } else {
+                ERRORA("No channel???\n", SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_answered(channel);
+                //DEBUGA_SKYPE("skype_call: %s, answered\n", SKYPIAX_P_LOG, id);
+        } else {
+                ERRORA("No channel???\n", SKYPIAX_P_LOG);
+        }
+
+        switch_core_session_rwunlock(session);
+
+ done:
+        DEBUGA_SKYPE("outbound_channel_answered!\n", SKYPIAX_P_LOG);
+
+        return 0;
+}
+
+private_t *find_available_skypiax_interface_rr(private_t * tech_pvt_calling)
+{
+        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 */
+        //XXX no, is just a convention, but you can have it start from 0. I do not, for aestetic reasons :-)
+        //if (globals.next_interface == 0) globals.next_interface = 1;
+
+        for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) {
+                int interface_id;
+
+                interface_id = globals.next_interface;
+                //interface_id = interface_id < SKYPIAX_MAX_INTERFACES ? interface_id : interface_id - SKYPIAX_MAX_INTERFACES + 1;
+                globals.next_interface = interface_id + 1 < SKYPIAX_MAX_INTERFACES ? interface_id + 1 : 0;
+
+                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 ((tech_pvt_calling ? strcmp(tech_pvt->skype_user, tech_pvt_calling->skype_user) : 1)
+                                && (SKYPIAX_STATE_DOWN == skype_state || 0 == skype_state) && (tech_pvt->skype_callflow == CALLFLOW_STATUS_FINISHED
+                                                                                                                                                         || 0 == tech_pvt->skype_callflow)) {
+                                DEBUGA_SKYPE("returning as available skype interface name: %s, state: %d callflow: %d\n", SKYPIAX_P_LOG, tech_pvt->name, skype_state,
+                                                         tech_pvt->skype_callflow);
+                                /*set to Dialing state to avoid other thread fint it, don't know if it is safe */
+                                //XXX no, it's not safe
+                                if (tech_pvt_calling == NULL) {
+                                        tech_pvt->interface_state = SKYPIAX_STATE_SELECTED;
+                                }
+
+                                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)
+{
+        char *mycmd = NULL, *argv[10] = { 0 };
+        int argc = 0;
+
+        if (globals.sk_console)
+                stream->write_function(stream, "sk console is: |||%s|||\n", globals.sk_console->name);
+        else
+                stream->write_function(stream, "sk console is NOT yet assigned\n");
+
+        if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+                argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+        }
+
+        if (!argc || !argv[0]) {
+                stream->write_function(stream, "%s", SK_SYNTAX);
+                goto end;
+        }
+
+        if (!strcasecmp(argv[0], "list")) {
+                int i;
+                char next_flag_char = ' ';
+
+                stream->write_function(stream, "F ID\t Name \tIB (F/T) OB (F/T)\tState\tCallFlw\t\tUUID\n");
+                stream->write_function(stream, "= ====\t ======== \t======= =======\t======\t============\t======\n");
+
+                for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) {
+                        next_flag_char = i == globals.next_interface ? '*' : ' ';
+
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+                                stream->write_function(stream,
+                                                                         "%c %d\t[%s]\t%3ld/%ld\t%6ld/%ld\t%s\t%s\t%s\n",
+                                                                         next_flag_char,
+                                                                         i, globals.SKYPIAX_INTERFACES[i].name,
+                                                                         globals.SKYPIAX_INTERFACES[i].ib_failed_calls,
+                                                                         globals.SKYPIAX_INTERFACES[i].ib_calls,
+                                                                         globals.SKYPIAX_INTERFACES[i].ob_failed_calls,
+                                                                         globals.SKYPIAX_INTERFACES[i].ob_calls,
+                                                                         interface_status[globals.SKYPIAX_INTERFACES[i].interface_state],
+                                                                         skype_callflow[globals.SKYPIAX_INTERFACES[i].skype_callflow], globals.SKYPIAX_INTERFACES[i].session_uuid_str);
+                        } 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;
+
+                if (argc == 2) {
+                        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)
+                                        && (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[1], strlen(argv[1])) == 0)) {
+                                        globals.sk_console = &globals.SKYPIAX_INTERFACES[i];
+                                        stream->write_function(stream,
+                                                                                 "sk console is now: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n", i, globals.SKYPIAX_INTERFACES[i].name);
+                                        stream->write_function(stream, "sk console is: |||%s|||\n", globals.sk_console->name);
+                                        found = 1;
+                                        break;
+                                }
+
+                        }
+                        if (!found)
+                                stream->write_function(stream, "ERROR: A Skypiax interface with name='%s' was not found\n", argv[1]);
+                } else {
+
+                        stream->write_function(stream, "-ERR Usage: sk console interface_name\n");
+                        goto end;
+                }
+
+        } else if (!strcasecmp(argv[0], "ciapalino")) {
+
+/* BEGIN: Changes heres */
+        } else if (!strcasecmp(argv[0], "reload")) {
+                if (load_config(SOFT_RELOAD) != SWITCH_STATUS_SUCCESS) {
+                        stream->write_function(stream, "sk reload failed\n");
+                } else {
+                        stream->write_function(stream, "sk reload success\n");
+                }
+        } else if (!strcasecmp(argv[0], "remove")) {
+                if (argc == 2) {
+                        if (remove_interface(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                                if (interface_exists(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                                        stream->write_function(stream, "sk remove '%s' failed\n", argv[1]);
+                                } else {
+                                        stream->write_function(stream, "sk remove '%s' success\n", argv[1]);
+                                }
+                        }
+                } else {
+                        stream->write_function(stream, "-ERR Usage: sk remove interface_name\n");
+                        goto end;
+                }
+/* END: Changes heres */
+
+        } else {
+                if (globals.sk_console)
+                        skypiax_signaling_write(globals.sk_console, (char *) cmd);
+                else
+                        stream->write_function(stream, "sk console is NOT yet assigned\n");
+        }
+ end:
+        switch_safe_free(mycmd);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_API(skypiax_function)
+{
+        char *mycmd = NULL, *argv[10] = { 0 };
+        int argc = 0;
+        private_t *tech_pvt = NULL;
+
+        if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+                argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+        }
+
+        if (!argc) {
+                stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_SYNTAX);
+                goto end;
+        }
+
+        if (argc < 2) {
+                stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_SYNTAX);
+                goto end;
+        }
+
+        if (argv[0]) {
+                int i;
+                int found = 0;
+
+                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)
+                                && (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
+                                tech_pvt = &globals.SKYPIAX_INTERFACES[i];
+                                stream->write_function(stream, "Using interface: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n", i, globals.SKYPIAX_INTERFACES[i].name);
+                                found = 1;
+                                break;
+                        }
+
+                }
+                if (!found) {
+                        stream->write_function(stream, "ERROR: A Skypiax interface with name='%s' was not found\n", argv[0]);
+                        switch_safe_free(mycmd);
+
+                        return SWITCH_STATUS_SUCCESS;
+                } else {
+                        skypiax_signaling_write(tech_pvt, (char *) &cmd[strlen(argv[0]) + 1]);
+                }
+        } else {
+                stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_SYNTAX);
+        }
+ end:
+        switch_safe_free(mycmd);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+int skypiax_answer(private_t * tech_pvt, char *id, char *value)
+{
+        char msg_to_skype[1024];
+        int i;
+        int found = 0;
+        private_t *giovatech;
+        struct timeval timenow;
+
+        switch_mutex_lock(globals.mutex);
+
+        gettimeofday(&timenow, NULL);
+        for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                        giovatech = &globals.SKYPIAX_INTERFACES[i];
+                        //NOTICA("skype interface: %d, name: %s, state: %d, value=%s, giovatech->callid_number=%s, giovatech->skype_user=%s\n", SKYPIAX_P_LOG, i, giovatech->name, giovatech->interface_state, value, giovatech->callid_number, giovatech->skype_user);
+                        //FIXME check a timestamp here
+                        if (strlen(giovatech->skype_call_id) && (giovatech->interface_state != SKYPIAX_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->callid_number, value)) && ((((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) < 500000)) {        //0.5sec
+                                found = 1;
+                                DEBUGA_SKYPE
+                                        ("FOUND (name=%s, giovatech->interface_state=%d != SKYPIAX_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
+                                         SKYPIAX_P_LOG, giovatech->name, giovatech->interface_state,
+                                         giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number, value)
+                                        if (tech_pvt->interface_state == SKYPIAX_STATE_PRERING) {
+                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                } else if (tech_pvt->interface_state != 0 && tech_pvt->interface_state != SKYPIAX_STATE_DOWN) {
+                                        WARNINGA("Why an interface_state %d HERE?\n", SKYPIAX_P_LOG, tech_pvt->interface_state);
+                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                }
+
+                                break;
+                        }
+                }
+        }
+
+        if (found) {
+                //tech_pvt->callid_number[0]='\0';
+                //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_mutex_unlock(globals.mutex);
+                return 0;
+        }
+        DEBUGA_SKYPE("NOT FOUND\n", SKYPIAX_P_LOG);
+
+        if (tech_pvt && tech_pvt->skype_call_id && !strlen(tech_pvt->skype_call_id)) {
+                /* we are not inside an active call */
+
+                tech_pvt->ib_calls++;
+
+                sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_sleep(10000);
+                tech_pvt->interface_state = SKYPIAX_STATE_PREANSWER;
+                sprintf(msg_to_skype, "ALTER CALL %s ANSWER", id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                DEBUGA_SKYPE("We answered a Skype RING on skype_call %s\n", SKYPIAX_P_LOG, id);
+                //FIXME write a timestamp here
+                gettimeofday(&tech_pvt->answer_time, NULL);
+                switch_copy_string(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+
+                switch_copy_string(tech_pvt->callid_number, value, sizeof(tech_pvt->callid_number) - 1);
+
+                DEBUGA_SKYPE
+                        ("NEW! name: %s, state: %d, value=%s, tech_pvt->callid_number=%s, tech_pvt->skype_user=%s\n",
+                         SKYPIAX_P_LOG, tech_pvt->name, tech_pvt->interface_state, value, tech_pvt->callid_number, tech_pvt->skype_user);
+        } else if (!tech_pvt || !tech_pvt->skype_call_id) {
+                ERRORA("No Call ID?\n", SKYPIAX_P_LOG);
+        } else {
+                DEBUGA_SKYPE("We're in a call now (%s), let's refuse this one (%s)\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id, id);
+                sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+        }
+
+        switch_mutex_unlock(globals.mutex);
+        return 0;
+}
+int skypiax_transfer(private_t * tech_pvt, char *id, char *value)
+{
+        char msg_to_skype[1024];
+        int i;
+        int found = 0;
+        private_t *giovatech;
+        struct timeval timenow;
+
+        switch_mutex_lock(globals.mutex);
+
+        gettimeofday(&timenow, NULL);
+        for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                        giovatech = &globals.SKYPIAX_INTERFACES[i];
+                        //NOTICA("skype interface: %d, name: %s, state: %d, value=%s, giovatech->callid_number=%s, giovatech->skype_user=%s\n", SKYPIAX_P_LOG, i, giovatech->name, giovatech->interface_state, value, giovatech->callid_number, giovatech->skype_user);
+                        //FIXME check a timestamp here
+                        if (strlen(giovatech->skype_call_id) && (giovatech->interface_state != SKYPIAX_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->callid_number, value)) && ((((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) < 500000)) {        //0.5sec
+                                found = 1;
+                                DEBUGA_SKYPE
+                                        ("FOUND (name=%s, giovatech->interface_state=%d != SKYPIAX_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
+                                         SKYPIAX_P_LOG, giovatech->name, giovatech->interface_state,
+                                         giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number, value)
+                                        break;
+                        }
+                }
+        }
+
+        if (found) {
+                //tech_pvt->callid_number[0]='\0';
+                //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_mutex_unlock(globals.mutex);
+                return 0;
+        }
+        DEBUGA_SKYPE("NOT FOUND\n", SKYPIAX_P_LOG);
+
+        if (!tech_pvt || !tech_pvt->skype_call_id || !strlen(tech_pvt->skype_call_id)) {
+                /* we are not inside an active call */
+                DEBUGA_SKYPE("We're NO MORE in a call now %s\n", SKYPIAX_P_LOG, (tech_pvt && tech_pvt->skype_call_id) ? tech_pvt->skype_call_id : "");
+                switch_mutex_unlock(globals.mutex);
+
+        } else {
+
+                /* we're owned, we're in a call, let's try to transfer */
+                /************************** TODO
+                 Checking here if it is possible to transfer this call to Test2
+                 -> GET CALL 288 CAN_TRANSFER Test2
+                 <- CALL 288 CAN_TRANSFER test2 TRUE
+                 **********************************/
+
+                private_t *available_skypiax_interface = NULL;
+
+                gettimeofday(&timenow, NULL);
+                for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                                giovatech = &globals.SKYPIAX_INTERFACES[i];
+                                //NOTICA("skype interface: %d, name: %s, state: %d, value=%s, giovatech->callid_number=%s, giovatech->skype_user=%s\n", SKYPIAX_P_LOG, i, giovatech->name, giovatech->interface_state, value, giovatech->callid_number, giovatech->skype_user);
+                                //FIXME check a timestamp here
+                                if (strlen(giovatech->skype_transfer_call_id) && (giovatech->interface_state != SKYPIAX_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->transfer_callid_number, value)) && ((((timenow.tv_sec - giovatech->transfer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->transfer_time.tv_usec)) < 1000000)) {        //1.0 sec
+                                        found = 1;
+                                        DEBUGA_SKYPE
+                                                ("FOUND (name=%s, giovatech->interface_state=%d != SKYPIAX_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->transfer_callid_number=%s == value=%s)\n",
+                                                 SKYPIAX_P_LOG, giovatech->name, giovatech->interface_state,
+                                                 giovatech->skype_user, tech_pvt->skype_user, giovatech->transfer_callid_number, value)
+                                                break;
+                                }
+                        }
+                }
+
+                if (found) {
+                        //tech_pvt->callid_number[0]='\0';
+                        //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                        //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                        switch_mutex_unlock(globals.mutex);
+                        return 0;
+                }
+                DEBUGA_SKYPE("NOT FOUND\n", SKYPIAX_P_LOG);
+
+                available_skypiax_interface = find_available_skypiax_interface_rr(tech_pvt);
+                if (available_skypiax_interface) {
+                        /* there is a skypiax interface idle, let's transfer the call to it */
+
+                        //FIXME write a timestamp here
+                        gettimeofday(&tech_pvt->transfer_time, NULL);
+                        switch_copy_string(tech_pvt->skype_transfer_call_id, id, sizeof(tech_pvt->skype_transfer_call_id) - 1);
+
+                        switch_copy_string(tech_pvt->transfer_callid_number, value, sizeof(tech_pvt->transfer_callid_number) - 1);
+
+                        DEBUGA_SKYPE
+                                ("Let's transfer the skype_call %s to %s interface (with skype_user: %s), because we are already in a skypiax call(%s)\n",
+                                 SKYPIAX_P_LOG, tech_pvt->skype_call_id, available_skypiax_interface->name, available_skypiax_interface->skype_user, id);
+
+                        //FIXME why this? the inbound call will come, eventually, on that other interface
+                        //available_skypiax_interface->ib_calls++;
+
+                        sprintf(msg_to_skype, "ALTER CALL %s TRANSFER %s", id, available_skypiax_interface->skype_user);
+                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                        if (tech_pvt->interface_state == SKYPIAX_STATE_SELECTED) {
+                                tech_pvt->interface_state = SKYPIAX_STATE_IDLE;        //we marked it SKYPIAX_STATE_SELECTED just in case it has to make an outbound call
+                        }
+                } else {
+                        /* no skypiax interfaces idle, do nothing */
+                        DEBUGA_SKYPE
+                                ("Not answering the skype_call %s, because we are already in a skypiax call(%s) and not transferring, because no other skypiax interfaces are available\n",
+                                 SKYPIAX_P_LOG, id, tech_pvt->skype_call_id);
+                        sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                }
+                switch_sleep(10000);
+                DEBUGA_SKYPE
+                        ("We have NOT answered a Skype RING from skype_call %s, because we are already in a skypiax call (%s)\n",
+                         SKYPIAX_P_LOG, id, tech_pvt->skype_call_id);
+
+                switch_mutex_unlock(globals.mutex);
+        }
+        return 0;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
</ins></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxmod_skypiaxso"></a>
<div class="addfile"><h4>Added: freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.so (0 => 14544)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.so         (rev 0)
+++ freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.so        2009-08-17 09:17:09 UTC (rev 14544)
</span><span class="lines">@@ -0,0 +1,129 @@
</span><ins>+#! /bin/sh
+
+# mod_skypiax.so - temporary wrapper script for .libs/mod_skypiax.so
+# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06)
+#
+# The mod_skypiax.so program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='/bin/sed -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /usr/src/freeswitch/src/mod/endpoints/mod_skypiax; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=\"/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin\"; export PATH; gcc -DSKYPIAX_SVN_VERSION=\\\"14534\\\" -I/usr/src/freeswitch/src/include -I/usr/src/freeswitch/libs/libteletone/src -fPIC -Werror -fvisibility=hidden -DSWITCH_API_VISIBILITY=1 -DHAVE_VISIBILITY=1 -g -ggdb -g -O2 -Wall -std=c99 -pedantic -D_GNU_SOURCE -shared -o \$progdir/\$file -shared -Wl,-x .libs/mod_skypiax.o skypiax_protocol.o -lm /usr/src/freeswitch/.libs/libfreeswitch.so -L/usr/src/freeswitch/libs/apr-util/xml/expat/lib /usr/src/freeswitch/libs/apr-util/xml/expat/lib/.libs/libexpat.a /usr/src/freeswitch/libs/apr/.libs/libapr-1.a -lrt -lcrypt -lpthread -L/usr/src/freeswitch/libs/srtp -L/usr/kerberos/lib64 -lssl -lcrypto -ldl -lz -lncurses -lX11 -Wl,--rpath -Wl,/usr/src/freeswitch/.libs -Wl,--rpath -Wl,/usr/local/freeswitch/lib -Wl,--rpath -Wl,/usr/local/freeswitch/mod ) "
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+ # install mode needs the following variable:
+ notinst_deplibs=' /usr/src/freeswitch/libfreeswitch.la'
+else
+ # When we are sourced in execute mode, $file and $echo are already set.
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ echo="echo"
+ file="$0"
+ # Make sure echo works.
+ if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec /bin/sh "$0" --no-reexec ${1+"$@"}
+ fi
+ fi
+
+ # Find the directory that this script lives in.
+ thisdir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "x$thisdir" = "x$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+ while test -n "$file"; do
+ destdir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+
+ # If there was a directory component, then change thisdir.
+ if test "x$destdir" != "x$file"; then
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+ *) thisdir="$thisdir/$destdir" ;;
+ esac
+ fi
+
+ file=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=`cd "$thisdir" && pwd`
+ test -n "$absdir" && thisdir="$absdir"
+
+ program=lt-'mod_skypiax.so'
+ progdir="$thisdir/.libs"
+
+ if test ! -f "$progdir/$program" || \
+ { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
+ test "X$file" != "X$progdir/$program"; }; then
+
+ file="$$-$program"
+
+ if test ! -d "$progdir"; then
+ mkdir "$progdir"
+ else
+ rm -f "$progdir/$file"
+ fi
+
+ # relink executable if necessary
+ if test -n "$relink_command"; then
+ if relink_command_output=`eval $relink_command 2>&1`; then :
+ else
+        echo "$relink_command_output" >&2
+        rm -f "$progdir/$file"
+        exit 1
+ fi
+ fi
+
+ mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+ { rm -f "$progdir/$program";
+ mv -f "$progdir/$file" "$progdir/$program"; }
+ rm -f "$progdir/$file"
+ fi
+
+ if test -f "$progdir/$program"; then
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ # Run the actual program with our arguments.
+
+ exec "$progdir/$program" ${1+"$@"}
+
+ $echo "$0: cannot exec $program $*"
+ exit 1
+ fi
+ else
+ # The program doesn't exist.
+ $echo "$0: error: \`$progdir/$program' does not exist" 1>&2
+ $echo "This script is just a wrapper for $program." 1>&2
+ echo "See the libtool documentation for more information." 1>&2
+ exit 1
+ fi
+fi
</ins><span class="cx">Property changes on: freeswitch/branches/gmaruzz/mod_celliax/mod_skypiax.so
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:executable
</span><span class="cx"> + *
</span></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxskypiaxh"></a>
<div class="addfile"><h4>Added: freeswitch/branches/gmaruzz/mod_celliax/skypiax.h (0 => 14544)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/skypiax.h         (rev 0)
+++ freeswitch/branches/gmaruzz/mod_celliax/skypiax.h        2009-08-17 09:17:09 UTC (rev 14544)
</span><span class="lines">@@ -0,0 +1,291 @@
</span><ins>+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * This module (mod_skypiax) has been contributed by:
+ *
+ * Giovanni Maruzzelli (gmaruzz@gmail.com)
+ *
+ *
+ * Further Contributors:
+ *
+ *
+ *
+ * mod_skypiax.c -- Skype compatible Endpoint Module
+ *
+ */
+
+#include <switch.h>
+#include <switch_version.h>
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#include <X11/Xatom.h>
+#endif //WIN32
+
+#ifdef _MSC_VER
+//Windows macro for FD_SET includes a warning C4127: conditional expression is constant
+#pragma warning(push)
+#pragma warning(disable:4127)
+#endif
+
+#define SAMPLERATE_SKYPIAX 16000
+#define SAMPLES_PER_FRAME SAMPLERATE_SKYPIAX/50
+
+#ifndef SKYPIAX_SVN_VERSION
+#define SKYPIAX_SVN_VERSION SWITCH_VERSION_REVISION
+#endif /* SKYPIAX_SVN_VERSION */
+
+typedef enum {
+        TFLAG_IO = (1 << 0),
+        TFLAG_INBOUND = (1 << 1),
+        TFLAG_OUTBOUND = (1 << 2),
+        TFLAG_DTMF = (1 << 3),
+        TFLAG_VOICE = (1 << 4),
+        TFLAG_HANGUP = (1 << 5),
+        TFLAG_LINEAR = (1 << 6),
+        TFLAG_CODEC = (1 << 7),
+        TFLAG_BREAK = (1 << 8)
+} TFLAGS;
+
+typedef enum {
+        GFLAG_MY_CODEC_PREFS = (1 << 0)
+} GFLAGS;
+
+#define DEBUGA_SKYPE(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_SKYPE %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_CALL(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_CALL %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_PBX(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_PBX %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define ERRORA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][ERRORA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define WARNINGA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][WARNINGA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define NOTICA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,                 "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][NOTICA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+
+#define SKYPIAX_P_LOG NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt->name ? tech_pvt->name : "none" : "none", -1, tech_pvt ? tech_pvt->interface_state : -1, tech_pvt ? tech_pvt->skype_callflow : -1
+
+/*********************************/
+#define SKYPIAX_CAUSE_NORMAL                1
+/*********************************/
+#define SKYPIAX_FRAME_DTMF                        1
+/*********************************/
+#define SKYPIAX_CONTROL_RINGING                1
+#define SKYPIAX_CONTROL_ANSWER                2
+
+/*********************************/
+#define                SKYPIAX_STATE_IDLE                                        0
+#define                SKYPIAX_STATE_DOWN                                        1
+#define                SKYPIAX_STATE_RING                                        2
+#define                SKYPIAX_STATE_DIALING                                3
+#define                SKYPIAX_STATE_BUSY                                        4
+#define                SKYPIAX_STATE_UP                                        5
+#define                SKYPIAX_STATE_RINGING                                6
+#define                SKYPIAX_STATE_PRERING                                7
+#define                SKYPIAX_STATE_ERROR_DOUBLE_CALL                8
+#define                SKYPIAX_STATE_SELECTED                                9
+#define         SKYPIAX_STATE_HANGUP_REQUESTED                10
+#define                SKYPIAX_STATE_PREANSWER                                11
+/*********************************/
+/* call flow from the device */
+#define         CALLFLOW_CALL_IDLE                                        0
+#define         CALLFLOW_CALL_DOWN                                        1
+#define         CALLFLOW_INCOMING_RING                                2
+#define         CALLFLOW_CALL_DIALING                                3
+#define         CALLFLOW_CALL_LINEBUSY                                4
+#define         CALLFLOW_CALL_ACTIVE                                5
+#define         CALLFLOW_INCOMING_HANGUP                        6
+#define         CALLFLOW_CALL_RELEASED                                7
+#define         CALLFLOW_CALL_NOCARRIER                                8
+#define         CALLFLOW_CALL_INFLUX                                9
+#define         CALLFLOW_CALL_INCOMING                                10
+#define         CALLFLOW_CALL_FAILED                                11
+#define         CALLFLOW_CALL_NOSERVICE                                12
+#define         CALLFLOW_CALL_OUTGOINGRESTRICTED        13
+#define         CALLFLOW_CALL_SECURITYFAIL                        14
+#define         CALLFLOW_CALL_NOANSWER                                15
+#define         CALLFLOW_STATUS_FINISHED                        16
+#define         CALLFLOW_STATUS_CANCELLED                        17
+#define         CALLFLOW_STATUS_FAILED                                18
+#define         CALLFLOW_STATUS_REFUSED                                19
+#define         CALLFLOW_STATUS_RINGING                                20
+#define         CALLFLOW_STATUS_INPROGRESS                        21
+#define         CALLFLOW_STATUS_UNPLACED                        22
+#define         CALLFLOW_STATUS_ROUTING                                23
+#define         CALLFLOW_STATUS_EARLYMEDIA                        24
+#define         CALLFLOW_INCOMING_CALLID                        25
+#define         CALLFLOW_STATUS_REMOTEHOLD                        26
+
+/*********************************/
+
+#define SKYPIAX_MAX_INTERFACES 64
+
+#ifndef WIN32
+struct SkypiaxHandles {
+        Window skype_win;
+        Display *disp;
+        Window win;
+        int currentuserhandle;
+        int api_connected;
+        int fdesc[2];
+};
+#else //WIN32
+
+struct SkypiaxHandles {
+        HWND win32_hInit_MainWindowHandle;
+        HWND win32_hGlobal_SkypeAPIWindowHandle;
+        HINSTANCE win32_hInit_ProcessHandle;
+        char win32_acInit_WindowClassName[128];
+        UINT win32_uiGlobal_MsgID_SkypeControlAPIAttach;
+        UINT win32_uiGlobal_MsgID_SkypeControlAPIDiscover;
+        int currentuserhandle;
+        int api_connected;
+        switch_file_t *fdesc[2];
+};
+
+#endif //WIN32
+
+struct private_object {
+        unsigned int flags;
+        switch_codec_t read_codec;
+        switch_codec_t write_codec;
+        switch_frame_t read_frame;
+        unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+        char session_uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+        switch_caller_profile_t *caller_profile;
+        switch_mutex_t *mutex;
+        switch_mutex_t *flag_mutex;
+
+        char interface_id[80];
+        char name[80];
+        char dialplan[80];
+        char context[80];
+        char dial_regex[256];
+        char fail_dial_regex[256];
+        char hold_music[256];
+        char type[256];
+        char X11_display[256];
+#ifdef WIN32
+        unsigned short tcp_cli_port;
+        unsigned short tcp_srv_port;
+#else
+        int tcp_cli_port;
+        int tcp_srv_port;
+#endif
+        struct SkypiaxHandles SkypiaxHandles;
+
+        int interface_state;                /*!< \brief 'state' of the interface (channel) */
+        char language[80];                        /*!< \brief default Asterisk dialplan language for this interface */
+        char exten[80];                                /*!< \brief default Asterisk dialplan extension for this interface */
+        int skypiax_sound_rate;                /*!< \brief rate of the sound device, in Hz, eg: 8000 */
+        char callid_name[50];
+        char callid_number[50];
+        double playback_boost;
+        double capture_boost;
+        int stripmsd;
+        char skype_call_id[512];
+        int skype_call_ongoing;
+        char skype_friends[4096];
+        char skype_fullname[512];
+        char skype_displayname[512];
+        int skype_callflow;                        /*!< \brief 'callflow' of the skype interface (as opposed to phone interface) */
+        int skype;                                        /*!< \brief config flag, bool, Skype support on this interface (0 if false, -1 if true) */
+        int control_to_send;
+#ifdef WIN32
+        switch_file_t *audiopipe[2];
+        switch_file_t *audioskypepipe[2];
+        switch_file_t *skypiax_sound_capt_fd;        /*!< \brief file descriptor for sound capture dev */
+#else                                                        /* WIN32 */
+        int audiopipe[2];
+        int audioskypepipe[2];
+        int skypiax_sound_capt_fd;        /*!< \brief file descriptor for sound capture dev */
+#endif                                                        /* WIN32 */
+        switch_thread_t *tcp_srv_thread;
+        switch_thread_t *tcp_cli_thread;
+        switch_thread_t *skypiax_signaling_thread;
+        switch_thread_t *skypiax_api_thread;
+        short audiobuf[SAMPLES_PER_FRAME];
+        int audiobuf_is_loaded;
+
+        //int phonebook_listing;
+        //int phonebook_querying;
+        //int phonebook_listing_received_calls;
+
+        //int phonebook_first_entry;
+        //int phonebook_last_entry;
+        //int phonebook_number_lenght;
+        //int phonebook_text_lenght;
+        FILE *phonebook_writing_fp;
+        int skypiax_dir_entry_extension_prefix;
+        char skype_user[256];
+        char skype_password[256];
+        char destination[256];
+        struct timeval answer_time;
+
+        struct timeval transfer_time;
+        char transfer_callid_number[50];
+        char skype_transfer_call_id[512];
+        int running;
+        unsigned long ib_calls;
+        unsigned long ob_calls;
+        unsigned long ib_failed_calls;
+        unsigned long ob_failed_calls;
+};
+
+typedef struct private_object private_t;
+
+void *SWITCH_THREAD_FUNC skypiax_api_thread_func(switch_thread_t * thread, void *obj);
+int skypiax_audio_read(private_t * tech_pvt);
+int skypiax_audio_init(private_t * tech_pvt);
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype);
+int skypiax_signaling_read(private_t * tech_pvt);
+
+int skypiax_call(private_t * tech_pvt, char *idest, int timeout);
+int skypiax_senddigit(private_t * tech_pvt, char digit);
+
+void *skypiax_do_tcp_srv_thread_func(void *obj);
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_srv_thread(switch_thread_t * thread, void *obj);
+
+void *skypiax_do_tcp_cli_thread_func(void *obj);
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_cli_thread(switch_thread_t * thread, void *obj);
+
+void *skypiax_do_skypeapi_thread_func(void *obj);
+void *SWITCH_THREAD_FUNC skypiax_do_skypeapi_thread(switch_thread_t * thread, void *obj);
+int dtmf_received(private_t * tech_pvt, char *value);
+int start_audio_threads(private_t * tech_pvt);
+int new_inbound_channel(private_t * tech_pvt);
+int outbound_channel_answered(private_t * tech_pvt);
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype);
+#if defined(WIN32) && !defined(__CYGWIN__)
+int skypiax_pipe_read(switch_file_t * pipe, short *buf, int howmany);
+int skypiax_pipe_write(switch_file_t * pipe, short *buf, int howmany);
+/* Visual C do not have strsep ? */
+char *strsep(char **stringp, const char *delim);
+#else
+int skypiax_pipe_read(int pipe, short *buf, int howmany);
+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_rr(private_t * tech_pvt_calling);
+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);
+int skypiax_transfer(private_t * tech_pvt, char *id, char *value);
+int skypiax_socket_create_and_bind(private_t * tech_pvt, int *which_port);
</ins></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxskypiax_protocolc"></a>
<div class="addfile"><h4>Added: freeswitch/branches/gmaruzz/mod_celliax/skypiax_protocol.c (0 => 14544)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/skypiax_protocol.c         (rev 0)
+++ freeswitch/branches/gmaruzz/mod_celliax/skypiax_protocol.c        2009-08-17 09:17:09 UTC (rev 14544)
</span><span class="lines">@@ -0,0 +1,1548 @@
</span><ins>+#include "skypiax.h"
+
+#ifdef ASTERISK
+#define skypiax_sleep usleep
+#define skypiax_strncpy strncpy
+#define tech_pvt p
+extern int skypiax_debug;
+extern char *skypiax_console_active;
+#else /* FREESWITCH */
+#define skypiax_sleep switch_sleep
+#define skypiax_strncpy switch_copy_string
+extern switch_memory_pool_t *skypiax_module_pool;
+extern switch_endpoint_interface_t *skypiax_endpoint_interface;
+#endif /* ASTERISK */
+int samplerate_skypiax = SAMPLERATE_SKYPIAX;
+
+extern int running;
+
+/*************************************/
+/* suspicious globals FIXME */
+#ifdef WIN32
+DWORD win32_dwThreadId;
+#else
+XErrorHandler old_handler = 0;
+int xerror = 0;
+#endif /* WIN32 */
+/*************************************/
+
+int skypiax_socket_create_and_bind(private_t * tech_pvt, int *which_port)
+{
+        int s = -1;
+        struct sockaddr_in my_addr;
+        int start_port = 6001;
+
+        memset(&my_addr, 0, sizeof(my_addr));
+        my_addr.sin_family = AF_INET;
+        my_addr.sin_addr.s_addr = htonl(0x7f000001);        /* use the localhost */
+
+        if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+                ERRORA("socket Error\n", SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        if (*which_port != 0)
+                start_port = *which_port;
+
+        my_addr.sin_port = htons(start_port);
+        //tech_pvt->tcp_cli_port = start_port;
+        *which_port = start_port;
+        while (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) {
+                DEBUGA_SKYPE("*which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port,
+                                         tech_pvt->tcp_srv_port);
+                DEBUGA_SKYPE("bind errno=%d, error: %s\n", SKYPIAX_P_LOG, errno, strerror(errno));
+                start_port++;
+                my_addr.sin_port = htons(start_port);
+                *which_port = start_port;
+                DEBUGA_SKYPE("*which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port,
+                                         tech_pvt->tcp_srv_port);
+
+                if (start_port > 65000) {
+                        ERRORA("NO MORE PORTS! *which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port,
+                                 tech_pvt->tcp_cli_port, tech_pvt->tcp_srv_port);
+                        return -1;
+                }
+        }
+
+        DEBUGA_SKYPE("SUCCESS! *which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port,
+                                 tech_pvt->tcp_srv_port);
+        return s;
+}
+
+int skypiax_signaling_read(private_t * tech_pvt)
+{
+        char read_from_pipe[4096];
+        char message[4096];
+        char message_2[4096];
+        char *buf, obj[512] = "", id[512] = "", prop[512] = "", value[512] = "", *where;
+        char **stringp = NULL;
+        int a;
+        unsigned int howmany;
+        unsigned int i;
+
+        memset(read_from_pipe, 0, 4096);
+        memset(message, 0, 4096);
+        memset(message_2, 0, 4096);
+
+        howmany = skypiax_pipe_read(tech_pvt->SkypiaxHandles.fdesc[0], (short *) read_from_pipe, sizeof(read_from_pipe));
+
+        a = 0;
+        for (i = 0; i < howmany; i++) {
+                message[a] = read_from_pipe[i];
+                a++;
+
+                if (read_from_pipe[i] == '\0') {
+
+                        //if (!strstr(message, "DURATION")) {
+                        DEBUGA_SKYPE("READING: |||%s||| \n", SKYPIAX_P_LOG, message);
+                        //}
+
+                        if (!strcasecmp(message, "ERROR 68")) {
+                                DEBUGA_SKYPE
+                                        ("If I don't connect immediately, please give the Skype client authorization to be connected by Skypiax (and to not ask you again)\n",
+                                         SKYPIAX_P_LOG);
+                                skypiax_sleep(1000000);
+                                skypiax_signaling_write(tech_pvt, "PROTOCOL 7");
+                                skypiax_sleep(10000);
+                                return 0;
+                        }
+                        if (!strncasecmp(message, "ERROR 92 CALL", 12)) {
+                                ERRORA("Skype got ERROR: |||%s|||, the (skypeout) number we called was not recognized as valid\n", SKYPIAX_P_LOG, message);
+                                tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG);
+                                tech_pvt->skype_call_id[0] = '\0';
+
+                                if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                        return CALLFLOW_INCOMING_HANGUP;
+                                } else {
+                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                }
+                        }
+
+                        if (!strncasecmp(message, "ERROR", 4)) {
+                                if (!strncasecmp(message, "ERROR 96 CALL", 12)) {
+                                        DEBUGA_SKYPE
+                                                ("Skype got ERROR: |||%s|||, we are trying to use this interface to make or receive a call, but another call is half-active on this interface. Let's the previous one to continue.\n",
+                                                 SKYPIAX_P_LOG, message);
+                                } else if (!strncasecmp(message, "ERROR 99 CALL", 12)) {
+                                        ERRORA("Skype got ERROR: |||%s|||, another call is active on this interface\n\n\n", SKYPIAX_P_LOG, message);
+                                        tech_pvt->interface_state = SKYPIAX_STATE_ERROR_DOUBLE_CALL;
+                                } else if (!strncasecmp(message, "ERROR 592 ALTER CALL", 19)) {
+                                        ERRORA("Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n", SKYPIAX_P_LOG, message);
+                                } else if (!strncasecmp(message, "ERROR 559 CALL", 13)) {
+                                        DEBUGA_SKYPE("Skype got ERROR about a failed action (probably TRYING to HANGUP A CALL), no problem: |||%s|||\n", SKYPIAX_P_LOG,
+                                                                 message);
+                                } else {
+                                        ERRORA("Skype got ERROR: |||%s|||\n", SKYPIAX_P_LOG, message);
+                                        tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                        ERRORA("skype_call now is DOWN\n", SKYPIAX_P_LOG);
+                                        tech_pvt->skype_call_id[0] = '\0';
+
+                                        if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else {
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                        }
+                                }
+                        }
+
+
+
+
+                        skypiax_strncpy(message_2, message, sizeof(message) - 1);
+                        buf = message;
+                        stringp = &buf;
+                        where = strsep(stringp, " ");
+                        if (!where) {
+                                WARNINGA("Skype MSG without spaces: %s\n", SKYPIAX_P_LOG, message);
+                        }
+
+
+
+
+
+
+
+
+                        if (!strcasecmp(message, "CURRENTUSERHANDLE")) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                if (!strcasecmp(id, tech_pvt->skype_user)) {
+                                        tech_pvt->SkypiaxHandles.currentuserhandle = 1;
+                                        DEBUGA_SKYPE
+                                                ("Skype MSG: message: %s, currentuserhandle: %s, cuh: %s, skype_user: %s!\n",
+                                                 SKYPIAX_P_LOG, message, obj, id, tech_pvt->skype_user);
+                                }
+                        }
+                        if (!strcasecmp(message, "USER")) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                if (!strcasecmp(prop, "RECEIVEDAUTHREQUEST")) {
+                                        char msg_to_skype[256];
+                                        DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", SKYPIAX_P_LOG, message, obj, id, prop);
+                                        //TODO: allow authorization based on config param
+                                        sprintf(msg_to_skype, "SET USER %s ISAUTHORIZED TRUE", id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                }
+                        }
+                        if (!strcasecmp(message, "MESSAGE")) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                if (!strcasecmp(prop, "STATUS")) {
+                                        where = strsep(stringp, " ");
+                                        skypiax_strncpy(value, where, sizeof(value) - 1);
+                                        if (!strcasecmp(value, "RECEIVED")) {
+                                                char msg_to_skype[256];
+                                                DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s value: %s!\n", SKYPIAX_P_LOG, message, obj, id, prop, value);
+                                                //TODO: authomatically flag messages as read based on config param
+                                                sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                        }
+                                } else if (!strcasecmp(prop, "BODY")) {
+                                        char msg_to_skype[256];
+                                        DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", SKYPIAX_P_LOG, message, obj, id, prop);
+                                        //TODO: authomatically flag messages as read based on config param
+                                        sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                }
+                        }
+                        if (!strcasecmp(message, "CALL")) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                where = strsep(stringp, " ");
+                                skypiax_strncpy(value, where, sizeof(value) - 1);
+                                where = strsep(stringp, " ");
+
+                                //DEBUGA_SKYPE
+                                //("Skype MSG: message: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n",
+                                //SKYPIAX_P_LOG, message, obj, id, prop, value, where ? where : "NULL");
+
+                                if (!strcasecmp(prop, "PARTNER_HANDLE")) {
+                                        if (tech_pvt->interface_state != SKYPIAX_STATE_SELECTED && (!strlen(tech_pvt->skype_call_id) || !strlen(tech_pvt->session_uuid_str))) {
+                                                //if (!strlen(tech_pvt->skype_call_id)) {
+                                                /* we are NOT inside an active call */
+                                                DEBUGA_SKYPE("Call %s TRY ANSWER\n", SKYPIAX_P_LOG, id);
+                                                skypiax_answer(tech_pvt, id, value);
+                                        } else {
+                                                /* we are inside an active call */
+                                                if (!strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                        /* this is the call in which we are calling out */
+                                                        DEBUGA_SKYPE("Call %s DO NOTHING\n", SKYPIAX_P_LOG, id);
+                                                } else {
+                                                        skypiax_sleep(400000);        //0.4 seconds
+                                                        DEBUGA_SKYPE("Call %s TRY TRANSFER\n", SKYPIAX_P_LOG, id);
+                                                        skypiax_transfer(tech_pvt, id, value);
+                                                }
+                                        }
+                                }
+                                if (!strcasecmp(prop, "PARTNER_DISPNAME")) {
+                                        snprintf(tech_pvt->callid_name, sizeof(tech_pvt->callid_name) - 1, "%s%s%s", value, where ? " " : "", where ? where : "");
+                                        //DEBUGA_SKYPE
+                                        //("the skype_call %s caller PARTNER_DISPNAME (tech_pvt->callid_name) is: %s\n",
+                                        //SKYPIAX_P_LOG, id, tech_pvt->callid_name);
+                                }
+                                if (!strcasecmp(prop, "CONF_ID") && !strcasecmp(value, "0")) {
+                                        //DEBUGA_SKYPE("the skype_call %s is NOT a conference call\n", SKYPIAX_P_LOG, id);
+                                        //if (tech_pvt->interface_state == SKYPIAX_STATE_DOWN)
+                                        //tech_pvt->interface_state = SKYPIAX_STATE_PRERING;
+                                }
+                                if (!strcasecmp(prop, "CONF_ID") && strcasecmp(value, "0")) {
+                                        DEBUGA_SKYPE("the skype_call %s is a conference call\n", SKYPIAX_P_LOG, id);
+                                        //if (tech_pvt->interface_state == SKYPIAX_STATE_DOWN)
+                                        //tech_pvt->interface_state = SKYPIAX_STATE_PRERING;
+                                }
+                                if (!strcasecmp(prop, "DTMF")) {
+                                        DEBUGA_SKYPE("Call %s received a DTMF: %s\n", SKYPIAX_P_LOG, id, value);
+                                        dtmf_received(tech_pvt, value);
+                                }
+                                if (!strcasecmp(prop, "FAILUREREASON")) {
+                                        DEBUGA_SKYPE("Skype FAILED on skype_call %s. Let's wait for the FAILED message.\n", SKYPIAX_P_LOG, id);
+                                }
+                                if (!strcasecmp(prop, "DURATION") && (!strcasecmp(value, "1"))) {
+                                        if (strcasecmp(id, tech_pvt->skype_call_id)) {
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                DEBUGA_SKYPE("We called a Skype contact and he answered us on skype_call: %s.\n", SKYPIAX_P_LOG, id);
+                                        }
+                                }
+
+                                if (!strcasecmp(prop, "DURATION") && (tech_pvt->interface_state == SKYPIAX_STATE_ERROR_DOUBLE_CALL)) {
+                                        char msg_to_skype[1024];
+                                        skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                        ERRORA("We are in a double call situation, trying to get out hanging up call id: %s.\n", SKYPIAX_P_LOG, id);
+                                        sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                        skypiax_sleep(10000);
+                                        //return CALLFLOW_INCOMING_HANGUP;
+                                }
+
+                                if (!strcasecmp(prop, "STATUS")) {
+
+                                        if (!strcasecmp(value, "RINGING")) {
+                                                char msg_to_skype[1024];
+                                                if ((tech_pvt->interface_state != SKYPIAX_STATE_SELECTED && tech_pvt->interface_state != SKYPIAX_STATE_DIALING)
+                                                        && (!strlen(tech_pvt->skype_call_id) || !strlen(tech_pvt->session_uuid_str))) {
+                                                        /* we are NOT inside an active call */
+
+                                                        DEBUGA_SKYPE("NO ACTIVE calls in this moment, skype_call %s is RINGING, to ask PARTNER_HANDLE\n", SKYPIAX_P_LOG, id);
+                                                        sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id);
+                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                        skypiax_sleep(10000);
+                                                } else {
+                                                        /* we are inside an active call */
+                                                        if (!strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                                /* this is the call in which we are calling out */
+                                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_RINGING;
+                                                                tech_pvt->interface_state = SKYPIAX_STATE_RINGING;
+                                                                skypiax_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", SKYPIAX_P_LOG, id);
+                                                                remote_party_is_ringing(tech_pvt);
+                                                        } 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",
+                                                                         SKYPIAX_P_LOG, id);
+                                                                sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id);
+                                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                skypiax_sleep(10000);
+                                                        }
+                                                }
+                                        } else if (!strcasecmp(value, "EARLYMEDIA")) {
+                                                char msg_to_skype[1024];
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_EARLYMEDIA;
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DIALING;
+                                                DEBUGA_SKYPE("Our remote party in skype_call %s is EARLYMEDIA\n", SKYPIAX_P_LOG, id);
+                                                if (start_audio_threads(tech_pvt)) {
+                                                        ERRORA("start_audio_threads FAILED\n", SKYPIAX_P_LOG);
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                }
+                                                skypiax_sleep(1000);
+                                                sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                sprintf(msg_to_skype, "#output ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+
+                                                remote_party_is_early_media(tech_pvt);
+                                        } else if (!strcasecmp(value, "MISSED")) {
+                                                DEBUGA_SKYPE("We missed skype_call %s\n", SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, "FINISHED")) {
+                                                //DEBUGA_SKYPE("skype_call %s now is DOWN\n", SKYPIAX_P_LOG, id);
+                                                if (!strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                        //tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                                        DEBUGA_SKYPE("skype_call %s is MY call, now I'm going DOWN\n", SKYPIAX_P_LOG, id);
+                                                        //tech_pvt->skype_call_id[0] = '\0';
+                                                        if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                                //tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                                return CALLFLOW_INCOMING_HANGUP;
+                                                        } else {
+                                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                        }
+                                                } else {
+                                                        DEBUGA_SKYPE("skype_call %s is NOT MY call, ignoring\n", SKYPIAX_P_LOG, id);
+                                                }
+
+                                        } else if (!strcasecmp(value, "CANCELLED")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_CANCELLED;
+                                                DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now CANCELLED\n", SKYPIAX_P_LOG, id);
+                                                tech_pvt->skype_call_id[0] = '\0';
+                                                if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                } else {
+                                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                }
+                                        } else if (!strcasecmp(value, "FAILED")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now FAILED\n", SKYPIAX_P_LOG, id);
+                                                tech_pvt->skype_call_id[0] = '\0';
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else if (!strcasecmp(value, "REFUSED")) {
+                                                if (!strcasecmp(id, tech_pvt->skype_call_id)) {
+                                                        /* this is the id of the call we are in, probably we generated it */
+                                                        tech_pvt->skype_callflow = CALLFLOW_STATUS_REFUSED;
+                                                        DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now REFUSED\n", SKYPIAX_P_LOG, id);
+                                                        skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                        tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                        tech_pvt->skype_call_id[0] = '\0';
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                } else {
+                                                        /* we're here because were us that refused an incoming call */
+                                                        DEBUGA_SKYPE("we REFUSED skype_call %s\n", SKYPIAX_P_LOG, id);
+                                                }
+                                        } else if (!strcasecmp(value, "TRANSFERRING")) {
+                                                DEBUGA_SKYPE("skype_call %s is transferring\n", SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, "TRANSFERRED")) {
+                                                DEBUGA_SKYPE("skype_call %s has been transferred\n", SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, "ROUTING")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_ROUTING;
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DIALING;
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                DEBUGA_SKYPE("skype_call: %s is now ROUTING\n", SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, "UNPLACED")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_UNPLACED;
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DIALING;
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                DEBUGA_SKYPE("skype_call: %s is now UNPLACED\n", SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, "INPROGRESS")) {
+                                                char msg_to_skype[1024];
+
+                                                if (!strlen(tech_pvt->session_uuid_str)) {
+                                                        DEBUGA_SKYPE("no tech_pvt->session_uuid_str\n", SKYPIAX_P_LOG);
+                                                }
+                                                if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                        if (!strlen(tech_pvt->session_uuid_str) || !strlen(tech_pvt->skype_call_id)
+                                                                || !strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                                DEBUGA_SKYPE("skype_call: %s is now active\n", SKYPIAX_P_LOG, id);
+
+                                                                if (tech_pvt->skype_callflow != CALLFLOW_STATUS_EARLYMEDIA) {
+                                                                        tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                                        tech_pvt->interface_state = SKYPIAX_STATE_UP;
+
+                                                                        if (start_audio_threads(tech_pvt)) {
+                                                                                ERRORA("start_audio_threads FAILED\n", SKYPIAX_P_LOG);
+                                                                                return CALLFLOW_INCOMING_HANGUP;
+                                                                        }
+                                                                        skypiax_sleep(1000);        //FIXME
+                                                                        sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port);
+                                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                        skypiax_sleep(1000);        //FIXME
+                                                                        sprintf(msg_to_skype, "#output ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port);
+                                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                }
+                                                                tech_pvt->skype_callflow = SKYPIAX_STATE_UP;
+                                                                if (!strlen(tech_pvt->session_uuid_str)) {
+                                                                        DEBUGA_SKYPE("New Inbound Channel!\n\n\n\n", SKYPIAX_P_LOG);
+                                                                        new_inbound_channel(tech_pvt);
+                                                                } else {
+                                                                        DEBUGA_SKYPE("Outbound Channel Answered! session_uuid_str=%s\n", SKYPIAX_P_LOG, tech_pvt->session_uuid_str);
+                                                                        outbound_channel_answered(tech_pvt);
+                                                                }
+                                                        } else {
+                                                                DEBUGA_SKYPE("I'm on %s, skype_call %s is NOT MY call, ignoring\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id, id);
+                                                        }
+                                                } else {
+                                                        tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                        DEBUGA_SKYPE("Back from REMOTEHOLD!\n", SKYPIAX_P_LOG);
+                                                }
+
+                                        } else if (!strcasecmp(value, "REMOTEHOLD")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_REMOTEHOLD;
+                                                DEBUGA_SKYPE("skype_call: %s is now REMOTEHOLD\n", SKYPIAX_P_LOG, id);
+
+                                        } else if (!strcasecmp(value, "BUSY")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE
+                                                        ("we tried to call Skype on skype_call %s and remote party (destination) was BUSY. Our outbound call has failed\n",
+                                                         SKYPIAX_P_LOG, id);
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                tech_pvt->skype_call_id[0] = '\0';
+                                                skypiax_sleep(1000);
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else if (!strcasecmp(value, "WAITING_REDIAL_COMMAND")) {
+                                                tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE
+                                                        ("we tried to call Skype on skype_call %s and remote party (destination) has rejected us (WAITING_REDIAL_COMMAND). Our outbound call has failed\n",
+                                                         SKYPIAX_P_LOG, id);
+                                                skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                tech_pvt->skype_call_id[0] = '\0';
+                                                skypiax_sleep(1000);
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else {
+                                                WARNINGA("skype_call: %s, STATUS: %s is not recognized\n", SKYPIAX_P_LOG, id, value);
+                                        }
+                                }                                //STATUS
+                        }                                        //CALL
+                        /* the "numbered" messages that follows are used by the directory application, not yet ported */
+                        if (!strcasecmp(message, "#333")) {
+                                /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[11]: %s\n", SKYPIAX_P_LOG,
+                                 * message_2, &message_2[11]); */
+                                memset(tech_pvt->skype_friends, 0, 4096);
+                                skypiax_strncpy(tech_pvt->skype_friends, &message_2[11], 4095);
+                        }
+                        if (!strcasecmp(message, "#222")) {
+                                /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[10]: %s\n", SKYPIAX_P_LOG,
+                                 * message_2, &message_2[10]); */
+                                memset(tech_pvt->skype_fullname, 0, 512);
+                                skypiax_strncpy(tech_pvt->skype_fullname, &message_2[10], 511);
+                        }
+                        if (!strcasecmp(message, "#765")) {
+                                /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[10]: %s\n", SKYPIAX_P_LOG,
+                                 * message_2, &message_2[10]); */
+                                memset(tech_pvt->skype_displayname, 0, 512);
+                                skypiax_strncpy(tech_pvt->skype_displayname, &message_2[10], 511);
+                        }
+                        a = 0;
+                }                                                //message end
+        }                                                        //read_from_pipe
+        return 0;
+}
+
+void *skypiax_do_tcp_srv_thread_func(void *obj)
+{
+        private_t *tech_pvt = obj;
+        int s;
+        unsigned int len;
+        unsigned int i;
+        unsigned int a;
+#if defined(WIN32) && !defined(__CYGWIN__)
+        int sin_size;
+#else /* WIN32 */
+        unsigned int sin_size;
+#endif /* WIN32 */
+        unsigned int fd;
+        short srv_in[SAMPLES_PER_FRAME];
+        short srv_out[SAMPLES_PER_FRAME / 2];
+        //struct sockaddr_in my_addr;
+        struct sockaddr_in remote_addr;
+        //int exit = 0;
+        unsigned int kill_cli_size;
+        short kill_cli_buff[SAMPLES_PER_FRAME];
+        short totalbuf[SAMPLES_PER_FRAME];
+
+        s = skypiax_socket_create_and_bind(tech_pvt, &tech_pvt->tcp_srv_port);
+        if (s < 0) {
+                ERRORA("skypiax_socket_create_and_bind error!\n", SKYPIAX_P_LOG);
+                return NULL;
+        }
+        DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+
+        listen(s, 6);
+
+        sin_size = sizeof(remote_addr);
+
+ /****************************/
+        while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                 && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                         || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                         || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+
+                unsigned int fdselectgio;
+                int rtgio;
+                fd_set fsgio;
+                struct timeval togio;
+
+                if (!(running && tech_pvt->running))
+                        break;
+                FD_ZERO(&fsgio);
+                togio.tv_usec = 20000;        //20msec
+                togio.tv_sec = 0;
+                fdselectgio = s;
+                FD_SET(fdselectgio, &fsgio);
+
+                rtgio = select(fdselectgio + 1, &fsgio, NULL, NULL, &togio);
+
+                if (rtgio) {
+
+ /****************************/
+
+                        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 && tech_pvt->running))
+                                        break;
+                                while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                                         && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                                                 || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                                                 || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+
+                                        unsigned int fdselect;
+                                        int rt;
+                                        fd_set fs;
+                                        struct timeval to;
+
+                                        if (!(running && tech_pvt->running))
+                                                break;
+                                        //exit = 1;
+
+                                        fdselect = fd;
+                                        FD_ZERO(&fs);
+                                        FD_SET(fdselect, &fs);
+                                        //to.tv_usec = 2000000; //2000 msec
+                                        to.tv_usec = 60000;        //60 msec
+                                        to.tv_sec = 0;
+
+                                        rt = select(fdselect + 1, &fs, NULL, NULL, &to);
+                                        if (rt > 0) {
+
+                                                if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                        len = recv(fd, (char *) srv_in, 320, 0);        //seems that Skype only sends 320 bytes at time
+                                                } else {
+                                                        len = 0;
+                                                }
+
+                                                if (len == 320) {
+                                                        unsigned int howmany;
+
+                                                        if (samplerate_skypiax == 8000) {
+                                                                /* we're downsampling from 16khz to 8khz, srv_out will contain each other sample from srv_in */
+                                                                a = 0;
+                                                                for (i = 0; i < len / sizeof(short); i++) {
+                                                                        srv_out[a] = srv_in[i];
+                                                                        i++;
+                                                                        a++;
+                                                                }
+                                                        } else if (samplerate_skypiax == 16000) {
+                                                                /* we're NOT downsampling, srv_out will contain ALL samples from srv_in */
+                                                                for (i = 0; i < len / sizeof(short); i++) {
+                                                                        srv_out[i] = srv_in[i];
+                                                                }
+                                                        } else {
+                                                                ERRORA("SAMPLERATE_SKYPIAX can only be 8000 or 16000\n", SKYPIAX_P_LOG);
+                                                        }
+                                                        /* if not yet done, let's store the half incoming frame */
+                                                        if (!tech_pvt->audiobuf_is_loaded) {
+                                                                for (i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
+                                                                        tech_pvt->audiobuf[i] = srv_out[i];
+                                                                }
+                                                                tech_pvt->audiobuf_is_loaded = 1;
+                                                        } else {
+                                                                /* we got a stored half frame, build a complete frame in totalbuf using the stored half frame and the current half frame */
+                                                                for (i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
+                                                                        totalbuf[i] = tech_pvt->audiobuf[i];
+                                                                }
+                                                                for (a = 0; a < SAMPLES_PER_FRAME / 2; a++) {
+                                                                        totalbuf[i] = srv_out[a];
+                                                                        i++;
+                                                                }
+                                                                /* send the complete frame through the pipe to our code waiting for incoming audio */
+                                                                howmany = skypiax_pipe_write(tech_pvt->audiopipe[1], totalbuf, SAMPLES_PER_FRAME * sizeof(short));
+                                                                if (howmany != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                        ERRORA("howmany is %d, but was expected to be %d\n", SKYPIAX_P_LOG,
+                                                                                 howmany, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                                }
+                                                                /* done with the stored half frame */
+                                                                tech_pvt->audiobuf_is_loaded = 0;
+                                                        }
+
+                                                } else if (len == 0) {
+                                                        skypiax_sleep(1000);
+                                                } else {
+                                                        DEBUGA_SKYPE("len=%d, expected 320\n", SKYPIAX_P_LOG, len);
+                                                }
+
+                                        } else {
+                                                if (rt)
+                                                        ERRORA("SRV rt=%d\n", SKYPIAX_P_LOG, rt);
+                                                skypiax_sleep(10000);
+                                        }
+
+                                }
+
+                                /* let's send some frame in the pipes, so both tcp_cli and tcp_srv will have an occasion to die */
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt->audiopipe[1], kill_cli_buff, kill_cli_size);
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt->audioskypepipe[1], kill_cli_buff, kill_cli_size);
+                                tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt->audiopipe[1], kill_cli_buff, kill_cli_size);
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt->audioskypepipe[1], kill_cli_buff, kill_cli_size);
+
+                                DEBUGA_SKYPE("Skype incoming audio GONE\n", SKYPIAX_P_LOG);
+                                skypiax_close_socket(fd);
+                                //if (exit)
+                                break;
+                        }
+                }
+        }
+
+        DEBUGA_SKYPE("incoming audio server (I am it) EXITING\n", SKYPIAX_P_LOG);
+        skypiax_close_socket(s);
+        tech_pvt->tcp_srv_thread = NULL;
+        return NULL;
+}
+
+void *skypiax_do_tcp_cli_thread_func(void *obj)
+{
+        private_t *tech_pvt = obj;
+        int s;
+        //struct sockaddr_in my_addr;
+        struct sockaddr_in remote_addr;
+        unsigned int got;
+        unsigned int len;
+        unsigned int i;
+        unsigned int a;
+        unsigned int fd;
+        short cli_out[SAMPLES_PER_FRAME * 2];
+        short cli_in[SAMPLES_PER_FRAME];
+#ifdef WIN32
+        int sin_size;
+#else
+        unsigned int sin_size;
+#endif /* WIN32 */
+
+        s = skypiax_socket_create_and_bind(tech_pvt, &tech_pvt->tcp_cli_port);
+        if (s < 0) {
+                ERRORA("skypiax_socket_create_and_bind error!\n", SKYPIAX_P_LOG);
+                return NULL;
+        }
+
+
+
+        DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+
+        listen(s, 6);
+
+        sin_size = sizeof(remote_addr);
+
+ /****************************/
+        while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                 && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                         || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                         || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+
+                unsigned int fdselectgio;
+                int rtgio;
+                fd_set fsgio;
+                struct timeval togio;
+
+                if (!(running && tech_pvt->running))
+                        break;
+                FD_ZERO(&fsgio);
+                togio.tv_usec = 20000;        //20msec
+                togio.tv_sec = 0;
+                fdselectgio = s;
+                FD_SET(fdselectgio, &fsgio);
+
+                rtgio = select(fdselectgio + 1, &fsgio, NULL, NULL, &togio);
+
+                if (rtgio) {
+
+ /****************************/
+
+                        while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
+                                DEBUGA_SKYPE("ACCEPTED here you send me %d\n", SKYPIAX_P_LOG, tech_pvt->tcp_cli_port);
+#ifndef WIN32
+                                fcntl(tech_pvt->audioskypepipe[0], F_SETFL, O_NONBLOCK);
+                                fcntl(tech_pvt->audioskypepipe[1], F_SETFL, O_NONBLOCK);
+#endif //WIN32
+
+                                if (!(running && tech_pvt->running))
+                                        break;
+                                while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                                         && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                                                 || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                                                 || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+                                        unsigned int fdselect;
+                                        int rt;
+                                        fd_set fs;
+                                        struct timeval to;
+
+                                        if (!(running && tech_pvt->running))
+                                                break;
+                                        FD_ZERO(&fs);
+                                        to.tv_usec = 120000;        //120msec
+                                        to.tv_sec = 0;
+#if defined(WIN32) && !defined(__CYGWIN__)
+/* on win32 we cannot select from the apr "pipe", so we select on socket writability */
+                                        fdselect = fd;
+                                        FD_SET(fdselect, &fs);
+
+                                        rt = select(fdselect + 1, NULL, &fs, NULL, &to);
+#else
+/* on *unix and cygwin we select from the real pipe */
+                                        fdselect = tech_pvt->audioskypepipe[0];
+                                        FD_SET(fdselect, &fs);
+
+                                        rt = select(fdselect + 1, &fs, NULL, NULL, &to);
+#endif
+
+                                        if (rt > 0) {
+                                                int counter;
+
+                                                /* until we drained the pipe to empty */
+                                                for (counter = 0; counter < 10; counter++) {
+                                                        /* read from the pipe the audio frame we are supposed to send out */
+                                                        got = skypiax_pipe_read(tech_pvt->audioskypepipe[0], cli_in, SAMPLES_PER_FRAME * sizeof(short));
+                                                        if (got == -1)
+                                                                break;
+
+                                                        if (got != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                WARNINGA("got is %d, but was expected to be %d\n", SKYPIAX_P_LOG, got, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                        }
+
+                                                        if (got == SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                if (samplerate_skypiax == 8000) {
+
+                                                                        /* we're upsampling from 8khz to 16khz, cli_out will contain two times each sample from cli_in */
+                                                                        a = 0;
+                                                                        for (i = 0; i < got / sizeof(short); i++) {
+                                                                                cli_out[a] = cli_in[i];
+                                                                                a++;
+                                                                                cli_out[a] = cli_in[i];
+                                                                                a++;
+                                                                        }
+                                                                        got = got * 2;
+                                                                } else if (samplerate_skypiax == 16000) {
+                                                                        /* we're NOT upsampling, cli_out will contain just ALL samples from cli_in */
+                                                                        for (i = 0; i < got / sizeof(short); i++) {
+                                                                                cli_out[i] = cli_in[i];
+                                                                        }
+                                                                } else {
+                                                                        ERRORA("SAMPLERATE_SKYPIAX can only be 8000 or 16000\n", SKYPIAX_P_LOG);
+                                                                }
+
+                                                                /* send the 16khz frame to the Skype client waiting for incoming audio to be sent to the remote party */
+                                                                if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                                        len = send(fd, (char *) cli_out, got, 0);
+                                                                        skypiax_sleep(5000);        //5 msec
+
+                                                                        if (len == -1) {
+                                                                                break;
+                                                                        } else if (len != got) {
+                                                                                ERRORA("len=%d\n", SKYPIAX_P_LOG, len);
+                                                                                skypiax_sleep(1000);
+                                                                                break;
+                                                                        }
+                                                                }
+
+                                                        } else {
+
+                                                                WARNINGA("got is %d, but was expected to be %d\n", SKYPIAX_P_LOG, got, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                        }
+                                                }
+                                        } else {
+                                                if (rt)
+                                                        ERRORA("CLI rt=%d\n", SKYPIAX_P_LOG, rt);
+                                                memset(cli_out, 0, sizeof(cli_out));
+                                                if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                        len = send(fd, (char *) cli_out, sizeof(cli_out), 0);
+                                                        len = send(fd, (char *) cli_out, sizeof(cli_out) / 2, 0);
+                                                        //WARNINGA("sent %d of zeros to keep the Skype client socket busy\n", SKYPIAX_P_LOG, sizeof(cli_out) + sizeof(cli_out)/2);
+                                                } else {
+                                                        /*
+                                                         XXX do nothing
+                                                         */
+                                                        //WARNINGA("we don't send it\n", SKYPIAX_P_LOG);
+                                                }
+                                                skypiax_sleep(1000);
+                                        }
+
+                                }
+                                DEBUGA_SKYPE("Skype outbound audio GONE\n", SKYPIAX_P_LOG);
+                                skypiax_close_socket(fd);
+                                break;
+                        }
+                }
+        }
+
+        DEBUGA_SKYPE("outbound audio server (I am it) EXITING\n", SKYPIAX_P_LOG);
+        skypiax_close_socket(s);
+        tech_pvt->tcp_cli_thread = NULL;
+        return NULL;
+}
+
+int skypiax_audio_read(private_t * tech_pvt)
+{
+        unsigned int samples;
+
+        samples = skypiax_pipe_read(tech_pvt->audiopipe[0], tech_pvt->read_frame.data, SAMPLES_PER_FRAME * sizeof(short));
+
+        if (samples != SAMPLES_PER_FRAME * sizeof(short)) {
+                if (samples)
+                        WARNINGA("read samples=%u expected=%u\n", SKYPIAX_P_LOG, samples, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                return 0;
+        } else {
+                /* A real frame */
+                tech_pvt->read_frame.datalen = samples;
+        }
+        return 1;
+}
+
+int skypiax_senddigit(private_t * tech_pvt, char digit)
+{
+        char msg_to_skype[1024];
+
+        DEBUGA_SKYPE("DIGIT received: %c\n", SKYPIAX_P_LOG, digit);
+        sprintf(msg_to_skype, "SET CALL %s DTMF %c", tech_pvt->skype_call_id, digit);
+        skypiax_signaling_write(tech_pvt, msg_to_skype);
+
+        return 0;
+}
+
+int skypiax_call(private_t * tech_pvt, char *rdest, int timeout)
+{
+        char msg_to_skype[1024];
+
+        //skypiax_sleep(5000);
+        DEBUGA_SKYPE("Calling Skype, rdest is: %s\n", SKYPIAX_P_LOG, rdest);
+        //skypiax_signaling_write(tech_pvt, "SET AGC OFF");
+        //skypiax_sleep(10000);
+        //skypiax_signaling_write(tech_pvt, "SET AEC OFF");
+        //skypiax_sleep(10000);
+
+        sprintf(msg_to_skype, "CALL %s", rdest);
+        if (skypiax_signaling_write(tech_pvt, msg_to_skype) < 0) {
+                ERRORA("failed to communicate with Skype client, now exit\n", SKYPIAX_P_LOG);
+                return -1;
+        }
+        return 0;
+}
+
+/***************************/
+/* PLATFORM SPECIFIC */
+/***************************/
+#if defined(WIN32) && !defined(__CYGWIN__)
+int skypiax_pipe_read(switch_file_t * pipe, short *buf, int howmany)
+{
+        switch_size_t quantity;
+
+        quantity = howmany;
+
+        switch_file_read(pipe, buf, &quantity);
+
+        howmany = quantity;
+
+        return howmany;
+}
+
+int skypiax_pipe_write(switch_file_t * pipe, short *buf, int howmany)
+{
+        switch_size_t quantity;
+
+        quantity = howmany;
+
+        switch_file_write(pipe, buf, &quantity);
+
+        howmany = quantity;
+
+        return howmany;
+}
+
+int skypiax_close_socket(unsigned int fd)
+{
+        int res;
+
+        res = closesocket(fd);
+
+        return res;
+}
+
+int skypiax_audio_init(private_t * tech_pvt)
+{
+        switch_status_t rv;
+        rv = switch_file_pipe_create(&tech_pvt->audiopipe[0], &tech_pvt->audiopipe[1], skypiax_module_pool);
+        rv = switch_file_pipe_create(&tech_pvt->audioskypepipe[0], &tech_pvt->audioskypepipe[1], skypiax_module_pool);
+        return 0;
+}
+#else /* WIN32 */
+int skypiax_pipe_read(int pipe, short *buf, int howmany)
+{
+        howmany = read(pipe, buf, howmany);
+        return howmany;
+}
+
+int skypiax_pipe_write(int pipe, short *buf, int howmany)
+{
+        howmany = write(pipe, buf, howmany);
+        return howmany;
+}
+
+int skypiax_close_socket(unsigned int fd)
+{
+        int res;
+
+        res = close(fd);
+
+        return res;
+}
+
+int skypiax_audio_init(private_t * tech_pvt)
+{
+        if (pipe(tech_pvt->audiopipe)) {
+                fcntl(tech_pvt->audiopipe[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt->audiopipe[1], F_SETFL, O_NONBLOCK);
+        }
+        if (pipe(tech_pvt->audioskypepipe)) {
+                fcntl(tech_pvt->audioskypepipe[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt->audioskypepipe[1], F_SETFL, O_NONBLOCK);
+        }
+
+/* this pipe is the audio fd for asterisk to poll on during a call. FS do not use it */
+        tech_pvt->skypiax_sound_capt_fd = tech_pvt->audiopipe[0];
+
+        return 0;
+}
+#endif /* WIN32 */
+
+#ifdef WIN32
+
+enum {
+        SKYPECONTROLAPI_ATTACH_SUCCESS = 0,        /* Client is successfully
+                                                                                 attached and API window handle can be found
+                                                                                 in wParam parameter */
+        SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION = 1,        /* Skype has acknowledged
+                                                                                                                 connection request and is waiting
+                                                                                                                 for confirmation from the user. */
+        /* The client is not yet attached
+         * and should wait for SKYPECONTROLAPI_ATTACH_SUCCESS message */
+        SKYPECONTROLAPI_ATTACH_REFUSED = 2,        /* User has explicitly
+                                                                                 denied access to client */
+        SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE = 3,        /* API is not available
+                                                                                                 at the moment.
+                                                                                                 For example, this happens when no user
+                                                                                                 is currently logged in. */
+        /* Client should wait for
+         * SKYPECONTROLAPI_ATTACH_API_AVAILABLE
+         * broadcast before making any further */
+        /* connection attempts. */
+        SKYPECONTROLAPI_ATTACH_API_AVAILABLE = 0x8001
+};
+
+/* Visual C do not have strsep? */
+char
+ *strsep(char **stringp, const char *delim)
+{
+        char *res;
+
+        if (!stringp || !*stringp || !**stringp)
+                return (char *) 0;
+
+        res = *stringp;
+        while (**stringp && !strchr(delim, **stringp))
+                ++(*stringp);
+
+        if (**stringp) {
+                **stringp = '\0';
+                ++(*stringp);
+        }
+
+        return res;
+}
+
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype)
+{
+        static char acInputRow[1024];
+        COPYDATASTRUCT oCopyData;
+
+        DEBUGA_SKYPE("SENDING: |||%s||||\n", SKYPIAX_P_LOG, msg_to_skype);
+
+        sprintf(acInputRow, "%s", msg_to_skype);
+        DEBUGA_SKYPE("acInputRow: |||%s||||\n", SKYPIAX_P_LOG, acInputRow);
+        /* send command to skype */
+        oCopyData.dwData = 0;
+        oCopyData.lpData = acInputRow;
+        oCopyData.cbData = strlen(acInputRow) + 1;
+        if (oCopyData.cbData != 1) {
+                if (SendMessage
+                        (tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle, WM_COPYDATA,
+                         (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, (LPARAM) & oCopyData) == FALSE) {
+                        ERRORA("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax, then launch Skypiax and try again.\n", SKYPIAX_P_LOG);
+                        return -1;
+                }
+        }
+
+        return 0;
+
+}
+
+LRESULT APIENTRY skypiax_present(HWND hWindow, UINT uiMessage, WPARAM uiParam, LPARAM ulParam)
+{
+        LRESULT lReturnCode;
+        int fIssueDefProc;
+        private_t *tech_pvt = NULL;
+
+        lReturnCode = 0;
+        fIssueDefProc = 0;
+        tech_pvt = (private_t *) GetWindowLong(hWindow, GWL_USERDATA);
+        if (!running)
+                return lReturnCode;
+        switch (uiMessage) {
+        case WM_CREATE:
+                tech_pvt = (private_t *) ((LPCREATESTRUCT) ulParam)->lpCreateParams;
+                SetWindowLong(hWindow, GWL_USERDATA, (LONG) tech_pvt);
+                DEBUGA_SKYPE("got CREATE\n", SKYPIAX_P_LOG);
+                break;
+        case WM_DESTROY:
+                DEBUGA_SKYPE("got DESTROY\n", SKYPIAX_P_LOG);
+                tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = NULL;
+                PostQuitMessage(0);
+                break;
+        case WM_COPYDATA:
+                if (tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle == (HWND) uiParam) {
+                        unsigned int howmany;
+                        char msg_from_skype[2048];
+
+                        PCOPYDATASTRUCT poCopyData = (PCOPYDATASTRUCT) ulParam;
+
+                        memset(msg_from_skype, '\0', sizeof(msg_from_skype));
+                        skypiax_strncpy(msg_from_skype, (const char *) poCopyData->lpData, sizeof(msg_from_skype) - 2);
+
+                        howmany = strlen(msg_from_skype) + 1;
+                        howmany = skypiax_pipe_write(tech_pvt->SkypiaxHandles.fdesc[1], (short *) msg_from_skype, howmany);
+                        //DEBUGA_SKYPE("From Skype API: %s\n", SKYPIAX_P_LOG, msg_from_skype);
+                        lReturnCode = 1;
+                }
+                break;
+        default:
+                if (tech_pvt && tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+                        if (uiMessage == tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+                                switch (ulParam) {
+                                case SKYPECONTROLAPI_ATTACH_SUCCESS:
+                                        if (!tech_pvt->SkypiaxHandles.currentuserhandle) {
+                                                //DEBUGA_SKYPE("\n\n\tConnected to Skype API!\n", SKYPIAX_P_LOG);
+                                                tech_pvt->SkypiaxHandles.api_connected = 1;
+                                                tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle = (HWND) uiParam;
+                                                tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle = tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle;
+                                        }
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION:
+                                        //DEBUGA_SKYPE ("\n\n\tIf I do not (almost) immediately connect to Skype API,\n\tplease give the Skype client authorization to be connected \n\tby Asterisk and to not ask you again.\n\n", SKYPIAX_P_LOG);
+                                        skypiax_sleep(5000);
+#if 0
+                                        if (!tech_pvt->SkypiaxHandles.currentuserhandle) {
+                                                SendMessage(HWND_BROADCAST,
+                                                                        tech_pvt->SkypiaxHandles.
+                                                                        win32_uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0);
+                                        }
+#endif
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_REFUSED:
+                                        ERRORA("Skype client refused to be connected by Skypiax!\n", SKYPIAX_P_LOG);
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE:
+                                        ERRORA("Skype API not (yet?) available\n", SKYPIAX_P_LOG);
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_API_AVAILABLE:
+                                        DEBUGA_SKYPE("Skype API available\n", SKYPIAX_P_LOG);
+                                        skypiax_sleep(5000);
+#if 0
+                                        if (!tech_pvt->SkypiaxHandles.currentuserhandle) {
+                                                SendMessage(HWND_BROADCAST,
+                                                                        tech_pvt->SkypiaxHandles.
+                                                                        win32_uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0);
+                                        }
+#endif
+                                        break;
+                                default:
+                                        WARNINGA("GOT AN UNKNOWN SKYPE WINDOWS MSG\n", SKYPIAX_P_LOG);
+                                }
+                                lReturnCode = 1;
+                                break;
+                        }
+                }
+                fIssueDefProc = 1;
+                break;
+        }
+        if (fIssueDefProc)
+                lReturnCode = DefWindowProc(hWindow, uiMessage, uiParam, ulParam);
+        return (lReturnCode);
+}
+
+int win32_Initialize_CreateWindowClass(private_t * tech_pvt)
+{
+        unsigned char *paucUUIDString;
+        RPC_STATUS lUUIDResult;
+        int fReturnStatus;
+        UUID oUUID;
+
+        fReturnStatus = 0;
+        lUUIDResult = UuidCreate(&oUUID);
+        tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle = (HINSTANCE) OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
+        if (tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle != NULL && (lUUIDResult == RPC_S_OK || lUUIDResult == RPC_S_UUID_LOCAL_ONLY)) {
+                if (UuidToString(&oUUID, &paucUUIDString) == RPC_S_OK) {
+                        WNDCLASS oWindowClass;
+
+                        strcpy(tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, "Skype-API-Skypiax-");
+                        strcat(tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, (char *) paucUUIDString);
+
+                        oWindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+                        oWindowClass.lpfnWndProc = (WNDPROC) & skypiax_present;
+                        oWindowClass.cbClsExtra = 0;
+                        oWindowClass.cbWndExtra = 0;
+                        oWindowClass.hInstance = tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle;
+                        oWindowClass.hIcon = NULL;
+                        oWindowClass.hCursor = NULL;
+                        oWindowClass.hbrBackground = NULL;
+                        oWindowClass.lpszMenuName = NULL;
+                        oWindowClass.lpszClassName = tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName;
+
+                        if (RegisterClass(&oWindowClass) != 0)
+                                fReturnStatus = 1;
+
+                        RpcStringFree(&paucUUIDString);
+                }
+        }
+        if (fReturnStatus == 0)
+                CloseHandle(tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle);
+        tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle = NULL;
+        return (fReturnStatus);
+}
+
+void win32_DeInitialize_DestroyWindowClass(private_t * tech_pvt)
+{
+        UnregisterClass(tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle);
+        CloseHandle(tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle);
+        tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle = NULL;
+}
+
+int win32_Initialize_CreateMainWindow(private_t * tech_pvt)
+{
+        tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle =
+                CreateWindowEx(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,
+                                         tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, "",
+                                         WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT,
+                                         128, 128, NULL, 0, tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle, tech_pvt);
+        return (tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle != NULL ? 1 : 0);
+}
+
+void win32_DeInitialize_DestroyMainWindow(private_t * tech_pvt)
+{
+        if (tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle != NULL)
+                DestroyWindow(tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle), tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = NULL;
+}
+
+void *skypiax_do_skypeapi_thread_func(void *obj)
+{
+        private_t *tech_pvt = obj;
+#if defined(WIN32) && !defined(__CYGWIN__)
+        switch_status_t rv;
+
+        switch_file_pipe_create(&tech_pvt->SkypiaxHandles.fdesc[0], &tech_pvt->SkypiaxHandles.fdesc[1], skypiax_module_pool);
+        rv = switch_file_pipe_create(&tech_pvt->SkypiaxHandles.fdesc[0], &tech_pvt->SkypiaxHandles.fdesc[1], skypiax_module_pool);
+#else /* WIN32 */
+        if (pipe(tech_pvt->SkypiaxHandles.fdesc)) {
+                fcntl(tech_pvt->SkypiaxHandles.fdesc[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt->SkypiaxHandles.fdesc[1], F_SETFL, O_NONBLOCK);
+        }
+#endif /* WIN32 */
+
+        tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach = RegisterWindowMessage("SkypeControlAPIAttach");
+        tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover = RegisterWindowMessage("SkypeControlAPIDiscover");
+
+        skypiax_sleep(200000);                //0,2 sec
+
+        if (tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach != 0
+                && tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover != 0) {
+                if (win32_Initialize_CreateWindowClass(tech_pvt)) {
+                        if (win32_Initialize_CreateMainWindow(tech_pvt)) {
+                                if (SendMessage
+                                        (HWND_BROADCAST,
+                                         tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover,
+                                         (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0) != 0) {
+                                        tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle;
+                                        while (running && tech_pvt->running) {
+                                                MSG oMessage;
+                                                if (!(running && tech_pvt->running))
+                                                        break;
+                                                while (GetMessage(&oMessage, 0, 0, 0)) {
+                                                        TranslateMessage(&oMessage);
+                                                        DispatchMessage(&oMessage);
+                                                }
+                                        }
+                                }
+                                win32_DeInitialize_DestroyMainWindow(tech_pvt);
+                        }
+                        win32_DeInitialize_DestroyWindowClass(tech_pvt);
+                }
+        }
+
+        return NULL;
+}
+
+#else /* NOT WIN32 */
+int X11_errors_handler(Display * dpy, XErrorEvent * err)
+{
+        (void) dpy;
+        private_t *tech_pvt = NULL;
+
+        xerror = err->error_code;
+        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 */
+}
+
+static void X11_errors_trap(void)
+{
+        xerror = 0;
+        old_handler = XSetErrorHandler(X11_errors_handler);
+}
+
+static int X11_errors_untrap(void)
+{
+        XSetErrorHandler(old_handler);
+        return (xerror != BadValue) && (xerror != BadWindow);
+}
+
+int skypiax_send_message(struct SkypiaxHandles *SkypiaxHandles, const char *message_P)
+{
+
+        Window w_P;
+        Display *disp;
+        Window handle_P;
+        int ok;
+        private_t *tech_pvt = NULL;
+
+        w_P = SkypiaxHandles->skype_win;
+        disp = SkypiaxHandles->disp;
+        handle_P = SkypiaxHandles->win;
+
+        Atom atom1 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+        Atom atom2 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
+        unsigned int pos = 0;
+        unsigned int len = strlen(message_P);
+        XEvent e;
+
+        memset(&e, 0, sizeof(e));
+        e.xclient.type = ClientMessage;
+        e.xclient.message_type = atom1;        /* leading message */
+        e.xclient.display = disp;
+        e.xclient.window = handle_P;
+        e.xclient.format = 8;
+
+        X11_errors_trap();
+        //XLockDisplay(disp);
+        do {
+                unsigned int i;
+                for (i = 0; i < 20 && i + pos <= len; ++i)
+                        e.xclient.data.b[i] = message_P[i + pos];
+                XSendEvent(disp, w_P, False, 0, &e);
+
+                e.xclient.message_type = atom2;        /* following messages */
+                pos += i;
+        } while (pos <= len);
+
+        XSync(disp, False);
+        ok = X11_errors_untrap();
+
+        if (!ok)
+                ERRORA("Sending message failed with status %d\n", SKYPIAX_P_LOG, xerror);
+        //XUnlockDisplay(disp);
+
+        return 1;
+}
+
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype)
+{
+        struct SkypiaxHandles *SkypiaxHandles;
+
+        DEBUGA_SKYPE("SENDING: |||%s||||\n", SKYPIAX_P_LOG, msg_to_skype);
+
+        SkypiaxHandles = &tech_pvt->SkypiaxHandles;
+
+        if (!skypiax_send_message(SkypiaxHandles, msg_to_skype)) {
+                ERRORA
+                        ("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax, then restart Skype, then launch Skypiax and try again.\n",
+                         SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        return 0;
+
+}
+
+int skypiax_present(struct SkypiaxHandles *SkypiaxHandles)
+{
+        Atom skype_inst = XInternAtom(SkypiaxHandles->disp, "_SKYPE_INSTANCE", True);
+
+        Atom type_ret;
+        int format_ret;
+        unsigned long nitems_ret;
+        unsigned long bytes_after_ret;
+        unsigned char *prop;
+        int status;
+        private_t *tech_pvt = NULL;
+
+        X11_errors_trap();
+        //XLockDisplay(disp);
+        status =
+                XGetWindowProperty(SkypiaxHandles->disp, DefaultRootWindow(SkypiaxHandles->disp),
+                                                 skype_inst, 0, 1, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &bytes_after_ret, &prop);
+        //XUnlockDisplay(disp);
+        X11_errors_untrap();
+
+        /* sanity check */
+        if (status != Success || format_ret != 32 || nitems_ret != 1) {
+                SkypiaxHandles->skype_win = (Window) - 1;
+                DEBUGA_SKYPE("Skype instance not found\n", SKYPIAX_P_LOG);
+                running = 0;
+                SkypiaxHandles->api_connected = 0;
+                return 0;
+        }
+
+        SkypiaxHandles->skype_win = *(const unsigned long *) prop & 0xffffffff;
+        DEBUGA_SKYPE("Skype instance found with id #%d\n", SKYPIAX_P_LOG, (unsigned int) SkypiaxHandles->skype_win);
+        SkypiaxHandles->api_connected = 1;
+        return 1;
+}
+
+void skypiax_clean_disp(void *data)
+{
+
+        int *dispptr;
+        int disp;
+        private_t *tech_pvt = NULL;
+
+        dispptr = data;
+        disp = *dispptr;
+
+        if (disp) {
+                DEBUGA_SKYPE("to be destroyed disp %d\n", SKYPIAX_P_LOG, disp);
+                close(disp);
+                DEBUGA_SKYPE("destroyed disp\n", SKYPIAX_P_LOG);
+        } else {
+                DEBUGA_SKYPE("NOT destroyed disp\n", SKYPIAX_P_LOG);
+        }
+        DEBUGA_SKYPE("OUT destroyed disp\n", SKYPIAX_P_LOG);
+        skypiax_sleep(1000);
+}
+
+void *skypiax_do_skypeapi_thread_func(void *obj)
+{
+
+        private_t *tech_pvt = obj;
+        struct SkypiaxHandles *SkypiaxHandles;
+        char buf[512];
+        Display *disp = NULL;
+        Window root = -1;
+        Window win = -1;
+
+        if (!strlen(tech_pvt->X11_display))
+                strcpy(tech_pvt->X11_display, getenv("DISPLAY"));
+
+        if (!tech_pvt->tcp_srv_port)
+                tech_pvt->tcp_srv_port = 10160;
+
+        if (!tech_pvt->tcp_cli_port)
+                tech_pvt->tcp_cli_port = 10161;
+
+        if (pipe(tech_pvt->SkypiaxHandles.fdesc)) {
+                fcntl(tech_pvt->SkypiaxHandles.fdesc[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt->SkypiaxHandles.fdesc[1], F_SETFL, O_NONBLOCK);
+        }
+        SkypiaxHandles = &tech_pvt->SkypiaxHandles;
+        disp = XOpenDisplay(tech_pvt->X11_display);
+        if (!disp) {
+                ERRORA("Cannot open X Display '%s', exiting skype thread\n", SKYPIAX_P_LOG, tech_pvt->X11_display);
+                running = 0;
+                return NULL;
+        } else {
+                DEBUGA_SKYPE("X Display '%s' opened\n", SKYPIAX_P_LOG, tech_pvt->X11_display);
+        }
+
+        int xfd;
+        xfd = XConnectionNumber(disp);
+        fcntl(xfd, F_SETFD, FD_CLOEXEC);
+
+        SkypiaxHandles->disp = disp;
+
+        if (skypiax_present(SkypiaxHandles)) {
+                root = DefaultRootWindow(disp);
+                win = XCreateSimpleWindow(disp, root, 0, 0, 1, 1, 0, BlackPixel(disp, DefaultScreen(disp)), BlackPixel(disp, DefaultScreen(disp)));
+
+                SkypiaxHandles->win = win;
+
+                snprintf(buf, 512, "NAME skypiax");
+
+                if (!skypiax_send_message(SkypiaxHandles, buf)) {
+                        ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n", SKYPIAX_P_LOG);
+                        running = 0;
+                        return NULL;
+                }
+
+                snprintf(buf, 512, "PROTOCOL 7");
+                if (!skypiax_send_message(SkypiaxHandles, buf)) {
+                        ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n", SKYPIAX_P_LOG);
+                        running = 0;
+                        return NULL;
+                }
+
+                /* perform an events loop */
+                XEvent an_event;
+                char buf[21];                        /* can't be longer */
+                char buffer[17000];
+                char *b;
+                int i;
+                int continue_is_broken = 0;
+                Atom atom_begin = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+                Atom atom_continue = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
+
+                b = buffer;
+
+                while (1) {
+                        XNextEvent(disp, &an_event);
+                        if (!(running && tech_pvt->running))
+                                break;
+                        switch (an_event.type) {
+                        case ClientMessage:
+
+                                if (an_event.xclient.format != 8)
+                                        break;
+
+                                for (i = 0; i < 20 && an_event.xclient.data.b[i] != '\0'; ++i)
+                                        buf[i] = an_event.xclient.data.b[i];
+
+                                buf[i] = '\0';
+
+                                //DEBUGA_SKYPE ("BUF=|||%s|||\n", SKYPIAX_P_LOG, buf);
+
+                                if (an_event.xclient.message_type == atom_begin) {
+
+                                        if (strlen(buffer)) {
+                                                unsigned int howmany;
+                                                howmany = strlen(b) + 1;
+                                                howmany = write(SkypiaxHandles->fdesc[1], b, howmany);
+                                                DEBUGA_SKYPE("RECEIVED2=|||%s|||\n", SKYPIAX_P_LOG, buffer);
+                                                memset(buffer, '\0', 17000);
+                                        }
+                                }
+                                if (an_event.xclient.message_type == atom_continue) {
+
+                                        if (!strlen(buffer)) {
+                                                DEBUGA_SKYPE
+                                                        ("Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||\n", SKYPIAX_P_LOG, buf);
+                                                continue_is_broken = 1;
+                                                if (!strncmp(buf, "ognised identity", 15)) {
+                                                        WARNINGA
+                                                                ("Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||. Let's introduce a 1 second delay.\n",
+                                                                 SKYPIAX_P_LOG, buf);
+                                                        skypiax_sleep(1000000);        //1 sec
+                                                }
+                                                break;
+                                        }
+                                }
+
+                                strcat(buffer, buf);
+
+                                if (i < 20 || continue_is_broken) {        /* last fragment */
+                                        unsigned int howmany;
+
+                                        howmany = strlen(b) + 1;
+
+                                        howmany = write(SkypiaxHandles->fdesc[1], b, howmany);
+                                        //DEBUGA_SKYPE ("RECEIVED=|||%s|||\n", SKYPIAX_P_LOG, buffer);
+                                        memset(buffer, '\0', 17000);
+                                        XFlush(disp);
+                                        continue_is_broken = 0;
+                                }
+
+                                break;
+                        default:
+                                break;
+                        }
+                }
+        } else {
+                ERRORA("Skype is not running, maybe crashed. Please run/restart Skype and relaunch Skypiax\n", SKYPIAX_P_LOG);
+                running = 0;
+                return NULL;
+        }
+        //running = 0;
+        return NULL;
+
+}
+#endif // WIN32
</ins></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>
</body>
</html>