<!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=&quot;$(shell svnversion -n .)&quot;'
+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
+
+&lt; gmaruzz at gmail dot com &gt;
+
</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 &lt;anthmct@yahoo.com&gt;
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the &quot;License&quot;); 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 &quot;AS IS&quot; 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 &lt;anthmct@yahoo.com&gt;
+ * 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 &lt;switch.h&gt;
+#include &lt;switch_version.h&gt;
+
+#ifndef WIN32
+#include &lt;sys/time.h&gt;
+#include &lt;X11/Xlib.h&gt;
+#include &lt;X11/Xlibint.h&gt;
+#include &lt;X11/Xatom.h&gt;
+#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 &lt;&lt; 0),
+        TFLAG_INBOUND = (1 &lt;&lt; 1),
+        TFLAG_OUTBOUND = (1 &lt;&lt; 2),
+        TFLAG_DTMF = (1 &lt;&lt; 3),
+        TFLAG_VOICE = (1 &lt;&lt; 4),
+        TFLAG_HANGUP = (1 &lt;&lt; 5),
+        TFLAG_LINEAR = (1 &lt;&lt; 6),
+        TFLAG_CODEC = (1 &lt;&lt; 7),
+        TFLAG_BREAK = (1 &lt;&lt; 8)
+} TFLAGS;
+
+typedef enum {
+        GFLAG_MY_CODEC_PREFS = (1 &lt;&lt; 0)
+} GFLAGS;
+
+#define DEBUGA_SKYPE(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][DEBUG_SKYPE  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+#define DEBUGA_CALL(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][DEBUG_CALL  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+#define DEBUGA_PBX(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][DEBUG_PBX  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+#define ERRORA(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][ERRORA  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+#define WARNINGA(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][WARNINGA  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+#define NOTICA(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][NOTICA  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+
+#define SKYPIAX_P_LOG NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt-&gt;name ? tech_pvt-&gt;name : &quot;none&quot; : &quot;none&quot;, -1, tech_pvt ? tech_pvt-&gt;interface_state : -1, tech_pvt ? tech_pvt-&gt;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;                /*!&lt; \brief 'state' of the interface (channel) */
+        char language[80];                        /*!&lt; \brief default Asterisk dialplan language for this interface */
+        char exten[80];                                /*!&lt; \brief default Asterisk dialplan extension for this interface */
+        int skypiax_sound_rate;                /*!&lt; \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;                        /*!&lt; \brief 'callflow' of the skype interface (as opposed to phone interface) */
+        int skype;                                        /*!&lt; \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;        /*!&lt; \brief file descriptor for sound capture dev */
+#else                                                        /* WIN32 */
+        int audiopipe[2];
+        int audioskypepipe[2];
+        int skypiax_sound_capt_fd;        /*!&lt; \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) &amp;&amp; !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 &quot;skypiax.h&quot;
+
+#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(&amp;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)) &lt; 0) {
+                ERRORA(&quot;socket Error\n&quot;, SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        if (*which_port != 0)
+                start_port = *which_port;
+
+        my_addr.sin_port = htons(start_port);
+        //tech_pvt-&gt;tcp_cli_port = start_port;
+        *which_port = start_port;
+        while (bind(s, (struct sockaddr *) &amp;my_addr, sizeof(struct sockaddr)) &lt; 0) {
+                DEBUGA_SKYPE(&quot;*which_port=%d, tech_pvt-&gt;tcp_cli_port=%d, tech_pvt-&gt;tcp_srv_port=%d\n&quot;, SKYPIAX_P_LOG, *which_port, tech_pvt-&gt;tcp_cli_port,
+                                         tech_pvt-&gt;tcp_srv_port);
+                DEBUGA_SKYPE(&quot;bind errno=%d, error: %s\n&quot;, SKYPIAX_P_LOG, errno, strerror(errno));
+                start_port++;
+                my_addr.sin_port = htons(start_port);
+                *which_port = start_port;
+                DEBUGA_SKYPE(&quot;*which_port=%d, tech_pvt-&gt;tcp_cli_port=%d, tech_pvt-&gt;tcp_srv_port=%d\n&quot;, SKYPIAX_P_LOG, *which_port, tech_pvt-&gt;tcp_cli_port,
+                                         tech_pvt-&gt;tcp_srv_port);
+
+                if (start_port &gt; 65000) {
+                        ERRORA(&quot;NO MORE PORTS! *which_port=%d, tech_pvt-&gt;tcp_cli_port=%d, tech_pvt-&gt;tcp_srv_port=%d\n&quot;, SKYPIAX_P_LOG, *which_port,
+                                   tech_pvt-&gt;tcp_cli_port, tech_pvt-&gt;tcp_srv_port);
+                        return -1;
+                }
+        }
+
+        DEBUGA_SKYPE(&quot;SUCCESS! *which_port=%d, tech_pvt-&gt;tcp_cli_port=%d, tech_pvt-&gt;tcp_srv_port=%d\n&quot;, SKYPIAX_P_LOG, *which_port, tech_pvt-&gt;tcp_cli_port,
+                                 tech_pvt-&gt;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] = &quot;&quot;, id[512] = &quot;&quot;, prop[512] = &quot;&quot;, value[512] = &quot;&quot;, *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-&gt;SkypiaxHandles.fdesc[0], (short *) read_from_pipe, sizeof(read_from_pipe));
+
+        a = 0;
+        for (i = 0; i &lt; howmany; i++) {
+                message[a] = read_from_pipe[i];
+                a++;
+
+                if (read_from_pipe[i] == '\0') {
+
+                        //if (!strstr(message, &quot;DURATION&quot;)) {
+                        DEBUGA_SKYPE(&quot;READING: |||%s||| \n&quot;, SKYPIAX_P_LOG, message);
+                        //}
+
+                        if (!strcasecmp(message, &quot;ERROR 68&quot;)) {
+                                DEBUGA_SKYPE
+                                        (&quot;If I don't connect immediately, please give the Skype client authorization to be connected by Skypiax (and to not ask you again)\n&quot;,
+                                         SKYPIAX_P_LOG);
+                                skypiax_sleep(1000000);
+                                skypiax_signaling_write(tech_pvt, &quot;PROTOCOL 7&quot;);
+                                skypiax_sleep(10000);
+                                return 0;
+                        }
+                        if (!strncasecmp(message, &quot;ERROR 92 CALL&quot;, 12)) {
+                                ERRORA(&quot;Skype got ERROR: |||%s|||, the (skypeout) number we called was not recognized as valid\n&quot;, SKYPIAX_P_LOG, message);
+                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                DEBUGA_SKYPE(&quot;skype_call now is DOWN\n&quot;, SKYPIAX_P_LOG);
+                                tech_pvt-&gt;skype_call_id[0] = '\0';
+
+                                if (tech_pvt-&gt;interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                        return CALLFLOW_INCOMING_HANGUP;
+                                } else {
+                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                }
+                        }
+
+                        if (!strncasecmp(message, &quot;ERROR&quot;, 4)) {
+                                if (!strncasecmp(message, &quot;ERROR 96 CALL&quot;, 12)) {
+                                        DEBUGA_SKYPE
+                                                (&quot;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&quot;,
+                                                 SKYPIAX_P_LOG, message);
+                                } else if (!strncasecmp(message, &quot;ERROR 99 CALL&quot;, 12)) {
+                                        ERRORA(&quot;Skype got ERROR: |||%s|||, another call is active on this interface\n\n\n&quot;, SKYPIAX_P_LOG, message);
+                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_ERROR_DOUBLE_CALL;
+                                } else if (!strncasecmp(message, &quot;ERROR 592 ALTER CALL&quot;, 19)) {
+                                        ERRORA(&quot;Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n&quot;, SKYPIAX_P_LOG, message);
+                                } else if (!strncasecmp(message, &quot;ERROR 559 CALL&quot;, 13)) {
+                                        DEBUGA_SKYPE(&quot;Skype got ERROR about a failed action (probably TRYING to HANGUP A CALL), no problem: |||%s|||\n&quot;, SKYPIAX_P_LOG,
+                                                                 message);
+                                } else {
+                                        ERRORA(&quot;Skype got ERROR: |||%s|||\n&quot;, SKYPIAX_P_LOG, message);
+                                        tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                        ERRORA(&quot;skype_call now is DOWN\n&quot;, SKYPIAX_P_LOG);
+                                        tech_pvt-&gt;skype_call_id[0] = '\0';
+
+                                        if (tech_pvt-&gt;interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else {
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                        }
+                                }
+                        }
+
+
+
+
+                        skypiax_strncpy(message_2, message, sizeof(message) - 1);
+                        buf = message;
+                        stringp = &amp;buf;
+                        where = strsep(stringp, &quot; &quot;);
+                        if (!where) {
+                                WARNINGA(&quot;Skype MSG without spaces: %s\n&quot;, SKYPIAX_P_LOG, message);
+                        }
+
+
+
+
+
+
+
+
+                        if (!strcasecmp(message, &quot;CURRENTUSERHANDLE&quot;)) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                if (!strcasecmp(id, tech_pvt-&gt;skype_user)) {
+                                        tech_pvt-&gt;SkypiaxHandles.currentuserhandle = 1;
+                                        DEBUGA_SKYPE
+                                                (&quot;Skype MSG: message: %s, currentuserhandle: %s, cuh: %s, skype_user: %s!\n&quot;,
+                                                 SKYPIAX_P_LOG, message, obj, id, tech_pvt-&gt;skype_user);
+                                }
+                        }
+                        if (!strcasecmp(message, &quot;USER&quot;)) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                if (!strcasecmp(prop, &quot;RECEIVEDAUTHREQUEST&quot;)) {
+                                        char msg_to_skype[256];
+                                        DEBUGA_SKYPE(&quot;Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n&quot;, SKYPIAX_P_LOG, message, obj, id, prop);
+                                        //TODO: allow authorization based on config param
+                                        sprintf(msg_to_skype, &quot;SET USER %s ISAUTHORIZED TRUE&quot;, id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                }
+                        }
+                        if (!strcasecmp(message, &quot;MESSAGE&quot;)) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                if (!strcasecmp(prop, &quot;STATUS&quot;)) {
+                                        where = strsep(stringp, &quot; &quot;);
+                                        skypiax_strncpy(value, where, sizeof(value) - 1);
+                                        if (!strcasecmp(value, &quot;RECEIVED&quot;)) {
+                                                char msg_to_skype[256];
+                                                DEBUGA_SKYPE(&quot;Skype MSG: message: %s, obj: %s, id: %s, prop: %s value: %s!\n&quot;, SKYPIAX_P_LOG, message, obj, id, prop, value);
+                                                //TODO: authomatically flag messages as read based on config param
+                                                sprintf(msg_to_skype, &quot;SET MESSAGE %s SEEN&quot;, id);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                        }
+                                } else if (!strcasecmp(prop, &quot;BODY&quot;)) {
+                                        char msg_to_skype[256];
+                                        DEBUGA_SKYPE(&quot;Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n&quot;, SKYPIAX_P_LOG, message, obj, id, prop);
+                                        //TODO: authomatically flag messages as read based on config param
+                                        sprintf(msg_to_skype, &quot;SET MESSAGE %s SEEN&quot;, id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                }
+                        }
+                        if (!strcasecmp(message, &quot;CALL&quot;)) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(value, where, sizeof(value) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+
+                                //DEBUGA_SKYPE
+                                //(&quot;Skype MSG: message: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n&quot;,
+                                //SKYPIAX_P_LOG, message, obj, id, prop, value, where ? where : &quot;NULL&quot;);
+
+                                if (!strcasecmp(prop, &quot;PARTNER_HANDLE&quot;)) {
+                                        if (tech_pvt-&gt;interface_state != SKYPIAX_STATE_SELECTED &amp;&amp; (!strlen(tech_pvt-&gt;skype_call_id) || !strlen(tech_pvt-&gt;session_uuid_str))) {
+                                                //if (!strlen(tech_pvt-&gt;skype_call_id)) {
+                                                /* we are NOT inside an active call */
+                                                DEBUGA_SKYPE(&quot;Call %s TRY ANSWER\n&quot;, SKYPIAX_P_LOG, id);
+                                                skypiax_answer(tech_pvt, id, value);
+                                        } else {
+                                                /* we are inside an active call */
+                                                if (!strcasecmp(tech_pvt-&gt;skype_call_id, id)) {
+                                                        /* this is the call in which we are calling out */
+                                                        DEBUGA_SKYPE(&quot;Call %s DO NOTHING\n&quot;, SKYPIAX_P_LOG, id);
+                                                } else {
+                                                        skypiax_sleep(400000);        //0.4 seconds
+                                                        DEBUGA_SKYPE(&quot;Call %s TRY TRANSFER\n&quot;, SKYPIAX_P_LOG, id);
+                                                        skypiax_transfer(tech_pvt, id, value);
+                                                }
+                                        }
+                                }
+                                if (!strcasecmp(prop, &quot;PARTNER_DISPNAME&quot;)) {
+                                        snprintf(tech_pvt-&gt;callid_name, sizeof(tech_pvt-&gt;callid_name) - 1, &quot;%s%s%s&quot;, value, where ? &quot; &quot; : &quot;&quot;, where ? where : &quot;&quot;);
+                                        //DEBUGA_SKYPE
+                                        //(&quot;the skype_call %s caller PARTNER_DISPNAME (tech_pvt-&gt;callid_name) is: %s\n&quot;,
+                                        //SKYPIAX_P_LOG, id, tech_pvt-&gt;callid_name);
+                                }
+                                if (!strcasecmp(prop, &quot;CONF_ID&quot;) &amp;&amp; !strcasecmp(value, &quot;0&quot;)) {
+                                        //DEBUGA_SKYPE(&quot;the skype_call %s is NOT a conference call\n&quot;, SKYPIAX_P_LOG, id);
+                                        //if (tech_pvt-&gt;interface_state == SKYPIAX_STATE_DOWN)
+                                        //tech_pvt-&gt;interface_state = SKYPIAX_STATE_PRERING;
+                                }
+                                if (!strcasecmp(prop, &quot;CONF_ID&quot;) &amp;&amp; strcasecmp(value, &quot;0&quot;)) {
+                                        DEBUGA_SKYPE(&quot;the skype_call %s is a conference call\n&quot;, SKYPIAX_P_LOG, id);
+                                        //if (tech_pvt-&gt;interface_state == SKYPIAX_STATE_DOWN)
+                                        //tech_pvt-&gt;interface_state = SKYPIAX_STATE_PRERING;
+                                }
+                                if (!strcasecmp(prop, &quot;DTMF&quot;)) {
+                                        DEBUGA_SKYPE(&quot;Call %s received a DTMF: %s\n&quot;, SKYPIAX_P_LOG, id, value);
+                                        dtmf_received(tech_pvt, value);
+                                }
+                                if (!strcasecmp(prop, &quot;FAILUREREASON&quot;)) {
+                                        DEBUGA_SKYPE(&quot;Skype FAILED on skype_call %s. Let's wait for the FAILED message.\n&quot;, SKYPIAX_P_LOG, id);
+                                }
+                                if (!strcasecmp(prop, &quot;DURATION&quot;) &amp;&amp; (!strcasecmp(value, &quot;1&quot;))) {
+                                        if (strcasecmp(id, tech_pvt-&gt;skype_call_id)) {
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                DEBUGA_SKYPE(&quot;We called a Skype contact and he answered us on skype_call: %s.\n&quot;, SKYPIAX_P_LOG, id);
+                                        }
+                                }
+
+                                if (!strcasecmp(prop, &quot;DURATION&quot;) &amp;&amp; (tech_pvt-&gt;interface_state == SKYPIAX_STATE_ERROR_DOUBLE_CALL)) {
+                                        char msg_to_skype[1024];
+                                        skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                        ERRORA(&quot;We are in a double call situation, trying to get out hanging up call id: %s.\n&quot;, SKYPIAX_P_LOG, id);
+                                        sprintf(msg_to_skype, &quot;ALTER CALL %s HANGUP&quot;, id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                        skypiax_sleep(10000);
+                                        //return CALLFLOW_INCOMING_HANGUP;
+                                }
+
+                                if (!strcasecmp(prop, &quot;STATUS&quot;)) {
+
+                                        if (!strcasecmp(value, &quot;RINGING&quot;)) {
+                                                char msg_to_skype[1024];
+                                                if ((tech_pvt-&gt;interface_state != SKYPIAX_STATE_SELECTED &amp;&amp; tech_pvt-&gt;interface_state != SKYPIAX_STATE_DIALING)
+                                                        &amp;&amp; (!strlen(tech_pvt-&gt;skype_call_id) || !strlen(tech_pvt-&gt;session_uuid_str))) {
+                                                        /* we are NOT inside an active call */
+
+                                                        DEBUGA_SKYPE(&quot;NO ACTIVE calls in this moment, skype_call %s is RINGING, to ask PARTNER_HANDLE\n&quot;, SKYPIAX_P_LOG, id);
+                                                        sprintf(msg_to_skype, &quot;GET CALL %s PARTNER_HANDLE&quot;, id);
+                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                        skypiax_sleep(10000);
+                                                } else {
+                                                        /* we are inside an active call */
+                                                        if (!strcasecmp(tech_pvt-&gt;skype_call_id, id)) {
+                                                                /* this is the call in which we are calling out */
+                                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_RINGING;
+                                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_RINGING;
+                                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                                DEBUGA_SKYPE(&quot;Our remote party in skype_call %s is RINGING\n&quot;, SKYPIAX_P_LOG, id);
+                                                                remote_party_is_ringing(tech_pvt);
+                                                        } else {
+                                                                DEBUGA_SKYPE
+                                                                        (&quot;We are in another call, but skype_call %s is RINGING on us, let's ask PARTNER_HANDLE, so maybe we'll TRANSFER\n&quot;,
+                                                                         SKYPIAX_P_LOG, id);
+                                                                sprintf(msg_to_skype, &quot;GET CALL %s PARTNER_HANDLE&quot;, id);
+                                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                skypiax_sleep(10000);
+                                                        }
+                                                }
+                                        } else if (!strcasecmp(value, &quot;EARLYMEDIA&quot;)) {
+                                                char msg_to_skype[1024];
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_EARLYMEDIA;
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DIALING;
+                                                DEBUGA_SKYPE(&quot;Our remote party in skype_call %s is EARLYMEDIA\n&quot;, SKYPIAX_P_LOG, id);
+                                                if (start_audio_threads(tech_pvt)) {
+                                                        ERRORA(&quot;start_audio_threads FAILED\n&quot;, SKYPIAX_P_LOG);
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                }
+                                                skypiax_sleep(1000);
+                                                sprintf(msg_to_skype, &quot;ALTER CALL %s SET_INPUT PORT=\&quot;%d\&quot;&quot;, id, tech_pvt-&gt;tcp_cli_port);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                sprintf(msg_to_skype, &quot;#output ALTER CALL %s SET_OUTPUT PORT=\&quot;%d\&quot;&quot;, id, tech_pvt-&gt;tcp_srv_port);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+
+                                                remote_party_is_early_media(tech_pvt);
+                                        } else if (!strcasecmp(value, &quot;MISSED&quot;)) {
+                                                DEBUGA_SKYPE(&quot;We missed skype_call %s\n&quot;, SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, &quot;FINISHED&quot;)) {
+                                                //DEBUGA_SKYPE(&quot;skype_call %s now is DOWN\n&quot;, SKYPIAX_P_LOG, id);
+                                                if (!strcasecmp(tech_pvt-&gt;skype_call_id, id)) {
+                                                        //tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                                        DEBUGA_SKYPE(&quot;skype_call %s is MY call, now I'm going DOWN\n&quot;, SKYPIAX_P_LOG, id);
+                                                        //tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                        if (tech_pvt-&gt;interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                                //tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                                return CALLFLOW_INCOMING_HANGUP;
+                                                        } else {
+                                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                        }
+                                                } else {
+                                                        DEBUGA_SKYPE(&quot;skype_call %s is NOT MY call, ignoring\n&quot;, SKYPIAX_P_LOG, id);
+                                                }
+
+                                        } else if (!strcasecmp(value, &quot;CANCELLED&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_CANCELLED;
+                                                DEBUGA_SKYPE(&quot;we tried to call Skype on skype_call %s and Skype has now CANCELLED\n&quot;, SKYPIAX_P_LOG, id);
+                                                tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                if (tech_pvt-&gt;interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                } else {
+                                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                }
+                                        } else if (!strcasecmp(value, &quot;FAILED&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE(&quot;we tried to call Skype on skype_call %s and Skype has now FAILED\n&quot;, SKYPIAX_P_LOG, id);
+                                                tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else if (!strcasecmp(value, &quot;REFUSED&quot;)) {
+                                                if (!strcasecmp(id, tech_pvt-&gt;skype_call_id)) {
+                                                        /* this is the id of the call we are in, probably we generated it */
+                                                        tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_REFUSED;
+                                                        DEBUGA_SKYPE(&quot;we tried to call Skype on skype_call %s and Skype has now REFUSED\n&quot;, SKYPIAX_P_LOG, id);
+                                                        skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                        tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                } else {
+                                                        /* we're here because were us that refused an incoming call */
+                                                        DEBUGA_SKYPE(&quot;we REFUSED skype_call %s\n&quot;, SKYPIAX_P_LOG, id);
+                                                }
+                                        } else if (!strcasecmp(value, &quot;TRANSFERRING&quot;)) {
+                                                DEBUGA_SKYPE(&quot;skype_call %s is transferring\n&quot;, SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, &quot;TRANSFERRED&quot;)) {
+                                                DEBUGA_SKYPE(&quot;skype_call %s has been transferred\n&quot;, SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, &quot;ROUTING&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_ROUTING;
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DIALING;
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                DEBUGA_SKYPE(&quot;skype_call: %s is now ROUTING\n&quot;, SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, &quot;UNPLACED&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_UNPLACED;
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DIALING;
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                DEBUGA_SKYPE(&quot;skype_call: %s is now UNPLACED\n&quot;, SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, &quot;INPROGRESS&quot;)) {
+                                                char msg_to_skype[1024];
+
+                                                if (!strlen(tech_pvt-&gt;session_uuid_str)) {
+                                                        DEBUGA_SKYPE(&quot;no tech_pvt-&gt;session_uuid_str\n&quot;, SKYPIAX_P_LOG);
+                                                }
+                                                if (tech_pvt-&gt;skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                        if (!strlen(tech_pvt-&gt;session_uuid_str) || !strlen(tech_pvt-&gt;skype_call_id)
+                                                                || !strcasecmp(tech_pvt-&gt;skype_call_id, id)) {
+                                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                                DEBUGA_SKYPE(&quot;skype_call: %s is now active\n&quot;, SKYPIAX_P_LOG, id);
+
+                                                                if (tech_pvt-&gt;skype_callflow != CALLFLOW_STATUS_EARLYMEDIA) {
+                                                                        tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_UP;
+
+                                                                        if (start_audio_threads(tech_pvt)) {
+                                                                                ERRORA(&quot;start_audio_threads FAILED\n&quot;, SKYPIAX_P_LOG);
+                                                                                return CALLFLOW_INCOMING_HANGUP;
+                                                                        }
+                                                                        skypiax_sleep(1000);        //FIXME
+                                                                        sprintf(msg_to_skype, &quot;ALTER CALL %s SET_INPUT PORT=\&quot;%d\&quot;&quot;, id, tech_pvt-&gt;tcp_cli_port);
+                                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                        skypiax_sleep(1000);        //FIXME
+                                                                        sprintf(msg_to_skype, &quot;#output ALTER CALL %s SET_OUTPUT PORT=\&quot;%d\&quot;&quot;, id, tech_pvt-&gt;tcp_srv_port);
+                                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                }
+                                                                tech_pvt-&gt;skype_callflow = SKYPIAX_STATE_UP;
+                                                                if (!strlen(tech_pvt-&gt;session_uuid_str)) {
+                                                                        DEBUGA_SKYPE(&quot;New Inbound Channel!\n\n\n\n&quot;, SKYPIAX_P_LOG);
+                                                                        new_inbound_channel(tech_pvt);
+                                                                } else {
+                                                                        DEBUGA_SKYPE(&quot;Outbound Channel Answered! session_uuid_str=%s\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;session_uuid_str);
+                                                                        outbound_channel_answered(tech_pvt);
+                                                                }
+                                                        } else {
+                                                                DEBUGA_SKYPE(&quot;I'm on %s, skype_call %s is NOT MY call, ignoring\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;skype_call_id, id);
+                                                        }
+                                                } else {
+                                                        tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                        DEBUGA_SKYPE(&quot;Back from REMOTEHOLD!\n&quot;, SKYPIAX_P_LOG);
+                                                }
+
+                                        } else if (!strcasecmp(value, &quot;REMOTEHOLD&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_REMOTEHOLD;
+                                                DEBUGA_SKYPE(&quot;skype_call: %s is now REMOTEHOLD\n&quot;, SKYPIAX_P_LOG, id);
+
+                                        } else if (!strcasecmp(value, &quot;BUSY&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE
+                                                        (&quot;we tried to call Skype on skype_call %s and remote party (destination) was BUSY. Our outbound call has failed\n&quot;,
+                                                         SKYPIAX_P_LOG, id);
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                skypiax_sleep(1000);
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else if (!strcasecmp(value, &quot;WAITING_REDIAL_COMMAND&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE
+                                                        (&quot;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&quot;,
+                                                         SKYPIAX_P_LOG, id);
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                skypiax_sleep(1000);
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else {
+                                                WARNINGA(&quot;skype_call: %s, STATUS: %s is not recognized\n&quot;, SKYPIAX_P_LOG, id, value);
+                                        }
+                                }                                //STATUS
+                        }                                        //CALL
+                        /* the &quot;numbered&quot; messages that follows are used by the directory application, not yet ported */
+                        if (!strcasecmp(message, &quot;#333&quot;)) {
+                                /* DEBUGA_SKYPE(&quot;Skype MSG: message_2: %s, message2[11]: %s\n&quot;, SKYPIAX_P_LOG,
+                                 * message_2, &amp;message_2[11]); */
+                                memset(tech_pvt-&gt;skype_friends, 0, 4096);
+                                skypiax_strncpy(tech_pvt-&gt;skype_friends, &amp;message_2[11], 4095);
+                        }
+                        if (!strcasecmp(message, &quot;#222&quot;)) {
+                                /* DEBUGA_SKYPE(&quot;Skype MSG: message_2: %s, message2[10]: %s\n&quot;, SKYPIAX_P_LOG,
+                                 * message_2, &amp;message_2[10]); */
+                                memset(tech_pvt-&gt;skype_fullname, 0, 512);
+                                skypiax_strncpy(tech_pvt-&gt;skype_fullname, &amp;message_2[10], 511);
+                        }
+                        if (!strcasecmp(message, &quot;#765&quot;)) {
+                                /* DEBUGA_SKYPE(&quot;Skype MSG: message_2: %s, message2[10]: %s\n&quot;, SKYPIAX_P_LOG,
+                                 * message_2, &amp;message_2[10]); */
+                                memset(tech_pvt-&gt;skype_displayname, 0, 512);
+                                skypiax_strncpy(tech_pvt-&gt;skype_displayname, &amp;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) &amp;&amp; !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, &amp;tech_pvt-&gt;tcp_srv_port);
+        if (s &lt; 0) {
+                ERRORA(&quot;skypiax_socket_create_and_bind error!\n&quot;, SKYPIAX_P_LOG);
+                return NULL;
+        }
+        DEBUGA_SKYPE(&quot;started tcp_srv_thread thread.\n&quot;, SKYPIAX_P_LOG);
+
+        listen(s, 6);
+
+        sin_size = sizeof(remote_addr);
+
+  /****************************/
+        while (tech_pvt-&gt;interface_state != SKYPIAX_STATE_DOWN
+                   &amp;&amp; (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                           || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                           || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt-&gt;skype_callflow == SKYPIAX_STATE_UP)) {
+
+                unsigned int fdselectgio;
+                int rtgio;
+                fd_set fsgio;
+                struct timeval togio;
+
+                if (!(running &amp;&amp; tech_pvt-&gt;running))
+                        break;
+                FD_ZERO(&amp;fsgio);
+                togio.tv_usec = 20000;        //20msec
+                togio.tv_sec = 0;
+                fdselectgio = s;
+                FD_SET(fdselectgio, &amp;fsgio);
+
+                rtgio = select(fdselectgio + 1, &amp;fsgio, NULL, NULL, &amp;togio);
+
+                if (rtgio) {
+
+  /****************************/
+
+                        while ((fd = accept(s, (struct sockaddr *) &amp;remote_addr, &amp;sin_size)) &gt; 0) {
+                                DEBUGA_SKYPE(&quot;ACCEPTED here I send you %d\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;tcp_srv_port);
+                                if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                        break;
+                                while (tech_pvt-&gt;interface_state != SKYPIAX_STATE_DOWN
+                                           &amp;&amp; (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                                                   || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                                                   || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt-&gt;skype_callflow == SKYPIAX_STATE_UP)) {
+
+                                        unsigned int fdselect;
+                                        int rt;
+                                        fd_set fs;
+                                        struct timeval to;
+
+                                        if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                                break;
+                                        //exit = 1;
+
+                                        fdselect = fd;
+                                        FD_ZERO(&amp;fs);
+                                        FD_SET(fdselect, &amp;fs);
+                                        //to.tv_usec = 2000000;     //2000 msec
+                                        to.tv_usec = 60000;        //60 msec
+                                        to.tv_sec = 0;
+
+                                        rt = select(fdselect + 1, &amp;fs, NULL, NULL, &amp;to);
+                                        if (rt &gt; 0) {
+
+                                                if (tech_pvt-&gt;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 &lt; 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 &lt; len / sizeof(short); i++) {
+                                                                        srv_out[i] = srv_in[i];
+                                                                }
+                                                        } else {
+                                                                ERRORA(&quot;SAMPLERATE_SKYPIAX can only be 8000 or 16000\n&quot;, SKYPIAX_P_LOG);
+                                                        }
+                                                        /* if not yet done, let's store the half incoming frame */
+                                                        if (!tech_pvt-&gt;audiobuf_is_loaded) {
+                                                                for (i = 0; i &lt; SAMPLES_PER_FRAME / 2; i++) {
+                                                                        tech_pvt-&gt;audiobuf[i] = srv_out[i];
+                                                                }
+                                                                tech_pvt-&gt;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 &lt; SAMPLES_PER_FRAME / 2; i++) {
+                                                                        totalbuf[i] = tech_pvt-&gt;audiobuf[i];
+                                                                }
+                                                                for (a = 0; a &lt; 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-&gt;audiopipe[1], totalbuf, SAMPLES_PER_FRAME * sizeof(short));
+                                                                if (howmany != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                        ERRORA(&quot;howmany is %d, but was expected to be %d\n&quot;, SKYPIAX_P_LOG,
+                                                                                   howmany, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                                }
+                                                                /* done with the stored half frame */
+                                                                tech_pvt-&gt;audiobuf_is_loaded = 0;
+                                                        }
+
+                                                } else if (len == 0) {
+                                                        skypiax_sleep(1000);
+                                                } else {
+                                                        DEBUGA_SKYPE(&quot;len=%d, expected 320\n&quot;, SKYPIAX_P_LOG, len);
+                                                }
+
+                                        } else {
+                                                if (rt)
+                                                        ERRORA(&quot;SRV rt=%d\n&quot;, 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-&gt;audiopipe[1], kill_cli_buff, kill_cli_size);
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt-&gt;audioskypepipe[1], kill_cli_buff, kill_cli_size);
+                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt-&gt;audiopipe[1], kill_cli_buff, kill_cli_size);
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt-&gt;audioskypepipe[1], kill_cli_buff, kill_cli_size);
+
+                                DEBUGA_SKYPE(&quot;Skype incoming audio GONE\n&quot;, SKYPIAX_P_LOG);
+                                skypiax_close_socket(fd);
+                                //if (exit)
+                                break;
+                        }
+                }
+        }
+
+        DEBUGA_SKYPE(&quot;incoming audio server (I am it) EXITING\n&quot;, SKYPIAX_P_LOG);
+        skypiax_close_socket(s);
+        tech_pvt-&gt;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, &amp;tech_pvt-&gt;tcp_cli_port);
+        if (s &lt; 0) {
+                ERRORA(&quot;skypiax_socket_create_and_bind error!\n&quot;, SKYPIAX_P_LOG);
+                return NULL;
+        }
+
+
+
+        DEBUGA_SKYPE(&quot;started tcp_cli_thread thread.\n&quot;, SKYPIAX_P_LOG);
+
+        listen(s, 6);
+
+        sin_size = sizeof(remote_addr);
+
+  /****************************/
+        while (tech_pvt-&gt;interface_state != SKYPIAX_STATE_DOWN
+                   &amp;&amp; (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                           || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                           || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt-&gt;skype_callflow == SKYPIAX_STATE_UP)) {
+
+                unsigned int fdselectgio;
+                int rtgio;
+                fd_set fsgio;
+                struct timeval togio;
+
+                if (!(running &amp;&amp; tech_pvt-&gt;running))
+                        break;
+                FD_ZERO(&amp;fsgio);
+                togio.tv_usec = 20000;        //20msec
+                togio.tv_sec = 0;
+                fdselectgio = s;
+                FD_SET(fdselectgio, &amp;fsgio);
+
+                rtgio = select(fdselectgio + 1, &amp;fsgio, NULL, NULL, &amp;togio);
+
+                if (rtgio) {
+
+  /****************************/
+
+                        while ((fd = accept(s, (struct sockaddr *) &amp;remote_addr, &amp;sin_size)) &gt; 0) {
+                                DEBUGA_SKYPE(&quot;ACCEPTED here you send me %d\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;tcp_cli_port);
+#ifndef WIN32
+                                fcntl(tech_pvt-&gt;audioskypepipe[0], F_SETFL, O_NONBLOCK);
+                                fcntl(tech_pvt-&gt;audioskypepipe[1], F_SETFL, O_NONBLOCK);
+#endif //WIN32
+
+                                if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                        break;
+                                while (tech_pvt-&gt;interface_state != SKYPIAX_STATE_DOWN
+                                           &amp;&amp; (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                                                   || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                                                   || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt-&gt;skype_callflow == SKYPIAX_STATE_UP)) {
+                                        unsigned int fdselect;
+                                        int rt;
+                                        fd_set fs;
+                                        struct timeval to;
+
+                                        if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                                break;
+                                        FD_ZERO(&amp;fs);
+                                        to.tv_usec = 120000;        //120msec
+                                        to.tv_sec = 0;
+#if defined(WIN32) &amp;&amp; !defined(__CYGWIN__)
+/* on win32 we cannot select from the apr &quot;pipe&quot;, so we select on socket writability */
+                                        fdselect = fd;
+                                        FD_SET(fdselect, &amp;fs);
+
+                                        rt = select(fdselect + 1, NULL, &amp;fs, NULL, &amp;to);
+#else
+/* on *unix and cygwin we select from the real pipe */
+                                        fdselect = tech_pvt-&gt;audioskypepipe[0];
+                                        FD_SET(fdselect, &amp;fs);
+
+                                        rt = select(fdselect + 1, &amp;fs, NULL, NULL, &amp;to);
+#endif
+
+                                        if (rt &gt; 0) {
+                                                int counter;
+
+                                                /* until we drained the pipe to empty */
+                                                for (counter = 0; counter &lt; 10; counter++) {
+                                                        /* read from the pipe the audio frame we are supposed to send out */
+                                                        got = skypiax_pipe_read(tech_pvt-&gt;audioskypepipe[0], cli_in, SAMPLES_PER_FRAME * sizeof(short));
+                                                        if (got == -1)
+                                                                break;
+
+                                                        if (got != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                WARNINGA(&quot;got is %d, but was expected to be %d\n&quot;, 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 &lt; 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 &lt; got / sizeof(short); i++) {
+                                                                                cli_out[i] = cli_in[i];
+                                                                        }
+                                                                } else {
+                                                                        ERRORA(&quot;SAMPLERATE_SKYPIAX can only be 8000 or 16000\n&quot;, 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-&gt;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(&quot;len=%d\n&quot;, SKYPIAX_P_LOG, len);
+                                                                                skypiax_sleep(1000);
+                                                                                break;
+                                                                        }
+                                                                }
+
+                                                        } else {
+
+                                                                WARNINGA(&quot;got is %d, but was expected to be %d\n&quot;, SKYPIAX_P_LOG, got, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                        }
+                                                }
+                                        } else {
+                                                if (rt)
+                                                        ERRORA(&quot;CLI rt=%d\n&quot;, SKYPIAX_P_LOG, rt);
+                                                memset(cli_out, 0, sizeof(cli_out));
+                                                if (tech_pvt-&gt;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(&quot;sent %d of zeros to keep the Skype client socket busy\n&quot;, SKYPIAX_P_LOG, sizeof(cli_out) + sizeof(cli_out)/2);
+                                                } else {
+                                                        /*
+                                                           XXX do nothing 
+                                                         */
+                                                        //WARNINGA(&quot;we don't send it\n&quot;, SKYPIAX_P_LOG);
+                                                }
+                                                skypiax_sleep(1000);
+                                        }
+
+                                }
+                                DEBUGA_SKYPE(&quot;Skype outbound audio GONE\n&quot;, SKYPIAX_P_LOG);
+                                skypiax_close_socket(fd);
+                                break;
+                        }
+                }
+        }
+
+        DEBUGA_SKYPE(&quot;outbound audio server (I am it) EXITING\n&quot;, SKYPIAX_P_LOG);
+        skypiax_close_socket(s);
+        tech_pvt-&gt;tcp_cli_thread = NULL;
+        return NULL;
+}
+
+int skypiax_audio_read(private_t * tech_pvt)
+{
+        unsigned int samples;
+
+        samples = skypiax_pipe_read(tech_pvt-&gt;audiopipe[0], tech_pvt-&gt;read_frame.data, SAMPLES_PER_FRAME * sizeof(short));
+
+        if (samples != SAMPLES_PER_FRAME * sizeof(short)) {
+                if (samples)
+                        WARNINGA(&quot;read samples=%u expected=%u\n&quot;, SKYPIAX_P_LOG, samples, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                return 0;
+        } else {
+                /* A real frame */
+                tech_pvt-&gt;read_frame.datalen = samples;
+        }
+        return 1;
+}
+
+int skypiax_senddigit(private_t * tech_pvt, char digit)
+{
+        char msg_to_skype[1024];
+
+        DEBUGA_SKYPE(&quot;DIGIT received: %c\n&quot;, SKYPIAX_P_LOG, digit);
+        sprintf(msg_to_skype, &quot;SET CALL %s DTMF %c&quot;, tech_pvt-&gt;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(&quot;Calling Skype, rdest is: %s\n&quot;, SKYPIAX_P_LOG, rdest);
+        //skypiax_signaling_write(tech_pvt, &quot;SET AGC OFF&quot;);
+        //skypiax_sleep(10000);
+        //skypiax_signaling_write(tech_pvt, &quot;SET AEC OFF&quot;);
+        //skypiax_sleep(10000);
+
+        sprintf(msg_to_skype, &quot;CALL %s&quot;, rdest);
+        if (skypiax_signaling_write(tech_pvt, msg_to_skype) &lt; 0) {
+                ERRORA(&quot;failed to communicate with Skype client, now exit\n&quot;, SKYPIAX_P_LOG);
+                return -1;
+        }
+        return 0;
+}
+
+/***************************/
+/* PLATFORM SPECIFIC */
+/***************************/
+#if defined(WIN32) &amp;&amp; !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, &amp;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, &amp;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(&amp;tech_pvt-&gt;audiopipe[0], &amp;tech_pvt-&gt;audiopipe[1], skypiax_module_pool);
+        rv = switch_file_pipe_create(&amp;tech_pvt-&gt;audioskypepipe[0], &amp;tech_pvt-&gt;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-&gt;audiopipe)) {
+                fcntl(tech_pvt-&gt;audiopipe[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt-&gt;audiopipe[1], F_SETFL, O_NONBLOCK);
+        }
+        if (pipe(tech_pvt-&gt;audioskypepipe)) {
+                fcntl(tech_pvt-&gt;audioskypepipe[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt-&gt;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-&gt;skypiax_sound_capt_fd = tech_pvt-&gt;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 &amp;&amp; !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(&quot;SENDING: |||%s||||\n&quot;, SKYPIAX_P_LOG, msg_to_skype);
+
+        sprintf(acInputRow, &quot;%s&quot;, msg_to_skype);
+        DEBUGA_SKYPE(&quot;acInputRow: |||%s||||\n&quot;, 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-&gt;SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle, WM_COPYDATA,
+                         (WPARAM) tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, (LPARAM) &amp; oCopyData) == FALSE) {
+                        ERRORA(&quot;Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax, then launch Skypiax and try again.\n&quot;, 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)-&gt;lpCreateParams;
+                SetWindowLong(hWindow, GWL_USERDATA, (LONG) tech_pvt);
+                DEBUGA_SKYPE(&quot;got CREATE\n&quot;, SKYPIAX_P_LOG);
+                break;
+        case WM_DESTROY:
+                DEBUGA_SKYPE(&quot;got DESTROY\n&quot;, SKYPIAX_P_LOG);
+                tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle = NULL;
+                PostQuitMessage(0);
+                break;
+        case WM_COPYDATA:
+                if (tech_pvt-&gt;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-&gt;lpData, sizeof(msg_from_skype) - 2);
+
+                        howmany = strlen(msg_from_skype) + 1;
+                        howmany = skypiax_pipe_write(tech_pvt-&gt;SkypiaxHandles.fdesc[1], (short *) msg_from_skype, howmany);
+                        //DEBUGA_SKYPE(&quot;From Skype API: %s\n&quot;, SKYPIAX_P_LOG, msg_from_skype);
+                        lReturnCode = 1;
+                }
+                break;
+        default:
+                if (tech_pvt &amp;&amp; tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+                        if (uiMessage == tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+                                switch (ulParam) {
+                                case SKYPECONTROLAPI_ATTACH_SUCCESS:
+                                        if (!tech_pvt-&gt;SkypiaxHandles.currentuserhandle) {
+                                                //DEBUGA_SKYPE(&quot;\n\n\tConnected to Skype API!\n&quot;, SKYPIAX_P_LOG);
+                                                tech_pvt-&gt;SkypiaxHandles.api_connected = 1;
+                                                tech_pvt-&gt;SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle = (HWND) uiParam;
+                                                tech_pvt-&gt;SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle = tech_pvt-&gt;SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle;
+                                        }
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION:
+                                        //DEBUGA_SKYPE (&quot;\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&quot;, SKYPIAX_P_LOG);
+                                        skypiax_sleep(5000);
+#if 0
+                                        if (!tech_pvt-&gt;SkypiaxHandles.currentuserhandle) {
+                                                SendMessage(HWND_BROADCAST,
+                                                                        tech_pvt-&gt;SkypiaxHandles.
+                                                                        win32_uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM) tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, 0);
+                                        }
+#endif
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_REFUSED:
+                                        ERRORA(&quot;Skype client refused to be connected by Skypiax!\n&quot;, SKYPIAX_P_LOG);
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE:
+                                        ERRORA(&quot;Skype API not (yet?) available\n&quot;, SKYPIAX_P_LOG);
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_API_AVAILABLE:
+                                        DEBUGA_SKYPE(&quot;Skype API available\n&quot;, SKYPIAX_P_LOG);
+                                        skypiax_sleep(5000);
+#if 0
+                                        if (!tech_pvt-&gt;SkypiaxHandles.currentuserhandle) {
+                                                SendMessage(HWND_BROADCAST,
+                                                                        tech_pvt-&gt;SkypiaxHandles.
+                                                                        win32_uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM) tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, 0);
+                                        }
+#endif
+                                        break;
+                                default:
+                                        WARNINGA(&quot;GOT AN UNKNOWN SKYPE WINDOWS MSG\n&quot;, 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(&amp;oUUID);
+        tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle = (HINSTANCE) OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
+        if (tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle != NULL &amp;&amp; (lUUIDResult == RPC_S_OK || lUUIDResult == RPC_S_UUID_LOCAL_ONLY)) {
+                if (UuidToString(&amp;oUUID, &amp;paucUUIDString) == RPC_S_OK) {
+                        WNDCLASS oWindowClass;
+
+                        strcpy(tech_pvt-&gt;SkypiaxHandles.win32_acInit_WindowClassName, &quot;Skype-API-Skypiax-&quot;);
+                        strcat(tech_pvt-&gt;SkypiaxHandles.win32_acInit_WindowClassName, (char *) paucUUIDString);
+
+                        oWindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+                        oWindowClass.lpfnWndProc = (WNDPROC) &amp; skypiax_present;
+                        oWindowClass.cbClsExtra = 0;
+                        oWindowClass.cbWndExtra = 0;
+                        oWindowClass.hInstance = tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle;
+                        oWindowClass.hIcon = NULL;
+                        oWindowClass.hCursor = NULL;
+                        oWindowClass.hbrBackground = NULL;
+                        oWindowClass.lpszMenuName = NULL;
+                        oWindowClass.lpszClassName = tech_pvt-&gt;SkypiaxHandles.win32_acInit_WindowClassName;
+
+                        if (RegisterClass(&amp;oWindowClass) != 0)
+                                fReturnStatus = 1;
+
+                        RpcStringFree(&amp;paucUUIDString);
+                }
+        }
+        if (fReturnStatus == 0)
+                CloseHandle(tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle);
+        tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle = NULL;
+        return (fReturnStatus);
+}
+
+void win32_DeInitialize_DestroyWindowClass(private_t * tech_pvt)
+{
+        UnregisterClass(tech_pvt-&gt;SkypiaxHandles.win32_acInit_WindowClassName, tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle);
+        CloseHandle(tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle);
+        tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle = NULL;
+}
+
+int win32_Initialize_CreateMainWindow(private_t * tech_pvt)
+{
+        tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle =
+                CreateWindowEx(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,
+                                           tech_pvt-&gt;SkypiaxHandles.win32_acInit_WindowClassName, &quot;&quot;,
+                                           WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT,
+                                           128, 128, NULL, 0, tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle, tech_pvt);
+        return (tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle != NULL ? 1 : 0);
+}
+
+void win32_DeInitialize_DestroyMainWindow(private_t * tech_pvt)
+{
+        if (tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle != NULL)
+                DestroyWindow(tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle), tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle = NULL;
+}
+
+void *skypiax_do_skypeapi_thread_func(void *obj)
+{
+        private_t *tech_pvt = obj;
+#if defined(WIN32) &amp;&amp; !defined(__CYGWIN__)
+        switch_status_t rv;
+
+        switch_file_pipe_create(&amp;tech_pvt-&gt;SkypiaxHandles.fdesc[0], &amp;tech_pvt-&gt;SkypiaxHandles.fdesc[1], skypiax_module_pool);
+        rv = switch_file_pipe_create(&amp;tech_pvt-&gt;SkypiaxHandles.fdesc[0], &amp;tech_pvt-&gt;SkypiaxHandles.fdesc[1], skypiax_module_pool);
+#else /* WIN32 */
+        if (pipe(tech_pvt-&gt;SkypiaxHandles.fdesc)) {
+                fcntl(tech_pvt-&gt;SkypiaxHandles.fdesc[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt-&gt;SkypiaxHandles.fdesc[1], F_SETFL, O_NONBLOCK);
+        }
+#endif /* WIN32 */
+
+        tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach = RegisterWindowMessage(&quot;SkypeControlAPIAttach&quot;);
+        tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover = RegisterWindowMessage(&quot;SkypeControlAPIDiscover&quot;);
+
+        skypiax_sleep(200000);                //0,2 sec
+
+        if (tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach != 0
+                &amp;&amp; tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover != 0) {
+                if (win32_Initialize_CreateWindowClass(tech_pvt)) {
+                        if (win32_Initialize_CreateMainWindow(tech_pvt)) {
+                                if (SendMessage
+                                        (HWND_BROADCAST,
+                                         tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover,
+                                         (WPARAM) tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, 0) != 0) {
+                                        tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle = tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle;
+                                        while (running &amp;&amp; tech_pvt-&gt;running) {
+                                                MSG oMessage;
+                                                if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                                        break;
+                                                while (GetMessage(&amp;oMessage, 0, 0, 0)) {
+                                                        TranslateMessage(&amp;oMessage);
+                                                        DispatchMessage(&amp;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-&gt;error_code;
+        ERRORA(&quot;Received error code %d from X Server\n\n&quot;, 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) &amp;&amp; (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-&gt;skype_win;
+        disp = SkypiaxHandles-&gt;disp;
+        handle_P = SkypiaxHandles-&gt;win;
+
+        Atom atom1 = XInternAtom(disp, &quot;SKYPECONTROLAPI_MESSAGE_BEGIN&quot;, False);
+        Atom atom2 = XInternAtom(disp, &quot;SKYPECONTROLAPI_MESSAGE&quot;, False);
+        unsigned int pos = 0;
+        unsigned int len = strlen(message_P);
+        XEvent e;
+
+        memset(&amp;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 &lt; 20 &amp;&amp; i + pos &lt;= len; ++i)
+                        e.xclient.data.b[i] = message_P[i + pos];
+                XSendEvent(disp, w_P, False, 0, &amp;e);
+
+                e.xclient.message_type = atom2;        /*  following messages */
+                pos += i;
+        } while (pos &lt;= len);
+
+        XSync(disp, False);
+        ok = X11_errors_untrap();
+
+        if (!ok)
+                ERRORA(&quot;Sending message failed with status %d\n&quot;, 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(&quot;SENDING: |||%s||||\n&quot;, SKYPIAX_P_LOG, msg_to_skype);
+
+        SkypiaxHandles = &amp;tech_pvt-&gt;SkypiaxHandles;
+
+        if (!skypiax_send_message(SkypiaxHandles, msg_to_skype)) {
+                ERRORA
+                        (&quot;Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax, then restart Skype, then launch Skypiax and try again.\n&quot;,
+                         SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        return 0;
+
+}
+
+int skypiax_present(struct SkypiaxHandles *SkypiaxHandles)
+{
+        Atom skype_inst = XInternAtom(SkypiaxHandles-&gt;disp, &quot;_SKYPE_INSTANCE&quot;, 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-&gt;disp, DefaultRootWindow(SkypiaxHandles-&gt;disp),
+                                                   skype_inst, 0, 1, False, XA_WINDOW, &amp;type_ret, &amp;format_ret, &amp;nitems_ret, &amp;bytes_after_ret, &amp;prop);
+        //XUnlockDisplay(disp);
+        X11_errors_untrap();
+
+        /*  sanity check */
+        if (status != Success || format_ret != 32 || nitems_ret != 1) {
+                SkypiaxHandles-&gt;skype_win = (Window) - 1;
+                DEBUGA_SKYPE(&quot;Skype instance not found\n&quot;, SKYPIAX_P_LOG);
+                running = 0;
+                SkypiaxHandles-&gt;api_connected = 0;
+                return 0;
+        }
+
+        SkypiaxHandles-&gt;skype_win = *(const unsigned long *) prop &amp; 0xffffffff;
+        DEBUGA_SKYPE(&quot;Skype instance found with id #%d\n&quot;, SKYPIAX_P_LOG, (unsigned int) SkypiaxHandles-&gt;skype_win);
+        SkypiaxHandles-&gt;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(&quot;to be destroyed disp %d\n&quot;, SKYPIAX_P_LOG, disp);
+                close(disp);
+                DEBUGA_SKYPE(&quot;destroyed disp\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                DEBUGA_SKYPE(&quot;NOT destroyed disp\n&quot;, SKYPIAX_P_LOG);
+        }
+        DEBUGA_SKYPE(&quot;OUT destroyed disp\n&quot;, 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-&gt;X11_display))
+                strcpy(tech_pvt-&gt;X11_display, getenv(&quot;DISPLAY&quot;));
+
+        if (!tech_pvt-&gt;tcp_srv_port)
+                tech_pvt-&gt;tcp_srv_port = 10160;
+
+        if (!tech_pvt-&gt;tcp_cli_port)
+                tech_pvt-&gt;tcp_cli_port = 10161;
+
+        if (pipe(tech_pvt-&gt;SkypiaxHandles.fdesc)) {
+                fcntl(tech_pvt-&gt;SkypiaxHandles.fdesc[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt-&gt;SkypiaxHandles.fdesc[1], F_SETFL, O_NONBLOCK);
+        }
+        SkypiaxHandles = &amp;tech_pvt-&gt;SkypiaxHandles;
+        disp = XOpenDisplay(tech_pvt-&gt;X11_display);
+        if (!disp) {
+                ERRORA(&quot;Cannot open X Display '%s', exiting skype thread\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;X11_display);
+                running = 0;
+                return NULL;
+        } else {
+                DEBUGA_SKYPE(&quot;X Display '%s' opened\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;X11_display);
+        }
+
+        int xfd;
+        xfd = XConnectionNumber(disp);
+        fcntl(xfd, F_SETFD, FD_CLOEXEC);
+
+        SkypiaxHandles-&gt;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-&gt;win = win;
+
+                snprintf(buf, 512, &quot;NAME skypiax&quot;);
+
+                if (!skypiax_send_message(SkypiaxHandles, buf)) {
+                        ERRORA(&quot;Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n&quot;, SKYPIAX_P_LOG);
+                        running = 0;
+                        return NULL;
+                }
+
+                snprintf(buf, 512, &quot;PROTOCOL 7&quot;);
+                if (!skypiax_send_message(SkypiaxHandles, buf)) {
+                        ERRORA(&quot;Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n&quot;, 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, &quot;SKYPECONTROLAPI_MESSAGE_BEGIN&quot;, False);
+                Atom atom_continue = XInternAtom(disp, &quot;SKYPECONTROLAPI_MESSAGE&quot;, False);
+
+                b = buffer;
+
+                while (1) {
+                        XNextEvent(disp, &amp;an_event);
+                        if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                break;
+                        switch (an_event.type) {
+                        case ClientMessage:
+
+                                if (an_event.xclient.format != 8)
+                                        break;
+
+                                for (i = 0; i &lt; 20 &amp;&amp; an_event.xclient.data.b[i] != '\0'; ++i)
+                                        buf[i] = an_event.xclient.data.b[i];
+
+                                buf[i] = '\0';
+
+                                //DEBUGA_SKYPE (&quot;BUF=|||%s|||\n&quot;, 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-&gt;fdesc[1], b, howmany);
+                                                DEBUGA_SKYPE(&quot;RECEIVED2=|||%s|||\n&quot;, SKYPIAX_P_LOG, buffer);
+                                                memset(buffer, '\0', 17000);
+                                        }
+                                }
+                                if (an_event.xclient.message_type == atom_continue) {
+
+                                        if (!strlen(buffer)) {
+                                                DEBUGA_SKYPE
+                                                        (&quot;Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||\n&quot;, SKYPIAX_P_LOG, buf);
+                                                continue_is_broken = 1;
+                                                if (!strncmp(buf, &quot;ognised identity&quot;, 15)) {
+                                                        WARNINGA
+                                                                (&quot;Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||. Let's introduce a 1 second delay.\n&quot;,
+                                                                 SKYPIAX_P_LOG, buf);
+                                                        skypiax_sleep(1000000);        //1 sec
+                                                }
+                                                break;
+                                        }
+                                }
+
+                                strcat(buffer, buf);
+
+                                if (i &lt; 20 || continue_is_broken) {        /* last fragment */
+                                        unsigned int howmany;
+
+                                        howmany = strlen(b) + 1;
+
+                                        howmany = write(SkypiaxHandles-&gt;fdesc[1], b, howmany);
+                                        //DEBUGA_SKYPE (&quot;RECEIVED=|||%s|||\n&quot;, SKYPIAX_P_LOG, buffer);
+                                        memset(buffer, '\0', 17000);
+                                        XFlush(disp);
+                                        continue_is_broken = 0;
+                                }
+
+                                break;
+                        default:
+                                break;
+                        }
+                }
+        } else {
+                ERRORA(&quot;Skype is not running, maybe crashed. Please run/restart Skype and relaunch Skypiax\n&quot;, 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 &lt;anthmct@yahoo.com&gt;
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the &quot;License&quot;); 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 &quot;AS IS&quot; 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 &lt;anthmct@yahoo.com&gt;
+ * 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 &quot;skypiax.h&quot;
+
+#ifdef WIN32
+/***************/
+// from http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
+
+#include &lt;time.h&gt;
+
+#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(&amp;ft);
+                tmpres |= ft.dwHighDateTime;
+                tmpres &lt;&lt;= 32;
+                tmpres |= ft.dwLowDateTime;
+
+                /*converting file time to unix epoch */
+                tmpres /= 10;                        /*convert into microseconds */
+                tmpres -= DELTA_EPOCH_IN_MICROSECS;
+                tv-&gt;tv_sec = (long) (tmpres / 1000000UL);
+                tv-&gt;tv_usec = (long) (tmpres % 1000000UL);
+        }
+        if (NULL != tz) {
+                if (!tzflag) {
+                        _tzset();
+                        tzflag++;
+                }
+                tz-&gt;tz_minuteswest = _timezone / 60;
+                tz-&gt;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 &quot;list [full] || console || skype_API_msg || remove &lt; skypeusername | #interface_name | #interface_id &gt; || reload&quot;
+/* END: Changes heres */
+SWITCH_STANDARD_API(skypiax_function);
+#define SKYPIAX_SYNTAX &quot;interface_name skype_API_msg&quot;
+
+/* 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 */
+        &quot;IDLE&quot;,
+        &quot;DOWN&quot;,
+        &quot;RING&quot;,
+        &quot;DIALING&quot;,
+        &quot;BUSY&quot;,
+        &quot;UP&quot;,
+        &quot;RINGING&quot;,
+        &quot;PRERING&quot;,
+        &quot;DOUBLE&quot;,
+        &quot;SELECTD&quot;,
+        &quot;HANG_RQ&quot;,
+        &quot;PREANSW&quot;
+};
+char *skype_callflow[] = {                /* should match CALLFLOW_XXX in skypiax.h */
+        &quot;CALL_IDLE&quot;,
+        &quot;CALL_DOWN&quot;,
+        &quot;INCOMING_RNG&quot;,
+        &quot;CALL_DIALING&quot;,
+        &quot;CALL_LINEBUSY&quot;,
+        &quot;CALL_ACTIVE&quot;,
+        &quot;INCOMING_HNG&quot;,
+        &quot;CALL_RLEASD&quot;,
+        &quot;CALL_NOCARR&quot;,
+        &quot;CALL_INFLUX&quot;,
+        &quot;CALL_INCOMING&quot;,
+        &quot;CALL_FAILED&quot;,
+        &quot;CALL_NOSRVC&quot;,
+        &quot;CALL_OUTRESTR&quot;,
+        &quot;CALL_SECFAIL&quot;,
+        &quot;CALL_NOANSWER&quot;,
+        &quot;STATUS_FNSHED&quot;,
+        &quot;STATUS_CANCLED&quot;,
+        &quot;STATUS_FAILED&quot;,
+        &quot;STATUS_REFUSED&quot;,
+        &quot;STATUS_RINGING&quot;,
+        &quot;STATUS_INPROGRS&quot;,
+        &quot;STATUS_UNPLACD&quot;,
+        &quot;STATUS_ROUTING&quot;,
+        &quot;STATUS_EARLYMD&quot;,
+        &quot;INCOMING_CLID&quot;,
+        &quot;STATUS_RMTEHOLD&quot;
+};
+
+
+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
+                (&amp;tech_pvt-&gt;read_codec, &quot;L16&quot;, NULL, sample_rate, codec_ms, 1,
+                 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+                ERRORA(&quot;Can't load codec?\n&quot;, SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+
+        if (switch_core_codec_init
+                (&amp;tech_pvt-&gt;write_codec, &quot;L16&quot;, NULL, sample_rate, codec_ms, 1,
+                 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+                ERRORA(&quot;Can't load codec?\n&quot;, SKYPIAX_P_LOG);
+                switch_core_codec_destroy(&amp;tech_pvt-&gt;read_codec);
+                return SWITCH_STATUS_FALSE;
+        }
+
+        tech_pvt-&gt;read_frame.rate = sample_rate;
+        tech_pvt-&gt;read_frame.codec = &amp;tech_pvt-&gt;read_codec;
+
+        session = switch_core_session_locate(tech_pvt-&gt;session_uuid_str);
+
+        if (session) {
+                switch_core_session_set_read_codec(session, &amp;tech_pvt-&gt;read_codec);
+                switch_core_session_set_write_codec(session, &amp;tech_pvt-&gt;write_codec);
+                switch_core_session_rwunlock(session);
+        } else {
+                ERRORA(&quot;no session\n&quot;, 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-&gt;read_frame.data = tech_pvt-&gt;databuf;
+        tech_pvt-&gt;read_frame.buflen = sizeof(tech_pvt-&gt;databuf);
+        switch_mutex_init(&amp;tech_pvt-&gt;mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+        switch_mutex_init(&amp;tech_pvt-&gt;flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+        switch_core_session_set_private(session, tech_pvt);
+        switch_copy_string(tech_pvt-&gt;session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt-&gt;session_uuid_str));
+        if (!strlen(tech_pvt-&gt;session_uuid_str)) {
+                ERRORA(&quot;no tech_pvt-&gt;session_uuid_str\n&quot;, SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+        if (skypiax_codec(tech_pvt, SAMPLERATE_SKYPIAX, 20) != SWITCH_STATUS_SUCCESS) {
+                ERRORA(&quot;skypiax_codec FAILED\n&quot;, SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+        DEBUGA_SKYPE(&quot;skypiax_codec SUCCESS\n&quot;, 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 &gt; 0 || (interface_id == 0 &amp;&amp; strcmp(the_interface, &quot;0&quot;) == 0)) {
+                        if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                                return SWITCH_STATUS_SUCCESS;
+                        }
+                } else {
+                        /* interface name */
+                        for (interface_id = 0; interface_id &lt; 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 &lt; 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 &gt; 0 || (interface_id == 0 &amp;&amp; strcmp(the_interface, &quot;0&quot;) == 0)) {
+                        /* take a number as interface id */
+                        tech_pvt = &amp;globals.SKYPIAX_INTERFACES[interface_id];
+                } else {
+
+                        for (interface_id = 0; interface_id &lt; SKYPIAX_MAX_INTERFACES; interface_id++) {
+                                if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].name, the_interface) == 0) {
+                                        tech_pvt = &amp;globals.SKYPIAX_INTERFACES[interface_id];
+                                        break;
+                                }
+                        }
+                }
+        } else {                                        /* remove by skype_user */
+                for (interface_id = 0; interface_id &lt; SKYPIAX_MAX_INTERFACES; interface_id++) {
+                        if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].skype_user, the_interface) == 0) {
+                                tech_pvt = &amp;globals.SKYPIAX_INTERFACES[interface_id];
+                                break;
+                        }
+                }
+        }
+
+        if (!tech_pvt) {
+                DEBUGA_SKYPE(&quot;interface '%s' does not exist\n&quot;, SKYPIAX_P_LOG, the_interface);
+                goto end;
+        }
+
+        if (strlen(globals.SKYPIAX_INTERFACES[interface_id].session_uuid_str)) {
+                DEBUGA_SKYPE(&quot;interface '%s' is busy\n&quot;, 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-&gt;SkypiaxHandles.fdesc[1], &quot;sciutati&quot;, &amp;howmany);        // let's the controldev_thread die
+#else /* WIN32 */
+                howmany = write(tech_pvt-&gt;SkypiaxHandles.fdesc[1], &quot;sciutati&quot;, howmany);
+#endif /* WIN32 */
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+#ifdef WIN32
+                if (SendMessage(tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {        // let's the skypiax_api_thread_func die
+                        DEBUGA_SKYPE(&quot;got FALSE here, thread probably was already dead. GetLastError returned: %d\n&quot;, SKYPIAX_P_LOG, GetLastError());
+                        globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread = NULL;
+                }
+#else
+                XEvent e;
+                Atom atom1 = XInternAtom(tech_pvt-&gt;SkypiaxHandles.disp, &quot;SKYPECONTROLAPI_MESSAGE_BEGIN&quot;, False);
+                memset(&amp;e, 0, sizeof(e));
+                e.xclient.type = ClientMessage;
+                e.xclient.message_type = atom1;        /*  leading message */
+                e.xclient.display = tech_pvt-&gt;SkypiaxHandles.disp;
+                e.xclient.window = tech_pvt-&gt;SkypiaxHandles.skype_win;
+                e.xclient.format = 8;
+
+                XSendEvent(tech_pvt-&gt;SkypiaxHandles.disp, tech_pvt-&gt;SkypiaxHandles.win, False, 0, &amp;e);
+                XSync(tech_pvt-&gt;SkypiaxHandles.disp, False);
+#endif
+        }
+
+        while (x) {
+                x--;
+                switch_yield(50000);
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
+                switch_thread_join(&amp;status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread);
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+                switch_thread_join(&amp;status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread);
+        }
+
+        switch_mutex_lock(globals.mutex);
+        if (globals.sk_console == &amp;globals.SKYPIAX_INTERFACES[interface_id]) {
+                DEBUGA_SKYPE(&quot;interface '%s' no more console\n&quot;, SKYPIAX_P_LOG, the_interface);
+                globals.sk_console = NULL;
+        } else {
+                DEBUGA_SKYPE(&quot;interface '%s' STILL console\n&quot;, SKYPIAX_P_LOG, the_interface);
+        }
+        memset(&amp;globals.SKYPIAX_INTERFACES[interface_id], '\0', sizeof(private_t));
+        globals.real_interfaces--;
+        switch_mutex_unlock(globals.mutex);
+
+        DEBUGA_SKYPE(&quot;interface '%s' deleted successfully\n&quot;, 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(&quot;%s CHANNEL INIT\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL INIT %s\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL DESTROY %s\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;name, switch_core_session_get_uuid(session));
+
+                if (switch_core_codec_ready(&amp;tech_pvt-&gt;read_codec)) {
+                        switch_core_codec_destroy(&amp;tech_pvt-&gt;read_codec);
+                }
+
+                if (switch_core_codec_ready(&amp;tech_pvt-&gt;write_codec)) {
+                        switch_core_codec_destroy(&amp;tech_pvt-&gt;write_codec);
+                }
+                *tech_pvt-&gt;session_uuid_str = '\0';
+                tech_pvt-&gt;interface_state = SKYPIAX_STATE_IDLE;
+                if (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_FINISHED) {
+                        tech_pvt-&gt;skype_callflow = CALLFLOW_CALL_IDLE;
+                }
+                switch_core_session_set_private(session, NULL);
+        } else {
+                DEBUGA_SKYPE(&quot;!!!!!!NO tech_pvt!!!! CHANNEL DESTROY %s\n&quot;, 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-&gt;ob_failed_calls++;
+                } else {
+                        tech_pvt-&gt;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-&gt;skype_call_id)) {
+                //switch_thread_cond_signal(tech_pvt-&gt;cond);
+                DEBUGA_SKYPE(&quot;hanging up skype call: %s\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;skype_call_id);
+                sprintf(msg_to_skype, &quot;ALTER CALL %s HANGUP&quot;, tech_pvt-&gt;skype_call_id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+        }
+        //memset(tech_pvt-&gt;session_uuid_str, '\0', sizeof(tech_pvt-&gt;session_uuid_str));
+        //*tech_pvt-&gt;session_uuid_str = '\0';
+        DEBUGA_SKYPE(&quot;%s CHANNEL HANGUP\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;name);
+        switch_mutex_lock(globals.mutex);
+        globals.calls--;
+        if (globals.calls &lt; 0) {
+                globals.calls = 0;
+        }
+
+        tech_pvt-&gt;interface_state = SKYPIAX_STATE_IDLE;
+        if (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_FINISHED) {
+                tech_pvt-&gt;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(&quot;%s CHANNEL ROUTING\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL EXECUTE\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL KILL_CHANNEL\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;name);
+        switch (sig) {
+        case SWITCH_SIG_KILL:
+                DEBUGA_SKYPE(&quot;%s CHANNEL got SWITCH_SIG_KILL\n&quot;, SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                //switch_mutex_lock(tech_pvt-&gt;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-&gt;flag_mutex);
+                break;
+        case SWITCH_SIG_BREAK:
+                DEBUGA_SKYPE(&quot;%s CHANNEL got SWITCH_SIG_BREAK\n&quot;, SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                //switch_set_flag(tech_pvt, TFLAG_BREAK);
+                //switch_mutex_lock(tech_pvt-&gt;flag_mutex);
+                switch_set_flag(tech_pvt, TFLAG_BREAK);
+                //switch_mutex_unlock(tech_pvt-&gt;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(&quot;%s CHANNEL CONSUME_MEDIA\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL EXCHANGE_MEDIA\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL SOFT_EXECUTE\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL SEND_DTMF\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;name);
+        DEBUGA_SKYPE(&quot;DTMF: %c\n&quot;, SKYPIAX_P_LOG, dtmf-&gt;digit);
+
+        skypiax_senddigit(tech_pvt, dtmf-&gt;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(&quot;channel not ready \n&quot;, SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                return SWITCH_STATUS_FALSE;
+        }
+
+        tech_pvt-&gt;read_frame.flags = SFF_NONE;
+        *frame = NULL;
+
+        if (!skypiax_audio_read(tech_pvt)) {
+
+                ERRORA(&quot;skypiax_audio_read ERROR\n&quot;, 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(&quot;CHANNEL READ FRAME goto CNG\n&quot;, SKYPIAX_P_LOG);
+                        goto cng;
+                }
+
+                if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
+                        DEBUGA_SKYPE(&quot;CHANNEL READ FRAME not IO\n&quot;, SKYPIAX_P_LOG);
+                        return SWITCH_STATUS_FALSE;
+                }
+
+                if (switch_test_flag(tech_pvt, TFLAG_IO) &amp;&amp; switch_test_flag(tech_pvt, TFLAG_VOICE)) {
+                        switch_clear_flag(tech_pvt, TFLAG_VOICE);
+                        if (!tech_pvt-&gt;read_frame.datalen) {
+                                DEBUGA_SKYPE(&quot;CHANNEL READ CONTINUE\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        *frame = &amp;tech_pvt-&gt;read_frame;
+#ifdef BIGENDIAN
+                        if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+                                switch_swap_linear((*frame)-&gt;data, (int) (*frame)-&gt;datalen / 2);
+                        }
+#endif
+                        return SWITCH_STATUS_SUCCESS;
+                }
+
+                DEBUGA_SKYPE(&quot;CHANNEL READ no TFLAG_IO\n&quot;, SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+
+        }
+
+        DEBUGA_SKYPE(&quot;CHANNEL READ FALSE\n&quot;, SKYPIAX_P_LOG);
+        return SWITCH_STATUS_FALSE;
+
+  cng:
+        data = (switch_byte_t *) tech_pvt-&gt;read_frame.data;
+        data[0] = 65;
+        data[1] = 0;
+        tech_pvt-&gt;read_frame.datalen = 2;
+        tech_pvt-&gt;read_frame.flags = SFF_CNG;
+        *frame = &amp;tech_pvt-&gt;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(&quot;channel not ready \n&quot;, 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-&gt;data, (int) frame-&gt;datalen / 2);
+        }
+#endif
+
+        sent = frame-&gt;datalen;
+#ifdef WIN32
+        switch_file_write(tech_pvt-&gt;audioskypepipe[1], frame-&gt;data, &amp;sent);
+#else /* WIN32 */
+        sent = write(tech_pvt-&gt;audioskypepipe[1], frame-&gt;data, sent);
+#endif /* WIN32 */
+        if (sent != frame-&gt;datalen &amp;&amp; sent != -1) {
+                DEBUGA_SKYPE(&quot;CLI PIPE write %d\n&quot;, 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(&quot;ANSWERED! \n&quot;, 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-&gt;message_id) {
+        case SWITCH_MESSAGE_INDICATE_ANSWER:
+                {
+                        DEBUGA_SKYPE(&quot;MSG_ID=%d, TO BE ANSWERED!\n&quot;, SKYPIAX_P_LOG, msg-&gt;message_id);
+                        channel_answer_channel(session);
+                }
+                break;
+        default:
+                {
+                        DEBUGA_SKYPE(&quot;MSG_ID=%d\n&quot;, SKYPIAX_P_LOG, msg-&gt;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 = &quot;&quot;;
+        }
+
+        WARNINGA(&quot;event: |||%s|||\n&quot;, 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(&quot;1 SESSION_REQUEST %s\n&quot;, SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+                switch_core_session_add_stream(*new_session, NULL);
+
+
+                if (!switch_strlen_zero(outbound_profile-&gt;destination_number)) {
+                        int i;
+                        char *slash;
+
+                        switch_copy_string(interface_name, outbound_profile-&gt;destination_number, 255);
+                        slash = strrchr(interface_name, '/');
+                        *slash = '\0';
+
+                        switch_mutex_lock(globals.mutex);
+                        if (strncmp(&quot;ANY&quot;, interface_name, strlen(interface_name)) == 0 || strncmp(&quot;RR&quot;, interface_name, strlen(interface_name)) == 0) {
+                                /* we've been asked for the &quot;ANY&quot; interface, let's find the first idle interface */
+                                //DEBUGA_SKYPE(&quot;Finding one available skype interface\n&quot;, SKYPIAX_P_LOG);
+                                //tech_pvt = find_available_skypiax_interface(NULL);
+                                //if (tech_pvt)
+                                //found = 1;
+                                //} else if (strncmp(&quot;RR&quot;, interface_name, strlen(interface_name)) == 0) {
+                                /* Find the first idle interface using Round Robin */
+                                DEBUGA_SKYPE(&quot;Finding one available skype interface RR\n&quot;, SKYPIAX_P_LOG);
+                                tech_pvt = find_available_skypiax_interface_rr(NULL);
+                                if (tech_pvt)
+                                        found = 1;
+                        }
+
+                        for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                                /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the &quot;ANY&quot; interface */
+                                if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                                        &amp;&amp; (strncmp(globals.SKYPIAX_INTERFACES[i].name, interface_name, strlen(interface_name)) == 0)) {
+                                        if (strlen(globals.SKYPIAX_INTERFACES[i].session_uuid_str)) {
+                                                DEBUGA_SKYPE
+                                                        (&quot;globals.SKYPIAX_INTERFACES[%d].name=|||%s||| session_uuid_str=|||%s||| is BUSY\n&quot;,
+                                                         SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name, globals.SKYPIAX_INTERFACES[i].session_uuid_str);
+                                                DEBUGA_SKYPE(&quot;1 SESSION_DESTROY %s\n&quot;, 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(&quot;globals.SKYPIAX_INTERFACES[%d].name=|||%s|||?\n&quot;, SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name);
+                                        tech_pvt = &amp;globals.SKYPIAX_INTERFACES[i];
+                                        found = 1;
+                                        break;
+                                }
+
+                        }
+
+                } else {
+                        ERRORA(&quot;Doh! no destination number?\n&quot;, SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+
+                if (!found) {
+                        DEBUGA_SKYPE(&quot;Doh! no available interface for |||%s|||?\n&quot;, SKYPIAX_P_LOG, interface_name);
+                        DEBUGA_SKYPE(&quot;2 SESSION_DESTROY %s\n&quot;, 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(&quot;Doh! no channel?\n&quot;, 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(&quot;Doh! no tech_init?\n&quot;, 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), &quot;skypiax/%s&quot;, outbound_profile-&gt;destination_number);
+                        //snprintf(name, sizeof(name), &quot;skypiax/%s&quot;, tech_pvt-&gt;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-&gt;caller_profile = caller_profile;
+                } else {
+                        ERRORA(&quot;Doh! no caller profile\n&quot;, SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        switch_mutex_unlock(globals.mutex);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+
+                tech_pvt-&gt;ob_calls++;
+
+                rdest = strchr(caller_profile-&gt;destination_number, '/');
+                *rdest++ = '\0';
+
+                //skypiax_call(tech_pvt, rdest, 30);
+
+                switch_copy_string(tech_pvt-&gt;session_uuid_str, switch_core_session_get_uuid(*new_session), sizeof(tech_pvt-&gt;session_uuid_str));
+                caller_profile = tech_pvt-&gt;caller_profile;
+                caller_profile-&gt;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(&quot;Doh! no new_session\n&quot;, 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(&quot;In skypiax_signaling_thread_func: started, p=%p\n&quot;, SKYPIAX_P_LOG, (void *) tech_pvt);
+
+        while (forever) {
+                if (!(running &amp;&amp; tech_pvt-&gt;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(&quot;skype call ended\n&quot;, SKYPIAX_P_LOG);
+
+                        if (tech_pvt) {
+                                session = switch_core_session_locate(tech_pvt-&gt;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 &lt; CS_EXECUTE) {
+                                                        switch_sleep(10000);        //10 msec, let the state evolve from CS_NEW
+                                                }
+                                                switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+                                        } else {
+                                                ERRORA(&quot;no channel?\n&quot;, SKYPIAX_P_LOG);
+                                        }
+                                        switch_core_session_rwunlock(session);
+                                } else {
+                                        DEBUGA_SKYPE(&quot;no session\n&quot;, SKYPIAX_P_LOG);
+                                }
+                                switch_mutex_lock(globals.mutex);
+                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                *tech_pvt-&gt;session_uuid_str = '\0';
+                                *tech_pvt-&gt;skype_call_id = '\0';
+                                switch_mutex_unlock(globals.mutex);
+
+                                //ERRORA(&quot;LET'S WAIT\n&quot;, SKYPIAX_P_LOG);
+                                switch_sleep(300000);        //0.3 sec
+                                //ERRORA(&quot;WAIT'S OVER\n&quot;, SKYPIAX_P_LOG);
+                                //tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                //usleep(30000);    //0.03 sec
+                                switch_mutex_lock(globals.mutex);
+                                tech_pvt-&gt;skype_callflow = CALLFLOW_CALL_IDLE;
+                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_IDLE;
+                                switch_mutex_unlock(globals.mutex);
+                        } else {
+                                ERRORA(&quot;no tech_pvt?\n&quot;, SKYPIAX_P_LOG);
+                        }
+                }
+        }
+        return NULL;
+}
+
+/* BEGIN: Changes heres */
+static switch_status_t load_config(int reload_type)
+/* END: Changes heres */
+{
+        char *cf = &quot;skypiax.conf&quot;;
+        switch_xml_t cfg, xml, global_settings, param, interfaces, myinterface;
+        private_t *tech_pvt = NULL;
+
+        switch_mutex_init(&amp;globals.mutex, SWITCH_MUTEX_NESTED, skypiax_module_pool);
+        if (!(xml = switch_xml_open_cfg(cf, &amp;cfg, NULL))) {
+                ERRORA(&quot;open of %s failed\n&quot;, 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, &quot;global_settings&quot;))) {
+                for (param = switch_xml_child(global_settings, &quot;param&quot;); param; param = param-&gt;next) {
+                        char *var = (char *) switch_xml_attr_soft(param, &quot;name&quot;);
+                        char *val = (char *) switch_xml_attr_soft(param, &quot;value&quot;);
+
+                        if (!strcasecmp(var, &quot;debug&quot;)) {
+                                DEBUGA_SKYPE(&quot;globals.debug=%d\n&quot;, SKYPIAX_P_LOG, globals.debug);
+                                globals.debug = atoi(val);
+                                DEBUGA_SKYPE(&quot;globals.debug=%d\n&quot;, SKYPIAX_P_LOG, globals.debug);
+                        } else if (!strcasecmp(var, &quot;hold-music&quot;)) {
+                                switch_set_string(globals.hold_music, val);
+                                DEBUGA_SKYPE(&quot;globals.hold_music=%s\n&quot;, SKYPIAX_P_LOG, globals.hold_music);
+                        } else if (!strcmp(var, &quot;port&quot;)) {
+                                globals.port = atoi(val);
+                                DEBUGA_SKYPE(&quot;globals.port=%d\n&quot;, SKYPIAX_P_LOG, globals.port);
+                        } else if (!strcmp(var, &quot;codec-master&quot;)) {
+                                if (!strcasecmp(val, &quot;us&quot;)) {
+                                        switch_set_flag(&amp;globals, GFLAG_MY_CODEC_PREFS);
+                                }
+                                DEBUGA_SKYPE(&quot;codec-master globals.debug=%d\n&quot;, SKYPIAX_P_LOG, globals.debug);
+                        } else if (!strcmp(var, &quot;dialplan&quot;)) {
+                                set_global_dialplan(val);
+                                DEBUGA_SKYPE(&quot;globals.dialplan=%s\n&quot;, SKYPIAX_P_LOG, globals.dialplan);
+                        } else if (!strcmp(var, &quot;destination&quot;)) {
+                                set_global_destination(val);
+                                DEBUGA_SKYPE(&quot;globals.destination=%s\n&quot;, SKYPIAX_P_LOG, globals.destination);
+                        } else if (!strcmp(var, &quot;context&quot;)) {
+                                set_global_context(val);
+                                DEBUGA_SKYPE(&quot;globals.context=%s\n&quot;, SKYPIAX_P_LOG, globals.context);
+                        } else if (!strcmp(var, &quot;codec-prefs&quot;)) {
+                                set_global_codec_string(val);
+                                DEBUGA_SKYPE(&quot;globals.codec_string=%s\n&quot;, 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, &quot;codec-rates&quot;)) {
+                                set_global_codec_rates_string(val);
+                                DEBUGA_SKYPE(&quot;globals.codec_rates_string=%s\n&quot;, 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, &quot;per_interface_settings&quot;))) {
+                int i = 0;
+
+                for (myinterface = switch_xml_child(interfaces, &quot;interface&quot;); myinterface; myinterface = myinterface-&gt;next) {
+                        char *id = (char *) switch_xml_attr(myinterface, &quot;id&quot;);
+                        char *name = (char *) switch_xml_attr(myinterface, &quot;name&quot;);
+                        char *context = &quot;default&quot;;
+                        char *dialplan = &quot;XML&quot;;
+                        char *destination = &quot;5000&quot;;
+                        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 = &quot;true&quot;;
+                        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, &quot;param&quot;); param; param = param-&gt;next) {
+                                char *var = (char *) switch_xml_attr_soft(param, &quot;name&quot;);
+                                char *val = (char *) switch_xml_attr_soft(param, &quot;value&quot;);
+
+                                if (!strcasecmp(var, &quot;tonegroup&quot;)) {
+                                        tonegroup = val;
+                                } else if (!strcasecmp(var, &quot;digit_timeout&quot;) || !strcasecmp(var, &quot;digit-timeout&quot;)) {
+                                        digit_timeout = val;
+                                } else if (!strcasecmp(var, &quot;context&quot;)) {
+                                        context = val;
+                                } else if (!strcasecmp(var, &quot;dialplan&quot;)) {
+                                        dialplan = val;
+                                } else if (!strcasecmp(var, &quot;destination&quot;)) {
+                                        destination = val;
+                                } else if (!strcasecmp(var, &quot;dial-regex&quot;)) {
+                                        dial_regex = val;
+                                } else if (!strcasecmp(var, &quot;enable-callerid&quot;)) {
+                                        enable_callerid = val;
+                                } else if (!strcasecmp(var, &quot;fail-dial-regex&quot;)) {
+                                        fail_dial_regex = val;
+                                } else if (!strcasecmp(var, &quot;hold-music&quot;)) {
+                                        hold_music = val;
+                                } else if (!strcasecmp(var, &quot;skype_user&quot;)) {
+                                        skype_user = val;
+                                } else if (!strcasecmp(var, &quot;tcp_cli_port&quot;)) {
+                                        tcp_cli_port = val;
+                                } else if (!strcasecmp(var, &quot;tcp_srv_port&quot;)) {
+                                        tcp_srv_port = val;
+                                } else if (!strcasecmp(var, &quot;X11-display&quot;) || !strcasecmp(var, &quot;X11_display&quot;)) {
+                                        X11_display = val;
+                                } else if (!strcasecmp(var, &quot;max_digits&quot;) || !strcasecmp(var, &quot;max-digits&quot;)) {
+                                        max_digits = val;
+                                } else if (!strcasecmp(var, &quot;hotline&quot;)) {
+                                        hotline = val;
+                                }
+
+                        }
+                        if (!skype_user) {
+                                ERRORA(&quot;interface missing REQUIRED param 'skype_user'\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+
+                        /* BEGIN: Changes here */
+                        if (reload_type == SOFT_RELOAD) {
+                                char the_interface[256];
+                                sprintf(the_interface, &quot;#%s&quot;, name);
+
+                                if (interface_exists(the_interface) == SWITCH_STATUS_SUCCESS) {
+                                        continue;
+                                }
+                        }
+                        /* END: Changes here */
+
+                        if (!X11_display) {
+                                ERRORA(&quot;interface missing REQUIRED param 'X11_display'\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (!tcp_cli_port) {
+                                ERRORA(&quot;interface missing REQUIRED param 'tcp_cli_port'\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+
+                        if (!tcp_srv_port) {
+                                ERRORA(&quot;interface missing REQUIRED param 'tcp_srv_port'\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (!id) {
+                                ERRORA(&quot;interface missing REQUIRED param 'id'\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (switch_is_number(id)) {
+                                interface_id = atoi(id);
+                                DEBUGA_SKYPE(&quot;interface_id=%d\n&quot;, SKYPIAX_P_LOG, interface_id);
+                        } else {
+                                ERRORA(&quot;interface param 'id' MUST be a number, now id='%s'\n&quot;, SKYPIAX_P_LOG, id);
+                                continue;
+                        }
+
+                        if (!name) {
+                                WARNINGA(&quot;interface missing param 'name', not nice, but works\n&quot;, SKYPIAX_P_LOG);
+                        }
+
+                        if (!tonegroup) {
+                                tonegroup = &quot;us&quot;;
+                        }
+
+                        if (digit_timeout) {
+                                to = atoi(digit_timeout);
+                        }
+
+                        if (max_digits) {
+                                max = atoi(max_digits);
+                        }
+
+                        if (name) {
+                                DEBUGA_SKYPE(&quot;name=%s\n&quot;, SKYPIAX_P_LOG, name);
+                        }
+#ifndef WIN32
+                        if (!XInitThreads()) {
+                                ERRORA(&quot;Not initialized XInitThreads!\n&quot;, SKYPIAX_P_LOG);
+                        } else {
+                                DEBUGA_SKYPE(&quot;Initialized XInitThreads!\n&quot;, SKYPIAX_P_LOG);
+                        }
+                        switch_sleep(100);
+#endif /* WIN32 */
+
+                        if (interface_id &amp;&amp; interface_id &lt; SKYPIAX_MAX_INTERFACES) {
+                                private_t newconf;
+                                switch_threadattr_t *skypiax_api_thread_attr = NULL;
+                                switch_threadattr_t *skypiax_signaling_thread_attr = NULL;
+
+                                memset(&amp;newconf, '\0', sizeof(newconf));
+                                globals.SKYPIAX_INTERFACES[interface_id] = newconf;
+                                globals.SKYPIAX_INTERFACES[interface_id].running = 1;
+
+
+                                tech_pvt = &amp;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, &quot;N/A&quot;);
+                                }
+                                DEBUGA_SKYPE(&quot;CONFIGURING interface_id=%d\n&quot;, 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
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].X11_display=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].X11_display);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].skype_user=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port=%d\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port=%d\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port);
+                                DEBUGA_SKYPE(&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].name=%s\n&quot;,
+                                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].name);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].dialplan=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].dialplan);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].destination=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].destination);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
+                                WARNINGA(&quot;STARTING interface_id=%d\n&quot;, SKYPIAX_P_LOG, interface_id);
+
+                                switch_threadattr_create(&amp;skypiax_api_thread_attr, skypiax_module_pool);
+                                switch_threadattr_stacksize_set(skypiax_api_thread_attr, SWITCH_THREAD_STACKSIZE);
+                                switch_thread_create(&amp;globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread,
+                                                                         skypiax_api_thread_attr, skypiax_do_skypeapi_thread, &amp;globals.SKYPIAX_INTERFACES[interface_id], skypiax_module_pool);
+
+                                switch_sleep(100000);
+
+                                switch_threadattr_create(&amp;skypiax_signaling_thread_attr, skypiax_module_pool);
+                                switch_threadattr_stacksize_set(skypiax_signaling_thread_attr, SWITCH_THREAD_STACKSIZE);
+                                switch_thread_create(&amp;globals.SKYPIAX_INTERFACES[interface_id].
+                                                                         skypiax_signaling_thread, skypiax_signaling_thread_attr,
+                                                                         skypiax_signaling_thread_func, &amp;globals.SKYPIAX_INTERFACES[interface_id], skypiax_module_pool);
+
+                                switch_sleep(100000);
+
+                                skypiax_audio_init(&amp;globals.SKYPIAX_INTERFACES[interface_id]);
+
+                                NOTICA
+                                        (&quot;WAITING roughly 10 seconds to find a running Skype client and connect to its SKYPE API for interface_id=%d\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id);
+                                i = 0;
+                                while (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.api_connected == 0 &amp;&amp; running &amp;&amp; i &lt; 200) {        // 10 seconds! thanks Jeff Lenk
+                                        switch_sleep(50000);
+                                        i++;
+                                }
+                                if (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.api_connected) {
+                                        NOTICA
+                                                (&quot;Found a running Skype client, connected to its SKYPE API for interface_id=%d, waiting 60 seconds for CURRENTUSERHANDLE==%s\n&quot;,
+                                                 SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                } else {
+                                        ERRORA
+                                                (&quot;Failed to connect to a SKYPE API for interface_id=%d, no SKYPE client running, please (re)start Skype client. Skypiax exiting\n&quot;,
+                                                 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 &amp;&amp; running &amp;&amp; i &lt; 1200) {        // 60 seconds! thanks Jeff Lenk
+                                        switch_sleep(50000);
+                                        i++;
+                                }
+                                if (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.currentuserhandle) {
+                                        WARNINGA
+                                                (&quot;Interface_id=%d is now STARTED, the Skype client to which we are connected gave us the correct CURRENTUSERHANDLE (%s)\n&quot;,
+                                                 SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+
+                                        skypiax_signaling_write(&amp;globals.SKYPIAX_INTERFACES[interface_id], &quot;SET AUTOAWAY OFF&quot;);
+                                } else {
+                                        ERRORA
+                                                (&quot;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&quot;,
+                                                 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(&quot;interface id %d is higher than SKYPIAX_MAX_INTERFACES (%d)\n&quot;, SKYPIAX_P_LOG, interface_id, SKYPIAX_MAX_INTERFACES);
+                                continue;
+                        }
+
+                }
+
+                for (i = 0; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+                                /* How many real intterfaces */
+                                globals.real_interfaces = i + 1;
+
+                                tech_pvt = &amp;globals.SKYPIAX_INTERFACES[i];
+
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].interface_id=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].interface_id);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].X11_display=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].X11_display);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].name=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].name);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].context);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].dialplan=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].dialplan);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].destination=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].destination);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n&quot;, 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(&amp;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-&gt;interface_name = &quot;skypiax&quot;;
+        skypiax_endpoint_interface-&gt;io_routines = &amp;skypiax_io_routines;
+        skypiax_endpoint_interface-&gt;state_handler = &amp;skypiax_state_handlers;
+
+        if (running) {
+
+                SWITCH_ADD_API(commands_api_interface, &quot;sk&quot;, &quot;Skypiax console commands&quot;, sk_function, SK_SYNTAX);
+                SWITCH_ADD_API(commands_api_interface, &quot;skypiax&quot;, &quot;Skypiax interface commands&quot;, 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 &lt; SKYPIAX_MAX_INTERFACES; interface_id++) {
+                tech_pvt = &amp;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-&gt;SkypiaxHandles.fdesc[1], &quot;sciutati&quot;, &amp;howmany);        // let's the controldev_thread die
+#else /* WIN32 */
+                                howmany = write(tech_pvt-&gt;SkypiaxHandles.fdesc[1], &quot;sciutati&quot;, howmany);
+#endif /* WIN32 */
+                        }
+
+                        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+#ifdef WIN32
+                                if (SendMessage(tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {        // let's the skypiax_api_thread_func die
+                                        DEBUGA_SKYPE(&quot;got FALSE here, thread probably was already dead. GetLastError returned: %d\n&quot;, SKYPIAX_P_LOG, GetLastError());
+                                        globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread = NULL;
+                                }
+#else
+                                XEvent e;
+                                Atom atom1 = XInternAtom(tech_pvt-&gt;SkypiaxHandles.disp, &quot;SKYPECONTROLAPI_MESSAGE_BEGIN&quot;,
+                                                                                 False);
+                                memset(&amp;e, 0, sizeof(e));
+                                e.xclient.type = ClientMessage;
+                                e.xclient.message_type = atom1;        /*  leading message */
+                                e.xclient.display = tech_pvt-&gt;SkypiaxHandles.disp;
+                                e.xclient.window = tech_pvt-&gt;SkypiaxHandles.skype_win;
+                                e.xclient.format = 8;
+
+                                XSendEvent(tech_pvt-&gt;SkypiaxHandles.disp, tech_pvt-&gt;SkypiaxHandles.win, False, 0, &amp;e);
+                                XSync(tech_pvt-&gt;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(&amp;status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread);
+                        }
+                        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+                                switch_thread_join(&amp;status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread);
+                        }
+#ifndef WIN32
+                        WARNINGA(&quot;SHUTDOWN interface_id=%d\n&quot;, SKYPIAX_P_LOG, interface_id);
+                        shutdown(tech_pvt-&gt;audioskypepipe[0], 2);
+                        close(tech_pvt-&gt;audioskypepipe[0]);
+                        shutdown(tech_pvt-&gt;audioskypepipe[1], 2);
+                        close(tech_pvt-&gt;audioskypepipe[1]);
+                        shutdown(tech_pvt-&gt;audiopipe[0], 2);
+                        close(tech_pvt-&gt;audiopipe[0]);
+                        shutdown(tech_pvt-&gt;audiopipe[1], 2);
+                        close(tech_pvt-&gt;audiopipe[1]);
+                        shutdown(tech_pvt-&gt;SkypiaxHandles.fdesc[0], 2);
+                        close(tech_pvt-&gt;SkypiaxHandles.fdesc[0]);
+                        shutdown(tech_pvt-&gt;SkypiaxHandles.fdesc[1], 2);
+                        close(tech_pvt-&gt;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-&gt;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(&quot;received DTMF %c on channel %s\n&quot;, SKYPIAX_P_LOG, dtmf.digit, switch_channel_get_name(channel));
+                        switch_mutex_lock(tech_pvt-&gt;flag_mutex);
+                        //FIXME: why sometimes DTMFs from here do not seems to be get by FS?
+                        switch_channel_queue_dtmf(channel, &amp;dtmf);
+                        switch_set_flag(tech_pvt, TFLAG_DTMF);
+                        switch_mutex_unlock(tech_pvt-&gt;flag_mutex);
+                } else {
+                        DEBUGA_SKYPE
+                                (&quot;received a DTMF on channel %s, but we're BRIDGED, so let's NOT relay it out of band\n&quot;, SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                }
+        } else {
+                WARNINGA(&quot;received %c DTMF, but no channel?\n&quot;, 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(&amp;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(&amp;tech_pvt-&gt;tcp_srv_thread, thd_attr, skypiax_do_tcp_srv_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) {
+                DEBUGA_SKYPE(&quot;started tcp_srv_thread thread.\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                ERRORA(&quot;failed to start tcp_srv_thread thread.\n&quot;, SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        switch_threadattr_create(&amp;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(&amp;tech_pvt-&gt;tcp_cli_thread, thd_attr, skypiax_do_tcp_cli_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) {
+                DEBUGA_SKYPE(&quot;started tcp_cli_thread thread.\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                ERRORA(&quot;failed to start tcp_cli_thread thread.\n&quot;, SKYPIAX_P_LOG);
+                return -1;
+        }
+        switch_sleep(100000);
+
+        if (tech_pvt-&gt;tcp_cli_thread == NULL || tech_pvt-&gt;tcp_srv_thread == NULL) {
+                ERRORA(&quot;tcp_cli_thread or tcp_srv_thread exited\n&quot;, 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(&quot;2 SESSION_REQUEST %s\n&quot;, 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(&quot;Doh! no channel?\n&quot;, SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&amp;session);
+                        return 0;
+                }
+                if (skypiax_tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS) {
+                        ERRORA(&quot;Doh! no tech_init?\n&quot;, SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&amp;session);
+                        return 0;
+                }
+
+                if ((tech_pvt-&gt;caller_profile =
+                         switch_caller_profile_new(switch_core_session_get_pool(session), &quot;skypiax&quot;,
+                                                                           tech_pvt-&gt;dialplan, tech_pvt-&gt;callid_name,
+                                                                           tech_pvt-&gt;callid_number, NULL, NULL, NULL, NULL, &quot;mod_skypiax&quot;, tech_pvt-&gt;context, tech_pvt-&gt;destination)) != 0) {
+                        char name[128];
+                        //switch_snprintf(name, sizeof(name), &quot;skypiax/%s/%s&quot;, tech_pvt-&gt;name, tech_pvt-&gt;caller_profile-&gt;destination_number);
+                        switch_snprintf(name, sizeof(name), &quot;skypiax/%s&quot;, tech_pvt-&gt;name);
+                        switch_channel_set_name(channel, name);
+                        switch_channel_set_caller_profile(channel, tech_pvt-&gt;caller_profile);
+                }
+                switch_channel_set_state(channel, CS_INIT);
+                if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
+                        ERRORA(&quot;Error spawning thread\n&quot;, SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&amp;session);
+                        return 0;
+                }
+        }
+        if (channel) {
+                switch_channel_mark_answered(channel);
+        }
+
+        DEBUGA_SKYPE(&quot;new_inbound_channel\n&quot;, 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-&gt;session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt-&gt;session_uuid_str);
+        } else {
+                ERRORA(&quot;No session???\n&quot;, SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (session) {
+                channel = switch_core_session_get_channel(session);
+        } else {
+                ERRORA(&quot;No session???\n&quot;, SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_ring_ready(channel);
+                DEBUGA_SKYPE(&quot;skype_call: REMOTE PARTY RINGING\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                ERRORA(&quot;No channel???\n&quot;, 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-&gt;session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt-&gt;session_uuid_str);
+        } else {
+                ERRORA(&quot;No session???\n\n\n&quot;, 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(&quot;No session???\n&quot;, SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_pre_answered(channel);
+                DEBUGA_SKYPE(&quot;skype_call: REMOTE PARTY EARLY MEDIA\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                ERRORA(&quot;No channel???\n&quot;, 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-&gt;session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt-&gt;session_uuid_str);
+        } else {
+                ERRORA(&quot;No session???\n&quot;, SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (session) {
+                channel = switch_core_session_get_channel(session);
+        } else {
+                ERRORA(&quot;No channel???\n&quot;, SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_answered(channel);
+                //DEBUGA_SKYPE(&quot;skype_call: %s, answered\n&quot;, SKYPIAX_P_LOG, id);
+        } else {
+                ERRORA(&quot;No channel???\n&quot;, SKYPIAX_P_LOG);
+        }
+
+        switch_core_session_rwunlock(session);
+
+  done:
+        DEBUGA_SKYPE(&quot;outbound_channel_answered!\n&quot;, 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 &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                int interface_id;
+
+                interface_id = globals.next_interface;
+                //interface_id = interface_id &lt; SKYPIAX_MAX_INTERFACES ? interface_id : interface_id - SKYPIAX_MAX_INTERFACES + 1;
+                globals.next_interface = interface_id + 1 &lt; SKYPIAX_MAX_INTERFACES ? interface_id + 1 : 0;
+
+                if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                        int skype_state = 0;
+
+                        tech_pvt = &amp;globals.SKYPIAX_INTERFACES[interface_id];
+                        skype_state = tech_pvt-&gt;interface_state;
+                        //DEBUGA_SKYPE(&quot;skype interface: %d, name: %s, state: %d\n&quot;, SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].name, skype_state);
+                        if ((tech_pvt_calling ? strcmp(tech_pvt-&gt;skype_user, tech_pvt_calling-&gt;skype_user) : 1)
+                                &amp;&amp; (SKYPIAX_STATE_DOWN == skype_state || 0 == skype_state) &amp;&amp; (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_FINISHED
+                                                                                                                                                           || 0 == tech_pvt-&gt;skype_callflow)) {
+                                DEBUGA_SKYPE(&quot;returning as available skype interface name: %s, state: %d callflow: %d\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;name, skype_state,
+                                                         tech_pvt-&gt;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-&gt;interface_state = SKYPIAX_STATE_SELECTED;
+                                }
+
+                                switch_mutex_unlock(globals.mutex);
+                                return tech_pvt;
+                        }
+                }                                                // else {
+                //DEBUGA_SKYPE(&quot;Skype interface: %d blank!! A hole here means we cannot hunt the last interface.\n&quot;, 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-&gt;write_function(stream, &quot;sk console is: |||%s|||\n&quot;, globals.sk_console-&gt;name);
+        else
+                stream-&gt;write_function(stream, &quot;sk console is NOT yet assigned\n&quot;);
+
+        if (!switch_strlen_zero(cmd) &amp;&amp; (mycmd = strdup(cmd))) {
+                argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+        }
+
+        if (!argc || !argv[0]) {
+                stream-&gt;write_function(stream, &quot;%s&quot;, SK_SYNTAX);
+                goto end;
+        }
+
+        if (!strcasecmp(argv[0], &quot;list&quot;)) {
+                int i;
+                char next_flag_char = ' ';
+
+                stream-&gt;write_function(stream, &quot;F ID\t    Name    \tIB (F/T)    OB (F/T)\tState\tCallFlw\t\tUUID\n&quot;);
+                stream-&gt;write_function(stream, &quot;= ====\t  ========  \t=======     =======\t======\t============\t======\n&quot;);
+
+                for (i = 0; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                        next_flag_char = i == globals.next_interface ? '*' : ' ';
+
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+                                stream-&gt;write_function(stream,
+                                                                           &quot;%c %d\t[%s]\t%3ld/%ld\t%6ld/%ld\t%s\t%s\t%s\n&quot;,
+                                                                           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 &gt; 1 &amp;&amp; !strcasecmp(argv[1], &quot;full&quot;)) {
+                                stream-&gt;write_function(stream, &quot;%c\t%d\n&quot;, next_flag_char, i);
+                        }
+
+                }
+                stream-&gt;write_function(stream, &quot;\nTotal: %d\n&quot;, globals.real_interfaces - 1);
+
+        } else if (!strcasecmp(argv[0], &quot;console&quot;)) {
+                int i;
+                int found = 0;
+
+                if (argc == 2) {
+                        for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                                /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the &quot;ANY&quot; interface */
+                                if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                                        &amp;&amp; (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[1], strlen(argv[1])) == 0)) {
+                                        globals.sk_console = &amp;globals.SKYPIAX_INTERFACES[i];
+                                        stream-&gt;write_function(stream,
+                                                                                   &quot;sk console is now: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n&quot;, i, globals.SKYPIAX_INTERFACES[i].name);
+                                        stream-&gt;write_function(stream, &quot;sk console is: |||%s|||\n&quot;, globals.sk_console-&gt;name);
+                                        found = 1;
+                                        break;
+                                }
+
+                        }
+                        if (!found)
+                                stream-&gt;write_function(stream, &quot;ERROR: A Skypiax interface with name='%s' was not found\n&quot;, argv[1]);
+                } else {
+
+                        stream-&gt;write_function(stream, &quot;-ERR Usage: sk console interface_name\n&quot;);
+                        goto end;
+                }
+
+        } else if (!strcasecmp(argv[0], &quot;ciapalino&quot;)) {
+
+/* BEGIN: Changes heres */
+        } else if (!strcasecmp(argv[0], &quot;reload&quot;)) {
+                if (load_config(SOFT_RELOAD) != SWITCH_STATUS_SUCCESS) {
+                        stream-&gt;write_function(stream, &quot;sk reload failed\n&quot;);
+                } else {
+                        stream-&gt;write_function(stream, &quot;sk reload success\n&quot;);
+                }
+        } else if (!strcasecmp(argv[0], &quot;remove&quot;)) {
+                if (argc == 2) {
+                        if (remove_interface(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                                if (interface_exists(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                                        stream-&gt;write_function(stream, &quot;sk remove '%s' failed\n&quot;, argv[1]);
+                                } else {
+                                        stream-&gt;write_function(stream, &quot;sk remove '%s' success\n&quot;, argv[1]);
+                                }
+                        }
+                } else {
+                        stream-&gt;write_function(stream, &quot;-ERR Usage: sk remove interface_name\n&quot;);
+                        goto end;
+                }
+/* END: Changes heres */
+
+        } else {
+                if (globals.sk_console)
+                        skypiax_signaling_write(globals.sk_console, (char *) cmd);
+                else
+                        stream-&gt;write_function(stream, &quot;sk console is NOT yet assigned\n&quot;);
+        }
+  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) &amp;&amp; (mycmd = strdup(cmd))) {
+                argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+        }
+
+        if (!argc) {
+                stream-&gt;write_function(stream, &quot;ERROR, usage: %s&quot;, SKYPIAX_SYNTAX);
+                goto end;
+        }
+
+        if (argc &lt; 2) {
+                stream-&gt;write_function(stream, &quot;ERROR, usage: %s&quot;, SKYPIAX_SYNTAX);
+                goto end;
+        }
+
+        if (argv[0]) {
+                int i;
+                int found = 0;
+
+                for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                        /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the &quot;ANY&quot; interface */
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                                &amp;&amp; (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
+                                tech_pvt = &amp;globals.SKYPIAX_INTERFACES[i];
+                                stream-&gt;write_function(stream, &quot;Using interface: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n&quot;, i, globals.SKYPIAX_INTERFACES[i].name);
+                                found = 1;
+                                break;
+                        }
+
+                }
+                if (!found) {
+                        stream-&gt;write_function(stream, &quot;ERROR: A Skypiax interface with name='%s' was not found\n&quot;, argv[0]);
+                        switch_safe_free(mycmd);
+
+                        return SWITCH_STATUS_SUCCESS;
+                } else {
+                        skypiax_signaling_write(tech_pvt, (char *) &amp;cmd[strlen(argv[0]) + 1]);
+                }
+        } else {
+                stream-&gt;write_function(stream, &quot;ERROR, usage: %s&quot;, 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(&amp;timenow, NULL);
+        for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                        giovatech = &amp;globals.SKYPIAX_INTERFACES[i];
+                        //NOTICA(&quot;skype interface: %d, name: %s, state: %d, value=%s, giovatech-&gt;callid_number=%s, giovatech-&gt;skype_user=%s\n&quot;, SKYPIAX_P_LOG, i, giovatech-&gt;name, giovatech-&gt;interface_state, value, giovatech-&gt;callid_number, giovatech-&gt;skype_user);
+                        //FIXME check a timestamp here
+                        if (strlen(giovatech-&gt;skype_call_id) &amp;&amp; (giovatech-&gt;interface_state != SKYPIAX_STATE_DOWN) &amp;&amp; (!strcmp(giovatech-&gt;skype_user, tech_pvt-&gt;skype_user)) &amp;&amp; (!strcmp(giovatech-&gt;callid_number, value)) &amp;&amp; ((((timenow.tv_sec - giovatech-&gt;answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech-&gt;answer_time.tv_usec)) &lt; 500000)) {        //0.5sec
+                                found = 1;
+                                DEBUGA_SKYPE
+                                        (&quot;FOUND  (name=%s, giovatech-&gt;interface_state=%d != SKYPIAX_STATE_DOWN) &amp;&amp; (giovatech-&gt;skype_user=%s == tech_pvt-&gt;skype_user=%s) &amp;&amp; (giovatech-&gt;callid_number=%s == value=%s)\n&quot;,
+                                         SKYPIAX_P_LOG, giovatech-&gt;name, giovatech-&gt;interface_state,
+                                         giovatech-&gt;skype_user, tech_pvt-&gt;skype_user, giovatech-&gt;callid_number, value)
+                                        if (tech_pvt-&gt;interface_state == SKYPIAX_STATE_PRERING) {
+                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                } else if (tech_pvt-&gt;interface_state != 0 &amp;&amp; tech_pvt-&gt;interface_state != SKYPIAX_STATE_DOWN) {
+                                        WARNINGA(&quot;Why an interface_state %d HERE?\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;interface_state);
+                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                }
+
+                                break;
+                        }
+                }
+        }
+
+        if (found) {
+                //tech_pvt-&gt;callid_number[0]='\0';
+                //sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, id);
+                //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_mutex_unlock(globals.mutex);
+                return 0;
+        }
+        DEBUGA_SKYPE(&quot;NOT FOUND\n&quot;, SKYPIAX_P_LOG);
+
+        if (tech_pvt &amp;&amp; tech_pvt-&gt;skype_call_id &amp;&amp; !strlen(tech_pvt-&gt;skype_call_id)) {
+                /* we are not inside an active call */
+
+                tech_pvt-&gt;ib_calls++;
+
+                sprintf(msg_to_skype, &quot;GET CALL %s PARTNER_DISPNAME&quot;, id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_sleep(10000);
+                tech_pvt-&gt;interface_state = SKYPIAX_STATE_PREANSWER;
+                sprintf(msg_to_skype, &quot;ALTER CALL %s ANSWER&quot;, id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                DEBUGA_SKYPE(&quot;We answered a Skype RING on skype_call %s\n&quot;, SKYPIAX_P_LOG, id);
+                //FIXME write a timestamp here
+                gettimeofday(&amp;tech_pvt-&gt;answer_time, NULL);
+                switch_copy_string(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+
+                switch_copy_string(tech_pvt-&gt;callid_number, value, sizeof(tech_pvt-&gt;callid_number) - 1);
+
+                DEBUGA_SKYPE
+                        (&quot;NEW!  name: %s, state: %d, value=%s, tech_pvt-&gt;callid_number=%s, tech_pvt-&gt;skype_user=%s\n&quot;,
+                         SKYPIAX_P_LOG, tech_pvt-&gt;name, tech_pvt-&gt;interface_state, value, tech_pvt-&gt;callid_number, tech_pvt-&gt;skype_user);
+        } else if (!tech_pvt || !tech_pvt-&gt;skype_call_id) {
+                ERRORA(&quot;No Call ID?\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                DEBUGA_SKYPE(&quot;We're in a call now (%s), let's refuse this one (%s)\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;skype_call_id, id);
+                sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, 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(&amp;timenow, NULL);
+        for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                        giovatech = &amp;globals.SKYPIAX_INTERFACES[i];
+                        //NOTICA(&quot;skype interface: %d, name: %s, state: %d, value=%s, giovatech-&gt;callid_number=%s, giovatech-&gt;skype_user=%s\n&quot;, SKYPIAX_P_LOG, i, giovatech-&gt;name, giovatech-&gt;interface_state, value, giovatech-&gt;callid_number, giovatech-&gt;skype_user);
+                        //FIXME check a timestamp here
+                        if (strlen(giovatech-&gt;skype_call_id) &amp;&amp; (giovatech-&gt;interface_state != SKYPIAX_STATE_DOWN) &amp;&amp; (!strcmp(giovatech-&gt;skype_user, tech_pvt-&gt;skype_user)) &amp;&amp; (!strcmp(giovatech-&gt;callid_number, value)) &amp;&amp; ((((timenow.tv_sec - giovatech-&gt;answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech-&gt;answer_time.tv_usec)) &lt; 500000)) {        //0.5sec
+                                found = 1;
+                                DEBUGA_SKYPE
+                                        (&quot;FOUND  (name=%s, giovatech-&gt;interface_state=%d != SKYPIAX_STATE_DOWN) &amp;&amp; (giovatech-&gt;skype_user=%s == tech_pvt-&gt;skype_user=%s) &amp;&amp; (giovatech-&gt;callid_number=%s == value=%s)\n&quot;,
+                                         SKYPIAX_P_LOG, giovatech-&gt;name, giovatech-&gt;interface_state,
+                                         giovatech-&gt;skype_user, tech_pvt-&gt;skype_user, giovatech-&gt;callid_number, value)
+                                        break;
+                        }
+                }
+        }
+
+        if (found) {
+                //tech_pvt-&gt;callid_number[0]='\0';
+                //sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, id);
+                //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_mutex_unlock(globals.mutex);
+                return 0;
+        }
+        DEBUGA_SKYPE(&quot;NOT FOUND\n&quot;, SKYPIAX_P_LOG);
+
+        if (!tech_pvt || !tech_pvt-&gt;skype_call_id || !strlen(tech_pvt-&gt;skype_call_id)) {
+                /* we are not inside an active call */
+                DEBUGA_SKYPE(&quot;We're NO MORE in a call now %s\n&quot;, SKYPIAX_P_LOG, (tech_pvt &amp;&amp; tech_pvt-&gt;skype_call_id) ? tech_pvt-&gt;skype_call_id : &quot;&quot;);
+                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
+                  -&gt; GET CALL 288 CAN_TRANSFER Test2
+                  &lt;- CALL 288 CAN_TRANSFER test2 TRUE
+                 **********************************/
+
+                private_t *available_skypiax_interface = NULL;
+
+                gettimeofday(&amp;timenow, NULL);
+                for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                                giovatech = &amp;globals.SKYPIAX_INTERFACES[i];
+                                //NOTICA(&quot;skype interface: %d, name: %s, state: %d, value=%s, giovatech-&gt;callid_number=%s, giovatech-&gt;skype_user=%s\n&quot;, SKYPIAX_P_LOG, i, giovatech-&gt;name, giovatech-&gt;interface_state, value, giovatech-&gt;callid_number, giovatech-&gt;skype_user);
+                                //FIXME check a timestamp here
+                                if (strlen(giovatech-&gt;skype_transfer_call_id) &amp;&amp; (giovatech-&gt;interface_state != SKYPIAX_STATE_DOWN) &amp;&amp; (!strcmp(giovatech-&gt;skype_user, tech_pvt-&gt;skype_user)) &amp;&amp; (!strcmp(giovatech-&gt;transfer_callid_number, value)) &amp;&amp; ((((timenow.tv_sec - giovatech-&gt;transfer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech-&gt;transfer_time.tv_usec)) &lt; 1000000)) {        //1.0 sec
+                                        found = 1;
+                                        DEBUGA_SKYPE
+                                                (&quot;FOUND  (name=%s, giovatech-&gt;interface_state=%d != SKYPIAX_STATE_DOWN) &amp;&amp; (giovatech-&gt;skype_user=%s == tech_pvt-&gt;skype_user=%s) &amp;&amp; (giovatech-&gt;transfer_callid_number=%s == value=%s)\n&quot;,
+                                                 SKYPIAX_P_LOG, giovatech-&gt;name, giovatech-&gt;interface_state,
+                                                 giovatech-&gt;skype_user, tech_pvt-&gt;skype_user, giovatech-&gt;transfer_callid_number, value)
+                                                break;
+                                }
+                        }
+                }
+
+                if (found) {
+                        //tech_pvt-&gt;callid_number[0]='\0';
+                        //sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, id);
+                        //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                        switch_mutex_unlock(globals.mutex);
+                        return 0;
+                }
+                DEBUGA_SKYPE(&quot;NOT FOUND\n&quot;, 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(&amp;tech_pvt-&gt;transfer_time, NULL);
+                        switch_copy_string(tech_pvt-&gt;skype_transfer_call_id, id, sizeof(tech_pvt-&gt;skype_transfer_call_id) - 1);
+
+                        switch_copy_string(tech_pvt-&gt;transfer_callid_number, value, sizeof(tech_pvt-&gt;transfer_callid_number) - 1);
+
+                        DEBUGA_SKYPE
+                                (&quot;Let's transfer the skype_call %s to %s interface (with skype_user: %s), because we are already in a skypiax call(%s)\n&quot;,
+                                 SKYPIAX_P_LOG, tech_pvt-&gt;skype_call_id, available_skypiax_interface-&gt;name, available_skypiax_interface-&gt;skype_user, id);
+
+                        //FIXME why this? the inbound call will come, eventually, on that other interface
+                        //available_skypiax_interface-&gt;ib_calls++;
+
+                        sprintf(msg_to_skype, &quot;ALTER CALL %s TRANSFER %s&quot;, id, available_skypiax_interface-&gt;skype_user);
+                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                        if (tech_pvt-&gt;interface_state == SKYPIAX_STATE_SELECTED) {
+                                tech_pvt-&gt;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
+                                (&quot;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&quot;,
+                                 SKYPIAX_P_LOG, id, tech_pvt-&gt;skype_call_id);
+                        sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, id);
+                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                }
+                switch_sleep(10000);
+                DEBUGA_SKYPE
+                        (&quot;We have NOT answered a Skype RING from skype_call %s, because we are already in a skypiax call (%s)\n&quot;,
+                         SKYPIAX_P_LOG, id, tech_pvt-&gt;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>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;Windows-1252&quot;?&gt;
+&lt;VisualStudioProject
+        ProjectType=&quot;Visual C++&quot;
+        Version=&quot;9.00&quot;
+        Name=&quot;mod_skypiax&quot;
+        ProjectGUID=&quot;{C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}&quot;
+        RootNamespace=&quot;mod_skypiax&quot;
+        Keyword=&quot;Win32Proj&quot;
+        TargetFrameworkVersion=&quot;131072&quot;
+        &gt;
+        &lt;Platforms&gt;
+                &lt;Platform
+                        Name=&quot;Win32&quot;
+                /&gt;
+        &lt;/Platforms&gt;
+        &lt;ToolFiles&gt;
+        &lt;/ToolFiles&gt;
+        &lt;Configurations&gt;
+                &lt;Configuration
+                        Name=&quot;Debug|Win32&quot;
+                        ConfigurationType=&quot;2&quot;
+                        InheritedPropertySheets=&quot;..\..\..\..\w32\module_debug.vsprops&quot;
+                        CharacterSet=&quot;2&quot;
+                        &gt;
+                        &lt;Tool
+                                Name=&quot;VCPreBuildEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCustomBuildTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXMLDataGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebServiceProxyGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCMIDLTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCLCompilerTool&quot;
+                                UsePrecompiledHeader=&quot;0&quot;
+                                WarningLevel=&quot;4&quot;
+                                WarnAsError=&quot;false&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManagedResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPreLinkEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCLinkerTool&quot;
+                                AdditionalOptions=&quot;rpcrt4.lib &quot;
+                                RandomizedBaseAddress=&quot;1&quot;
+                                DataExecutionPrevention=&quot;0&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCALinkTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManifestTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXDCMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCBscMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCFxCopTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCAppVerifierTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPostBuildEventTool&quot;
+                        /&gt;
+                &lt;/Configuration&gt;
+                &lt;Configuration
+                        Name=&quot;Release|Win32&quot;
+                        ConfigurationType=&quot;2&quot;
+                        InheritedPropertySheets=&quot;..\..\..\..\w32\module_release.vsprops&quot;
+                        CharacterSet=&quot;2&quot;
+                        &gt;
+                        &lt;Tool
+                                Name=&quot;VCPreBuildEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCustomBuildTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXMLDataGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebServiceProxyGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCMIDLTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCLCompilerTool&quot;
+                                UsePrecompiledHeader=&quot;0&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManagedResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPreLinkEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCLinkerTool&quot;
+                                AdditionalOptions=&quot;rpcrt4.lib &quot;
+                                RandomizedBaseAddress=&quot;1&quot;
+                                DataExecutionPrevention=&quot;0&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCALinkTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManifestTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXDCMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCBscMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCFxCopTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCAppVerifierTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPostBuildEventTool&quot;
+                        /&gt;
+                &lt;/Configuration&gt;
+        &lt;/Configurations&gt;
+        &lt;References&gt;
+        &lt;/References&gt;
+        &lt;Files&gt;
+                &lt;File
+                        RelativePath=&quot;..\mod_skypiax\mod_skypiax.c&quot;
+                        &gt;
+                &lt;/File&gt;
+                &lt;File
+                        RelativePath=&quot;.\skypiax.h&quot;
+                        &gt;
+                &lt;/File&gt;
+                &lt;File
+                        RelativePath=&quot;.\skypiax_protocol.c&quot;
+                        &gt;
+                &lt;/File&gt;
+        &lt;/Files&gt;
+        &lt;Globals&gt;
+        &lt;/Globals&gt;
+&lt;/VisualStudioProject&gt;
</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 &lt;anthmct@yahoo.com&gt;
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the &quot;License&quot;); 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 &quot;AS IS&quot; 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 &lt;anthmct@yahoo.com&gt;
+ * 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 &quot;skypiax.h&quot;
+
+#ifdef WIN32
+/***************/
+// from http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
+
+#include &lt;time.h&gt;
+
+#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(&amp;ft);
+                tmpres |= ft.dwHighDateTime;
+                tmpres &lt;&lt;= 32;
+                tmpres |= ft.dwLowDateTime;
+
+                /*converting file time to unix epoch */
+                tmpres /= 10;                        /*convert into microseconds */
+                tmpres -= DELTA_EPOCH_IN_MICROSECS;
+                tv-&gt;tv_sec = (long) (tmpres / 1000000UL);
+                tv-&gt;tv_usec = (long) (tmpres % 1000000UL);
+        }
+        if (NULL != tz) {
+                if (!tzflag) {
+                        _tzset();
+                        tzflag++;
+                }
+                tz-&gt;tz_minuteswest = _timezone / 60;
+                tz-&gt;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 &quot;list [full] || console || skype_API_msg || remove &lt; skypeusername | #interface_name | #interface_id &gt; || reload&quot;
+/* END: Changes heres */
+SWITCH_STANDARD_API(skypiax_function);
+#define SKYPIAX_SYNTAX &quot;interface_name skype_API_msg&quot;
+
+/* 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 */
+        &quot;IDLE&quot;,
+        &quot;DOWN&quot;,
+        &quot;RING&quot;,
+        &quot;DIALING&quot;,
+        &quot;BUSY&quot;,
+        &quot;UP&quot;,
+        &quot;RINGING&quot;,
+        &quot;PRERING&quot;,
+        &quot;DOUBLE&quot;,
+        &quot;SELECTD&quot;,
+        &quot;HANG_RQ&quot;,
+        &quot;PREANSW&quot;
+};
+char *skype_callflow[] = {                /* should match CALLFLOW_XXX in skypiax.h */
+        &quot;CALL_IDLE&quot;,
+        &quot;CALL_DOWN&quot;,
+        &quot;INCOMING_RNG&quot;,
+        &quot;CALL_DIALING&quot;,
+        &quot;CALL_LINEBUSY&quot;,
+        &quot;CALL_ACTIVE&quot;,
+        &quot;INCOMING_HNG&quot;,
+        &quot;CALL_RLEASD&quot;,
+        &quot;CALL_NOCARR&quot;,
+        &quot;CALL_INFLUX&quot;,
+        &quot;CALL_INCOMING&quot;,
+        &quot;CALL_FAILED&quot;,
+        &quot;CALL_NOSRVC&quot;,
+        &quot;CALL_OUTRESTR&quot;,
+        &quot;CALL_SECFAIL&quot;,
+        &quot;CALL_NOANSWER&quot;,
+        &quot;STATUS_FNSHED&quot;,
+        &quot;STATUS_CANCLED&quot;,
+        &quot;STATUS_FAILED&quot;,
+        &quot;STATUS_REFUSED&quot;,
+        &quot;STATUS_RINGING&quot;,
+        &quot;STATUS_INPROGRS&quot;,
+        &quot;STATUS_UNPLACD&quot;,
+        &quot;STATUS_ROUTING&quot;,
+        &quot;STATUS_EARLYMD&quot;,
+        &quot;INCOMING_CLID&quot;,
+        &quot;STATUS_RMTEHOLD&quot;
+};
+
+
+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
+                (&amp;tech_pvt-&gt;read_codec, &quot;L16&quot;, NULL, sample_rate, codec_ms, 1,
+                 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+                ERRORA(&quot;Can't load codec?\n&quot;, SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+
+        if (switch_core_codec_init
+                (&amp;tech_pvt-&gt;write_codec, &quot;L16&quot;, NULL, sample_rate, codec_ms, 1,
+                 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+                ERRORA(&quot;Can't load codec?\n&quot;, SKYPIAX_P_LOG);
+                switch_core_codec_destroy(&amp;tech_pvt-&gt;read_codec);
+                return SWITCH_STATUS_FALSE;
+        }
+
+        tech_pvt-&gt;read_frame.rate = sample_rate;
+        tech_pvt-&gt;read_frame.codec = &amp;tech_pvt-&gt;read_codec;
+
+        session = switch_core_session_locate(tech_pvt-&gt;session_uuid_str);
+
+        if (session) {
+                switch_core_session_set_read_codec(session, &amp;tech_pvt-&gt;read_codec);
+                switch_core_session_set_write_codec(session, &amp;tech_pvt-&gt;write_codec);
+                switch_core_session_rwunlock(session);
+        } else {
+                ERRORA(&quot;no session\n&quot;, 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-&gt;read_frame.data = tech_pvt-&gt;databuf;
+        tech_pvt-&gt;read_frame.buflen = sizeof(tech_pvt-&gt;databuf);
+        switch_mutex_init(&amp;tech_pvt-&gt;mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+        switch_mutex_init(&amp;tech_pvt-&gt;flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+        switch_core_session_set_private(session, tech_pvt);
+        switch_copy_string(tech_pvt-&gt;session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt-&gt;session_uuid_str));
+        if (!strlen(tech_pvt-&gt;session_uuid_str)) {
+                ERRORA(&quot;no tech_pvt-&gt;session_uuid_str\n&quot;, SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+        if (skypiax_codec(tech_pvt, SAMPLERATE_SKYPIAX, 20) != SWITCH_STATUS_SUCCESS) {
+                ERRORA(&quot;skypiax_codec FAILED\n&quot;, SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+        }
+        DEBUGA_SKYPE(&quot;skypiax_codec SUCCESS\n&quot;, 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 &gt; 0 || (interface_id == 0 &amp;&amp; strcmp(the_interface, &quot;0&quot;) == 0)) {
+                        if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                                return SWITCH_STATUS_SUCCESS;
+                        }
+                } else {
+                        /* interface name */
+                        for (interface_id = 0; interface_id &lt; 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 &lt; 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 &gt; 0 || (interface_id == 0 &amp;&amp; strcmp(the_interface, &quot;0&quot;) == 0)) {
+                        /* take a number as interface id */
+                        tech_pvt = &amp;globals.SKYPIAX_INTERFACES[interface_id];
+                } else {
+
+                        for (interface_id = 0; interface_id &lt; SKYPIAX_MAX_INTERFACES; interface_id++) {
+                                if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].name, the_interface) == 0) {
+                                        tech_pvt = &amp;globals.SKYPIAX_INTERFACES[interface_id];
+                                        break;
+                                }
+                        }
+                }
+        } else {                                        /* remove by skype_user */
+                for (interface_id = 0; interface_id &lt; SKYPIAX_MAX_INTERFACES; interface_id++) {
+                        if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].skype_user, the_interface) == 0) {
+                                tech_pvt = &amp;globals.SKYPIAX_INTERFACES[interface_id];
+                                break;
+                        }
+                }
+        }
+
+        if (!tech_pvt) {
+                DEBUGA_SKYPE(&quot;interface '%s' does not exist\n&quot;, SKYPIAX_P_LOG, the_interface);
+                goto end;
+        }
+
+        if (strlen(globals.SKYPIAX_INTERFACES[interface_id].session_uuid_str)) {
+                DEBUGA_SKYPE(&quot;interface '%s' is busy\n&quot;, 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-&gt;SkypiaxHandles.fdesc[1], &quot;sciutati&quot;, &amp;howmany);        // let's the controldev_thread die
+#else /* WIN32 */
+                howmany = write(tech_pvt-&gt;SkypiaxHandles.fdesc[1], &quot;sciutati&quot;, howmany);
+#endif /* WIN32 */
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+#ifdef WIN32
+                if (SendMessage(tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {        // let's the skypiax_api_thread_func die
+                        DEBUGA_SKYPE(&quot;got FALSE here, thread probably was already dead. GetLastError returned: %d\n&quot;, SKYPIAX_P_LOG, GetLastError());
+                        globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread = NULL;
+                }
+#else
+                XEvent e;
+                Atom atom1 = XInternAtom(tech_pvt-&gt;SkypiaxHandles.disp, &quot;SKYPECONTROLAPI_MESSAGE_BEGIN&quot;, False);
+                memset(&amp;e, 0, sizeof(e));
+                e.xclient.type = ClientMessage;
+                e.xclient.message_type = atom1;        /*  leading message */
+                e.xclient.display = tech_pvt-&gt;SkypiaxHandles.disp;
+                e.xclient.window = tech_pvt-&gt;SkypiaxHandles.skype_win;
+                e.xclient.format = 8;
+
+                XSendEvent(tech_pvt-&gt;SkypiaxHandles.disp, tech_pvt-&gt;SkypiaxHandles.win, False, 0, &amp;e);
+                XSync(tech_pvt-&gt;SkypiaxHandles.disp, False);
+#endif
+        }
+
+        while (x) {
+                x--;
+                switch_yield(50000);
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
+                switch_thread_join(&amp;status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread);
+        }
+
+        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+                switch_thread_join(&amp;status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread);
+        }
+
+        switch_mutex_lock(globals.mutex);
+        if (globals.sk_console == &amp;globals.SKYPIAX_INTERFACES[interface_id]) {
+                DEBUGA_SKYPE(&quot;interface '%s' no more console\n&quot;, SKYPIAX_P_LOG, the_interface);
+                globals.sk_console = NULL;
+        } else {
+                DEBUGA_SKYPE(&quot;interface '%s' STILL console\n&quot;, SKYPIAX_P_LOG, the_interface);
+        }
+        memset(&amp;globals.SKYPIAX_INTERFACES[interface_id], '\0', sizeof(private_t));
+        globals.real_interfaces--;
+        switch_mutex_unlock(globals.mutex);
+
+        DEBUGA_SKYPE(&quot;interface '%s' deleted successfully\n&quot;, 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(&quot;%s CHANNEL INIT\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL INIT %s\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL DESTROY %s\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;name, switch_core_session_get_uuid(session));
+
+                if (switch_core_codec_ready(&amp;tech_pvt-&gt;read_codec)) {
+                        switch_core_codec_destroy(&amp;tech_pvt-&gt;read_codec);
+                }
+
+                if (switch_core_codec_ready(&amp;tech_pvt-&gt;write_codec)) {
+                        switch_core_codec_destroy(&amp;tech_pvt-&gt;write_codec);
+                }
+                *tech_pvt-&gt;session_uuid_str = '\0';
+                tech_pvt-&gt;interface_state = SKYPIAX_STATE_IDLE;
+                if (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_FINISHED) {
+                        tech_pvt-&gt;skype_callflow = CALLFLOW_CALL_IDLE;
+                }
+                switch_core_session_set_private(session, NULL);
+        } else {
+                DEBUGA_SKYPE(&quot;!!!!!!NO tech_pvt!!!! CHANNEL DESTROY %s\n&quot;, 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-&gt;ob_failed_calls++;
+                } else {
+                        tech_pvt-&gt;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-&gt;skype_call_id)) {
+                //switch_thread_cond_signal(tech_pvt-&gt;cond);
+                DEBUGA_SKYPE(&quot;hanging up skype call: %s\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;skype_call_id);
+                sprintf(msg_to_skype, &quot;ALTER CALL %s HANGUP&quot;, tech_pvt-&gt;skype_call_id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+        }
+        //memset(tech_pvt-&gt;session_uuid_str, '\0', sizeof(tech_pvt-&gt;session_uuid_str));
+        //*tech_pvt-&gt;session_uuid_str = '\0';
+        DEBUGA_SKYPE(&quot;%s CHANNEL HANGUP\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;name);
+        switch_mutex_lock(globals.mutex);
+        globals.calls--;
+        if (globals.calls &lt; 0) {
+                globals.calls = 0;
+        }
+
+        tech_pvt-&gt;interface_state = SKYPIAX_STATE_IDLE;
+        if (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_FINISHED) {
+                tech_pvt-&gt;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(&quot;%s CHANNEL ROUTING\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL EXECUTE\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL KILL_CHANNEL\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;name);
+        switch (sig) {
+        case SWITCH_SIG_KILL:
+                DEBUGA_SKYPE(&quot;%s CHANNEL got SWITCH_SIG_KILL\n&quot;, SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                //switch_mutex_lock(tech_pvt-&gt;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-&gt;flag_mutex);
+                break;
+        case SWITCH_SIG_BREAK:
+                DEBUGA_SKYPE(&quot;%s CHANNEL got SWITCH_SIG_BREAK\n&quot;, SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                //switch_set_flag(tech_pvt, TFLAG_BREAK);
+                //switch_mutex_lock(tech_pvt-&gt;flag_mutex);
+                switch_set_flag(tech_pvt, TFLAG_BREAK);
+                //switch_mutex_unlock(tech_pvt-&gt;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(&quot;%s CHANNEL CONSUME_MEDIA\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL EXCHANGE_MEDIA\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL SOFT_EXECUTE\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;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(&quot;%s CHANNEL SEND_DTMF\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;name);
+        DEBUGA_SKYPE(&quot;DTMF: %c\n&quot;, SKYPIAX_P_LOG, dtmf-&gt;digit);
+
+        skypiax_senddigit(tech_pvt, dtmf-&gt;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(&quot;channel not ready \n&quot;, SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                return SWITCH_STATUS_FALSE;
+        }
+
+        tech_pvt-&gt;read_frame.flags = SFF_NONE;
+        *frame = NULL;
+
+        if (!skypiax_audio_read(tech_pvt)) {
+
+                ERRORA(&quot;skypiax_audio_read ERROR\n&quot;, 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(&quot;CHANNEL READ FRAME goto CNG\n&quot;, SKYPIAX_P_LOG);
+                        goto cng;
+                }
+
+                if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
+                        DEBUGA_SKYPE(&quot;CHANNEL READ FRAME not IO\n&quot;, SKYPIAX_P_LOG);
+                        return SWITCH_STATUS_FALSE;
+                }
+
+                if (switch_test_flag(tech_pvt, TFLAG_IO) &amp;&amp; switch_test_flag(tech_pvt, TFLAG_VOICE)) {
+                        switch_clear_flag(tech_pvt, TFLAG_VOICE);
+                        if (!tech_pvt-&gt;read_frame.datalen) {
+                                DEBUGA_SKYPE(&quot;CHANNEL READ CONTINUE\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        *frame = &amp;tech_pvt-&gt;read_frame;
+#ifdef BIGENDIAN
+                        if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+                                switch_swap_linear((*frame)-&gt;data, (int) (*frame)-&gt;datalen / 2);
+                        }
+#endif
+                        return SWITCH_STATUS_SUCCESS;
+                }
+
+                DEBUGA_SKYPE(&quot;CHANNEL READ no TFLAG_IO\n&quot;, SKYPIAX_P_LOG);
+                return SWITCH_STATUS_FALSE;
+
+        }
+
+        DEBUGA_SKYPE(&quot;CHANNEL READ FALSE\n&quot;, SKYPIAX_P_LOG);
+        return SWITCH_STATUS_FALSE;
+
+  cng:
+        data = (switch_byte_t *) tech_pvt-&gt;read_frame.data;
+        data[0] = 65;
+        data[1] = 0;
+        tech_pvt-&gt;read_frame.datalen = 2;
+        tech_pvt-&gt;read_frame.flags = SFF_CNG;
+        *frame = &amp;tech_pvt-&gt;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(&quot;channel not ready \n&quot;, 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-&gt;data, (int) frame-&gt;datalen / 2);
+        }
+#endif
+
+        sent = frame-&gt;datalen;
+#ifdef WIN32
+        switch_file_write(tech_pvt-&gt;audioskypepipe[1], frame-&gt;data, &amp;sent);
+#else /* WIN32 */
+        sent = write(tech_pvt-&gt;audioskypepipe[1], frame-&gt;data, sent);
+#endif /* WIN32 */
+        if (sent != frame-&gt;datalen &amp;&amp; sent != -1) {
+                DEBUGA_SKYPE(&quot;CLI PIPE write %d\n&quot;, 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(&quot;ANSWERED! \n&quot;, 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-&gt;message_id) {
+        case SWITCH_MESSAGE_INDICATE_ANSWER:
+                {
+                        DEBUGA_SKYPE(&quot;MSG_ID=%d, TO BE ANSWERED!\n&quot;, SKYPIAX_P_LOG, msg-&gt;message_id);
+                        channel_answer_channel(session);
+                }
+                break;
+        default:
+                {
+                        DEBUGA_SKYPE(&quot;MSG_ID=%d\n&quot;, SKYPIAX_P_LOG, msg-&gt;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 = &quot;&quot;;
+        }
+
+        WARNINGA(&quot;event: |||%s|||\n&quot;, 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(&quot;1 SESSION_REQUEST %s\n&quot;, SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+                switch_core_session_add_stream(*new_session, NULL);
+
+
+                if (!switch_strlen_zero(outbound_profile-&gt;destination_number)) {
+                        int i;
+                        char *slash;
+
+                        switch_copy_string(interface_name, outbound_profile-&gt;destination_number, 255);
+                        slash = strrchr(interface_name, '/');
+                        *slash = '\0';
+
+                        switch_mutex_lock(globals.mutex);
+                        if (strncmp(&quot;ANY&quot;, interface_name, strlen(interface_name)) == 0 || strncmp(&quot;RR&quot;, interface_name, strlen(interface_name)) == 0) {
+                                /* we've been asked for the &quot;ANY&quot; interface, let's find the first idle interface */
+                                //DEBUGA_SKYPE(&quot;Finding one available skype interface\n&quot;, SKYPIAX_P_LOG);
+                                //tech_pvt = find_available_skypiax_interface(NULL);
+                                //if (tech_pvt)
+                                //found = 1;
+                                //} else if (strncmp(&quot;RR&quot;, interface_name, strlen(interface_name)) == 0) {
+                                /* Find the first idle interface using Round Robin */
+                                DEBUGA_SKYPE(&quot;Finding one available skype interface RR\n&quot;, SKYPIAX_P_LOG);
+                                tech_pvt = find_available_skypiax_interface_rr(NULL);
+                                if (tech_pvt)
+                                        found = 1;
+                        }
+
+                        for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                                /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the &quot;ANY&quot; interface */
+                                if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                                        &amp;&amp; (strncmp(globals.SKYPIAX_INTERFACES[i].name, interface_name, strlen(interface_name)) == 0)) {
+                                        if (strlen(globals.SKYPIAX_INTERFACES[i].session_uuid_str)) {
+                                                DEBUGA_SKYPE
+                                                        (&quot;globals.SKYPIAX_INTERFACES[%d].name=|||%s||| session_uuid_str=|||%s||| is BUSY\n&quot;,
+                                                         SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name, globals.SKYPIAX_INTERFACES[i].session_uuid_str);
+                                                DEBUGA_SKYPE(&quot;1 SESSION_DESTROY %s\n&quot;, 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(&quot;globals.SKYPIAX_INTERFACES[%d].name=|||%s|||?\n&quot;, SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name);
+                                        tech_pvt = &amp;globals.SKYPIAX_INTERFACES[i];
+                                        found = 1;
+                                        break;
+                                }
+
+                        }
+
+                } else {
+                        ERRORA(&quot;Doh! no destination number?\n&quot;, SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+
+                if (!found) {
+                        DEBUGA_SKYPE(&quot;Doh! no available interface for |||%s|||?\n&quot;, SKYPIAX_P_LOG, interface_name);
+                        DEBUGA_SKYPE(&quot;2 SESSION_DESTROY %s\n&quot;, 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(&quot;Doh! no channel?\n&quot;, 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(&quot;Doh! no tech_init?\n&quot;, 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), &quot;skypiax/%s&quot;, outbound_profile-&gt;destination_number);
+                        //snprintf(name, sizeof(name), &quot;skypiax/%s&quot;, tech_pvt-&gt;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-&gt;caller_profile = caller_profile;
+                } else {
+                        ERRORA(&quot;Doh! no caller profile\n&quot;, SKYPIAX_P_LOG);
+                        switch_core_session_destroy(new_session);
+                        switch_mutex_unlock(globals.mutex);
+                        return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                }
+
+                tech_pvt-&gt;ob_calls++;
+
+                rdest = strchr(caller_profile-&gt;destination_number, '/');
+                *rdest++ = '\0';
+
+                //skypiax_call(tech_pvt, rdest, 30);
+
+                switch_copy_string(tech_pvt-&gt;session_uuid_str, switch_core_session_get_uuid(*new_session), sizeof(tech_pvt-&gt;session_uuid_str));
+                caller_profile = tech_pvt-&gt;caller_profile;
+                caller_profile-&gt;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(&quot;Doh! no new_session\n&quot;, 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(&quot;In skypiax_signaling_thread_func: started, p=%p\n&quot;, SKYPIAX_P_LOG, (void *) tech_pvt);
+
+        while (forever) {
+                if (!(running &amp;&amp; tech_pvt-&gt;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(&quot;skype call ended\n&quot;, SKYPIAX_P_LOG);
+
+                        if (tech_pvt) {
+                                session = switch_core_session_locate(tech_pvt-&gt;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 &lt; CS_EXECUTE) {
+                                                        switch_sleep(10000);        //10 msec, let the state evolve from CS_NEW
+                                                }
+                                                switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+                                        } else {
+                                                ERRORA(&quot;no channel?\n&quot;, SKYPIAX_P_LOG);
+                                        }
+                                        switch_core_session_rwunlock(session);
+                                } else {
+                                        DEBUGA_SKYPE(&quot;no session\n&quot;, SKYPIAX_P_LOG);
+                                }
+                                switch_mutex_lock(globals.mutex);
+                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                *tech_pvt-&gt;session_uuid_str = '\0';
+                                *tech_pvt-&gt;skype_call_id = '\0';
+                                switch_mutex_unlock(globals.mutex);
+
+                                //ERRORA(&quot;LET'S WAIT\n&quot;, SKYPIAX_P_LOG);
+                                switch_sleep(300000);        //0.3 sec
+                                //ERRORA(&quot;WAIT'S OVER\n&quot;, SKYPIAX_P_LOG);
+                                //tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                //usleep(30000);    //0.03 sec
+                                switch_mutex_lock(globals.mutex);
+                                tech_pvt-&gt;skype_callflow = CALLFLOW_CALL_IDLE;
+                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_IDLE;
+                                switch_mutex_unlock(globals.mutex);
+                        } else {
+                                ERRORA(&quot;no tech_pvt?\n&quot;, SKYPIAX_P_LOG);
+                        }
+                }
+        }
+        return NULL;
+}
+
+/* BEGIN: Changes heres */
+static switch_status_t load_config(int reload_type)
+/* END: Changes heres */
+{
+        char *cf = &quot;skypiax.conf&quot;;
+        switch_xml_t cfg, xml, global_settings, param, interfaces, myinterface;
+        private_t *tech_pvt = NULL;
+
+        switch_mutex_init(&amp;globals.mutex, SWITCH_MUTEX_NESTED, skypiax_module_pool);
+        if (!(xml = switch_xml_open_cfg(cf, &amp;cfg, NULL))) {
+                ERRORA(&quot;open of %s failed\n&quot;, 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, &quot;global_settings&quot;))) {
+                for (param = switch_xml_child(global_settings, &quot;param&quot;); param; param = param-&gt;next) {
+                        char *var = (char *) switch_xml_attr_soft(param, &quot;name&quot;);
+                        char *val = (char *) switch_xml_attr_soft(param, &quot;value&quot;);
+
+                        if (!strcasecmp(var, &quot;debug&quot;)) {
+                                DEBUGA_SKYPE(&quot;globals.debug=%d\n&quot;, SKYPIAX_P_LOG, globals.debug);
+                                globals.debug = atoi(val);
+                                DEBUGA_SKYPE(&quot;globals.debug=%d\n&quot;, SKYPIAX_P_LOG, globals.debug);
+                        } else if (!strcasecmp(var, &quot;hold-music&quot;)) {
+                                switch_set_string(globals.hold_music, val);
+                                DEBUGA_SKYPE(&quot;globals.hold_music=%s\n&quot;, SKYPIAX_P_LOG, globals.hold_music);
+                        } else if (!strcmp(var, &quot;port&quot;)) {
+                                globals.port = atoi(val);
+                                DEBUGA_SKYPE(&quot;globals.port=%d\n&quot;, SKYPIAX_P_LOG, globals.port);
+                        } else if (!strcmp(var, &quot;codec-master&quot;)) {
+                                if (!strcasecmp(val, &quot;us&quot;)) {
+                                        switch_set_flag(&amp;globals, GFLAG_MY_CODEC_PREFS);
+                                }
+                                DEBUGA_SKYPE(&quot;codec-master globals.debug=%d\n&quot;, SKYPIAX_P_LOG, globals.debug);
+                        } else if (!strcmp(var, &quot;dialplan&quot;)) {
+                                set_global_dialplan(val);
+                                DEBUGA_SKYPE(&quot;globals.dialplan=%s\n&quot;, SKYPIAX_P_LOG, globals.dialplan);
+                        } else if (!strcmp(var, &quot;destination&quot;)) {
+                                set_global_destination(val);
+                                DEBUGA_SKYPE(&quot;globals.destination=%s\n&quot;, SKYPIAX_P_LOG, globals.destination);
+                        } else if (!strcmp(var, &quot;context&quot;)) {
+                                set_global_context(val);
+                                DEBUGA_SKYPE(&quot;globals.context=%s\n&quot;, SKYPIAX_P_LOG, globals.context);
+                        } else if (!strcmp(var, &quot;codec-prefs&quot;)) {
+                                set_global_codec_string(val);
+                                DEBUGA_SKYPE(&quot;globals.codec_string=%s\n&quot;, 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, &quot;codec-rates&quot;)) {
+                                set_global_codec_rates_string(val);
+                                DEBUGA_SKYPE(&quot;globals.codec_rates_string=%s\n&quot;, 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, &quot;per_interface_settings&quot;))) {
+                int i = 0;
+
+                for (myinterface = switch_xml_child(interfaces, &quot;interface&quot;); myinterface; myinterface = myinterface-&gt;next) {
+                        char *id = (char *) switch_xml_attr(myinterface, &quot;id&quot;);
+                        char *name = (char *) switch_xml_attr(myinterface, &quot;name&quot;);
+                        char *context = &quot;default&quot;;
+                        char *dialplan = &quot;XML&quot;;
+                        char *destination = &quot;5000&quot;;
+                        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 = &quot;true&quot;;
+                        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, &quot;param&quot;); param; param = param-&gt;next) {
+                                char *var = (char *) switch_xml_attr_soft(param, &quot;name&quot;);
+                                char *val = (char *) switch_xml_attr_soft(param, &quot;value&quot;);
+
+                                if (!strcasecmp(var, &quot;tonegroup&quot;)) {
+                                        tonegroup = val;
+                                } else if (!strcasecmp(var, &quot;digit_timeout&quot;) || !strcasecmp(var, &quot;digit-timeout&quot;)) {
+                                        digit_timeout = val;
+                                } else if (!strcasecmp(var, &quot;context&quot;)) {
+                                        context = val;
+                                } else if (!strcasecmp(var, &quot;dialplan&quot;)) {
+                                        dialplan = val;
+                                } else if (!strcasecmp(var, &quot;destination&quot;)) {
+                                        destination = val;
+                                } else if (!strcasecmp(var, &quot;dial-regex&quot;)) {
+                                        dial_regex = val;
+                                } else if (!strcasecmp(var, &quot;enable-callerid&quot;)) {
+                                        enable_callerid = val;
+                                } else if (!strcasecmp(var, &quot;fail-dial-regex&quot;)) {
+                                        fail_dial_regex = val;
+                                } else if (!strcasecmp(var, &quot;hold-music&quot;)) {
+                                        hold_music = val;
+                                } else if (!strcasecmp(var, &quot;skype_user&quot;)) {
+                                        skype_user = val;
+                                } else if (!strcasecmp(var, &quot;tcp_cli_port&quot;)) {
+                                        tcp_cli_port = val;
+                                } else if (!strcasecmp(var, &quot;tcp_srv_port&quot;)) {
+                                        tcp_srv_port = val;
+                                } else if (!strcasecmp(var, &quot;X11-display&quot;) || !strcasecmp(var, &quot;X11_display&quot;)) {
+                                        X11_display = val;
+                                } else if (!strcasecmp(var, &quot;max_digits&quot;) || !strcasecmp(var, &quot;max-digits&quot;)) {
+                                        max_digits = val;
+                                } else if (!strcasecmp(var, &quot;hotline&quot;)) {
+                                        hotline = val;
+                                }
+
+                        }
+                        if (!skype_user) {
+                                ERRORA(&quot;interface missing REQUIRED param 'skype_user'\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+
+                        /* BEGIN: Changes here */
+                        if (reload_type == SOFT_RELOAD) {
+                                char the_interface[256];
+                                sprintf(the_interface, &quot;#%s&quot;, name);
+
+                                if (interface_exists(the_interface) == SWITCH_STATUS_SUCCESS) {
+                                        continue;
+                                }
+                        }
+                        /* END: Changes here */
+
+                        if (!X11_display) {
+                                ERRORA(&quot;interface missing REQUIRED param 'X11_display'\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (!tcp_cli_port) {
+                                ERRORA(&quot;interface missing REQUIRED param 'tcp_cli_port'\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+
+                        if (!tcp_srv_port) {
+                                ERRORA(&quot;interface missing REQUIRED param 'tcp_srv_port'\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (!id) {
+                                ERRORA(&quot;interface missing REQUIRED param 'id'\n&quot;, SKYPIAX_P_LOG);
+                                continue;
+                        }
+                        if (switch_is_number(id)) {
+                                interface_id = atoi(id);
+                                DEBUGA_SKYPE(&quot;interface_id=%d\n&quot;, SKYPIAX_P_LOG, interface_id);
+                        } else {
+                                ERRORA(&quot;interface param 'id' MUST be a number, now id='%s'\n&quot;, SKYPIAX_P_LOG, id);
+                                continue;
+                        }
+
+                        if (!name) {
+                                WARNINGA(&quot;interface missing param 'name', not nice, but works\n&quot;, SKYPIAX_P_LOG);
+                        }
+
+                        if (!tonegroup) {
+                                tonegroup = &quot;us&quot;;
+                        }
+
+                        if (digit_timeout) {
+                                to = atoi(digit_timeout);
+                        }
+
+                        if (max_digits) {
+                                max = atoi(max_digits);
+                        }
+
+                        if (name) {
+                                DEBUGA_SKYPE(&quot;name=%s\n&quot;, SKYPIAX_P_LOG, name);
+                        }
+#ifndef WIN32
+                        if (!XInitThreads()) {
+                                ERRORA(&quot;Not initialized XInitThreads!\n&quot;, SKYPIAX_P_LOG);
+                        } else {
+                                DEBUGA_SKYPE(&quot;Initialized XInitThreads!\n&quot;, SKYPIAX_P_LOG);
+                        }
+                        switch_sleep(100);
+#endif /* WIN32 */
+
+                        if (interface_id &amp;&amp; interface_id &lt; SKYPIAX_MAX_INTERFACES) {
+                                private_t newconf;
+                                switch_threadattr_t *skypiax_api_thread_attr = NULL;
+                                switch_threadattr_t *skypiax_signaling_thread_attr = NULL;
+
+                                memset(&amp;newconf, '\0', sizeof(newconf));
+                                globals.SKYPIAX_INTERFACES[interface_id] = newconf;
+                                globals.SKYPIAX_INTERFACES[interface_id].running = 1;
+
+
+                                tech_pvt = &amp;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, &quot;N/A&quot;);
+                                }
+                                DEBUGA_SKYPE(&quot;CONFIGURING interface_id=%d\n&quot;, 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
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].X11_display=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].X11_display);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].skype_user=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port=%d\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port=%d\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port);
+                                DEBUGA_SKYPE(&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].name=%s\n&quot;,
+                                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].name);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].dialplan=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].dialplan);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].destination=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].destination);
+                                DEBUGA_SKYPE
+                                        (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
+                                WARNINGA(&quot;STARTING interface_id=%d\n&quot;, SKYPIAX_P_LOG, interface_id);
+
+                                switch_threadattr_create(&amp;skypiax_api_thread_attr, skypiax_module_pool);
+                                switch_threadattr_stacksize_set(skypiax_api_thread_attr, SWITCH_THREAD_STACKSIZE);
+                                switch_thread_create(&amp;globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread,
+                                                                         skypiax_api_thread_attr, skypiax_do_skypeapi_thread, &amp;globals.SKYPIAX_INTERFACES[interface_id], skypiax_module_pool);
+
+                                switch_sleep(100000);
+
+                                switch_threadattr_create(&amp;skypiax_signaling_thread_attr, skypiax_module_pool);
+                                switch_threadattr_stacksize_set(skypiax_signaling_thread_attr, SWITCH_THREAD_STACKSIZE);
+                                switch_thread_create(&amp;globals.SKYPIAX_INTERFACES[interface_id].
+                                                                         skypiax_signaling_thread, skypiax_signaling_thread_attr,
+                                                                         skypiax_signaling_thread_func, &amp;globals.SKYPIAX_INTERFACES[interface_id], skypiax_module_pool);
+
+                                switch_sleep(100000);
+
+                                skypiax_audio_init(&amp;globals.SKYPIAX_INTERFACES[interface_id]);
+
+                                NOTICA
+                                        (&quot;WAITING roughly 10 seconds to find a running Skype client and connect to its SKYPE API for interface_id=%d\n&quot;,
+                                         SKYPIAX_P_LOG, interface_id);
+                                i = 0;
+                                while (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.api_connected == 0 &amp;&amp; running &amp;&amp; i &lt; 200) {        // 10 seconds! thanks Jeff Lenk
+                                        switch_sleep(50000);
+                                        i++;
+                                }
+                                if (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.api_connected) {
+                                        NOTICA
+                                                (&quot;Found a running Skype client, connected to its SKYPE API for interface_id=%d, waiting 60 seconds for CURRENTUSERHANDLE==%s\n&quot;,
+                                                 SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                } else {
+                                        ERRORA
+                                                (&quot;Failed to connect to a SKYPE API for interface_id=%d, no SKYPE client running, please (re)start Skype client. Skypiax exiting\n&quot;,
+                                                 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 &amp;&amp; running &amp;&amp; i &lt; 1200) {        // 60 seconds! thanks Jeff Lenk
+                                        switch_sleep(50000);
+                                        i++;
+                                }
+                                if (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.currentuserhandle) {
+                                        WARNINGA
+                                                (&quot;Interface_id=%d is now STARTED, the Skype client to which we are connected gave us the correct CURRENTUSERHANDLE (%s)\n&quot;,
+                                                 SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+
+                                        skypiax_signaling_write(&amp;globals.SKYPIAX_INTERFACES[interface_id], &quot;SET AUTOAWAY OFF&quot;);
+                                } else {
+                                        ERRORA
+                                                (&quot;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&quot;,
+                                                 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(&quot;interface id %d is higher than SKYPIAX_MAX_INTERFACES (%d)\n&quot;, SKYPIAX_P_LOG, interface_id, SKYPIAX_MAX_INTERFACES);
+                                continue;
+                        }
+
+                }
+
+                for (i = 0; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+                                /* How many real intterfaces */
+                                globals.real_interfaces = i + 1;
+
+                                tech_pvt = &amp;globals.SKYPIAX_INTERFACES[i];
+
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].interface_id=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].interface_id);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].X11_display=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].X11_display);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].name=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].name);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].context);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].dialplan=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].dialplan);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].destination=%s\n&quot;, SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].destination);
+                                DEBUGA_SKYPE(&quot;i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n&quot;, 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(&amp;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-&gt;interface_name = &quot;skypiax&quot;;
+        skypiax_endpoint_interface-&gt;io_routines = &amp;skypiax_io_routines;
+        skypiax_endpoint_interface-&gt;state_handler = &amp;skypiax_state_handlers;
+
+        if (running) {
+
+                SWITCH_ADD_API(commands_api_interface, &quot;sk&quot;, &quot;Skypiax console commands&quot;, sk_function, SK_SYNTAX);
+                SWITCH_ADD_API(commands_api_interface, &quot;skypiax&quot;, &quot;Skypiax interface commands&quot;, 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 &lt; SKYPIAX_MAX_INTERFACES; interface_id++) {
+                tech_pvt = &amp;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-&gt;SkypiaxHandles.fdesc[1], &quot;sciutati&quot;, &amp;howmany);        // let's the controldev_thread die
+#else /* WIN32 */
+                                howmany = write(tech_pvt-&gt;SkypiaxHandles.fdesc[1], &quot;sciutati&quot;, howmany);
+#endif /* WIN32 */
+                        }
+
+                        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+#ifdef WIN32
+                                if (SendMessage(tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {        // let's the skypiax_api_thread_func die
+                                        DEBUGA_SKYPE(&quot;got FALSE here, thread probably was already dead. GetLastError returned: %d\n&quot;, SKYPIAX_P_LOG, GetLastError());
+                                        globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread = NULL;
+                                }
+#else
+                                XEvent e;
+                                Atom atom1 = XInternAtom(tech_pvt-&gt;SkypiaxHandles.disp, &quot;SKYPECONTROLAPI_MESSAGE_BEGIN&quot;,
+                                                                                 False);
+                                memset(&amp;e, 0, sizeof(e));
+                                e.xclient.type = ClientMessage;
+                                e.xclient.message_type = atom1;        /*  leading message */
+                                e.xclient.display = tech_pvt-&gt;SkypiaxHandles.disp;
+                                e.xclient.window = tech_pvt-&gt;SkypiaxHandles.skype_win;
+                                e.xclient.format = 8;
+
+                                XSendEvent(tech_pvt-&gt;SkypiaxHandles.disp, tech_pvt-&gt;SkypiaxHandles.win, False, 0, &amp;e);
+                                XSync(tech_pvt-&gt;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(&amp;status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread);
+                        }
+                        if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+                                switch_thread_join(&amp;status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread);
+                        }
+#ifndef WIN32
+                        WARNINGA(&quot;SHUTDOWN interface_id=%d\n&quot;, SKYPIAX_P_LOG, interface_id);
+                        shutdown(tech_pvt-&gt;audioskypepipe[0], 2);
+                        close(tech_pvt-&gt;audioskypepipe[0]);
+                        shutdown(tech_pvt-&gt;audioskypepipe[1], 2);
+                        close(tech_pvt-&gt;audioskypepipe[1]);
+                        shutdown(tech_pvt-&gt;audiopipe[0], 2);
+                        close(tech_pvt-&gt;audiopipe[0]);
+                        shutdown(tech_pvt-&gt;audiopipe[1], 2);
+                        close(tech_pvt-&gt;audiopipe[1]);
+                        shutdown(tech_pvt-&gt;SkypiaxHandles.fdesc[0], 2);
+                        close(tech_pvt-&gt;SkypiaxHandles.fdesc[0]);
+                        shutdown(tech_pvt-&gt;SkypiaxHandles.fdesc[1], 2);
+                        close(tech_pvt-&gt;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-&gt;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(&quot;received DTMF %c on channel %s\n&quot;, SKYPIAX_P_LOG, dtmf.digit, switch_channel_get_name(channel));
+                        switch_mutex_lock(tech_pvt-&gt;flag_mutex);
+                        //FIXME: why sometimes DTMFs from here do not seems to be get by FS?
+                        switch_channel_queue_dtmf(channel, &amp;dtmf);
+                        switch_set_flag(tech_pvt, TFLAG_DTMF);
+                        switch_mutex_unlock(tech_pvt-&gt;flag_mutex);
+                } else {
+                        DEBUGA_SKYPE
+                                (&quot;received a DTMF on channel %s, but we're BRIDGED, so let's NOT relay it out of band\n&quot;, SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                }
+        } else {
+                WARNINGA(&quot;received %c DTMF, but no channel?\n&quot;, 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(&amp;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(&amp;tech_pvt-&gt;tcp_srv_thread, thd_attr, skypiax_do_tcp_srv_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) {
+                DEBUGA_SKYPE(&quot;started tcp_srv_thread thread.\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                ERRORA(&quot;failed to start tcp_srv_thread thread.\n&quot;, SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        switch_threadattr_create(&amp;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(&amp;tech_pvt-&gt;tcp_cli_thread, thd_attr, skypiax_do_tcp_cli_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) {
+                DEBUGA_SKYPE(&quot;started tcp_cli_thread thread.\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                ERRORA(&quot;failed to start tcp_cli_thread thread.\n&quot;, SKYPIAX_P_LOG);
+                return -1;
+        }
+        switch_sleep(100000);
+
+        if (tech_pvt-&gt;tcp_cli_thread == NULL || tech_pvt-&gt;tcp_srv_thread == NULL) {
+                ERRORA(&quot;tcp_cli_thread or tcp_srv_thread exited\n&quot;, 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(&quot;2 SESSION_REQUEST %s\n&quot;, 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(&quot;Doh! no channel?\n&quot;, SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&amp;session);
+                        return 0;
+                }
+                if (skypiax_tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS) {
+                        ERRORA(&quot;Doh! no tech_init?\n&quot;, SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&amp;session);
+                        return 0;
+                }
+
+                if ((tech_pvt-&gt;caller_profile =
+                         switch_caller_profile_new(switch_core_session_get_pool(session), &quot;skypiax&quot;,
+                                                                           tech_pvt-&gt;dialplan, tech_pvt-&gt;callid_name,
+                                                                           tech_pvt-&gt;callid_number, NULL, NULL, NULL, NULL, &quot;mod_skypiax&quot;, tech_pvt-&gt;context, tech_pvt-&gt;destination)) != 0) {
+                        char name[128];
+                        //switch_snprintf(name, sizeof(name), &quot;skypiax/%s/%s&quot;, tech_pvt-&gt;name, tech_pvt-&gt;caller_profile-&gt;destination_number);
+                        switch_snprintf(name, sizeof(name), &quot;skypiax/%s&quot;, tech_pvt-&gt;name);
+                        switch_channel_set_name(channel, name);
+                        switch_channel_set_caller_profile(channel, tech_pvt-&gt;caller_profile);
+                }
+                switch_channel_set_state(channel, CS_INIT);
+                if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
+                        ERRORA(&quot;Error spawning thread\n&quot;, SKYPIAX_P_LOG);
+                        switch_core_session_destroy(&amp;session);
+                        return 0;
+                }
+        }
+        if (channel) {
+                switch_channel_mark_answered(channel);
+        }
+
+        DEBUGA_SKYPE(&quot;new_inbound_channel\n&quot;, 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-&gt;session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt-&gt;session_uuid_str);
+        } else {
+                ERRORA(&quot;No session???\n&quot;, SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (session) {
+                channel = switch_core_session_get_channel(session);
+        } else {
+                ERRORA(&quot;No session???\n&quot;, SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_ring_ready(channel);
+                DEBUGA_SKYPE(&quot;skype_call: REMOTE PARTY RINGING\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                ERRORA(&quot;No channel???\n&quot;, 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-&gt;session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt-&gt;session_uuid_str);
+        } else {
+                ERRORA(&quot;No session???\n\n\n&quot;, 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(&quot;No session???\n&quot;, SKYPIAX_P_LOG);
+                //TODO: kill the bastard
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_pre_answered(channel);
+                DEBUGA_SKYPE(&quot;skype_call: REMOTE PARTY EARLY MEDIA\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                ERRORA(&quot;No channel???\n&quot;, 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-&gt;session_uuid_str)) {
+                session = switch_core_session_locate(tech_pvt-&gt;session_uuid_str);
+        } else {
+                ERRORA(&quot;No session???\n&quot;, SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (session) {
+                channel = switch_core_session_get_channel(session);
+        } else {
+                ERRORA(&quot;No channel???\n&quot;, SKYPIAX_P_LOG);
+                goto done;
+        }
+        if (channel) {
+                switch_channel_mark_answered(channel);
+                //DEBUGA_SKYPE(&quot;skype_call: %s, answered\n&quot;, SKYPIAX_P_LOG, id);
+        } else {
+                ERRORA(&quot;No channel???\n&quot;, SKYPIAX_P_LOG);
+        }
+
+        switch_core_session_rwunlock(session);
+
+  done:
+        DEBUGA_SKYPE(&quot;outbound_channel_answered!\n&quot;, 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 &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                int interface_id;
+
+                interface_id = globals.next_interface;
+                //interface_id = interface_id &lt; SKYPIAX_MAX_INTERFACES ? interface_id : interface_id - SKYPIAX_MAX_INTERFACES + 1;
+                globals.next_interface = interface_id + 1 &lt; SKYPIAX_MAX_INTERFACES ? interface_id + 1 : 0;
+
+                if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                        int skype_state = 0;
+
+                        tech_pvt = &amp;globals.SKYPIAX_INTERFACES[interface_id];
+                        skype_state = tech_pvt-&gt;interface_state;
+                        //DEBUGA_SKYPE(&quot;skype interface: %d, name: %s, state: %d\n&quot;, SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].name, skype_state);
+                        if ((tech_pvt_calling ? strcmp(tech_pvt-&gt;skype_user, tech_pvt_calling-&gt;skype_user) : 1)
+                                &amp;&amp; (SKYPIAX_STATE_DOWN == skype_state || 0 == skype_state) &amp;&amp; (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_FINISHED
+                                                                                                                                                           || 0 == tech_pvt-&gt;skype_callflow)) {
+                                DEBUGA_SKYPE(&quot;returning as available skype interface name: %s, state: %d callflow: %d\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;name, skype_state,
+                                                         tech_pvt-&gt;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-&gt;interface_state = SKYPIAX_STATE_SELECTED;
+                                }
+
+                                switch_mutex_unlock(globals.mutex);
+                                return tech_pvt;
+                        }
+                }                                                // else {
+                //DEBUGA_SKYPE(&quot;Skype interface: %d blank!! A hole here means we cannot hunt the last interface.\n&quot;, 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-&gt;write_function(stream, &quot;sk console is: |||%s|||\n&quot;, globals.sk_console-&gt;name);
+        else
+                stream-&gt;write_function(stream, &quot;sk console is NOT yet assigned\n&quot;);
+
+        if (!switch_strlen_zero(cmd) &amp;&amp; (mycmd = strdup(cmd))) {
+                argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+        }
+
+        if (!argc || !argv[0]) {
+                stream-&gt;write_function(stream, &quot;%s&quot;, SK_SYNTAX);
+                goto end;
+        }
+
+        if (!strcasecmp(argv[0], &quot;list&quot;)) {
+                int i;
+                char next_flag_char = ' ';
+
+                stream-&gt;write_function(stream, &quot;F ID\t    Name    \tIB (F/T)    OB (F/T)\tState\tCallFlw\t\tUUID\n&quot;);
+                stream-&gt;write_function(stream, &quot;= ====\t  ========  \t=======     =======\t======\t============\t======\n&quot;);
+
+                for (i = 0; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                        next_flag_char = i == globals.next_interface ? '*' : ' ';
+
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+                                stream-&gt;write_function(stream,
+                                                                           &quot;%c %d\t[%s]\t%3ld/%ld\t%6ld/%ld\t%s\t%s\t%s\n&quot;,
+                                                                           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 &gt; 1 &amp;&amp; !strcasecmp(argv[1], &quot;full&quot;)) {
+                                stream-&gt;write_function(stream, &quot;%c\t%d\n&quot;, next_flag_char, i);
+                        }
+
+                }
+                stream-&gt;write_function(stream, &quot;\nTotal: %d\n&quot;, globals.real_interfaces - 1);
+
+        } else if (!strcasecmp(argv[0], &quot;console&quot;)) {
+                int i;
+                int found = 0;
+
+                if (argc == 2) {
+                        for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                                /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the &quot;ANY&quot; interface */
+                                if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                                        &amp;&amp; (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[1], strlen(argv[1])) == 0)) {
+                                        globals.sk_console = &amp;globals.SKYPIAX_INTERFACES[i];
+                                        stream-&gt;write_function(stream,
+                                                                                   &quot;sk console is now: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n&quot;, i, globals.SKYPIAX_INTERFACES[i].name);
+                                        stream-&gt;write_function(stream, &quot;sk console is: |||%s|||\n&quot;, globals.sk_console-&gt;name);
+                                        found = 1;
+                                        break;
+                                }
+
+                        }
+                        if (!found)
+                                stream-&gt;write_function(stream, &quot;ERROR: A Skypiax interface with name='%s' was not found\n&quot;, argv[1]);
+                } else {
+
+                        stream-&gt;write_function(stream, &quot;-ERR Usage: sk console interface_name\n&quot;);
+                        goto end;
+                }
+
+        } else if (!strcasecmp(argv[0], &quot;ciapalino&quot;)) {
+
+/* BEGIN: Changes heres */
+        } else if (!strcasecmp(argv[0], &quot;reload&quot;)) {
+                if (load_config(SOFT_RELOAD) != SWITCH_STATUS_SUCCESS) {
+                        stream-&gt;write_function(stream, &quot;sk reload failed\n&quot;);
+                } else {
+                        stream-&gt;write_function(stream, &quot;sk reload success\n&quot;);
+                }
+        } else if (!strcasecmp(argv[0], &quot;remove&quot;)) {
+                if (argc == 2) {
+                        if (remove_interface(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                                if (interface_exists(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                                        stream-&gt;write_function(stream, &quot;sk remove '%s' failed\n&quot;, argv[1]);
+                                } else {
+                                        stream-&gt;write_function(stream, &quot;sk remove '%s' success\n&quot;, argv[1]);
+                                }
+                        }
+                } else {
+                        stream-&gt;write_function(stream, &quot;-ERR Usage: sk remove interface_name\n&quot;);
+                        goto end;
+                }
+/* END: Changes heres */
+
+        } else {
+                if (globals.sk_console)
+                        skypiax_signaling_write(globals.sk_console, (char *) cmd);
+                else
+                        stream-&gt;write_function(stream, &quot;sk console is NOT yet assigned\n&quot;);
+        }
+  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) &amp;&amp; (mycmd = strdup(cmd))) {
+                argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+        }
+
+        if (!argc) {
+                stream-&gt;write_function(stream, &quot;ERROR, usage: %s&quot;, SKYPIAX_SYNTAX);
+                goto end;
+        }
+
+        if (argc &lt; 2) {
+                stream-&gt;write_function(stream, &quot;ERROR, usage: %s&quot;, SKYPIAX_SYNTAX);
+                goto end;
+        }
+
+        if (argv[0]) {
+                int i;
+                int found = 0;
+
+                for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                        /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the &quot;ANY&quot; interface */
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                                &amp;&amp; (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
+                                tech_pvt = &amp;globals.SKYPIAX_INTERFACES[i];
+                                stream-&gt;write_function(stream, &quot;Using interface: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n&quot;, i, globals.SKYPIAX_INTERFACES[i].name);
+                                found = 1;
+                                break;
+                        }
+
+                }
+                if (!found) {
+                        stream-&gt;write_function(stream, &quot;ERROR: A Skypiax interface with name='%s' was not found\n&quot;, argv[0]);
+                        switch_safe_free(mycmd);
+
+                        return SWITCH_STATUS_SUCCESS;
+                } else {
+                        skypiax_signaling_write(tech_pvt, (char *) &amp;cmd[strlen(argv[0]) + 1]);
+                }
+        } else {
+                stream-&gt;write_function(stream, &quot;ERROR, usage: %s&quot;, 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(&amp;timenow, NULL);
+        for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                        giovatech = &amp;globals.SKYPIAX_INTERFACES[i];
+                        //NOTICA(&quot;skype interface: %d, name: %s, state: %d, value=%s, giovatech-&gt;callid_number=%s, giovatech-&gt;skype_user=%s\n&quot;, SKYPIAX_P_LOG, i, giovatech-&gt;name, giovatech-&gt;interface_state, value, giovatech-&gt;callid_number, giovatech-&gt;skype_user);
+                        //FIXME check a timestamp here
+                        if (strlen(giovatech-&gt;skype_call_id) &amp;&amp; (giovatech-&gt;interface_state != SKYPIAX_STATE_DOWN) &amp;&amp; (!strcmp(giovatech-&gt;skype_user, tech_pvt-&gt;skype_user)) &amp;&amp; (!strcmp(giovatech-&gt;callid_number, value)) &amp;&amp; ((((timenow.tv_sec - giovatech-&gt;answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech-&gt;answer_time.tv_usec)) &lt; 500000)) {        //0.5sec
+                                found = 1;
+                                DEBUGA_SKYPE
+                                        (&quot;FOUND  (name=%s, giovatech-&gt;interface_state=%d != SKYPIAX_STATE_DOWN) &amp;&amp; (giovatech-&gt;skype_user=%s == tech_pvt-&gt;skype_user=%s) &amp;&amp; (giovatech-&gt;callid_number=%s == value=%s)\n&quot;,
+                                         SKYPIAX_P_LOG, giovatech-&gt;name, giovatech-&gt;interface_state,
+                                         giovatech-&gt;skype_user, tech_pvt-&gt;skype_user, giovatech-&gt;callid_number, value)
+                                        if (tech_pvt-&gt;interface_state == SKYPIAX_STATE_PRERING) {
+                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                } else if (tech_pvt-&gt;interface_state != 0 &amp;&amp; tech_pvt-&gt;interface_state != SKYPIAX_STATE_DOWN) {
+                                        WARNINGA(&quot;Why an interface_state %d HERE?\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;interface_state);
+                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                }
+
+                                break;
+                        }
+                }
+        }
+
+        if (found) {
+                //tech_pvt-&gt;callid_number[0]='\0';
+                //sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, id);
+                //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_mutex_unlock(globals.mutex);
+                return 0;
+        }
+        DEBUGA_SKYPE(&quot;NOT FOUND\n&quot;, SKYPIAX_P_LOG);
+
+        if (tech_pvt &amp;&amp; tech_pvt-&gt;skype_call_id &amp;&amp; !strlen(tech_pvt-&gt;skype_call_id)) {
+                /* we are not inside an active call */
+
+                tech_pvt-&gt;ib_calls++;
+
+                sprintf(msg_to_skype, &quot;GET CALL %s PARTNER_DISPNAME&quot;, id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_sleep(10000);
+                tech_pvt-&gt;interface_state = SKYPIAX_STATE_PREANSWER;
+                sprintf(msg_to_skype, &quot;ALTER CALL %s ANSWER&quot;, id);
+                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                DEBUGA_SKYPE(&quot;We answered a Skype RING on skype_call %s\n&quot;, SKYPIAX_P_LOG, id);
+                //FIXME write a timestamp here
+                gettimeofday(&amp;tech_pvt-&gt;answer_time, NULL);
+                switch_copy_string(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+
+                switch_copy_string(tech_pvt-&gt;callid_number, value, sizeof(tech_pvt-&gt;callid_number) - 1);
+
+                DEBUGA_SKYPE
+                        (&quot;NEW!  name: %s, state: %d, value=%s, tech_pvt-&gt;callid_number=%s, tech_pvt-&gt;skype_user=%s\n&quot;,
+                         SKYPIAX_P_LOG, tech_pvt-&gt;name, tech_pvt-&gt;interface_state, value, tech_pvt-&gt;callid_number, tech_pvt-&gt;skype_user);
+        } else if (!tech_pvt || !tech_pvt-&gt;skype_call_id) {
+                ERRORA(&quot;No Call ID?\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                DEBUGA_SKYPE(&quot;We're in a call now (%s), let's refuse this one (%s)\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;skype_call_id, id);
+                sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, 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(&amp;timenow, NULL);
+        for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                        giovatech = &amp;globals.SKYPIAX_INTERFACES[i];
+                        //NOTICA(&quot;skype interface: %d, name: %s, state: %d, value=%s, giovatech-&gt;callid_number=%s, giovatech-&gt;skype_user=%s\n&quot;, SKYPIAX_P_LOG, i, giovatech-&gt;name, giovatech-&gt;interface_state, value, giovatech-&gt;callid_number, giovatech-&gt;skype_user);
+                        //FIXME check a timestamp here
+                        if (strlen(giovatech-&gt;skype_call_id) &amp;&amp; (giovatech-&gt;interface_state != SKYPIAX_STATE_DOWN) &amp;&amp; (!strcmp(giovatech-&gt;skype_user, tech_pvt-&gt;skype_user)) &amp;&amp; (!strcmp(giovatech-&gt;callid_number, value)) &amp;&amp; ((((timenow.tv_sec - giovatech-&gt;answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech-&gt;answer_time.tv_usec)) &lt; 500000)) {        //0.5sec
+                                found = 1;
+                                DEBUGA_SKYPE
+                                        (&quot;FOUND  (name=%s, giovatech-&gt;interface_state=%d != SKYPIAX_STATE_DOWN) &amp;&amp; (giovatech-&gt;skype_user=%s == tech_pvt-&gt;skype_user=%s) &amp;&amp; (giovatech-&gt;callid_number=%s == value=%s)\n&quot;,
+                                         SKYPIAX_P_LOG, giovatech-&gt;name, giovatech-&gt;interface_state,
+                                         giovatech-&gt;skype_user, tech_pvt-&gt;skype_user, giovatech-&gt;callid_number, value)
+                                        break;
+                        }
+                }
+        }
+
+        if (found) {
+                //tech_pvt-&gt;callid_number[0]='\0';
+                //sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, id);
+                //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                switch_mutex_unlock(globals.mutex);
+                return 0;
+        }
+        DEBUGA_SKYPE(&quot;NOT FOUND\n&quot;, SKYPIAX_P_LOG);
+
+        if (!tech_pvt || !tech_pvt-&gt;skype_call_id || !strlen(tech_pvt-&gt;skype_call_id)) {
+                /* we are not inside an active call */
+                DEBUGA_SKYPE(&quot;We're NO MORE in a call now %s\n&quot;, SKYPIAX_P_LOG, (tech_pvt &amp;&amp; tech_pvt-&gt;skype_call_id) ? tech_pvt-&gt;skype_call_id : &quot;&quot;);
+                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
+                  -&gt; GET CALL 288 CAN_TRANSFER Test2
+                  &lt;- CALL 288 CAN_TRANSFER test2 TRUE
+                 **********************************/
+
+                private_t *available_skypiax_interface = NULL;
+
+                gettimeofday(&amp;timenow, NULL);
+                for (i = 0; !found &amp;&amp; i &lt; SKYPIAX_MAX_INTERFACES; i++) {
+                        if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                                giovatech = &amp;globals.SKYPIAX_INTERFACES[i];
+                                //NOTICA(&quot;skype interface: %d, name: %s, state: %d, value=%s, giovatech-&gt;callid_number=%s, giovatech-&gt;skype_user=%s\n&quot;, SKYPIAX_P_LOG, i, giovatech-&gt;name, giovatech-&gt;interface_state, value, giovatech-&gt;callid_number, giovatech-&gt;skype_user);
+                                //FIXME check a timestamp here
+                                if (strlen(giovatech-&gt;skype_transfer_call_id) &amp;&amp; (giovatech-&gt;interface_state != SKYPIAX_STATE_DOWN) &amp;&amp; (!strcmp(giovatech-&gt;skype_user, tech_pvt-&gt;skype_user)) &amp;&amp; (!strcmp(giovatech-&gt;transfer_callid_number, value)) &amp;&amp; ((((timenow.tv_sec - giovatech-&gt;transfer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech-&gt;transfer_time.tv_usec)) &lt; 1000000)) {        //1.0 sec
+                                        found = 1;
+                                        DEBUGA_SKYPE
+                                                (&quot;FOUND  (name=%s, giovatech-&gt;interface_state=%d != SKYPIAX_STATE_DOWN) &amp;&amp; (giovatech-&gt;skype_user=%s == tech_pvt-&gt;skype_user=%s) &amp;&amp; (giovatech-&gt;transfer_callid_number=%s == value=%s)\n&quot;,
+                                                 SKYPIAX_P_LOG, giovatech-&gt;name, giovatech-&gt;interface_state,
+                                                 giovatech-&gt;skype_user, tech_pvt-&gt;skype_user, giovatech-&gt;transfer_callid_number, value)
+                                                break;
+                                }
+                        }
+                }
+
+                if (found) {
+                        //tech_pvt-&gt;callid_number[0]='\0';
+                        //sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, id);
+                        //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                        switch_mutex_unlock(globals.mutex);
+                        return 0;
+                }
+                DEBUGA_SKYPE(&quot;NOT FOUND\n&quot;, 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(&amp;tech_pvt-&gt;transfer_time, NULL);
+                        switch_copy_string(tech_pvt-&gt;skype_transfer_call_id, id, sizeof(tech_pvt-&gt;skype_transfer_call_id) - 1);
+
+                        switch_copy_string(tech_pvt-&gt;transfer_callid_number, value, sizeof(tech_pvt-&gt;transfer_callid_number) - 1);
+
+                        DEBUGA_SKYPE
+                                (&quot;Let's transfer the skype_call %s to %s interface (with skype_user: %s), because we are already in a skypiax call(%s)\n&quot;,
+                                 SKYPIAX_P_LOG, tech_pvt-&gt;skype_call_id, available_skypiax_interface-&gt;name, available_skypiax_interface-&gt;skype_user, id);
+
+                        //FIXME why this? the inbound call will come, eventually, on that other interface
+                        //available_skypiax_interface-&gt;ib_calls++;
+
+                        sprintf(msg_to_skype, &quot;ALTER CALL %s TRANSFER %s&quot;, id, available_skypiax_interface-&gt;skype_user);
+                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                        if (tech_pvt-&gt;interface_state == SKYPIAX_STATE_SELECTED) {
+                                tech_pvt-&gt;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
+                                (&quot;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&quot;,
+                                 SKYPIAX_P_LOG, id, tech_pvt-&gt;skype_call_id);
+                        sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, id);
+                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                }
+                switch_sleep(10000);
+                DEBUGA_SKYPE
+                        (&quot;We have NOT answered a Skype RING from skype_call %s, because we are already in a skypiax call (%s)\n&quot;,
+                         SKYPIAX_P_LOG, id, tech_pvt-&gt;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/\([\\`\\&quot;$\\\\]\)/\\\1/g'
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n &quot;${ZSH_VERSION+set}&quot; &amp;&amp; (emulate sh) &gt;/dev/null 2&gt;&amp;1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+&quot;$@&quot;}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+&quot;$@&quot;}'='&quot;$@&quot;'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2&gt;/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) &gt;/dev/null 2&gt;&amp;1 &amp;&amp; unset CDPATH
+
+relink_command=&quot;(cd /usr/src/freeswitch/src/mod/endpoints/mod_skypiax; { test -z \&quot;\${LIBRARY_PATH+set}\&quot; || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \&quot;\${COMPILER_PATH+set}\&quot; || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \&quot;\${GCC_EXEC_PREFIX+set}\&quot; || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \&quot;\${LD_RUN_PATH+set}\&quot; || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \&quot;\${LD_LIBRARY_PATH+set}\&quot; || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=\&quot;/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin\&quot;; export PATH; gcc -DSKYPIAX_SVN_VERSION=\\\&quot;14534\\\&quot; -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 ) &quot;
+
+# This environment variable determines our operation mode.
+if test &quot;$libtool_install_magic&quot; = &quot;%%%MAGIC variable%%%&quot;; 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 &quot;$libtool_execute_magic&quot; != &quot;%%%MAGIC variable%%%&quot;; then
+    echo=&quot;echo&quot;
+    file=&quot;$0&quot;
+    # Make sure echo works.
+    if test &quot;X$1&quot; = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test &quot;X`($echo '\t') 2&gt;/dev/null`&quot; = 'X\t'; then
+      # Yippee, $echo works!
+      :
+    else
+      # Restart under the correct shell, and then maybe $echo will work.
+      exec /bin/sh &quot;$0&quot; --no-reexec ${1+&quot;$@&quot;}
+    fi
+  fi
+
+  # Find the directory that this script lives in.
+  thisdir=`$echo &quot;X$file&quot; | $Xsed -e 's%/[^/]*$%%'`
+  test &quot;x$thisdir&quot; = &quot;x$file&quot; &amp;&amp; thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=`ls -ld &quot;$file&quot; | /bin/sed -n 's/.*-&gt; //p'`
+  while test -n &quot;$file&quot;; do
+    destdir=`$echo &quot;X$file&quot; | $Xsed -e 's%/[^/]*$%%'`
+
+    # If there was a directory component, then change thisdir.
+    if test &quot;x$destdir&quot; != &quot;x$file&quot;; then
+      case &quot;$destdir&quot; in
+      [\\/]* | [A-Za-z]:[\\/]*) thisdir=&quot;$destdir&quot; ;;
+      *) thisdir=&quot;$thisdir/$destdir&quot; ;;
+      esac
+    fi
+
+    file=`$echo &quot;X$file&quot; | $Xsed -e 's%^.*/%%'`
+    file=`ls -ld &quot;$thisdir/$file&quot; | /bin/sed -n 's/.*-&gt; //p'`
+  done
+
+  # Try to get the absolute directory name.
+  absdir=`cd &quot;$thisdir&quot; &amp;&amp; pwd`
+  test -n &quot;$absdir&quot; &amp;&amp; thisdir=&quot;$absdir&quot;
+
+  program=lt-'mod_skypiax.so'
+  progdir=&quot;$thisdir/.libs&quot;
+
+  if test ! -f &quot;$progdir/$program&quot; || \
+     { file=`ls -1dt &quot;$progdir/$program&quot; &quot;$progdir/../$program&quot; 2&gt;/dev/null | /bin/sed 1q`; \
+       test &quot;X$file&quot; != &quot;X$progdir/$program&quot;; }; then
+
+    file=&quot;$$-$program&quot;
+
+    if test ! -d &quot;$progdir&quot;; then
+      mkdir &quot;$progdir&quot;
+    else
+      rm -f &quot;$progdir/$file&quot;
+    fi
+
+    # relink executable if necessary
+    if test -n &quot;$relink_command&quot;; then
+      if relink_command_output=`eval $relink_command 2&gt;&amp;1`; then :
+      else
+        echo &quot;$relink_command_output&quot; &gt;&amp;2
+        rm -f &quot;$progdir/$file&quot;
+        exit 1
+      fi
+    fi
+
+    mv -f &quot;$progdir/$file&quot; &quot;$progdir/$program&quot; 2&gt;/dev/null ||
+    { rm -f &quot;$progdir/$program&quot;;
+      mv -f &quot;$progdir/$file&quot; &quot;$progdir/$program&quot;; }
+    rm -f &quot;$progdir/$file&quot;
+  fi
+
+  if test -f &quot;$progdir/$program&quot;; then
+    if test &quot;$libtool_execute_magic&quot; != &quot;%%%MAGIC variable%%%&quot;; then
+      # Run the actual program with our arguments.
+
+      exec &quot;$progdir/$program&quot; ${1+&quot;$@&quot;}
+
+      $echo &quot;$0: cannot exec $program $*&quot;
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    $echo &quot;$0: error: \`$progdir/$program' does not exist&quot; 1&gt;&amp;2
+    $echo &quot;This script is just a wrapper for $program.&quot; 1&gt;&amp;2
+    echo &quot;See the libtool documentation for more information.&quot; 1&gt;&amp;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 &lt;anthmct@yahoo.com&gt;
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the &quot;License&quot;); 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 &quot;AS IS&quot; 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 &lt;anthmct@yahoo.com&gt;
+ * 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 &lt;switch.h&gt;
+#include &lt;switch_version.h&gt;
+
+#ifndef WIN32
+#include &lt;sys/time.h&gt;
+#include &lt;X11/Xlib.h&gt;
+#include &lt;X11/Xlibint.h&gt;
+#include &lt;X11/Xatom.h&gt;
+#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 &lt;&lt; 0),
+        TFLAG_INBOUND = (1 &lt;&lt; 1),
+        TFLAG_OUTBOUND = (1 &lt;&lt; 2),
+        TFLAG_DTMF = (1 &lt;&lt; 3),
+        TFLAG_VOICE = (1 &lt;&lt; 4),
+        TFLAG_HANGUP = (1 &lt;&lt; 5),
+        TFLAG_LINEAR = (1 &lt;&lt; 6),
+        TFLAG_CODEC = (1 &lt;&lt; 7),
+        TFLAG_BREAK = (1 &lt;&lt; 8)
+} TFLAGS;
+
+typedef enum {
+        GFLAG_MY_CODEC_PREFS = (1 &lt;&lt; 0)
+} GFLAGS;
+
+#define DEBUGA_SKYPE(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][DEBUG_SKYPE  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+#define DEBUGA_CALL(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][DEBUG_CALL  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+#define DEBUGA_PBX(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][DEBUG_PBX  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+#define ERRORA(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][ERRORA  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+#define WARNINGA(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][WARNINGA  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+#define NOTICA(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,                 &quot;rev &quot;SKYPIAX_SVN_VERSION &quot;[%p|%-7lx][NOTICA  %-5d][%-10s][%2d,%2d,%2d] &quot; __VA_ARGS__ );
+
+#define SKYPIAX_P_LOG NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt-&gt;name ? tech_pvt-&gt;name : &quot;none&quot; : &quot;none&quot;, -1, tech_pvt ? tech_pvt-&gt;interface_state : -1, tech_pvt ? tech_pvt-&gt;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;                /*!&lt; \brief 'state' of the interface (channel) */
+        char language[80];                        /*!&lt; \brief default Asterisk dialplan language for this interface */
+        char exten[80];                                /*!&lt; \brief default Asterisk dialplan extension for this interface */
+        int skypiax_sound_rate;                /*!&lt; \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;                        /*!&lt; \brief 'callflow' of the skype interface (as opposed to phone interface) */
+        int skype;                                        /*!&lt; \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;        /*!&lt; \brief file descriptor for sound capture dev */
+#else                                                        /* WIN32 */
+        int audiopipe[2];
+        int audioskypepipe[2];
+        int skypiax_sound_capt_fd;        /*!&lt; \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) &amp;&amp; !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 &quot;skypiax.h&quot;
+
+#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(&amp;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)) &lt; 0) {
+                ERRORA(&quot;socket Error\n&quot;, SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        if (*which_port != 0)
+                start_port = *which_port;
+
+        my_addr.sin_port = htons(start_port);
+        //tech_pvt-&gt;tcp_cli_port = start_port;
+        *which_port = start_port;
+        while (bind(s, (struct sockaddr *) &amp;my_addr, sizeof(struct sockaddr)) &lt; 0) {
+                DEBUGA_SKYPE(&quot;*which_port=%d, tech_pvt-&gt;tcp_cli_port=%d, tech_pvt-&gt;tcp_srv_port=%d\n&quot;, SKYPIAX_P_LOG, *which_port, tech_pvt-&gt;tcp_cli_port,
+                                         tech_pvt-&gt;tcp_srv_port);
+                DEBUGA_SKYPE(&quot;bind errno=%d, error: %s\n&quot;, SKYPIAX_P_LOG, errno, strerror(errno));
+                start_port++;
+                my_addr.sin_port = htons(start_port);
+                *which_port = start_port;
+                DEBUGA_SKYPE(&quot;*which_port=%d, tech_pvt-&gt;tcp_cli_port=%d, tech_pvt-&gt;tcp_srv_port=%d\n&quot;, SKYPIAX_P_LOG, *which_port, tech_pvt-&gt;tcp_cli_port,
+                                         tech_pvt-&gt;tcp_srv_port);
+
+                if (start_port &gt; 65000) {
+                        ERRORA(&quot;NO MORE PORTS! *which_port=%d, tech_pvt-&gt;tcp_cli_port=%d, tech_pvt-&gt;tcp_srv_port=%d\n&quot;, SKYPIAX_P_LOG, *which_port,
+                                   tech_pvt-&gt;tcp_cli_port, tech_pvt-&gt;tcp_srv_port);
+                        return -1;
+                }
+        }
+
+        DEBUGA_SKYPE(&quot;SUCCESS! *which_port=%d, tech_pvt-&gt;tcp_cli_port=%d, tech_pvt-&gt;tcp_srv_port=%d\n&quot;, SKYPIAX_P_LOG, *which_port, tech_pvt-&gt;tcp_cli_port,
+                                 tech_pvt-&gt;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] = &quot;&quot;, id[512] = &quot;&quot;, prop[512] = &quot;&quot;, value[512] = &quot;&quot;, *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-&gt;SkypiaxHandles.fdesc[0], (short *) read_from_pipe, sizeof(read_from_pipe));
+
+        a = 0;
+        for (i = 0; i &lt; howmany; i++) {
+                message[a] = read_from_pipe[i];
+                a++;
+
+                if (read_from_pipe[i] == '\0') {
+
+                        //if (!strstr(message, &quot;DURATION&quot;)) {
+                        DEBUGA_SKYPE(&quot;READING: |||%s||| \n&quot;, SKYPIAX_P_LOG, message);
+                        //}
+
+                        if (!strcasecmp(message, &quot;ERROR 68&quot;)) {
+                                DEBUGA_SKYPE
+                                        (&quot;If I don't connect immediately, please give the Skype client authorization to be connected by Skypiax (and to not ask you again)\n&quot;,
+                                         SKYPIAX_P_LOG);
+                                skypiax_sleep(1000000);
+                                skypiax_signaling_write(tech_pvt, &quot;PROTOCOL 7&quot;);
+                                skypiax_sleep(10000);
+                                return 0;
+                        }
+                        if (!strncasecmp(message, &quot;ERROR 92 CALL&quot;, 12)) {
+                                ERRORA(&quot;Skype got ERROR: |||%s|||, the (skypeout) number we called was not recognized as valid\n&quot;, SKYPIAX_P_LOG, message);
+                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                DEBUGA_SKYPE(&quot;skype_call now is DOWN\n&quot;, SKYPIAX_P_LOG);
+                                tech_pvt-&gt;skype_call_id[0] = '\0';
+
+                                if (tech_pvt-&gt;interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                        return CALLFLOW_INCOMING_HANGUP;
+                                } else {
+                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                }
+                        }
+
+                        if (!strncasecmp(message, &quot;ERROR&quot;, 4)) {
+                                if (!strncasecmp(message, &quot;ERROR 96 CALL&quot;, 12)) {
+                                        DEBUGA_SKYPE
+                                                (&quot;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&quot;,
+                                                 SKYPIAX_P_LOG, message);
+                                } else if (!strncasecmp(message, &quot;ERROR 99 CALL&quot;, 12)) {
+                                        ERRORA(&quot;Skype got ERROR: |||%s|||, another call is active on this interface\n\n\n&quot;, SKYPIAX_P_LOG, message);
+                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_ERROR_DOUBLE_CALL;
+                                } else if (!strncasecmp(message, &quot;ERROR 592 ALTER CALL&quot;, 19)) {
+                                        ERRORA(&quot;Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n&quot;, SKYPIAX_P_LOG, message);
+                                } else if (!strncasecmp(message, &quot;ERROR 559 CALL&quot;, 13)) {
+                                        DEBUGA_SKYPE(&quot;Skype got ERROR about a failed action (probably TRYING to HANGUP A CALL), no problem: |||%s|||\n&quot;, SKYPIAX_P_LOG,
+                                                                 message);
+                                } else {
+                                        ERRORA(&quot;Skype got ERROR: |||%s|||\n&quot;, SKYPIAX_P_LOG, message);
+                                        tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                        ERRORA(&quot;skype_call now is DOWN\n&quot;, SKYPIAX_P_LOG);
+                                        tech_pvt-&gt;skype_call_id[0] = '\0';
+
+                                        if (tech_pvt-&gt;interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else {
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                        }
+                                }
+                        }
+
+
+
+
+                        skypiax_strncpy(message_2, message, sizeof(message) - 1);
+                        buf = message;
+                        stringp = &amp;buf;
+                        where = strsep(stringp, &quot; &quot;);
+                        if (!where) {
+                                WARNINGA(&quot;Skype MSG without spaces: %s\n&quot;, SKYPIAX_P_LOG, message);
+                        }
+
+
+
+
+
+
+
+
+                        if (!strcasecmp(message, &quot;CURRENTUSERHANDLE&quot;)) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                if (!strcasecmp(id, tech_pvt-&gt;skype_user)) {
+                                        tech_pvt-&gt;SkypiaxHandles.currentuserhandle = 1;
+                                        DEBUGA_SKYPE
+                                                (&quot;Skype MSG: message: %s, currentuserhandle: %s, cuh: %s, skype_user: %s!\n&quot;,
+                                                 SKYPIAX_P_LOG, message, obj, id, tech_pvt-&gt;skype_user);
+                                }
+                        }
+                        if (!strcasecmp(message, &quot;USER&quot;)) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                if (!strcasecmp(prop, &quot;RECEIVEDAUTHREQUEST&quot;)) {
+                                        char msg_to_skype[256];
+                                        DEBUGA_SKYPE(&quot;Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n&quot;, SKYPIAX_P_LOG, message, obj, id, prop);
+                                        //TODO: allow authorization based on config param
+                                        sprintf(msg_to_skype, &quot;SET USER %s ISAUTHORIZED TRUE&quot;, id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                }
+                        }
+                        if (!strcasecmp(message, &quot;MESSAGE&quot;)) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                if (!strcasecmp(prop, &quot;STATUS&quot;)) {
+                                        where = strsep(stringp, &quot; &quot;);
+                                        skypiax_strncpy(value, where, sizeof(value) - 1);
+                                        if (!strcasecmp(value, &quot;RECEIVED&quot;)) {
+                                                char msg_to_skype[256];
+                                                DEBUGA_SKYPE(&quot;Skype MSG: message: %s, obj: %s, id: %s, prop: %s value: %s!\n&quot;, SKYPIAX_P_LOG, message, obj, id, prop, value);
+                                                //TODO: authomatically flag messages as read based on config param
+                                                sprintf(msg_to_skype, &quot;SET MESSAGE %s SEEN&quot;, id);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                        }
+                                } else if (!strcasecmp(prop, &quot;BODY&quot;)) {
+                                        char msg_to_skype[256];
+                                        DEBUGA_SKYPE(&quot;Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n&quot;, SKYPIAX_P_LOG, message, obj, id, prop);
+                                        //TODO: authomatically flag messages as read based on config param
+                                        sprintf(msg_to_skype, &quot;SET MESSAGE %s SEEN&quot;, id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                }
+                        }
+                        if (!strcasecmp(message, &quot;CALL&quot;)) {
+                                skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(id, where, sizeof(id) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+                                skypiax_strncpy(value, where, sizeof(value) - 1);
+                                where = strsep(stringp, &quot; &quot;);
+
+                                //DEBUGA_SKYPE
+                                //(&quot;Skype MSG: message: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n&quot;,
+                                //SKYPIAX_P_LOG, message, obj, id, prop, value, where ? where : &quot;NULL&quot;);
+
+                                if (!strcasecmp(prop, &quot;PARTNER_HANDLE&quot;)) {
+                                        if (tech_pvt-&gt;interface_state != SKYPIAX_STATE_SELECTED &amp;&amp; (!strlen(tech_pvt-&gt;skype_call_id) || !strlen(tech_pvt-&gt;session_uuid_str))) {
+                                                //if (!strlen(tech_pvt-&gt;skype_call_id)) {
+                                                /* we are NOT inside an active call */
+                                                DEBUGA_SKYPE(&quot;Call %s TRY ANSWER\n&quot;, SKYPIAX_P_LOG, id);
+                                                skypiax_answer(tech_pvt, id, value);
+                                        } else {
+                                                /* we are inside an active call */
+                                                if (!strcasecmp(tech_pvt-&gt;skype_call_id, id)) {
+                                                        /* this is the call in which we are calling out */
+                                                        DEBUGA_SKYPE(&quot;Call %s DO NOTHING\n&quot;, SKYPIAX_P_LOG, id);
+                                                } else {
+                                                        skypiax_sleep(400000);        //0.4 seconds
+                                                        DEBUGA_SKYPE(&quot;Call %s TRY TRANSFER\n&quot;, SKYPIAX_P_LOG, id);
+                                                        skypiax_transfer(tech_pvt, id, value);
+                                                }
+                                        }
+                                }
+                                if (!strcasecmp(prop, &quot;PARTNER_DISPNAME&quot;)) {
+                                        snprintf(tech_pvt-&gt;callid_name, sizeof(tech_pvt-&gt;callid_name) - 1, &quot;%s%s%s&quot;, value, where ? &quot; &quot; : &quot;&quot;, where ? where : &quot;&quot;);
+                                        //DEBUGA_SKYPE
+                                        //(&quot;the skype_call %s caller PARTNER_DISPNAME (tech_pvt-&gt;callid_name) is: %s\n&quot;,
+                                        //SKYPIAX_P_LOG, id, tech_pvt-&gt;callid_name);
+                                }
+                                if (!strcasecmp(prop, &quot;CONF_ID&quot;) &amp;&amp; !strcasecmp(value, &quot;0&quot;)) {
+                                        //DEBUGA_SKYPE(&quot;the skype_call %s is NOT a conference call\n&quot;, SKYPIAX_P_LOG, id);
+                                        //if (tech_pvt-&gt;interface_state == SKYPIAX_STATE_DOWN)
+                                        //tech_pvt-&gt;interface_state = SKYPIAX_STATE_PRERING;
+                                }
+                                if (!strcasecmp(prop, &quot;CONF_ID&quot;) &amp;&amp; strcasecmp(value, &quot;0&quot;)) {
+                                        DEBUGA_SKYPE(&quot;the skype_call %s is a conference call\n&quot;, SKYPIAX_P_LOG, id);
+                                        //if (tech_pvt-&gt;interface_state == SKYPIAX_STATE_DOWN)
+                                        //tech_pvt-&gt;interface_state = SKYPIAX_STATE_PRERING;
+                                }
+                                if (!strcasecmp(prop, &quot;DTMF&quot;)) {
+                                        DEBUGA_SKYPE(&quot;Call %s received a DTMF: %s\n&quot;, SKYPIAX_P_LOG, id, value);
+                                        dtmf_received(tech_pvt, value);
+                                }
+                                if (!strcasecmp(prop, &quot;FAILUREREASON&quot;)) {
+                                        DEBUGA_SKYPE(&quot;Skype FAILED on skype_call %s. Let's wait for the FAILED message.\n&quot;, SKYPIAX_P_LOG, id);
+                                }
+                                if (!strcasecmp(prop, &quot;DURATION&quot;) &amp;&amp; (!strcasecmp(value, &quot;1&quot;))) {
+                                        if (strcasecmp(id, tech_pvt-&gt;skype_call_id)) {
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                DEBUGA_SKYPE(&quot;We called a Skype contact and he answered us on skype_call: %s.\n&quot;, SKYPIAX_P_LOG, id);
+                                        }
+                                }
+
+                                if (!strcasecmp(prop, &quot;DURATION&quot;) &amp;&amp; (tech_pvt-&gt;interface_state == SKYPIAX_STATE_ERROR_DOUBLE_CALL)) {
+                                        char msg_to_skype[1024];
+                                        skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                        ERRORA(&quot;We are in a double call situation, trying to get out hanging up call id: %s.\n&quot;, SKYPIAX_P_LOG, id);
+                                        sprintf(msg_to_skype, &quot;ALTER CALL %s HANGUP&quot;, id);
+                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                        skypiax_sleep(10000);
+                                        //return CALLFLOW_INCOMING_HANGUP;
+                                }
+
+                                if (!strcasecmp(prop, &quot;STATUS&quot;)) {
+
+                                        if (!strcasecmp(value, &quot;RINGING&quot;)) {
+                                                char msg_to_skype[1024];
+                                                if ((tech_pvt-&gt;interface_state != SKYPIAX_STATE_SELECTED &amp;&amp; tech_pvt-&gt;interface_state != SKYPIAX_STATE_DIALING)
+                                                        &amp;&amp; (!strlen(tech_pvt-&gt;skype_call_id) || !strlen(tech_pvt-&gt;session_uuid_str))) {
+                                                        /* we are NOT inside an active call */
+
+                                                        DEBUGA_SKYPE(&quot;NO ACTIVE calls in this moment, skype_call %s is RINGING, to ask PARTNER_HANDLE\n&quot;, SKYPIAX_P_LOG, id);
+                                                        sprintf(msg_to_skype, &quot;GET CALL %s PARTNER_HANDLE&quot;, id);
+                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                        skypiax_sleep(10000);
+                                                } else {
+                                                        /* we are inside an active call */
+                                                        if (!strcasecmp(tech_pvt-&gt;skype_call_id, id)) {
+                                                                /* this is the call in which we are calling out */
+                                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_RINGING;
+                                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_RINGING;
+                                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                                DEBUGA_SKYPE(&quot;Our remote party in skype_call %s is RINGING\n&quot;, SKYPIAX_P_LOG, id);
+                                                                remote_party_is_ringing(tech_pvt);
+                                                        } else {
+                                                                DEBUGA_SKYPE
+                                                                        (&quot;We are in another call, but skype_call %s is RINGING on us, let's ask PARTNER_HANDLE, so maybe we'll TRANSFER\n&quot;,
+                                                                         SKYPIAX_P_LOG, id);
+                                                                sprintf(msg_to_skype, &quot;GET CALL %s PARTNER_HANDLE&quot;, id);
+                                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                skypiax_sleep(10000);
+                                                        }
+                                                }
+                                        } else if (!strcasecmp(value, &quot;EARLYMEDIA&quot;)) {
+                                                char msg_to_skype[1024];
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_EARLYMEDIA;
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DIALING;
+                                                DEBUGA_SKYPE(&quot;Our remote party in skype_call %s is EARLYMEDIA\n&quot;, SKYPIAX_P_LOG, id);
+                                                if (start_audio_threads(tech_pvt)) {
+                                                        ERRORA(&quot;start_audio_threads FAILED\n&quot;, SKYPIAX_P_LOG);
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                }
+                                                skypiax_sleep(1000);
+                                                sprintf(msg_to_skype, &quot;ALTER CALL %s SET_INPUT PORT=\&quot;%d\&quot;&quot;, id, tech_pvt-&gt;tcp_cli_port);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                sprintf(msg_to_skype, &quot;#output ALTER CALL %s SET_OUTPUT PORT=\&quot;%d\&quot;&quot;, id, tech_pvt-&gt;tcp_srv_port);
+                                                skypiax_signaling_write(tech_pvt, msg_to_skype);
+
+                                                remote_party_is_early_media(tech_pvt);
+                                        } else if (!strcasecmp(value, &quot;MISSED&quot;)) {
+                                                DEBUGA_SKYPE(&quot;We missed skype_call %s\n&quot;, SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, &quot;FINISHED&quot;)) {
+                                                //DEBUGA_SKYPE(&quot;skype_call %s now is DOWN\n&quot;, SKYPIAX_P_LOG, id);
+                                                if (!strcasecmp(tech_pvt-&gt;skype_call_id, id)) {
+                                                        //tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                                        DEBUGA_SKYPE(&quot;skype_call %s is MY call, now I'm going DOWN\n&quot;, SKYPIAX_P_LOG, id);
+                                                        //tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                        if (tech_pvt-&gt;interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                                //tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                                return CALLFLOW_INCOMING_HANGUP;
+                                                        } else {
+                                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                        }
+                                                } else {
+                                                        DEBUGA_SKYPE(&quot;skype_call %s is NOT MY call, ignoring\n&quot;, SKYPIAX_P_LOG, id);
+                                                }
+
+                                        } else if (!strcasecmp(value, &quot;CANCELLED&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_CANCELLED;
+                                                DEBUGA_SKYPE(&quot;we tried to call Skype on skype_call %s and Skype has now CANCELLED\n&quot;, SKYPIAX_P_LOG, id);
+                                                tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                if (tech_pvt-&gt;interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                } else {
+                                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                }
+                                        } else if (!strcasecmp(value, &quot;FAILED&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE(&quot;we tried to call Skype on skype_call %s and Skype has now FAILED\n&quot;, SKYPIAX_P_LOG, id);
+                                                tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else if (!strcasecmp(value, &quot;REFUSED&quot;)) {
+                                                if (!strcasecmp(id, tech_pvt-&gt;skype_call_id)) {
+                                                        /* this is the id of the call we are in, probably we generated it */
+                                                        tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_REFUSED;
+                                                        DEBUGA_SKYPE(&quot;we tried to call Skype on skype_call %s and Skype has now REFUSED\n&quot;, SKYPIAX_P_LOG, id);
+                                                        skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                        tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                        return CALLFLOW_INCOMING_HANGUP;
+                                                } else {
+                                                        /* we're here because were us that refused an incoming call */
+                                                        DEBUGA_SKYPE(&quot;we REFUSED skype_call %s\n&quot;, SKYPIAX_P_LOG, id);
+                                                }
+                                        } else if (!strcasecmp(value, &quot;TRANSFERRING&quot;)) {
+                                                DEBUGA_SKYPE(&quot;skype_call %s is transferring\n&quot;, SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, &quot;TRANSFERRED&quot;)) {
+                                                DEBUGA_SKYPE(&quot;skype_call %s has been transferred\n&quot;, SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, &quot;ROUTING&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_ROUTING;
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DIALING;
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                DEBUGA_SKYPE(&quot;skype_call: %s is now ROUTING\n&quot;, SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, &quot;UNPLACED&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_UNPLACED;
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DIALING;
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                DEBUGA_SKYPE(&quot;skype_call: %s is now UNPLACED\n&quot;, SKYPIAX_P_LOG, id);
+                                        } else if (!strcasecmp(value, &quot;INPROGRESS&quot;)) {
+                                                char msg_to_skype[1024];
+
+                                                if (!strlen(tech_pvt-&gt;session_uuid_str)) {
+                                                        DEBUGA_SKYPE(&quot;no tech_pvt-&gt;session_uuid_str\n&quot;, SKYPIAX_P_LOG);
+                                                }
+                                                if (tech_pvt-&gt;skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                        if (!strlen(tech_pvt-&gt;session_uuid_str) || !strlen(tech_pvt-&gt;skype_call_id)
+                                                                || !strcasecmp(tech_pvt-&gt;skype_call_id, id)) {
+                                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                                DEBUGA_SKYPE(&quot;skype_call: %s is now active\n&quot;, SKYPIAX_P_LOG, id);
+
+                                                                if (tech_pvt-&gt;skype_callflow != CALLFLOW_STATUS_EARLYMEDIA) {
+                                                                        tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                                        tech_pvt-&gt;interface_state = SKYPIAX_STATE_UP;
+
+                                                                        if (start_audio_threads(tech_pvt)) {
+                                                                                ERRORA(&quot;start_audio_threads FAILED\n&quot;, SKYPIAX_P_LOG);
+                                                                                return CALLFLOW_INCOMING_HANGUP;
+                                                                        }
+                                                                        skypiax_sleep(1000);        //FIXME
+                                                                        sprintf(msg_to_skype, &quot;ALTER CALL %s SET_INPUT PORT=\&quot;%d\&quot;&quot;, id, tech_pvt-&gt;tcp_cli_port);
+                                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                        skypiax_sleep(1000);        //FIXME
+                                                                        sprintf(msg_to_skype, &quot;#output ALTER CALL %s SET_OUTPUT PORT=\&quot;%d\&quot;&quot;, id, tech_pvt-&gt;tcp_srv_port);
+                                                                        skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                }
+                                                                tech_pvt-&gt;skype_callflow = SKYPIAX_STATE_UP;
+                                                                if (!strlen(tech_pvt-&gt;session_uuid_str)) {
+                                                                        DEBUGA_SKYPE(&quot;New Inbound Channel!\n\n\n\n&quot;, SKYPIAX_P_LOG);
+                                                                        new_inbound_channel(tech_pvt);
+                                                                } else {
+                                                                        DEBUGA_SKYPE(&quot;Outbound Channel Answered! session_uuid_str=%s\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;session_uuid_str);
+                                                                        outbound_channel_answered(tech_pvt);
+                                                                }
+                                                        } else {
+                                                                DEBUGA_SKYPE(&quot;I'm on %s, skype_call %s is NOT MY call, ignoring\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;skype_call_id, id);
+                                                        }
+                                                } else {
+                                                        tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                        DEBUGA_SKYPE(&quot;Back from REMOTEHOLD!\n&quot;, SKYPIAX_P_LOG);
+                                                }
+
+                                        } else if (!strcasecmp(value, &quot;REMOTEHOLD&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_REMOTEHOLD;
+                                                DEBUGA_SKYPE(&quot;skype_call: %s is now REMOTEHOLD\n&quot;, SKYPIAX_P_LOG, id);
+
+                                        } else if (!strcasecmp(value, &quot;BUSY&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE
+                                                        (&quot;we tried to call Skype on skype_call %s and remote party (destination) was BUSY. Our outbound call has failed\n&quot;,
+                                                         SKYPIAX_P_LOG, id);
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                skypiax_sleep(1000);
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else if (!strcasecmp(value, &quot;WAITING_REDIAL_COMMAND&quot;)) {
+                                                tech_pvt-&gt;skype_callflow = CALLFLOW_STATUS_FAILED;
+                                                DEBUGA_SKYPE
+                                                        (&quot;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&quot;,
+                                                         SKYPIAX_P_LOG, id);
+                                                skypiax_strncpy(tech_pvt-&gt;skype_call_id, id, sizeof(tech_pvt-&gt;skype_call_id) - 1);
+                                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                                tech_pvt-&gt;skype_call_id[0] = '\0';
+                                                skypiax_sleep(1000);
+                                                return CALLFLOW_INCOMING_HANGUP;
+                                        } else {
+                                                WARNINGA(&quot;skype_call: %s, STATUS: %s is not recognized\n&quot;, SKYPIAX_P_LOG, id, value);
+                                        }
+                                }                                //STATUS
+                        }                                        //CALL
+                        /* the &quot;numbered&quot; messages that follows are used by the directory application, not yet ported */
+                        if (!strcasecmp(message, &quot;#333&quot;)) {
+                                /* DEBUGA_SKYPE(&quot;Skype MSG: message_2: %s, message2[11]: %s\n&quot;, SKYPIAX_P_LOG,
+                                 * message_2, &amp;message_2[11]); */
+                                memset(tech_pvt-&gt;skype_friends, 0, 4096);
+                                skypiax_strncpy(tech_pvt-&gt;skype_friends, &amp;message_2[11], 4095);
+                        }
+                        if (!strcasecmp(message, &quot;#222&quot;)) {
+                                /* DEBUGA_SKYPE(&quot;Skype MSG: message_2: %s, message2[10]: %s\n&quot;, SKYPIAX_P_LOG,
+                                 * message_2, &amp;message_2[10]); */
+                                memset(tech_pvt-&gt;skype_fullname, 0, 512);
+                                skypiax_strncpy(tech_pvt-&gt;skype_fullname, &amp;message_2[10], 511);
+                        }
+                        if (!strcasecmp(message, &quot;#765&quot;)) {
+                                /* DEBUGA_SKYPE(&quot;Skype MSG: message_2: %s, message2[10]: %s\n&quot;, SKYPIAX_P_LOG,
+                                 * message_2, &amp;message_2[10]); */
+                                memset(tech_pvt-&gt;skype_displayname, 0, 512);
+                                skypiax_strncpy(tech_pvt-&gt;skype_displayname, &amp;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) &amp;&amp; !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, &amp;tech_pvt-&gt;tcp_srv_port);
+        if (s &lt; 0) {
+                ERRORA(&quot;skypiax_socket_create_and_bind error!\n&quot;, SKYPIAX_P_LOG);
+                return NULL;
+        }
+        DEBUGA_SKYPE(&quot;started tcp_srv_thread thread.\n&quot;, SKYPIAX_P_LOG);
+
+        listen(s, 6);
+
+        sin_size = sizeof(remote_addr);
+
+  /****************************/
+        while (tech_pvt-&gt;interface_state != SKYPIAX_STATE_DOWN
+                   &amp;&amp; (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                           || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                           || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt-&gt;skype_callflow == SKYPIAX_STATE_UP)) {
+
+                unsigned int fdselectgio;
+                int rtgio;
+                fd_set fsgio;
+                struct timeval togio;
+
+                if (!(running &amp;&amp; tech_pvt-&gt;running))
+                        break;
+                FD_ZERO(&amp;fsgio);
+                togio.tv_usec = 20000;        //20msec
+                togio.tv_sec = 0;
+                fdselectgio = s;
+                FD_SET(fdselectgio, &amp;fsgio);
+
+                rtgio = select(fdselectgio + 1, &amp;fsgio, NULL, NULL, &amp;togio);
+
+                if (rtgio) {
+
+  /****************************/
+
+                        while ((fd = accept(s, (struct sockaddr *) &amp;remote_addr, &amp;sin_size)) &gt; 0) {
+                                DEBUGA_SKYPE(&quot;ACCEPTED here I send you %d\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;tcp_srv_port);
+                                if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                        break;
+                                while (tech_pvt-&gt;interface_state != SKYPIAX_STATE_DOWN
+                                           &amp;&amp; (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                                                   || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                                                   || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt-&gt;skype_callflow == SKYPIAX_STATE_UP)) {
+
+                                        unsigned int fdselect;
+                                        int rt;
+                                        fd_set fs;
+                                        struct timeval to;
+
+                                        if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                                break;
+                                        //exit = 1;
+
+                                        fdselect = fd;
+                                        FD_ZERO(&amp;fs);
+                                        FD_SET(fdselect, &amp;fs);
+                                        //to.tv_usec = 2000000;     //2000 msec
+                                        to.tv_usec = 60000;        //60 msec
+                                        to.tv_sec = 0;
+
+                                        rt = select(fdselect + 1, &amp;fs, NULL, NULL, &amp;to);
+                                        if (rt &gt; 0) {
+
+                                                if (tech_pvt-&gt;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 &lt; 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 &lt; len / sizeof(short); i++) {
+                                                                        srv_out[i] = srv_in[i];
+                                                                }
+                                                        } else {
+                                                                ERRORA(&quot;SAMPLERATE_SKYPIAX can only be 8000 or 16000\n&quot;, SKYPIAX_P_LOG);
+                                                        }
+                                                        /* if not yet done, let's store the half incoming frame */
+                                                        if (!tech_pvt-&gt;audiobuf_is_loaded) {
+                                                                for (i = 0; i &lt; SAMPLES_PER_FRAME / 2; i++) {
+                                                                        tech_pvt-&gt;audiobuf[i] = srv_out[i];
+                                                                }
+                                                                tech_pvt-&gt;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 &lt; SAMPLES_PER_FRAME / 2; i++) {
+                                                                        totalbuf[i] = tech_pvt-&gt;audiobuf[i];
+                                                                }
+                                                                for (a = 0; a &lt; 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-&gt;audiopipe[1], totalbuf, SAMPLES_PER_FRAME * sizeof(short));
+                                                                if (howmany != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                        ERRORA(&quot;howmany is %d, but was expected to be %d\n&quot;, SKYPIAX_P_LOG,
+                                                                                   howmany, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                                }
+                                                                /* done with the stored half frame */
+                                                                tech_pvt-&gt;audiobuf_is_loaded = 0;
+                                                        }
+
+                                                } else if (len == 0) {
+                                                        skypiax_sleep(1000);
+                                                } else {
+                                                        DEBUGA_SKYPE(&quot;len=%d, expected 320\n&quot;, SKYPIAX_P_LOG, len);
+                                                }
+
+                                        } else {
+                                                if (rt)
+                                                        ERRORA(&quot;SRV rt=%d\n&quot;, 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-&gt;audiopipe[1], kill_cli_buff, kill_cli_size);
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt-&gt;audioskypepipe[1], kill_cli_buff, kill_cli_size);
+                                tech_pvt-&gt;interface_state = SKYPIAX_STATE_DOWN;
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt-&gt;audiopipe[1], kill_cli_buff, kill_cli_size);
+                                kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                                len = skypiax_pipe_write(tech_pvt-&gt;audioskypepipe[1], kill_cli_buff, kill_cli_size);
+
+                                DEBUGA_SKYPE(&quot;Skype incoming audio GONE\n&quot;, SKYPIAX_P_LOG);
+                                skypiax_close_socket(fd);
+                                //if (exit)
+                                break;
+                        }
+                }
+        }
+
+        DEBUGA_SKYPE(&quot;incoming audio server (I am it) EXITING\n&quot;, SKYPIAX_P_LOG);
+        skypiax_close_socket(s);
+        tech_pvt-&gt;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, &amp;tech_pvt-&gt;tcp_cli_port);
+        if (s &lt; 0) {
+                ERRORA(&quot;skypiax_socket_create_and_bind error!\n&quot;, SKYPIAX_P_LOG);
+                return NULL;
+        }
+
+
+
+        DEBUGA_SKYPE(&quot;started tcp_cli_thread thread.\n&quot;, SKYPIAX_P_LOG);
+
+        listen(s, 6);
+
+        sin_size = sizeof(remote_addr);
+
+  /****************************/
+        while (tech_pvt-&gt;interface_state != SKYPIAX_STATE_DOWN
+                   &amp;&amp; (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                           || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                           || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt-&gt;skype_callflow == SKYPIAX_STATE_UP)) {
+
+                unsigned int fdselectgio;
+                int rtgio;
+                fd_set fsgio;
+                struct timeval togio;
+
+                if (!(running &amp;&amp; tech_pvt-&gt;running))
+                        break;
+                FD_ZERO(&amp;fsgio);
+                togio.tv_usec = 20000;        //20msec
+                togio.tv_sec = 0;
+                fdselectgio = s;
+                FD_SET(fdselectgio, &amp;fsgio);
+
+                rtgio = select(fdselectgio + 1, &amp;fsgio, NULL, NULL, &amp;togio);
+
+                if (rtgio) {
+
+  /****************************/
+
+                        while ((fd = accept(s, (struct sockaddr *) &amp;remote_addr, &amp;sin_size)) &gt; 0) {
+                                DEBUGA_SKYPE(&quot;ACCEPTED here you send me %d\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;tcp_cli_port);
+#ifndef WIN32
+                                fcntl(tech_pvt-&gt;audioskypepipe[0], F_SETFL, O_NONBLOCK);
+                                fcntl(tech_pvt-&gt;audioskypepipe[1], F_SETFL, O_NONBLOCK);
+#endif //WIN32
+
+                                if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                        break;
+                                while (tech_pvt-&gt;interface_state != SKYPIAX_STATE_DOWN
+                                           &amp;&amp; (tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                                                   || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                                                   || tech_pvt-&gt;skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt-&gt;skype_callflow == SKYPIAX_STATE_UP)) {
+                                        unsigned int fdselect;
+                                        int rt;
+                                        fd_set fs;
+                                        struct timeval to;
+
+                                        if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                                break;
+                                        FD_ZERO(&amp;fs);
+                                        to.tv_usec = 120000;        //120msec
+                                        to.tv_sec = 0;
+#if defined(WIN32) &amp;&amp; !defined(__CYGWIN__)
+/* on win32 we cannot select from the apr &quot;pipe&quot;, so we select on socket writability */
+                                        fdselect = fd;
+                                        FD_SET(fdselect, &amp;fs);
+
+                                        rt = select(fdselect + 1, NULL, &amp;fs, NULL, &amp;to);
+#else
+/* on *unix and cygwin we select from the real pipe */
+                                        fdselect = tech_pvt-&gt;audioskypepipe[0];
+                                        FD_SET(fdselect, &amp;fs);
+
+                                        rt = select(fdselect + 1, &amp;fs, NULL, NULL, &amp;to);
+#endif
+
+                                        if (rt &gt; 0) {
+                                                int counter;
+
+                                                /* until we drained the pipe to empty */
+                                                for (counter = 0; counter &lt; 10; counter++) {
+                                                        /* read from the pipe the audio frame we are supposed to send out */
+                                                        got = skypiax_pipe_read(tech_pvt-&gt;audioskypepipe[0], cli_in, SAMPLES_PER_FRAME * sizeof(short));
+                                                        if (got == -1)
+                                                                break;
+
+                                                        if (got != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                WARNINGA(&quot;got is %d, but was expected to be %d\n&quot;, 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 &lt; 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 &lt; got / sizeof(short); i++) {
+                                                                                cli_out[i] = cli_in[i];
+                                                                        }
+                                                                } else {
+                                                                        ERRORA(&quot;SAMPLERATE_SKYPIAX can only be 8000 or 16000\n&quot;, 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-&gt;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(&quot;len=%d\n&quot;, SKYPIAX_P_LOG, len);
+                                                                                skypiax_sleep(1000);
+                                                                                break;
+                                                                        }
+                                                                }
+
+                                                        } else {
+
+                                                                WARNINGA(&quot;got is %d, but was expected to be %d\n&quot;, SKYPIAX_P_LOG, got, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                        }
+                                                }
+                                        } else {
+                                                if (rt)
+                                                        ERRORA(&quot;CLI rt=%d\n&quot;, SKYPIAX_P_LOG, rt);
+                                                memset(cli_out, 0, sizeof(cli_out));
+                                                if (tech_pvt-&gt;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(&quot;sent %d of zeros to keep the Skype client socket busy\n&quot;, SKYPIAX_P_LOG, sizeof(cli_out) + sizeof(cli_out)/2);
+                                                } else {
+                                                        /*
+                                                           XXX do nothing 
+                                                         */
+                                                        //WARNINGA(&quot;we don't send it\n&quot;, SKYPIAX_P_LOG);
+                                                }
+                                                skypiax_sleep(1000);
+                                        }
+
+                                }
+                                DEBUGA_SKYPE(&quot;Skype outbound audio GONE\n&quot;, SKYPIAX_P_LOG);
+                                skypiax_close_socket(fd);
+                                break;
+                        }
+                }
+        }
+
+        DEBUGA_SKYPE(&quot;outbound audio server (I am it) EXITING\n&quot;, SKYPIAX_P_LOG);
+        skypiax_close_socket(s);
+        tech_pvt-&gt;tcp_cli_thread = NULL;
+        return NULL;
+}
+
+int skypiax_audio_read(private_t * tech_pvt)
+{
+        unsigned int samples;
+
+        samples = skypiax_pipe_read(tech_pvt-&gt;audiopipe[0], tech_pvt-&gt;read_frame.data, SAMPLES_PER_FRAME * sizeof(short));
+
+        if (samples != SAMPLES_PER_FRAME * sizeof(short)) {
+                if (samples)
+                        WARNINGA(&quot;read samples=%u expected=%u\n&quot;, SKYPIAX_P_LOG, samples, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                return 0;
+        } else {
+                /* A real frame */
+                tech_pvt-&gt;read_frame.datalen = samples;
+        }
+        return 1;
+}
+
+int skypiax_senddigit(private_t * tech_pvt, char digit)
+{
+        char msg_to_skype[1024];
+
+        DEBUGA_SKYPE(&quot;DIGIT received: %c\n&quot;, SKYPIAX_P_LOG, digit);
+        sprintf(msg_to_skype, &quot;SET CALL %s DTMF %c&quot;, tech_pvt-&gt;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(&quot;Calling Skype, rdest is: %s\n&quot;, SKYPIAX_P_LOG, rdest);
+        //skypiax_signaling_write(tech_pvt, &quot;SET AGC OFF&quot;);
+        //skypiax_sleep(10000);
+        //skypiax_signaling_write(tech_pvt, &quot;SET AEC OFF&quot;);
+        //skypiax_sleep(10000);
+
+        sprintf(msg_to_skype, &quot;CALL %s&quot;, rdest);
+        if (skypiax_signaling_write(tech_pvt, msg_to_skype) &lt; 0) {
+                ERRORA(&quot;failed to communicate with Skype client, now exit\n&quot;, SKYPIAX_P_LOG);
+                return -1;
+        }
+        return 0;
+}
+
+/***************************/
+/* PLATFORM SPECIFIC */
+/***************************/
+#if defined(WIN32) &amp;&amp; !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, &amp;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, &amp;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(&amp;tech_pvt-&gt;audiopipe[0], &amp;tech_pvt-&gt;audiopipe[1], skypiax_module_pool);
+        rv = switch_file_pipe_create(&amp;tech_pvt-&gt;audioskypepipe[0], &amp;tech_pvt-&gt;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-&gt;audiopipe)) {
+                fcntl(tech_pvt-&gt;audiopipe[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt-&gt;audiopipe[1], F_SETFL, O_NONBLOCK);
+        }
+        if (pipe(tech_pvt-&gt;audioskypepipe)) {
+                fcntl(tech_pvt-&gt;audioskypepipe[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt-&gt;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-&gt;skypiax_sound_capt_fd = tech_pvt-&gt;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 &amp;&amp; !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(&quot;SENDING: |||%s||||\n&quot;, SKYPIAX_P_LOG, msg_to_skype);
+
+        sprintf(acInputRow, &quot;%s&quot;, msg_to_skype);
+        DEBUGA_SKYPE(&quot;acInputRow: |||%s||||\n&quot;, 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-&gt;SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle, WM_COPYDATA,
+                         (WPARAM) tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, (LPARAM) &amp; oCopyData) == FALSE) {
+                        ERRORA(&quot;Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax, then launch Skypiax and try again.\n&quot;, 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)-&gt;lpCreateParams;
+                SetWindowLong(hWindow, GWL_USERDATA, (LONG) tech_pvt);
+                DEBUGA_SKYPE(&quot;got CREATE\n&quot;, SKYPIAX_P_LOG);
+                break;
+        case WM_DESTROY:
+                DEBUGA_SKYPE(&quot;got DESTROY\n&quot;, SKYPIAX_P_LOG);
+                tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle = NULL;
+                PostQuitMessage(0);
+                break;
+        case WM_COPYDATA:
+                if (tech_pvt-&gt;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-&gt;lpData, sizeof(msg_from_skype) - 2);
+
+                        howmany = strlen(msg_from_skype) + 1;
+                        howmany = skypiax_pipe_write(tech_pvt-&gt;SkypiaxHandles.fdesc[1], (short *) msg_from_skype, howmany);
+                        //DEBUGA_SKYPE(&quot;From Skype API: %s\n&quot;, SKYPIAX_P_LOG, msg_from_skype);
+                        lReturnCode = 1;
+                }
+                break;
+        default:
+                if (tech_pvt &amp;&amp; tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+                        if (uiMessage == tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+                                switch (ulParam) {
+                                case SKYPECONTROLAPI_ATTACH_SUCCESS:
+                                        if (!tech_pvt-&gt;SkypiaxHandles.currentuserhandle) {
+                                                //DEBUGA_SKYPE(&quot;\n\n\tConnected to Skype API!\n&quot;, SKYPIAX_P_LOG);
+                                                tech_pvt-&gt;SkypiaxHandles.api_connected = 1;
+                                                tech_pvt-&gt;SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle = (HWND) uiParam;
+                                                tech_pvt-&gt;SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle = tech_pvt-&gt;SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle;
+                                        }
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION:
+                                        //DEBUGA_SKYPE (&quot;\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&quot;, SKYPIAX_P_LOG);
+                                        skypiax_sleep(5000);
+#if 0
+                                        if (!tech_pvt-&gt;SkypiaxHandles.currentuserhandle) {
+                                                SendMessage(HWND_BROADCAST,
+                                                                        tech_pvt-&gt;SkypiaxHandles.
+                                                                        win32_uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM) tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, 0);
+                                        }
+#endif
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_REFUSED:
+                                        ERRORA(&quot;Skype client refused to be connected by Skypiax!\n&quot;, SKYPIAX_P_LOG);
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE:
+                                        ERRORA(&quot;Skype API not (yet?) available\n&quot;, SKYPIAX_P_LOG);
+                                        break;
+                                case SKYPECONTROLAPI_ATTACH_API_AVAILABLE:
+                                        DEBUGA_SKYPE(&quot;Skype API available\n&quot;, SKYPIAX_P_LOG);
+                                        skypiax_sleep(5000);
+#if 0
+                                        if (!tech_pvt-&gt;SkypiaxHandles.currentuserhandle) {
+                                                SendMessage(HWND_BROADCAST,
+                                                                        tech_pvt-&gt;SkypiaxHandles.
+                                                                        win32_uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM) tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, 0);
+                                        }
+#endif
+                                        break;
+                                default:
+                                        WARNINGA(&quot;GOT AN UNKNOWN SKYPE WINDOWS MSG\n&quot;, 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(&amp;oUUID);
+        tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle = (HINSTANCE) OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
+        if (tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle != NULL &amp;&amp; (lUUIDResult == RPC_S_OK || lUUIDResult == RPC_S_UUID_LOCAL_ONLY)) {
+                if (UuidToString(&amp;oUUID, &amp;paucUUIDString) == RPC_S_OK) {
+                        WNDCLASS oWindowClass;
+
+                        strcpy(tech_pvt-&gt;SkypiaxHandles.win32_acInit_WindowClassName, &quot;Skype-API-Skypiax-&quot;);
+                        strcat(tech_pvt-&gt;SkypiaxHandles.win32_acInit_WindowClassName, (char *) paucUUIDString);
+
+                        oWindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+                        oWindowClass.lpfnWndProc = (WNDPROC) &amp; skypiax_present;
+                        oWindowClass.cbClsExtra = 0;
+                        oWindowClass.cbWndExtra = 0;
+                        oWindowClass.hInstance = tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle;
+                        oWindowClass.hIcon = NULL;
+                        oWindowClass.hCursor = NULL;
+                        oWindowClass.hbrBackground = NULL;
+                        oWindowClass.lpszMenuName = NULL;
+                        oWindowClass.lpszClassName = tech_pvt-&gt;SkypiaxHandles.win32_acInit_WindowClassName;
+
+                        if (RegisterClass(&amp;oWindowClass) != 0)
+                                fReturnStatus = 1;
+
+                        RpcStringFree(&amp;paucUUIDString);
+                }
+        }
+        if (fReturnStatus == 0)
+                CloseHandle(tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle);
+        tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle = NULL;
+        return (fReturnStatus);
+}
+
+void win32_DeInitialize_DestroyWindowClass(private_t * tech_pvt)
+{
+        UnregisterClass(tech_pvt-&gt;SkypiaxHandles.win32_acInit_WindowClassName, tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle);
+        CloseHandle(tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle);
+        tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle = NULL;
+}
+
+int win32_Initialize_CreateMainWindow(private_t * tech_pvt)
+{
+        tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle =
+                CreateWindowEx(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,
+                                           tech_pvt-&gt;SkypiaxHandles.win32_acInit_WindowClassName, &quot;&quot;,
+                                           WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT,
+                                           128, 128, NULL, 0, tech_pvt-&gt;SkypiaxHandles.win32_hInit_ProcessHandle, tech_pvt);
+        return (tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle != NULL ? 1 : 0);
+}
+
+void win32_DeInitialize_DestroyMainWindow(private_t * tech_pvt)
+{
+        if (tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle != NULL)
+                DestroyWindow(tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle), tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle = NULL;
+}
+
+void *skypiax_do_skypeapi_thread_func(void *obj)
+{
+        private_t *tech_pvt = obj;
+#if defined(WIN32) &amp;&amp; !defined(__CYGWIN__)
+        switch_status_t rv;
+
+        switch_file_pipe_create(&amp;tech_pvt-&gt;SkypiaxHandles.fdesc[0], &amp;tech_pvt-&gt;SkypiaxHandles.fdesc[1], skypiax_module_pool);
+        rv = switch_file_pipe_create(&amp;tech_pvt-&gt;SkypiaxHandles.fdesc[0], &amp;tech_pvt-&gt;SkypiaxHandles.fdesc[1], skypiax_module_pool);
+#else /* WIN32 */
+        if (pipe(tech_pvt-&gt;SkypiaxHandles.fdesc)) {
+                fcntl(tech_pvt-&gt;SkypiaxHandles.fdesc[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt-&gt;SkypiaxHandles.fdesc[1], F_SETFL, O_NONBLOCK);
+        }
+#endif /* WIN32 */
+
+        tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach = RegisterWindowMessage(&quot;SkypeControlAPIAttach&quot;);
+        tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover = RegisterWindowMessage(&quot;SkypeControlAPIDiscover&quot;);
+
+        skypiax_sleep(200000);                //0,2 sec
+
+        if (tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach != 0
+                &amp;&amp; tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover != 0) {
+                if (win32_Initialize_CreateWindowClass(tech_pvt)) {
+                        if (win32_Initialize_CreateMainWindow(tech_pvt)) {
+                                if (SendMessage
+                                        (HWND_BROADCAST,
+                                         tech_pvt-&gt;SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover,
+                                         (WPARAM) tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle, 0) != 0) {
+                                        tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle = tech_pvt-&gt;SkypiaxHandles.win32_hInit_MainWindowHandle;
+                                        while (running &amp;&amp; tech_pvt-&gt;running) {
+                                                MSG oMessage;
+                                                if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                                        break;
+                                                while (GetMessage(&amp;oMessage, 0, 0, 0)) {
+                                                        TranslateMessage(&amp;oMessage);
+                                                        DispatchMessage(&amp;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-&gt;error_code;
+        ERRORA(&quot;Received error code %d from X Server\n\n&quot;, 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) &amp;&amp; (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-&gt;skype_win;
+        disp = SkypiaxHandles-&gt;disp;
+        handle_P = SkypiaxHandles-&gt;win;
+
+        Atom atom1 = XInternAtom(disp, &quot;SKYPECONTROLAPI_MESSAGE_BEGIN&quot;, False);
+        Atom atom2 = XInternAtom(disp, &quot;SKYPECONTROLAPI_MESSAGE&quot;, False);
+        unsigned int pos = 0;
+        unsigned int len = strlen(message_P);
+        XEvent e;
+
+        memset(&amp;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 &lt; 20 &amp;&amp; i + pos &lt;= len; ++i)
+                        e.xclient.data.b[i] = message_P[i + pos];
+                XSendEvent(disp, w_P, False, 0, &amp;e);
+
+                e.xclient.message_type = atom2;        /*  following messages */
+                pos += i;
+        } while (pos &lt;= len);
+
+        XSync(disp, False);
+        ok = X11_errors_untrap();
+
+        if (!ok)
+                ERRORA(&quot;Sending message failed with status %d\n&quot;, 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(&quot;SENDING: |||%s||||\n&quot;, SKYPIAX_P_LOG, msg_to_skype);
+
+        SkypiaxHandles = &amp;tech_pvt-&gt;SkypiaxHandles;
+
+        if (!skypiax_send_message(SkypiaxHandles, msg_to_skype)) {
+                ERRORA
+                        (&quot;Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax, then restart Skype, then launch Skypiax and try again.\n&quot;,
+                         SKYPIAX_P_LOG);
+                return -1;
+        }
+
+        return 0;
+
+}
+
+int skypiax_present(struct SkypiaxHandles *SkypiaxHandles)
+{
+        Atom skype_inst = XInternAtom(SkypiaxHandles-&gt;disp, &quot;_SKYPE_INSTANCE&quot;, 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-&gt;disp, DefaultRootWindow(SkypiaxHandles-&gt;disp),
+                                                   skype_inst, 0, 1, False, XA_WINDOW, &amp;type_ret, &amp;format_ret, &amp;nitems_ret, &amp;bytes_after_ret, &amp;prop);
+        //XUnlockDisplay(disp);
+        X11_errors_untrap();
+
+        /*  sanity check */
+        if (status != Success || format_ret != 32 || nitems_ret != 1) {
+                SkypiaxHandles-&gt;skype_win = (Window) - 1;
+                DEBUGA_SKYPE(&quot;Skype instance not found\n&quot;, SKYPIAX_P_LOG);
+                running = 0;
+                SkypiaxHandles-&gt;api_connected = 0;
+                return 0;
+        }
+
+        SkypiaxHandles-&gt;skype_win = *(const unsigned long *) prop &amp; 0xffffffff;
+        DEBUGA_SKYPE(&quot;Skype instance found with id #%d\n&quot;, SKYPIAX_P_LOG, (unsigned int) SkypiaxHandles-&gt;skype_win);
+        SkypiaxHandles-&gt;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(&quot;to be destroyed disp %d\n&quot;, SKYPIAX_P_LOG, disp);
+                close(disp);
+                DEBUGA_SKYPE(&quot;destroyed disp\n&quot;, SKYPIAX_P_LOG);
+        } else {
+                DEBUGA_SKYPE(&quot;NOT destroyed disp\n&quot;, SKYPIAX_P_LOG);
+        }
+        DEBUGA_SKYPE(&quot;OUT destroyed disp\n&quot;, 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-&gt;X11_display))
+                strcpy(tech_pvt-&gt;X11_display, getenv(&quot;DISPLAY&quot;));
+
+        if (!tech_pvt-&gt;tcp_srv_port)
+                tech_pvt-&gt;tcp_srv_port = 10160;
+
+        if (!tech_pvt-&gt;tcp_cli_port)
+                tech_pvt-&gt;tcp_cli_port = 10161;
+
+        if (pipe(tech_pvt-&gt;SkypiaxHandles.fdesc)) {
+                fcntl(tech_pvt-&gt;SkypiaxHandles.fdesc[0], F_SETFL, O_NONBLOCK);
+                fcntl(tech_pvt-&gt;SkypiaxHandles.fdesc[1], F_SETFL, O_NONBLOCK);
+        }
+        SkypiaxHandles = &amp;tech_pvt-&gt;SkypiaxHandles;
+        disp = XOpenDisplay(tech_pvt-&gt;X11_display);
+        if (!disp) {
+                ERRORA(&quot;Cannot open X Display '%s', exiting skype thread\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;X11_display);
+                running = 0;
+                return NULL;
+        } else {
+                DEBUGA_SKYPE(&quot;X Display '%s' opened\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;X11_display);
+        }
+
+        int xfd;
+        xfd = XConnectionNumber(disp);
+        fcntl(xfd, F_SETFD, FD_CLOEXEC);
+
+        SkypiaxHandles-&gt;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-&gt;win = win;
+
+                snprintf(buf, 512, &quot;NAME skypiax&quot;);
+
+                if (!skypiax_send_message(SkypiaxHandles, buf)) {
+                        ERRORA(&quot;Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n&quot;, SKYPIAX_P_LOG);
+                        running = 0;
+                        return NULL;
+                }
+
+                snprintf(buf, 512, &quot;PROTOCOL 7&quot;);
+                if (!skypiax_send_message(SkypiaxHandles, buf)) {
+                        ERRORA(&quot;Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n&quot;, 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, &quot;SKYPECONTROLAPI_MESSAGE_BEGIN&quot;, False);
+                Atom atom_continue = XInternAtom(disp, &quot;SKYPECONTROLAPI_MESSAGE&quot;, False);
+
+                b = buffer;
+
+                while (1) {
+                        XNextEvent(disp, &amp;an_event);
+                        if (!(running &amp;&amp; tech_pvt-&gt;running))
+                                break;
+                        switch (an_event.type) {
+                        case ClientMessage:
+
+                                if (an_event.xclient.format != 8)
+                                        break;
+
+                                for (i = 0; i &lt; 20 &amp;&amp; an_event.xclient.data.b[i] != '\0'; ++i)
+                                        buf[i] = an_event.xclient.data.b[i];
+
+                                buf[i] = '\0';
+
+                                //DEBUGA_SKYPE (&quot;BUF=|||%s|||\n&quot;, 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-&gt;fdesc[1], b, howmany);
+                                                DEBUGA_SKYPE(&quot;RECEIVED2=|||%s|||\n&quot;, SKYPIAX_P_LOG, buffer);
+                                                memset(buffer, '\0', 17000);
+                                        }
+                                }
+                                if (an_event.xclient.message_type == atom_continue) {
+
+                                        if (!strlen(buffer)) {
+                                                DEBUGA_SKYPE
+                                                        (&quot;Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||\n&quot;, SKYPIAX_P_LOG, buf);
+                                                continue_is_broken = 1;
+                                                if (!strncmp(buf, &quot;ognised identity&quot;, 15)) {
+                                                        WARNINGA
+                                                                (&quot;Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||. Let's introduce a 1 second delay.\n&quot;,
+                                                                 SKYPIAX_P_LOG, buf);
+                                                        skypiax_sleep(1000000);        //1 sec
+                                                }
+                                                break;
+                                        }
+                                }
+
+                                strcat(buffer, buf);
+
+                                if (i &lt; 20 || continue_is_broken) {        /* last fragment */
+                                        unsigned int howmany;
+
+                                        howmany = strlen(b) + 1;
+
+                                        howmany = write(SkypiaxHandles-&gt;fdesc[1], b, howmany);
+                                        //DEBUGA_SKYPE (&quot;RECEIVED=|||%s|||\n&quot;, SKYPIAX_P_LOG, buffer);
+                                        memset(buffer, '\0', 17000);
+                                        XFlush(disp);
+                                        continue_is_broken = 0;
+                                }
+
+                                break;
+                        default:
+                                break;
+                        }
+                }
+        } else {
+                ERRORA(&quot;Skype is not running, maybe crashed. Please run/restart Skype and relaunch Skypiax\n&quot;, 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>