Freeswitch-branches
Threads by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
January 2009
- 5 participants
- 136 discussions
Author: ctrix
Date: Sat Jan 17 16:40:42 2009
New Revision: 11267
Log:
airpe_debug command.
Modified:
freeswitch/branches/ctrix/mod_airpe/airpe_api.c
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_api.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_api.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_api.c Sat Jan 17 16:40:42 2009
@@ -37,6 +37,51 @@
*/
+#define AIRPE_DEBUG_SYNTAX "airpe_debug <clientname> <on|off|true|false|1|0>"
+SWITCH_STANDARD_API(airpe_debug_command)
+{
+ int argc = 0;
+ char *argv[2] = { 0 };
+ char *mycmd = NULL;
+ char *client = NULL;
+ airpe_interface_t *airpe = NULL;
+
+ if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+ argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+ switch_assert(argv[0]);
+ }
+
+ if ( argc < 1 ) {
+ stream->write_function(stream, "-USAGE: %s\n", AIRPE_DEBUG_SYNTAX);
+ goto done;
+ }
+
+ client = argv[0];
+ airpe = airpe_find_interface(client);
+
+ if ( !airpe ) {
+ stream->write_function(stream, "-ERR interface not found for client ");
+ stream->write_function(stream, client);
+ stream->write_function(stream, "\n");
+ goto done;
+ }
+
+ if ( argc > 1 ) {
+ int debug = switch_true(argv[1]);
+ airpe->debug = debug;
+ }
+
+ stream->write_function(stream, "Debug status: ");
+ if ( airpe->debug )
+ stream->write_function(stream, "On");
+ else
+ stream->write_function(stream, "Off");
+ stream->write_function(stream, "\n");
+
+ done:
+ return SWITCH_STATUS_SUCCESS;
+}
+
#define AIRPE_MOODTEXT_SYNTAX "airpe_moodtext <clientname> [text]"
SWITCH_STANDARD_API(airpe_moodtext_command)
{
@@ -248,6 +293,9 @@
switch_api_interface_t *api;
+ switch_console_set_complete("add airpe_debug ");
+ SWITCH_ADD_API(api, "airpe_debug", "gets/sets debug status of an airpe client", airpe_debug_command, AIRPE_DEBUG_SYNTAX);
+
switch_console_set_complete("add airpe_moodtext ");
SWITCH_ADD_API(api, "airpe_moodtext", "gets/sets the mood text of an airpe client", airpe_moodtext_command, AIRPE_MOODTEXT_SYNTAX);
1
0
Author: ctrix
Date: Thu Jan 15 03:25:37 2009
New Revision: 11221
Log:
Cosmetics
Modified:
freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c Thu Jan 15 03:25:37 2009
@@ -533,8 +533,8 @@
if ( !strncmp( buf, "CURRENTUSERHANDLE", strlen("CURRENTUSERHANDLE")) ) {
/* The username that the client is using. */
- // TODO ... if the user handle mismatches, disconnect the channel or simply disable
- // all operations
+ /* TODO ... if the user handle mismatches, disconnect the channel or simply disable
+ all operations */
}
else if ( !strncmp( buf, "USERSTATUS", strlen("USERSTATUS")) && argc > 1 ) {
/* The status of the user of the client (ex: NA, ONLINE) */
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c Thu Jan 15 03:25:37 2009
@@ -257,7 +257,6 @@
return NULL;
}
- // perform an events loop
XEvent an_event;
char buf[X11_MSG_LEN + 2] = "";
char buffer[SKYPE_MSG_LEN] = "";
1
0
Author: ctrix
Date: Wed Jan 14 19:09:35 2009
New Revision: 11208
Log:
An application, some events and some channel variables.
Modified:
freeswitch/branches/ctrix/mod_airpe/airpe_api.c
freeswitch/branches/ctrix/mod_airpe/airpe_apps.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_api.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_api.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_api.c Wed Jan 14 19:09:35 2009
@@ -37,7 +37,7 @@
*/
-#define AIRPE_MOODTEXT_SYNTAX "airpe_moodtext <clientname> <text>"
+#define AIRPE_MOODTEXT_SYNTAX "airpe_moodtext <clientname> [text]"
SWITCH_STANDARD_API(airpe_moodtext_command)
{
int argc = 0;
@@ -67,11 +67,10 @@
}
if ( argc == 1 ) {
- stream->write_function(stream, "+OK: ");
if ( airpe->mood_text )
stream->write_function(stream, airpe->mood_text);
else
- stream->write_function(stream, "UNKNOWN");
+ stream->write_function(stream, "[UNKNOWN]");
stream->write_function(stream, "\n");
}
else {
@@ -91,7 +90,7 @@
return SWITCH_STATUS_SUCCESS;
}
-#define AIRPE_INFO_SYNTAX "airpe_status <clientname>"
+#define AIRPE_INFO_SYNTAX "airpe_info <clientname>"
SWITCH_STANDARD_API(airpe_info_command)
{
int argc = 0;
@@ -161,7 +160,7 @@
return SWITCH_STATUS_SUCCESS;
}
-#define AIRPE_STATUS_SYNTAX "airpe_status <clientname> <status>"
+#define AIRPE_STATUS_SYNTAX "airpe_status <clientname> [status]"
SWITCH_STANDARD_API(airpe_status_command)
{
int argc = 0;
@@ -197,7 +196,6 @@
if ( !cstatus ) {
const char *str_status = NULL;
str_status = skype_user_status_string( airpe->user_status );
- stream->write_function(stream, "+OK status is ");
if ( str_status )
stream->write_function(stream, str_status);
else
@@ -251,13 +249,13 @@
switch_api_interface_t *api;
switch_console_set_complete("add airpe_moodtext ");
- SWITCH_ADD_API(api, "airpe_moodtext", "sets the mood text of an airpe client", airpe_moodtext_command, AIRPE_MOODTEXT_SYNTAX);
+ SWITCH_ADD_API(api, "airpe_moodtext", "gets/sets the mood text of an airpe client", airpe_moodtext_command, AIRPE_MOODTEXT_SYNTAX);
switch_console_set_complete("add airpe_info ");
SWITCH_ADD_API(api, "airpe_info", "shows the status of an airpe client", airpe_info_command, AIRPE_INFO_SYNTAX);
switch_console_set_complete("add airpe_status ");
- SWITCH_ADD_API(api, "airpe_status", "sets the status of an airpe client", airpe_status_command, AIRPE_STATUS_SYNTAX);
+ SWITCH_ADD_API(api, "airpe_status", "gets/sets the status of an airpe client", airpe_status_command, AIRPE_STATUS_SYNTAX);
return SWITCH_STATUS_SUCCESS;
}
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_apps.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_apps.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_apps.c Wed Jan 14 19:09:35 2009
@@ -30,15 +30,67 @@
#include "mod_airpe.h"
-SWITCH_STANDARD_APP(airpe_app_test)
+#define AIRPE_SET_STATUS_SYNTAX "<client> <unknown|online|offline|skyoeme|away|na|dnd|invisible|loggedout>"
+SWITCH_STANDARD_APP(airpe_set_status)
{
+ airpe_interface_t *airpe = NULL;
+ const char *str_status = NULL;
+ char buf[SKYPE_MSG_LEN];
+ char *client = NULL;
+ char *text = NULL;
+
+ client = (char *) data;
+ if ( (text = strchr(client,' ')) ) {
+ *text++ = '\0';
+ }
+
+ if ( switch_strlen_zero(client) ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No client specified.\n");
+ return;
+ }
+
+ airpe = airpe_find_interface(client);
+
+ if ( !airpe ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No airpe client matching name '%s' found.\n", client);
+ return;
+ }
+
+ if ( !switch_strlen_zero(text) ) {
+
+ if ( !strncasecmp(text, "unknown", sizeof("unknown") ) )
+ str_status = skype_user_status_string(USER_STATUS_UNKNOWN);
+ else if ( !strncasecmp(text, "online", sizeof("online") ) )
+ str_status = skype_user_status_string(USER_STATUS_ONLINE);
+ else if ( !strncasecmp(text, "offline", sizeof("offline") ) )
+ str_status = skype_user_status_string(USER_STATUS_OFFLINE);
+ else if ( !strncasecmp(text, "skypeme", sizeof("skypeme") ) )
+ str_status = skype_user_status_string(USER_STATUS_SKYPEME);
+ else if ( !strncasecmp(text, "away", sizeof("away") ) )
+ str_status = skype_user_status_string(USER_STATUS_AWAY);
+ else if ( !strncasecmp(text, "na", sizeof("na") ) )
+ str_status = skype_user_status_string(USER_STATUS_NA);
+ else if ( !strncasecmp(text, "dnd", sizeof("dnd") ) )
+ str_status = skype_user_status_string(USER_STATUS_DND);
+ else if ( !strncasecmp(text, "invisible", sizeof("invisible") ) )
+ str_status = skype_user_status_string(USER_STATUS_INVISIBLE);
+ else if ( !strncasecmp(text, "loggedout", sizeof("loggedout") ) )
+ str_status = skype_user_status_string(USER_STATUS_LOGGEDOUT);
+
+ if ( str_status ) {
+ snprintf(buf, SKYPE_MSG_LEN, "SET USERSTATUS %s", str_status );
+ airpe_cmd_write(airpe, buf);
+ }
+
+ }
+
}
switch_status_t airpe_register_apps( switch_loadable_module_interface_t **module_interface ) {
switch_application_interface_t *app_interface;
- SWITCH_ADD_APP(app_interface, "airpe_test", "test text", "test text", airpe_app_test, "", SAF_SUPPORT_NOMEDIA);
+ SWITCH_ADD_APP(app_interface, "airpe_set_status", "Sets the status of an airpe client", "Sets the status of an airpe client", airpe_set_status, AIRPE_SET_STATUS_SYNTAX, SAF_SUPPORT_NOMEDIA);
return SWITCH_STATUS_SUCCESS;
}
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c Wed Jan 14 19:09:35 2009
@@ -373,6 +373,8 @@
else
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+ switch_channel_set_variable(channel, "airpe_client", airpe->name);
+ switch_channel_set_variable(channel, "airpe_user_status", skype_user_status_string(airpe->user_status) );
switch_set_flag(tech_pvt, TFLAG_INBOUND);
airpe_set_call_id(airpe, callid, switch_core_session_get_uuid(new_session) );
@@ -502,6 +504,8 @@
switch_status_t airpe_manage_skype_msg( airpe_interface_t *airpe, const char *msg ) {
switch_core_session_t *session = NULL;
+ switch_channel_t *channel = NULL;
+ switch_event_t *s_event = NULL;
char *buf = NULL;
int argc = 0;
char *argv[9] = { 0 };
@@ -512,8 +516,11 @@
if ( airpe->debug )
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "airpe client %s: < %s\n", airpe->name, msg);
- if ( airpe->active_session_uuid )
+ if ( airpe->active_session_uuid ) {
session = switch_core_session_locate(airpe->active_session_uuid);
+ if ( session )
+ channel = switch_core_session_get_channel(session);
+ }
buf = strdup(msg);
argc = switch_separate_string(buf, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
@@ -524,8 +531,6 @@
return SWITCH_STATUS_FALSE;
}
-
-
if ( !strncmp( buf, "CURRENTUSERHANDLE", strlen("CURRENTUSERHANDLE")) ) {
/* The username that the client is using. */
// TODO ... if the user handle mismatches, disconnect the channel or simply disable
@@ -553,9 +558,16 @@
else if ( !strncmp( buf, "USER", strlen("USER")) && argc >= 2 ) {
/* Updates about the users of our list or new auth requests */
if ( !strncmp(argv[2], "RECEIVEDAUTHREQUEST", strlen("RECEIVEDAUTHREQUEST") ) ) {
+ if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, AIRPE_EVENT_AUTHREQUEST) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "client-name", airpe->name);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "auth_user", argv[1]);
+ switch_event_fire(&s_event);
+ }
if ( airpe->auto_auth ) {
snprintf(buf, sizeof(buf), "SET USER %s ISAUTHORIZED TRUE", argv[1]);
airpe_cmd_write(airpe, buf);
+
+
}
}
}
@@ -627,6 +639,11 @@
else if ( !strncmp(cmd, "STATUS", strlen("STATUS")) && argc >=4 ) {
char *callstatus = argv[3];
airpe_manage_call_status( airpe, callid, callstatus );
+ if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, AIRPE_EVENT_STATUSCHANGE) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "client-name", airpe->name);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", callstatus);
+ switch_event_fire(&s_event);
+ }
}
else if ( !strncmp(cmd, "CONF_ID", strlen("CONF_ID")) ) {
char buf[SKYPE_MSG_LEN];
@@ -652,15 +669,11 @@
}
else if ( !strncmp(cmd, "DTMF", strlen("DTMF")) ) {
/* This is an incoming DTMF */
- if ( session ) {
- switch_channel_t *channel;
+ if ( session && channel ) {
switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) };
const char *signal_ptr;
int tmp;
- channel = switch_core_session_get_channel(session);
- assert(channel);
-
signal_ptr = argv[3];
if (*signal_ptr && (*signal_ptr == '*' || *signal_ptr == '#' || *signal_ptr == 'A' || *signal_ptr == 'B' || *signal_ptr == 'C' || *signal_ptr == 'D')) {
@@ -670,9 +683,7 @@
dtmf.digit = switch_rfc2833_to_char(tmp);
}
- switch_mutex_lock(airpe->tech_pvt->flag_mutex);
switch_channel_queue_dtmf(channel, &dtmf);
- switch_mutex_unlock(airpe->tech_pvt->flag_mutex);
}
}
else if ( !strncmp(cmd, "FAILUREREASON", strlen("FAILUREREASON")) && argc >=2 ) {
@@ -698,6 +709,8 @@
if ( data ) {
data += strlen("PARTNER_DISPNAME ");
airpe_set_partner_displayname(airpe, data);
+ if ( channel )
+ switch_channel_set_variable(channel, "airpe_partner_dispname", data);
}
}
switch_safe_free(tmp);
@@ -710,6 +723,8 @@
if ( data ) {
data += strlen("PARTNER_HANDLE ");
airpe_set_partner_handle(airpe, data);
+ if ( channel )
+ switch_channel_set_variable(channel, "airpe_partner_handle", data);
}
switch_safe_free(tmp);
}
@@ -735,10 +750,13 @@
}
else if ( !strncmp( buf, "ERROR", strlen("ERROR")) ) {
/* If we are in the middle of a call, hangup */
+ /*
if ( airpe->active_call_id ) {
+ char buf[SKYPE_MSG_LEN] = "";
snprintf(buf, sizeof(buf), "ALTER CALL %d END HANGUP", airpe->active_call_id );
airpe_cmd_write(airpe, buf);
}
+ */
}
else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unmanaged message\n");
Modified: freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/mod_airpe.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.c Wed Jan 14 19:09:35 2009
@@ -408,6 +408,10 @@
airpe_set_call_id(tech_pvt->airpe, 0, switch_core_session_get_uuid(*new_session) );
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
+
+ switch_channel_set_variable(channel, "airpe_client", tech_pvt->airpe->name);
+ switch_channel_set_variable(channel, "airpe_user_status", skype_user_status_string(tech_pvt->airpe->user_status) );
+
switch_channel_set_state(channel, CS_INIT);
return SWITCH_CAUSE_SUCCESS;
}
Modified: freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/mod_airpe.h (original)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.h Wed Jan 14 19:09:35 2009
@@ -33,6 +33,9 @@
#define MODNAME "airpe"
+#define AIRPE_EVENT_AUTHREQUEST "airpe::authrequest"
+#define AIRPE_EVENT_STATUSCHANGE "airpe::statuschange"
+
#define SKYPE_MSG_LEN 1024
#define CODEC_SAMPLE_RATE 16000
1
0
15 Jan '09
Author: ctrix
Date: Wed Jan 14 18:03:50 2009
New Revision: 11207
Log:
Add option to let the client auto-auth incoming requests
Modified:
freeswitch/branches/ctrix/mod_airpe/airpe_api.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c
freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml
freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_api.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_api.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_api.c Wed Jan 14 18:03:50 2009
@@ -152,6 +152,11 @@
switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Mood text", (airpe->mood_text ) ? airpe->mood_text : "Unknown" );
stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Debug", (airpe->debug ) ? "Yes" : "No" );
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Auto-auth", (airpe->auto_auth) ? "Yes" : "No" );
+ stream->write_function(stream, buf);
+
done:
return SWITCH_STATUS_SUCCESS;
}
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c Wed Jan 14 18:03:50 2009
@@ -553,10 +553,10 @@
else if ( !strncmp( buf, "USER", strlen("USER")) && argc >= 2 ) {
/* Updates about the users of our list or new auth requests */
if ( !strncmp(argv[2], "RECEIVEDAUTHREQUEST", strlen("RECEIVEDAUTHREQUEST") ) ) {
- /* TODO add option to ignore such requests */
- char buf[SKYPE_MSG_LEN] = "";
- snprintf(buf, sizeof(buf), "SET USER %s ISAUTHORIZED TRUE", argv[1]);
- airpe_cmd_write(airpe, buf);
+ if ( airpe->auto_auth ) {
+ snprintf(buf, sizeof(buf), "SET USER %s ISAUTHORIZED TRUE", argv[1]);
+ airpe_cmd_write(airpe, buf);
+ }
}
}
else if ( !strncmp( buf, "GROUP", strlen("GROUP")) ) {
@@ -583,7 +583,7 @@
else if ( !strncmp( buf, "CHAT", strlen("CHAT")) && argc >=2 ) {
/* Chat status - ignored. */
if ( airpe->protocol > 6 ) {
- //TODO : ALTER CHAT <chat_id> DISBAND - Doesn't seems to work on linux
+ /* ALTER CHAT <chat_id> DISBAND - Doesn't seems to work on linux */
char buf[SKYPE_MSG_LEN] = "";
snprintf(buf, sizeof(buf), "ALTER CHAT %s DISBAND", argv[1]);
airpe_cmd_write(airpe, buf);
@@ -616,13 +616,13 @@
if ( !strncmp(cmd, "DURATION", strlen("DURATION")) ) {
/* Ignore the duration that is updated every second */
+ /* TODO: maybe in the future we could consider this message as a keepalive signal */
if ( callid != airpe->active_call_id ) {
char buf[SKYPE_MSG_LEN] = "";
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: hanging up unknown call id %d\n", airpe->name, callid);
snprintf(buf, sizeof(buf), "SET CALL %d STATUS FINISHED", callid);
airpe_cmd_write(airpe, buf);
}
- //TODO: maybe we could consider this message as a keepalive signal
}
else if ( !strncmp(cmd, "STATUS", strlen("STATUS")) && argc >=4 ) {
char *callstatus = argv[3];
@@ -734,7 +734,11 @@
/* Ignoring by now */
}
else if ( !strncmp( buf, "ERROR", strlen("ERROR")) ) {
- //TODO If we are in the middle of a call, hangup
+ /* If we are in the middle of a call, hangup */
+ if ( airpe->active_call_id ) {
+ snprintf(buf, sizeof(buf), "ALTER CALL %d END HANGUP", airpe->active_call_id );
+ airpe_cmd_write(airpe, buf);
+ }
}
else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unmanaged message\n");
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c Wed Jan 14 18:03:50 2009
@@ -95,8 +95,7 @@
switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"HEY! where is my skype window gone ? Restarting skype for client...\n");
/*
-
- TODO AND TO USE
+ TODO AND TO USE - Start skype client
int fid;
const char *args[] = { "skype", "--actiondispatch", params, 0 };
Modified: freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml (original)
+++ freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml Wed Jan 14 18:03:50 2009
@@ -19,6 +19,7 @@
<param name="context" value="default"/>
<param name="destination" value="4321"/>
+ <param name="auto-auth" value="false"/>
<!--
The following params won't be affected by reloading xml
-->
Modified: freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/mod_airpe.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.c Wed Jan 14 18:03:50 2009
@@ -260,7 +260,6 @@
if ( switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ) {
airpe_originate(tech_pvt->airpe, tech_pvt->destination );
- // TODO if fail switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
switch_channel_set_state(channel, CS_ROUTING);
@@ -509,14 +508,13 @@
switch (sig) {
case SWITCH_SIG_KILL:
break;
- case SWITCH_SIG_BREAK:
+ case SWITCH_SIG_BREAK:
break;
- default:
- //TODO Log unhandled signal
- break;
- }
+ default:
+ break;
+ }
- return SWITCH_STATUS_SUCCESS;
+ return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_send_dtmf(switch_core_session_t * session, const switch_dtmf_t * dtmf) {
@@ -686,6 +684,7 @@
char *skype_password= NULL;
char *cid_name = NULL;
char *cid_num = NULL;
+ int auto_auth = 0;
int debug = 0;
airpe_interface_t *newconf = NULL;
@@ -701,6 +700,8 @@
if (!strcasecmp(var, "debug")) {
debug = switch_true(val) ? 1 : 0;
+ } else if (!strcasecmp(var, "auto-auth")) {
+ auto_auth = switch_true(val) ? 1 : 0;
} else if (!strcasecmp(var, "context")) {
context = val;
} else if (!strcasecmp(var, "dialplan")) {
@@ -765,6 +766,7 @@
newconf->dialplan = switch_core_strdup(pool, dialplan);
newconf->context = switch_core_strdup(pool, context);
newconf->destination = switch_core_strdup(pool, destination);
+ newconf->auto_auth = auto_auth;
newconf->debug = debug;
if ( reload ) {
Modified: freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/mod_airpe.h (original)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.h Wed Jan 14 18:03:50 2009
@@ -139,6 +139,7 @@
char *skype_user;
char *skype_password;
+ int auto_auth;
int audio_in_port;
int audio_out_port;
switch_socket_t *audio_in_socket;
1
0
14 Jan '09
Author: ctrix
Date: Wed Jan 14 17:39:21 2009
New Revision: 11206
Log:
Airpe: reloadxml configuration event - bindings and handler
Modified:
freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml
freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c Wed Jan 14 17:39:21 2009
@@ -175,6 +175,8 @@
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "msg to airpe client %s: > %s\n", airpe->name, msg);
status = airpe_skype_send_message(airpe->skype_window, msg);
+ /* Relax and calm down. Some skype clients don't like fast messages */
+ switch_sleep(10000);
return status;
}
Modified: freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml (original)
+++ freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml Wed Jan 14 17:39:21 2009
@@ -12,13 +12,17 @@
<clients>
<client name="airpe1">
<!-- Print out as notices the client messages -->
- <param name="debug" value="1"/>
+ <param name="debug" value="false"/>
<!-- Where our calls will land -->
<param name="dialplan" value="XML"/>
<param name="context" value="default"/>
<param name="destination" value="4321"/>
+ <!--
+ The following params won't be affected by reloading xml
+ -->
+
<!-- Linux only -->
<param name="X11-display" value=":101"/>
@@ -32,5 +36,4 @@
<param name="skype-password" value="password"/>
</client>
</clients>
-
</configuration>
Modified: freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/mod_airpe.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.c Wed Jan 14 17:39:21 2009
@@ -630,7 +630,7 @@
CONFIGURATION
*****************************************************************************/
-static switch_status_t load_config(void) {
+static switch_status_t load_config( int reload ) {
switch_xml_t cfg,
xml,
global_settings,
@@ -695,11 +695,6 @@
continue;
}
- if ( (newconf = switch_core_hash_find(globals.interfaces_hash, name)) ) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Duplicated client %s. Skipping\n", name);
- continue;
- }
-
for (param = switch_xml_child(client, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
@@ -746,43 +741,62 @@
if ( !destination )
destination = globals.destination;
- newconf = (airpe_interface_t *) switch_core_alloc( pool, sizeof(airpe_interface_t) );
+ if ( reload ) {
+ newconf = airpe_find_interface(name);
+ }
+ else {
+ if ( (newconf = switch_core_hash_find(globals.interfaces_hash, name)) ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Duplicated client %s. Skipping\n", name);
+ continue;
+ }
+ }
+
+ if ( !newconf ) {
+ newconf = (airpe_interface_t *) switch_core_alloc( pool, sizeof(airpe_interface_t) );
+ if ( newconf )
+ memset(newconf, 0, sizeof(airpe_interface_t));
+ }
+
if ( newconf ) {
switch_status_t status;
- memset(newconf, 0, sizeof(airpe_interface_t));
-
newconf->name = switch_core_strdup(pool, name);
newconf->dialplan = switch_core_strdup(pool, dialplan);
newconf->context = switch_core_strdup(pool, context);
newconf->destination = switch_core_strdup(pool, destination);
+ newconf->debug = debug;
+
+ if ( reload ) {
+ /* We won't update any other value on reload. */
+ newconf->should_reload = 0;
+ continue;
+ }
+
newconf->skype_user = switch_core_strdup(pool, skype_user);
newconf->skype_password = switch_core_strdup(pool, skype_password);
newconf->X11_display = switch_core_strdup(pool, X11_display);
newconf->audio_in_port = 0;
newconf->audio_in_port = 0;
- newconf->debug = debug;
-
newconf->skype_window = skype_window_alloc(pool);
if ( newconf->skype_window ) {
status = airpe_start_client(newconf);
-
if ( status == SWITCH_STATUS_SUCCESS ) {
switch_core_hash_insert(globals.interfaces_hash, name, newconf);
}
else {
- // LOG OUR ERROR
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Airpe: cannot start client %s.\n", newconf->name);
}
}
else {
- // LOG OUR ERROR
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Airpe: cannot alloc client %s.\n", newconf->name);
}
+
}
else {
- //TODO LOG ERROR ABOUT CREATING INTERFACE
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Airpe: cannot alloc client %s.\n", newconf->name);
}
}
@@ -792,11 +806,44 @@
return SWITCH_STATUS_SUCCESS;
}
+static void reloadxml_event_handler(switch_event_t *event)
+{
+ airpe_interface_t *airpe;
+ switch_hash_index_t *hi;
+ void *val;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Reloading airpe configuration.\n");
+
+ /* First, mark all of them to be reloaded */
+ for (hi = switch_hash_first(NULL, globals.interfaces_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, NULL, NULL, &val);
+ airpe = ( airpe_interface_t *) val;
+ airpe->should_reload = 1;
+ }
+
+ /* Update the data of each client */
+ load_config(1);
+
+ /* Find eventual clients not updated and stop them */
+ for (hi = switch_hash_first(NULL, globals.interfaces_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, NULL, NULL, &val);
+ airpe = ( airpe_interface_t *) val;
+ if ( airpe->should_reload ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Stopping airpe client %s.\n", airpe->name);
+ switch_core_hash_delete(globals.interfaces_hash, airpe->name);
+ airpe_stop_client(airpe);
+ }
+ }
+
+}
+
/*****************************************************************************
MODULE INITIALIZATION FUNCTIONS
*****************************************************************************/
+static switch_event_node_t *EVENT_NODE = NULL;
+
static switch_state_handler_table_t airpe_state_handlers = {
/*.on_init */ channel_on_init,
/*.on_routing */ channel_on_routing,
@@ -829,7 +876,7 @@
switch_core_hash_init(&globals.interfaces_hash, pool);
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, pool);
- load_config();
+ load_config(0);
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
@@ -839,6 +886,11 @@
airpe_endpoint_interface->io_routines = &airpe_io_routines;
airpe_endpoint_interface->state_handler = &airpe_state_handlers;
+ if ((switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, reloadxml_event_handler, NULL, &EVENT_NODE) != SWITCH_STATUS_SUCCESS)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our reloadxml handler!\n");
+ /* Not such severe to prevent loading */
+ }
+
airpe_register_api( &*module_interface );
airpe_register_apps( &*module_interface );
@@ -855,6 +907,8 @@
pool = airpe_module_pool;
+ switch_event_unbind(&EVENT_NODE);
+
for (hi = switch_hash_first(NULL, globals.interfaces_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
airpe = ( airpe_interface_t *) val;
Modified: freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/mod_airpe.h (original)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.h Wed Jan 14 17:39:21 2009
@@ -154,6 +154,7 @@
CALL_STATUS call_status;
CONN_STATUS conn_status;
+ int should_reload;
char *skype_version;
char *mood_text;
int active_call_id;
1
0
Author: ctrix
Date: Wed Jan 14 15:05:23 2009
New Revision: 11204
Log:
Reworked all the call logic.
Big cleanups of unused code.
Should be almost working 100%!
Modified:
freeswitch/branches/ctrix/mod_airpe/airpe_api.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_api.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_api.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_api.c Wed Jan 14 15:05:23 2009
@@ -30,6 +30,13 @@
#include "mod_airpe.h"
+/*
+ TODO
+ block / authorize users
+ add / remove users from contact list
+*/
+
+
#define AIRPE_MOODTEXT_SYNTAX "airpe_moodtext <clientname> <text>"
SWITCH_STANDARD_API(airpe_moodtext_command)
{
Modified: freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c Wed Jan 14 15:05:23 2009
@@ -146,10 +146,36 @@
return SWITCH_STATUS_SUCCESS;
}
+void airpe_clear_call_id(airpe_interface_t *airpe) {
+
+ airpe->active_call_id = 0;
+ switch_safe_free(airpe->active_session_uuid);
+ airpe->active_session_uuid = NULL;
+}
+
+switch_status_t airpe_set_call_id(airpe_interface_t *airpe, int sk_id, char *fs_uuid) {
+ assert(airpe);
+
+ airpe->active_call_id = sk_id;
+
+ if ( fs_uuid ) {
+ switch_safe_free(airpe->active_session_uuid);
+ airpe->active_session_uuid = strdup(fs_uuid);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* ************************************************************************* */
+
switch_status_t airpe_cmd_write(airpe_interface_t *airpe, char *msg) {
+ switch_status_t status;
+
if ( airpe->debug )
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "msg to airpe client %s: %s\n", airpe->name, msg);
- return airpe_skype_send_message(airpe->skype_window, msg);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "msg to airpe client %s: > %s\n", airpe->name, msg);
+
+ status = airpe_skype_send_message(airpe->skype_window, msg);
+ return status;
}
switch_status_t airpe_originate(airpe_interface_t *airpe, char *dest) {
@@ -161,7 +187,7 @@
airpe_cmd_write(p, "SET AGC OFF");
airpe_cmd_write(p, "SET AEC OFF");
*/
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: Originating to %s\n", airpe->name, dest);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "airpe client %s: Originating to client %s\n", airpe->name, dest);
snprintf(msg, sizeof(msg), "CALL %s", dest);
@@ -182,17 +208,14 @@
return SWITCH_STATUS_FALSE;
}
-
-
/*****************************************************************************
SKYPE AUDIO
*****************************************************************************/
-switch_status_t airpe_hangup( private_object_t *pvt ) {
+switch_status_t airpe_call_shutdown( private_object_t *pvt ) {
airpe_interface_t *airpe;
assert(pvt);
- assert(pvt->session);
assert(pvt->airpe);
airpe = pvt->airpe;
@@ -225,10 +248,14 @@
assert(pvt);
assert(pvt->session);
assert(pvt->airpe);
-
+
+ if ( !switch_test_flag(pvt, TFLAG_IO) )
+ return SWITCH_STATUS_SUCCESS;
+
airpe = pvt->airpe;
pool = switch_core_session_get_pool(pvt->session);
+
if ( !airpe->audio_in_active_socket ) {
rv = switch_socket_accept(&inbound_socket, airpe->audio_in_socket, pool);
if ( rv == SWITCH_STATUS_SUCCESS ) {
@@ -262,6 +289,9 @@
airpe = pvt->airpe;
pool = switch_core_session_get_pool(pvt->session);
+ if ( !switch_test_flag(pvt, TFLAG_IO) )
+ return SWITCH_STATUS_SUCCESS;
+
if ( !airpe->audio_out_active_socket ) {
rv = switch_socket_accept(&inbound_socket, airpe->audio_out_socket, pool);
if ( rv == SWITCH_STATUS_SUCCESS ) {
@@ -269,7 +299,7 @@
switch_sleep(100000);
}
else {
- return SWITCH_STATUS_FALSE;
+ return SWITCH_STATUS_SUCCESS;
}
}
@@ -281,9 +311,6 @@
if ( (rv==SWITCH_STATUS_SUCCESS) ) {
pvt->read_frame.datalen = mlen;
}
-// if ( mlen == 0 )
-// return SWITCH_STATUS_SUCCESS;
-
return rv;
}
@@ -320,7 +347,7 @@
}
tech_pvt->airpe = airpe;
- switch_snprintf(chan_name, sizeof(chan_name), MODNAME"/%s", airpe->name);
+ switch_snprintf(chan_name, sizeof(chan_name), MODNAME"/%s/%s", airpe->name, airpe->destination);
switch_channel_set_name(channel, chan_name);
tech_pvt->caller_profile = switch_caller_profile_new( switch_core_session_get_pool(new_session),
@@ -346,11 +373,12 @@
switch_set_flag(tech_pvt, TFLAG_INBOUND);
- airpe->active_call_id = callid;
+ airpe_set_call_id(airpe, callid, switch_core_session_get_uuid(new_session) );
+
switch_channel_set_state(channel, CS_INIT);
if ( switch_core_session_thread_launch(new_session) != SWITCH_STATUS_SUCCESS ) {
- airpe->active_call_id = 0;
+ airpe_clear_call_id(airpe);
switch_core_session_destroy(&new_session);
return SWITCH_STATUS_FALSE;
}
@@ -363,8 +391,23 @@
switch_core_session_t *session = NULL;
switch_channel_t *channel = NULL;
+ if ( airpe->active_session_uuid ) {
+ session = switch_core_session_locate(airpe->active_session_uuid);
+ if ( session )
+ channel = switch_core_session_get_channel(session);
+ }
+
+/*
+ADEBUG("MANAGING: %s - %d - %d - INB: %d - OUTB %d\n",
+ (airpe->active_session_uuid) ? airpe->active_session_uuid : "NO SESSION UUID",
+ (session) ? 1 : 0,
+ (channel) ? 1 : 0,
+ (airpe->tech_pvt) ? switch_test_flag(airpe->tech_pvt, TFLAG_INBOUND) : -1,
+ (airpe->tech_pvt) ? switch_test_flag(airpe->tech_pvt, TFLAG_OUTBOUND): -1
+);
+*/
+
if ( airpe->active_call_id && airpe->active_call_id != callid ) {
-ADEBUG("CASE 1 - different call\n");
if ( !strncmp(status, "UNPLACED", strlen("UNPLACED")) ) {
snprintf(buf, sizeof(buf), "SET CALL %d STATUS FINISHED", callid);
airpe_cmd_write(airpe, buf);
@@ -375,102 +418,88 @@
}
else if ( airpe->active_call_id && airpe->active_call_id == callid ) {
-ADEBUG("CASE 2 - my call\n");
- if ( airpe->tech_pvt ) {
- assert(airpe->tech_pvt);
- session = airpe->tech_pvt->session;
- assert(session);
-
- channel = switch_core_session_get_channel(session);
- assert(channel);
- }
-
if ( !strncmp(status, "ROUTING", strlen("ROUTING")) ) {
}
else if ( !strncmp(status, "RINGING", strlen("RINGING")) ) {
- //if ( switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ) {
- //switch_channel_set_state(channel, CS_RINGING);
- switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
- switch_channel_mark_ring_ready(channel);
- //}
-
- snprintf(buf, sizeof(buf), "ALTER CALL %d SET_INPUT PORT=\"%d\"", callid, airpe->audio_in_port);
- airpe_cmd_write(airpe, buf);
- snprintf(buf, sizeof(buf), "ALTER CALL %d SET_OUTPUT PORT=\"%d\"", callid, airpe->audio_out_port);
- airpe_cmd_write(airpe, buf);
-
-
-
- switch_channel_set_state(channel, CS_ROUTING);
-
- }
- else if ( !strncmp(status, "INPROGRESS", strlen("INPROGRESS")) ) {
- snprintf(buf, sizeof(buf), "ALTER CALL %d STOP_VIDEO_SEND", callid );
- airpe_cmd_write(airpe, buf);
- snprintf(buf, sizeof(buf), "ALTER CALL %d STOP_VIDEO_RECEIVE", callid );
- airpe_cmd_write(airpe, buf);
-
- if ( channel ) {
- switch_channel_mark_answered(channel);
+ if ( session && channel ) {
+ switch_channel_mark_ring_ready(channel);
}
else {
if ( airpe_manage_incoming_call(airpe, callid) != SWITCH_STATUS_SUCCESS ) {
snprintf(buf, sizeof(buf), "ALTER CALL %d END HANGUP", callid );
airpe_cmd_write(airpe, buf);
- airpe->active_call_id = 0;
+ airpe_clear_call_id(airpe);
}
}
}
+ else if ( !strncmp(status, "INPROGRESS", strlen("INPROGRESS")) ) {
+
+ if ( channel && switch_test_flag(airpe->tech_pvt, TFLAG_OUTBOUND) ) {
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_INPUT PORT=\"%d\"", callid, airpe->audio_in_port);
+ airpe_cmd_write(airpe, buf);
+ airpe_cmd_write(airpe, "PING");
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_OUTPUT PORT=\"%d\"", callid, airpe->audio_out_port);
+ airpe_cmd_write(airpe, buf);
+ airpe_cmd_write(airpe, "PING");
+ switch_set_flag(airpe->tech_pvt, TFLAG_IO);
+
+ snprintf(buf, sizeof(buf), "ALTER CALL %d STOP_VIDEO_SEND", callid );
+ airpe_cmd_write(airpe, buf);
+ snprintf(buf, sizeof(buf), "ALTER CALL %d STOP_VIDEO_RECEIVE", callid );
+ airpe_cmd_write(airpe, buf);
+
+ switch_channel_answer(channel);
+ }
+
+ }
else if ( !strncmp(status, "FINISHED", strlen("FINISHED")) ) {
if ( channel )
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
- airpe->active_call_id = 0;
+ airpe_clear_call_id(airpe);
}
else if ( !strncmp(status, "FAILED", strlen("FAILED")) ) {
if ( channel )
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
- airpe->active_call_id = 0;
+ airpe_clear_call_id(airpe);
}
else if ( !strncmp(status, "CANCELLED", strlen("CANCELLED")) ) {
if ( channel )
switch_channel_hangup(channel, SWITCH_CAUSE_ORIGINATOR_CANCEL);
- airpe->active_call_id = 0;
+ airpe_clear_call_id(airpe);
}
else if ( !strncmp(status, "REFUSED", strlen("REFUSED")) ) {
if ( channel )
switch_channel_hangup(channel, SWITCH_CAUSE_CALL_REJECTED);
- airpe->active_call_id = 0;
+ airpe_clear_call_id(airpe);
}
else if ( !strncmp(status, "MISSED", strlen("MISSED")) ) {
if ( channel )
switch_channel_hangup(channel, SWITCH_CAUSE_NO_ANSWER);
- airpe->active_call_id = 0;
+ airpe_clear_call_id(airpe);
}
else if ( !strncmp(status, "UNPLACED", strlen("UNPLACED")) ) {
}
else {
-ADEBUG("Unmanaged status \n");
+ ADEBUG("Unmanaged status \n");
}
}
else {
-ADEBUG("CASE 3 - no calls online\n");
- if ( !strncmp(status, "UNPLACED", strlen("UNPLACED")) ) {
- airpe->active_call_id = callid;
- }
- else if ( !strncmp(status, "RINGING", strlen("RINGING")) ) {
- airpe->active_call_id = callid;
- snprintf(buf, sizeof(buf), "ALTER CALL %d ANSWER", callid );
- airpe_cmd_write(airpe, buf);
+ if ( !strncmp(status, "UNPLACED", strlen("UNPLACED")) ) {
+ airpe_set_call_id(airpe, callid, NULL);
}
else {
ADEBUG("--- (%d/%d) Unmanaged status %s\n", airpe->active_call_id, callid, status);
}
}
+ if ( session )
+ switch_core_session_rwunlock(session);
+
return SWITCH_STATUS_SUCCESS;
}
switch_status_t airpe_manage_skype_msg( airpe_interface_t *airpe, const char *msg ) {
+ switch_core_session_t *session = NULL;
char *buf = NULL;
int argc = 0;
char *argv[9] = { 0 };
@@ -479,13 +508,16 @@
assert(msg);
if ( airpe->debug )
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "airpe client %s: %s\n", airpe->name, msg);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "airpe client %s: < %s\n", airpe->name, msg);
+
+ if ( airpe->active_session_uuid )
+ session = switch_core_session_locate(airpe->active_session_uuid);
buf = strdup(msg);
argc = switch_separate_string(buf, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
- if ( argc == 0 ) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: %s - Message without arguments? uh?\n", airpe->name, msg);
+ if ( argc == 0 ) {
+ /* Empty message. Shit happens (TM) */
free(buf);
return SWITCH_STATUS_FALSE;
}
@@ -516,8 +548,14 @@
/* The connection status of the client (ex: ONLINE) */
airpe->conn_status = skype_conn_status( argv[1] );
}
- else if ( !strncmp( buf, "USER", strlen("USER")) ) {
- /* Updates about the users of our list - ignored */
+ else if ( !strncmp( buf, "USER", strlen("USER")) && argc >= 2 ) {
+ /* Updates about the users of our list or new auth requests */
+ if ( !strncmp(argv[2], "RECEIVEDAUTHREQUEST", strlen("RECEIVEDAUTHREQUEST") ) ) {
+ /* TODO add option to ignore such requests */
+ char buf[SKYPE_MSG_LEN] = "";
+ snprintf(buf, sizeof(buf), "SET USER %s ISAUTHORIZED TRUE", argv[1]);
+ airpe_cmd_write(airpe, buf);
+ }
}
else if ( !strncmp( buf, "GROUP", strlen("GROUP")) ) {
/* Updates about the groups of our list - ignored */
@@ -531,7 +569,6 @@
else if ( !strncmp( buf, "AUTOAWAY", strlen("AUTOAWAY")) ) {
/* Autoaway - ignored */
}
-//TODO: RECEIVEDAUTHREQUEST - Add a config option to authorize or forget about it.
else if ( !strncmp( buf, "MUTE", strlen("MUTE")) && argc >= 2 ) {
if ( !strncmp(argv[1], "ON", 2) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: I don't like to be muted...\n", airpe->name);
@@ -598,11 +635,10 @@
snprintf(buf, sizeof(buf), "GET CALL %d PARTNER_DISPNAME", callid);
airpe_cmd_write(airpe, buf);
-
snprintf(buf, sizeof(buf), "GET CALL %d PARTNER_HANDLE", callid);
airpe_cmd_write(airpe, buf);
- airpe_cmd_write(airpe, "PING");
+ airpe_set_call_id(airpe, callid, NULL);
}
else {
snprintf(buf, sizeof(buf), "ALTER CALL %d END HANGUP", callid );
@@ -614,30 +650,28 @@
}
else if ( !strncmp(cmd, "DTMF", strlen("DTMF")) ) {
/* This is an incoming DTMF */
- switch_core_session_t *session;
- switch_channel_t *channel;
- switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) };
- const char *signal_ptr;
- int tmp;
-
- assert(airpe->tech_pvt);
- session = airpe->tech_pvt->session;
- assert(session);
- channel = switch_core_session_get_channel(session);
- assert(channel);
-
- signal_ptr = argv[3];
+ if ( session ) {
+ switch_channel_t *channel;
+ switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) };
+ const char *signal_ptr;
+ int tmp;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ signal_ptr = argv[3];
+
+ if (*signal_ptr && (*signal_ptr == '*' || *signal_ptr == '#' || *signal_ptr == 'A' || *signal_ptr == 'B' || *signal_ptr == 'C' || *signal_ptr == 'D')) {
+ dtmf.digit = *signal_ptr;
+ } else {
+ tmp = atoi(signal_ptr);
+ dtmf.digit = switch_rfc2833_to_char(tmp);
+ }
- if (*signal_ptr && (*signal_ptr == '*' || *signal_ptr == '#' || *signal_ptr == 'A' || *signal_ptr == 'B' || *signal_ptr == 'C' || *signal_ptr == 'D')) {
- dtmf.digit = *signal_ptr;
- } else {
- tmp = atoi(signal_ptr);
- dtmf.digit = switch_rfc2833_to_char(tmp);
+ switch_mutex_lock(airpe->tech_pvt->flag_mutex);
+ switch_channel_queue_dtmf(channel, &dtmf);
+ switch_mutex_unlock(airpe->tech_pvt->flag_mutex);
}
-
- switch_mutex_lock(airpe->tech_pvt->flag_mutex);
- switch_channel_queue_dtmf(channel, &dtmf);
- switch_mutex_unlock(airpe->tech_pvt->flag_mutex);
}
else if ( !strncmp(cmd, "FAILUREREASON", strlen("FAILUREREASON")) && argc >=2 ) {
airpe->last_fail_reason = atoi(argv[1]);
@@ -706,6 +740,9 @@
switch_safe_free(buf);
+ if ( session )
+ switch_core_session_rwunlock(session);
+
return SWITCH_STATUS_SUCCESS;
}
Modified: freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/mod_airpe.c (original)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.c Wed Jan 14 15:05:23 2009
@@ -196,7 +196,6 @@
airpe_audio_sockets_create(airpe);
switch_threadattr_create(&attr_skype, airpe_module_pool);
- //switch_threadattr_detach_set(attr_skype, 1);
switch_threadattr_stacksize_set(attr_skype, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&airpe->airpe_thread_skype,
@@ -230,6 +229,7 @@
airpe_set_mood_text(airpe, NULL);
airpe_set_partner_displayname(airpe, NULL);
airpe_set_partner_handle(airpe, NULL);
+ airpe_set_call_id(airpe, 0, NULL);
return SWITCH_STATUS_SUCCESS;
}
@@ -263,21 +263,12 @@
// TODO if fail switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
- if ( switch_test_flag(tech_pvt, TFLAG_INBOUND) ) {
- char buf[SKYPE_MSG_LEN];
- snprintf(buf, sizeof(buf), "ALTER CALL %d SET_INPUT PORT=\"%d\"", tech_pvt->airpe->active_call_id, tech_pvt->airpe->audio_in_port);
- airpe_cmd_write(tech_pvt->airpe, buf);
- snprintf(buf, sizeof(buf), "ALTER CALL %d SET_OUTPUT PORT=\"%d\"", tech_pvt->airpe->active_call_id, tech_pvt->airpe->audio_out_port);
- airpe_cmd_write(tech_pvt->airpe, buf);
-
- switch_channel_set_state(channel, CS_ROUTING);
- }
+ switch_channel_set_state(channel, CS_ROUTING);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_on_routing(switch_core_session_t * session) {
- char buf[SKYPE_MSG_LEN];
switch_channel_t *channel = NULL;
private_object_t *tech_pvt = NULL;
@@ -287,11 +278,6 @@
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt);
- if ( switch_test_flag(tech_pvt, TFLAG_INBOUND) ) {
- snprintf(buf, sizeof(buf), "ALTER CALL %d ANSWER", tech_pvt->airpe->active_call_id);
- airpe_cmd_write(tech_pvt->airpe, buf);
- }
-
return SWITCH_STATUS_SUCCESS;
}
@@ -313,7 +299,6 @@
switch_channel_t *channel = NULL;
private_object_t *tech_pvt = NULL;
airpe_interface_t *airpe = NULL;
- char msg[SKYPE_MSG_LEN];
channel = switch_core_session_get_channel(session);
assert(channel);
@@ -325,13 +310,11 @@
assert(airpe);
if ( airpe->active_call_id ) {
- snprintf(msg, sizeof(msg), "ALTER CALL %d HANGUP", airpe->active_call_id);
- airpe_cmd_write(airpe, msg);
-// airpe->active_call_id = 0;
-// airpe->tech_pvt = NULL;
+ char buf[SKYPE_MSG_LEN];
+ snprintf(buf, sizeof(buf), "ALTER CALL %d HANGUP", airpe->active_call_id);
+ airpe_cmd_write(airpe, buf);
}
-
- airpe_hangup( tech_pvt );
+ airpe_call_shutdown( tech_pvt );
if (tech_pvt->read_codec.implementation) {
switch_core_codec_destroy(&tech_pvt->read_codec);
@@ -351,6 +334,7 @@
/*****************************************************************************
CHANNEL IO INTERFACE / ROUTINES
*****************************************************************************/
+
static switch_call_cause_t channel_outgoing_channel(
switch_core_session_t *session,
switch_event_t *var_event,
@@ -422,9 +406,9 @@
switch_core_session_destroy(new_session);
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
}
-
- switch_channel_set_flag(channel, CF_OUTBOUND);
- switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
+ airpe_set_call_id(tech_pvt->airpe, 0, switch_core_session_get_uuid(*new_session) );
+ switch_channel_set_flag(channel, CF_OUTBOUND);
+ switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
return SWITCH_CAUSE_SUCCESS;
}
@@ -453,7 +437,10 @@
*frame = NULL;
if ( airpe_audio_read(tech_pvt) != SWITCH_STATUS_SUCCESS) {
- ADEBUG("airpe_audio_read ERROR\n");
+/*
+ if ( tech_pvt->airpe->debug )
+ ADEBUG("airpe_audio_read ERROR\n");
+*/
return SWITCH_STATUS_FALSE;
}
@@ -492,12 +479,19 @@
assert(tech_pvt);
if ( !tech_pvt->airpe ) {
+ ADEBUG("airpe_audio_write ERROR: no client\n");
return SWITCH_STATUS_FALSE;
}
airpe = tech_pvt->airpe;
rv = airpe_audio_write(tech_pvt, frame);
+
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ ADEBUG("airpe_audio_write ERROR\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
return rv;
}
@@ -546,6 +540,7 @@
{
switch_channel_t *channel;
private_object_t *tech_pvt;
+ airpe_interface_t *airpe;
channel = switch_core_session_get_channel(session);
assert(channel);
@@ -553,30 +548,57 @@
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
assert(tech_pvt);
+ airpe = tech_pvt->airpe;
+ assert(airpe);
+
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_ANSWER:
- ADEBUG("received message indicate answer...\n");
/*
- //switch_answer_channel(session);
- char buf[SKYPE_MSG_LEN];
- snprintf(buf, sizeof(buf), "ALTER CALL %d ANSWER", tech_pvt->airpe->active_call_id );
- airpe_cmd_write(tech_pvt->airpe, buf);
+ if ( airpe->debug )
+ ADEBUG("received message indicate answer...\n");
*/
+ if ( switch_test_flag(tech_pvt, TFLAG_INBOUND) ) {
+ char buf[SKYPE_MSG_LEN];
+ snprintf(buf, sizeof(buf), "ALTER CALL %d ANSWER\n", tech_pvt->airpe->active_call_id );
+ airpe_cmd_write(tech_pvt->airpe, buf);
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_INPUT PORT=\"%d\"", tech_pvt->airpe->active_call_id, tech_pvt->airpe->audio_in_port);
+ airpe_cmd_write(tech_pvt->airpe, buf);
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_OUTPUT PORT=\"%d\"", tech_pvt->airpe->active_call_id, tech_pvt->airpe->audio_out_port);
+ airpe_cmd_write(tech_pvt->airpe, buf);
+ switch_set_flag(tech_pvt, TFLAG_IO);
+ }
+ break;
+/*
+ case SWITCH_MESSAGE_INDICATE_PROGRESS:
+ if ( airpe->debug )
+ ADEBUG("received message indicate progress...\n");
+ break;
+ case SWITCH_MESSAGE_INDICATE_BRIDGE:
+ if ( airpe->debug )
+ ADEBUG("received message indicate bridge...\n");
break;
case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
- ADEBUG("received message indicate unbridge...\n");
+ if ( airpe->debug )
+ ADEBUG("received message indicate unbridge...\n");
break;
case SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY:
- ADEBUG("received message indicate transcode necessary...\n");
+ if ( airpe->debug )
+ ADEBUG("received message indicate transcode necessary...\n");
break;
case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC:
- ADEBUG("received message indicate audio sync...\n");
+ if ( airpe->debug )
+ ADEBUG("received message indicate audio sync...\n");
break;
case SWITCH_MESSAGE_INDICATE_TRANSFER:
- ADEBUG("received message indicate transfer...\n");
+ if ( airpe->debug )
+ ADEBUG("received message indicate transfer...\n");
break;
+*/
default:
- ADEBUG("Unmanaged received message... %d\n", msg->message_id);
+/*
+ if ( airpe->debug )
+ ADEBUG("Unmanaged received message... %d\n", msg->message_id);
+*/
break;
}
@@ -596,7 +618,6 @@
assert(tech_pvt);
body = switch_event_get_body(event);
-
if (!body) {
body = "";
}
Modified: freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
==============================================================================
--- freeswitch/branches/ctrix/mod_airpe/mod_airpe.h (original)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.h Wed Jan 14 15:05:23 2009
@@ -112,15 +112,15 @@
typedef enum {
TFLAG_INBOUND = (1 << 1),
TFLAG_OUTBOUND = (1 << 2),
+ TFLAG_IO = (1 << 3),
/*
- TFLAG_IO = (1 << 0),
- TFLAG_DTMF = (1 << 3),
TFLAG_VOICE = (1 << 4),
- TFLAG_HANGUP = (1 << 5),
- TFLAG_LINEAR = (1 << 6),
- TFLAG_CODEC = (1 << 7),
- TFLAG_BREAK = (1 << 8),
- TFLAG_ANSWER = (1 << 9)
+ TFLAG_DTMF = (1 << 5),
+ TFLAG_HANGUP = (1 << 6),
+ TFLAG_LINEAR = (1 << 7),
+ TFLAG_CODEC = (1 << 8),
+ TFLAG_BREAK = (1 << 9),
+ TFLAG_ANSWER = (1 <<10)
*/
} TFLAGS;
@@ -157,6 +157,7 @@
char *skype_version;
char *mood_text;
int active_call_id;
+ char *active_session_uuid;
int last_fail_reason;
int running;
private_object_t *tech_pvt;
@@ -202,8 +203,9 @@
switch_status_t airpe_set_mood_text(airpe_interface_t *airpe, char *string);
switch_status_t airpe_set_partner_displayname(airpe_interface_t *airpe, char *string);
switch_status_t airpe_set_partner_handle(airpe_interface_t *airpe, char *string);
+switch_status_t airpe_set_call_id(airpe_interface_t *airpe, int sk_id, char *fs_uuid);
-switch_status_t airpe_hangup( private_object_t *pvt );
+switch_status_t airpe_call_shutdown( private_object_t *pvt );
switch_status_t airpe_audio_read( private_object_t *pvt );
switch_status_t airpe_audio_write( private_object_t *pvt, switch_frame_t *frame );
1
0
[commit] r11159 - in freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax: . configs
by FreeSWITCH SVN 13 Jan '09
by FreeSWITCH SVN 13 Jan '09
13 Jan '09
Author: gmaruzz
Date: Tue Jan 13 06:40:46 2009
New Revision: 11159
Log:
skypiax: added Xserver (Xvfb) authorization file
Added:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/skypiax.X.conf
Modified:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.sh
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README Tue Jan 13 06:40:46 2009
@@ -131,6 +131,9 @@
root@8-04-srv:~/freeswitch_gmaruzz# cp src/mod/endpoints/mod_skypiax/configs/startskype.sh ./
root@8-04-srv:~/freeswitch_gmaruzz# vi startskype.sh
+**** let's copy the X servers' auth config file
+root@8-04-srv:~/freeswitch_gmaruzz#cp src/mod/endpoints/mod_skypiax/configs/skypiax.X.conf /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf
+
**** start the X servers and the Skype clients
root@8-04-srv:~/freeswitch_gmaruzz# sh ./startskype.sh
Added: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/skypiax.X.conf
==============================================================================
--- (empty file)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/skypiax.X.conf Tue Jan 13 06:40:46 2009
@@ -0,0 +1 @@
+localhost
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.sh
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.sh (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.sh Tue Jan 13 06:40:46 2009
@@ -8,14 +8,14 @@
sleep 3
#start the fake X server on a given port
-/usr/bin/Xvfb :101 &
+/usr/bin/Xvfb :101 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
sleep 3
# start a Skype client instance that will connect to the X server above, and will login to the Skype network using the "username password" you send to it on stdin. Here xxx would be the password and skypiax1 the username
echo "skypiax1 xxx"| DISPLAY=:101 /usr/bin/skype --pipelogin &
sleep 7
-/usr/bin/Xvfb :102 &
+/usr/bin/Xvfb :102 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
sleep 3
echo "skypiax2 xxx"| DISPLAY=:102 /usr/bin/skype --pipelogin &
@@ -25,109 +25,109 @@
#################################################################
# Following X server Skype client instances are commented out
#################################################################
-###/usr/bin/Xvfb :103 &
+###/usr/bin/Xvfb :103 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax3 xxx"| DISPLAY=:103 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :104 &
+###/usr/bin/Xvfb :104 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax4 xxx"| DISPLAY=:104 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :105 &
+###/usr/bin/Xvfb :105 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax5 xxx"| DISPLAY=:105 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :106 &
+###/usr/bin/Xvfb :106 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax6 xxx"| DISPLAY=:106 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :107 &
+###/usr/bin/Xvfb :107 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax7 xxx"| DISPLAY=:107 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :108 &
+###/usr/bin/Xvfb :108 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax8 xxx"| DISPLAY=:108 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :109 &
+###/usr/bin/Xvfb :109 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax9 xxx"| DISPLAY=:109 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :110 &
+###/usr/bin/Xvfb :110 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax10 xxx"| DISPLAY=:110 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :111 &
+###/usr/bin/Xvfb :111 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax11 xxx"| DISPLAY=:111 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :112 &
+###/usr/bin/Xvfb :112 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax12 xxx"| DISPLAY=:112 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :113 &
+###/usr/bin/Xvfb :113 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax13 xxx"| DISPLAY=:113 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :114 &
+###/usr/bin/Xvfb :114 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax14 xxx"| DISPLAY=:114 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :115 &
+###/usr/bin/Xvfb :115 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax15 xxx"| DISPLAY=:115 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :116 &
+###/usr/bin/Xvfb :116 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax16 xxx"| DISPLAY=:116 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :117 &
+###/usr/bin/Xvfb :117 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax17 xxx"| DISPLAY=:117 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :118 &
+###/usr/bin/Xvfb :118 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax18 xxx"| DISPLAY=:118 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :119 &
+###/usr/bin/Xvfb :119 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax19 xxx"| DISPLAY=:119 /usr/bin/skype --pipelogin &
###
###sleep 7
-###/usr/bin/Xvfb :120 &
+###/usr/bin/Xvfb :120 -auth /usr/local/freeswitch/conf/autoload_configs/skypiax.X.conf &
###sleep 3
###
###echo "skypiax20 xxx"| DISPLAY=:120 /usr/bin/skype --pipelogin &
1
0
[commit] r11158 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs
by FreeSWITCH SVN 13 Jan '09
by FreeSWITCH SVN 13 Jan '09
13 Jan '09
Author: gmaruzz
Date: Tue Jan 13 03:55:53 2009
New Revision: 11158
Log:
docs
Modified:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/README.skypiax_auth
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/README.skypiax_auth
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/README.skypiax_auth (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/README.skypiax_auth Tue Jan 13 03:55:53 2009
@@ -11,23 +11,19 @@
Then:
-1) Start the Skype client on a desktop linux machine, logout from your autologin username if any, and login with the username and password you want to use for skypiax
-
-2) Configure the Skype client to use the right audio devices, to not update, to not make "events", etc etc...
-
-3) Then, when satisfied, use skypiax_auth (that simulates FS-skypiax connecting to the Skype client). The Skype client will ask you to be authorized to let "skypiax" connect.
-
+1) on a Linux desktop machine, rmmod all the snd* modules
+2) on the desktop machine, modprobe snd-dummy
+3) on the desktop machine, logout from your autologin username if any, launch the Skype client and login as the username you'll use on server
+4) on the desktop machine, set the desktop client to use the "hw:dummy" audio device, to not update, to not make "events", etc etc... Make and receive a couple of test calls. Please note that you (and the remote party) will hear nothing (you're using the snd-dummy "fake" audio driver), that's ok.
+3) on the desktop machine, when satisfied of the Skype client setup, use skypiax_auth (that simulates FS-skypiax connecting to the Skype client). The Skype client will ask you to be authorized to let "skypiax" connect.
4) Give the authorization and check the "not ask me again" option.
-
5) Close (Quit) the Skype client from the tray icon, so it saves its config.
-
6) Then, relaunch the Skype client and use skypiax_auth again, just to be sure it now succeed.
-
7) Close (Quit) the Skype client from the tray icon, so it saves its config.
*** Do the steps 1-7 for all Skype usernames you will want to use on the server (eg: one Skype username per channel)
-When finished wityh all the Skype usernames:
+When finished with all the Skype usernames:
Copy or targzip the .Skype directory and all its content on the home directory of the server user that will launch the Skype client(s).
############################
1
0
Author: ctrix
Date: Mon Jan 12 17:26:39 2009
New Revision: 11154
Log:
Ohhh and empty docs are important, as well as the Makefile.
Added:
freeswitch/branches/ctrix/mod_airpe/INSTALL
freeswitch/branches/ctrix/mod_airpe/Makefile
freeswitch/branches/ctrix/mod_airpe/README
Added: freeswitch/branches/ctrix/mod_airpe/INSTALL
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/INSTALL Mon Jan 12 17:26:39 2009
@@ -0,0 +1,2 @@
+
+Nothing to read here as well.
Added: freeswitch/branches/ctrix/mod_airpe/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/Makefile Mon Jan 12 17:26:39 2009
@@ -0,0 +1,11 @@
+BASE=../../../..
+
+MODNAME=mod_airpe
+
+LOCAL_LDFLAGS=-lX11
+LOCAL_OBJS=airpe_if_common.o airpe_api.o airpe_apps.o airpe_if_x11.o airpe_if_osx.o airpe_if_win32.o
+LOCAL_SOURCES=airpe_if_common.c airpe_api.c airpe_apps.c airpe_if_x11.c airpe_if_osx.c airpe_if_win32.c
+
+include ../../../../build/modmake.rules
+
+
Added: freeswitch/branches/ctrix/mod_airpe/README
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/README Mon Jan 12 17:26:39 2009
@@ -0,0 +1,2 @@
+
+Nothing to read, sorry
1
0
12 Jan '09
Author: ctrix
Date: Mon Jan 12 17:24:44 2009
New Revision: 11153
Log:
Initial import of airpe...
Not yet fully working, don't expect too much.
Added:
freeswitch/branches/ctrix/mod_airpe/airpe_api.c
freeswitch/branches/ctrix/mod_airpe/airpe_apps.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_osx.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_win32.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c
freeswitch/branches/ctrix/mod_airpe/config/
freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml
freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
Added: freeswitch/branches/ctrix/mod_airpe/airpe_api.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_api.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,262 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#include "mod_airpe.h"
+
+#define AIRPE_MOODTEXT_SYNTAX "airpe_moodtext <clientname> <text>"
+SWITCH_STANDARD_API(airpe_moodtext_command)
+{
+ int argc = 0;
+ char *argv[2] = { 0 };
+ char *mycmd = NULL;
+ char *client = NULL;
+ airpe_interface_t *airpe = NULL;
+
+ if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+ argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+ switch_assert(argv[0]);
+ }
+
+ if ( argc < 1 ) {
+ stream->write_function(stream, "-USAGE: %s\n", AIRPE_MOODTEXT_SYNTAX);
+ goto done;
+ }
+
+ client = argv[0];
+ airpe = airpe_find_interface(client);
+
+ if ( !airpe ) {
+ stream->write_function(stream, "-ERR interface not found for client ");
+ stream->write_function(stream, client);
+ stream->write_function(stream, "\n");
+ goto done;
+ }
+
+ if ( argc == 1 ) {
+ stream->write_function(stream, "+OK: ");
+ if ( airpe->mood_text )
+ stream->write_function(stream, airpe->mood_text);
+ else
+ stream->write_function(stream, "UNKNOWN");
+ stream->write_function(stream, "\n");
+ }
+ else {
+ if ( airpe_set_mood_text(airpe, argv[1]) != SWITCH_STATUS_SUCCESS ) {
+ stream->write_function(stream, "-ERR cannot send message to the client\n");
+ goto done;
+ }
+ else {
+ char buf[SKYPE_MSG_LEN];
+ snprintf(buf, SKYPE_MSG_LEN, "SET PROFILE MOOD_TEXT %s", airpe->mood_text );
+ airpe_cmd_write(airpe, buf);
+ }
+ stream->write_function(stream, "+OK mood_text set.\n");
+ }
+
+ done:
+ return SWITCH_STATUS_SUCCESS;
+}
+
+#define AIRPE_INFO_SYNTAX "airpe_status <clientname>"
+SWITCH_STANDARD_API(airpe_info_command)
+{
+ int argc = 0;
+ char *argv[4] = { 0 };
+ char *mycmd = NULL;
+ char *client = NULL;
+ char buf[512];
+ airpe_interface_t *airpe = NULL;
+
+ if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+ argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+ switch_assert(argv[0]);
+ }
+
+ if ( argc < 1 ) {
+ stream->write_function(stream, "-USAGE: %s\n", AIRPE_INFO_SYNTAX);
+ goto done;
+ }
+
+ client = argv[0];
+ airpe = airpe_find_interface(client);
+
+ if ( !airpe ) {
+ stream->write_function(stream, "-ERR interface not found for client ");
+ stream->write_function(stream, client);
+ stream->write_function(stream, "\n");
+ goto done;
+ }
+
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Client name", airpe->name);
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Dialplan", airpe->dialplan);
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Context", airpe->context);
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Destination", airpe->destination);
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Skype username", airpe->skype_user);
+ stream->write_function(stream, buf);
+ if ( airpe->audio_in_port > 0 )
+ switch_snprintf(buf, sizeof(buf), "%-20s: %d\n", "Audio in port", airpe->audio_in_port);
+ else
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Audio in port", "NOT SET");
+ stream->write_function(stream, buf);
+ if ( airpe->audio_in_port > 0 )
+ switch_snprintf(buf, sizeof(buf), "%-20s: %d\n", "Audio out port", airpe->audio_out_port);
+ else
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Audio out port", "NOT SET");
+ stream->write_function(stream, buf);
+
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Connection status", skype_conn_status_string(airpe->conn_status) );
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Client status", skype_user_status_string(airpe->user_status) );
+ stream->write_function(stream, buf);
+
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Skype version", (airpe->skype_version) ? airpe->skype_version : "Unknown" );
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Mood text", (airpe->mood_text ) ? airpe->mood_text : "Unknown" );
+ stream->write_function(stream, buf);
+
+ done:
+ return SWITCH_STATUS_SUCCESS;
+}
+
+#define AIRPE_STATUS_SYNTAX "airpe_status <clientname> <status>"
+SWITCH_STANDARD_API(airpe_status_command)
+{
+ int argc = 0;
+ char *argv[4] = { 0 };
+ char *mycmd = NULL;
+ char *client = NULL;
+ char *cstatus= NULL;
+ airpe_interface_t *airpe = NULL;
+
+ if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+ argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+ switch_assert(argv[0]);
+ }
+
+ if ( argc < 1 ) {
+ stream->write_function(stream, "-USAGE: %s\n", AIRPE_STATUS_SYNTAX);
+ goto done;
+ }
+
+ client = argv[0];
+ if ( argc > 1 )
+ cstatus = argv[1];
+
+ airpe = airpe_find_interface(client);
+
+ if ( !airpe ) {
+ stream->write_function(stream, "-ERR interface not found: \n");
+ stream->write_function(stream, client);
+ stream->write_function(stream, "\n");
+ goto done;
+ }
+
+ if ( !cstatus ) {
+ const char *str_status = NULL;
+ str_status = skype_user_status_string( airpe->user_status );
+ stream->write_function(stream, "+OK status is ");
+ if ( str_status )
+ stream->write_function(stream, str_status);
+ else
+ stream->write_function(stream, "... uhmmm, ehmm, DUNNO... ");
+ stream->write_function(stream, "\n");
+ }
+ else {
+ char buf[SKYPE_MSG_LEN];
+ const char *str_status = NULL;
+
+ if ( !strncasecmp(cstatus, "unknown", sizeof("unknown") ) )
+ str_status = skype_user_status_string(USER_STATUS_UNKNOWN);
+ else if ( !strncasecmp(cstatus, "online", sizeof("online") ) )
+ str_status = skype_user_status_string(USER_STATUS_ONLINE);
+ else if ( !strncasecmp(cstatus, "offline", sizeof("offline") ) )
+ str_status = skype_user_status_string(USER_STATUS_OFFLINE);
+ else if ( !strncasecmp(cstatus, "skypeme", sizeof("skypeme") ) )
+ str_status = skype_user_status_string(USER_STATUS_SKYPEME);
+ else if ( !strncasecmp(cstatus, "away", sizeof("away") ) )
+ str_status = skype_user_status_string(USER_STATUS_AWAY);
+ else if ( !strncasecmp(cstatus, "na", sizeof("na") ) )
+ str_status = skype_user_status_string(USER_STATUS_NA);
+ else if ( !strncasecmp(cstatus, "dnd", sizeof("dnd") ) )
+ str_status = skype_user_status_string(USER_STATUS_DND);
+ else if ( !strncasecmp(cstatus, "invisible", sizeof("invisible") ) )
+ str_status = skype_user_status_string(USER_STATUS_INVISIBLE);
+ else if ( !strncasecmp(cstatus, "loggedout", sizeof("loggedout") ) )
+ str_status = skype_user_status_string(USER_STATUS_LOGGEDOUT);
+
+ if ( str_status ) {
+ snprintf(buf, SKYPE_MSG_LEN, "SET USERSTATUS %s", cstatus );
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS ) {
+ stream->write_function(stream, "-ERR cannot send message to the client\n");
+ goto done;
+ }
+ stream->write_function(stream, "+OK status set.\n");
+ }
+ else {
+ stream->write_function(stream, "-ERR invalid status string\n");
+ }
+ }
+
+ done:
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+
+switch_status_t airpe_register_api( switch_loadable_module_interface_t **module_interface ) {
+
+ switch_api_interface_t *api;
+
+ switch_console_set_complete("add airpe_moodtext ");
+ SWITCH_ADD_API(api, "airpe_moodtext", "sets the mood text of an airpe client", airpe_moodtext_command, AIRPE_MOODTEXT_SYNTAX);
+
+ switch_console_set_complete("add airpe_info ");
+ SWITCH_ADD_API(api, "airpe_info", "shows the status of an airpe client", airpe_info_command, AIRPE_INFO_SYNTAX);
+
+ switch_console_set_complete("add airpe_status ");
+ SWITCH_ADD_API(api, "airpe_status", "sets the status of an airpe client", airpe_status_command, AIRPE_STATUS_SYNTAX);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/airpe_apps.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_apps.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,56 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#include "mod_airpe.h"
+
+SWITCH_STANDARD_APP(airpe_app_test)
+{
+}
+
+
+switch_status_t airpe_register_apps( switch_loadable_module_interface_t **module_interface ) {
+ switch_application_interface_t *app_interface;
+
+ SWITCH_ADD_APP(app_interface, "airpe_test", "test text", "test text", airpe_app_test, "", SAF_SUPPORT_NOMEDIA);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* 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:
+ */
+
Added: freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,770 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#include "mod_airpe.h"
+
+static struct {
+ USER_STATUS status;
+ const char *name;
+} user_status_names[] = {
+ { USER_STATUS_UNKNOWN, "UNKNOWN" },
+ { USER_STATUS_ONLINE, "ONLINE" },
+ { USER_STATUS_OFFLINE, "OFFLINE" },
+ { USER_STATUS_SKYPEME, "SKYPEME" },
+ { USER_STATUS_AWAY, "AWAY" },
+ { USER_STATUS_NA, "NA" },
+ { USER_STATUS_DND, "DND" },
+ { USER_STATUS_INVISIBLE, "INVISIBLE" },
+ { USER_STATUS_LOGGEDOUT, "LOGGEDOUT" },
+};
+
+static struct {
+ CONN_STATUS status;
+ const char *name;
+} connection_status_names[] = {
+ { CONN_STATUS_UNKNOWN, "UNKNOWN" },
+ { CONN_STATUS_OFFLINE, "OFFLINE" },
+ { CONN_STATUS_CONNECTING, "CONNECTING" },
+ { CONN_STATUS_PAUSING, "PAUSING" },
+ { CONN_STATUS_ONLINE, "ONLINE" },
+};
+
+/* ************************************************************************* */
+
+const char *skype_user_status_string(USER_STATUS st) {
+ int t;
+ const char *ret = NULL;
+
+ for ( t = 0; t < sizeof(user_status_names) / sizeof(user_status_names[0]); t++ ) {
+ if ( user_status_names[t].status == st ) {
+ ret = user_status_names[t].name;
+ break;
+ }
+ }
+ return ret;
+}
+
+USER_STATUS skype_user_status(const char *str) {
+ int t;
+ USER_STATUS ret = USER_STATUS_UNKNOWN;
+
+ for ( t = 0; t < sizeof(user_status_names) / sizeof(user_status_names[0]); t++ ) {
+ if ( !strncasecmp(user_status_names[t].name, str, strlen(user_status_names[t].name) ) ) {
+ ret = user_status_names[t].status;
+ break;
+ }
+ }
+ return ret;
+}
+
+/* ************************************************************************* */
+
+const char *skype_conn_status_string(CONN_STATUS st) {
+ int t;
+ const char *ret = NULL;
+
+ for ( t = 0; t < sizeof(connection_status_names) / sizeof(connection_status_names[0]); t++ ) {
+ if ( connection_status_names[t].status == st ) {
+ ret = connection_status_names[t].name;
+ break;
+ }
+ }
+ return ret;
+}
+
+CONN_STATUS skype_conn_status(const char *str) {
+ int t;
+ CONN_STATUS ret = CONN_STATUS_UNKNOWN;
+
+ for ( t = 0; t < sizeof(connection_status_names) / sizeof(connection_status_names[0]); t++ ) {
+ if ( !strncasecmp(connection_status_names[t].name, str, strlen(connection_status_names[t].name) ) ) {
+ ret = connection_status_names[t].status;
+ break;
+ }
+ }
+ return ret;
+}
+
+/* ************************************************************************* */
+
+switch_status_t airpe_set_version(airpe_interface_t *airpe, char *string) {
+ assert(airpe);
+ switch_safe_free(airpe->skype_version);
+ if ( string )
+ airpe->skype_version = strdup(string);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_set_mood_text(airpe_interface_t *airpe, char *string) {
+ assert(airpe);
+ switch_safe_free(airpe->mood_text);
+ if ( string )
+ airpe->mood_text = strdup(string);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_set_partner_displayname(airpe_interface_t *airpe, char *string) {
+ assert(airpe);
+ switch_safe_free(airpe->partner_displayname);
+ if ( string )
+ airpe->partner_displayname = strdup(string);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_set_partner_handle(airpe_interface_t *airpe, char *string) {
+ assert(airpe);
+ switch_safe_free(airpe->partner_handle);
+ if ( string )
+ airpe->partner_handle = strdup(string);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_cmd_write(airpe_interface_t *airpe, char *msg) {
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "msg to airpe client %s: %s\n", airpe->name, msg);
+ return airpe_skype_send_message(airpe->skype_window, msg);
+}
+
+switch_status_t airpe_originate(airpe_interface_t *airpe, char *dest) {
+ char msg[SKYPE_MSG_LEN];
+
+ /*
+ Those commands are outdated and shouldn't be used
+ Documented so that no one adds them.
+ airpe_cmd_write(p, "SET AGC OFF");
+ airpe_cmd_write(p, "SET AEC OFF");
+ */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: Originating to %s\n", airpe->name, dest);
+
+ snprintf(msg, sizeof(msg), "CALL %s", dest);
+
+ if ( (airpe_cmd_write(airpe, msg) != SWITCH_STATUS_SUCCESS) ) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_explicit_hangup(airpe_interface_t *airpe) {
+ char buf[SKYPE_MSG_LEN];
+
+ if ( airpe->active_call_id > 0 ) {
+ snprintf(buf, sizeof(buf), "SET CALL %d STATUS FINISHED", airpe->active_call_id);
+ return airpe_cmd_write(airpe, buf);
+ }
+ return SWITCH_STATUS_FALSE;
+}
+
+
+
+/*****************************************************************************
+ SKYPE AUDIO
+ *****************************************************************************/
+
+switch_status_t airpe_hangup( private_object_t *pvt ) {
+ airpe_interface_t *airpe;
+
+ assert(pvt);
+ assert(pvt->session);
+ assert(pvt->airpe);
+
+ airpe = pvt->airpe;
+
+ if ( airpe->audio_in_active_socket ) {
+ switch_socket_shutdown(airpe->audio_in_active_socket, SWITCH_SHUTDOWN_READWRITE);
+ switch_socket_close(airpe->audio_in_active_socket);
+ airpe->audio_in_active_socket = 0;
+ }
+
+ if ( airpe->audio_out_active_socket ) {
+ switch_socket_shutdown(airpe->audio_out_active_socket, SWITCH_SHUTDOWN_READWRITE);
+ switch_socket_close(airpe->audio_out_active_socket);
+ airpe->audio_out_active_socket = 0;
+ }
+
+ airpe->tech_pvt = NULL;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_audio_write( private_object_t *pvt, switch_frame_t *frame ) {
+ switch_socket_t *inbound_socket = NULL;
+ switch_memory_pool_t *pool;
+ airpe_interface_t *airpe;
+ switch_status_t rv;
+ switch_size_t mlen;
+ char *mbuf;
+
+ assert(pvt);
+ assert(pvt->session);
+ assert(pvt->airpe);
+
+ airpe = pvt->airpe;
+ pool = switch_core_session_get_pool(pvt->session);
+
+ if ( !airpe->audio_in_active_socket ) {
+ rv = switch_socket_accept(&inbound_socket, airpe->audio_in_socket, pool);
+ if ( rv == SWITCH_STATUS_SUCCESS ) {
+ airpe->audio_in_active_socket = inbound_socket;
+ switch_sleep(100000);
+ }
+ else {
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ mbuf = frame->data;
+ mlen = frame->datalen;
+ rv = switch_socket_send(airpe->audio_in_active_socket, mbuf, &mlen);
+
+ return rv;
+}
+
+switch_status_t airpe_audio_read( private_object_t *pvt ) {
+ switch_socket_t *inbound_socket = NULL;
+ switch_memory_pool_t *pool;
+ airpe_interface_t *airpe;
+ switch_status_t rv;
+ switch_size_t mlen;
+ char *ptr;
+
+ assert(pvt);
+ assert(pvt->session);
+ assert(pvt->airpe);
+
+ airpe = pvt->airpe;
+ pool = switch_core_session_get_pool(pvt->session);
+
+ if ( !airpe->audio_out_active_socket ) {
+ rv = switch_socket_accept(&inbound_socket, airpe->audio_out_socket, pool);
+ if ( rv == SWITCH_STATUS_SUCCESS ) {
+ airpe->audio_out_active_socket = inbound_socket;
+ switch_sleep(100000);
+ }
+ else {
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ pvt->read_frame.datalen = 0;
+ ptr = pvt->read_frame.data;
+ mlen = sizeof(pvt->databuf);
+ rv = switch_socket_recv(airpe->audio_out_active_socket, ptr, &mlen);
+
+ if ( (rv==SWITCH_STATUS_SUCCESS) ) {
+ pvt->read_frame.datalen = mlen;
+ }
+// if ( mlen == 0 )
+// return SWITCH_STATUS_SUCCESS;
+
+ return rv;
+}
+
+/*****************************************************************************
+ SKYPE CONTROL MESSAGES
+ *****************************************************************************/
+
+static switch_status_t airpe_manage_incoming_call( airpe_interface_t *airpe, int callid ) {
+ char chan_name[256];
+ switch_channel_t *channel = NULL;
+ switch_core_session_t *new_session = NULL;
+ private_object_t *tech_pvt = NULL;
+
+ new_session = airpe_request_session(NULL);
+ if ( !new_session ) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ switch_core_session_add_stream(new_session, NULL);
+
+ tech_pvt = (private_object_t *) switch_core_session_alloc(new_session, sizeof(private_object_t));
+ if ( !tech_pvt ) {
+ switch_core_session_destroy(&new_session);
+ return SWITCH_STATUS_FALSE;
+ }
+ memset(tech_pvt, 0, sizeof(private_object_t));
+
+ channel = switch_core_session_get_channel(new_session);
+ assert(channel);
+
+ if ( airpe_tech_init(tech_pvt, new_session) != SWITCH_STATUS_SUCCESS ) {
+ switch_core_session_destroy(&new_session);
+ return SWITCH_STATUS_FALSE;
+ }
+ tech_pvt->airpe = airpe;
+
+ switch_snprintf(chan_name, sizeof(chan_name), MODNAME"/%s", airpe->name);
+ switch_channel_set_name(channel, chan_name);
+
+ tech_pvt->caller_profile = switch_caller_profile_new( switch_core_session_get_pool(new_session),
+ airpe->name, /* Username */
+ airpe->dialplan, /* Diaplan */
+ airpe->partner_displayname, /* cid_name */
+ airpe->partner_handle, /* cid_number */
+ NULL, /* network_addr */
+ NULL, /* ani */
+ NULL, /* aniii */
+ NULL, /* rdnis */
+ MODNAME, /* source */
+ airpe->context, /* context */
+ airpe->destination /* destination_number */
+ );
+
+ if ( !tech_pvt->caller_profile ) {
+ switch_core_session_destroy(&new_session);
+ return SWITCH_STATUS_FALSE;
+ }
+ else
+ switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+
+
+ switch_set_flag(tech_pvt, TFLAG_INBOUND);
+ airpe->active_call_id = callid;
+ switch_channel_set_state(channel, CS_INIT);
+
+ if ( switch_core_session_thread_launch(new_session) != SWITCH_STATUS_SUCCESS ) {
+ airpe->active_call_id = 0;
+ switch_core_session_destroy(&new_session);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t airpe_manage_call_status( airpe_interface_t *airpe, int callid, const char *status ) {
+ char buf[SKYPE_MSG_LEN];
+ switch_core_session_t *session = NULL;
+ switch_channel_t *channel = NULL;
+
+ if ( airpe->active_call_id && airpe->active_call_id != callid ) {
+ADEBUG("CASE 1 - different call\n");
+ if ( !strncmp(status, "UNPLACED", strlen("UNPLACED")) ) {
+ snprintf(buf, sizeof(buf), "SET CALL %d STATUS FINISHED", callid);
+ airpe_cmd_write(airpe, buf);
+ }
+ else {
+ ADEBUG("*** (%d/%d) Unmanaged status %s\n", airpe->active_call_id, callid, status);
+ }
+
+ }
+ else if ( airpe->active_call_id && airpe->active_call_id == callid ) {
+ADEBUG("CASE 2 - my call\n");
+ if ( airpe->tech_pvt ) {
+ assert(airpe->tech_pvt);
+ session = airpe->tech_pvt->session;
+ assert(session);
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+ }
+
+ if ( !strncmp(status, "ROUTING", strlen("ROUTING")) ) {
+ }
+ else if ( !strncmp(status, "RINGING", strlen("RINGING")) ) {
+ //if ( switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ) {
+ //switch_channel_set_state(channel, CS_RINGING);
+ switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
+ switch_channel_mark_ring_ready(channel);
+ //}
+
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_INPUT PORT=\"%d\"", callid, airpe->audio_in_port);
+ airpe_cmd_write(airpe, buf);
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_OUTPUT PORT=\"%d\"", callid, airpe->audio_out_port);
+ airpe_cmd_write(airpe, buf);
+
+
+
+ switch_channel_set_state(channel, CS_ROUTING);
+
+ }
+ else if ( !strncmp(status, "INPROGRESS", strlen("INPROGRESS")) ) {
+ snprintf(buf, sizeof(buf), "ALTER CALL %d STOP_VIDEO_SEND", callid );
+ airpe_cmd_write(airpe, buf);
+ snprintf(buf, sizeof(buf), "ALTER CALL %d STOP_VIDEO_RECEIVE", callid );
+ airpe_cmd_write(airpe, buf);
+
+ if ( channel ) {
+ switch_channel_mark_answered(channel);
+ }
+ else {
+ if ( airpe_manage_incoming_call(airpe, callid) != SWITCH_STATUS_SUCCESS ) {
+ snprintf(buf, sizeof(buf), "ALTER CALL %d END HANGUP", callid );
+ airpe_cmd_write(airpe, buf);
+ airpe->active_call_id = 0;
+ }
+ }
+ }
+ else if ( !strncmp(status, "FINISHED", strlen("FINISHED")) ) {
+ if ( channel )
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ airpe->active_call_id = 0;
+ }
+ else if ( !strncmp(status, "FAILED", strlen("FAILED")) ) {
+ if ( channel )
+ switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ airpe->active_call_id = 0;
+ }
+ else if ( !strncmp(status, "CANCELLED", strlen("CANCELLED")) ) {
+ if ( channel )
+ switch_channel_hangup(channel, SWITCH_CAUSE_ORIGINATOR_CANCEL);
+ airpe->active_call_id = 0;
+ }
+ else if ( !strncmp(status, "REFUSED", strlen("REFUSED")) ) {
+ if ( channel )
+ switch_channel_hangup(channel, SWITCH_CAUSE_CALL_REJECTED);
+ airpe->active_call_id = 0;
+ }
+ else if ( !strncmp(status, "MISSED", strlen("MISSED")) ) {
+ if ( channel )
+ switch_channel_hangup(channel, SWITCH_CAUSE_NO_ANSWER);
+ airpe->active_call_id = 0;
+ }
+ else if ( !strncmp(status, "UNPLACED", strlen("UNPLACED")) ) {
+ }
+ else {
+ADEBUG("Unmanaged status \n");
+ }
+ }
+ else {
+ADEBUG("CASE 3 - no calls online\n");
+ if ( !strncmp(status, "UNPLACED", strlen("UNPLACED")) ) {
+ airpe->active_call_id = callid;
+ }
+ else if ( !strncmp(status, "RINGING", strlen("RINGING")) ) {
+ airpe->active_call_id = callid;
+ snprintf(buf, sizeof(buf), "ALTER CALL %d ANSWER", callid );
+ airpe_cmd_write(airpe, buf);
+ }
+ else {
+ ADEBUG("--- (%d/%d) Unmanaged status %s\n", airpe->active_call_id, callid, status);
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_manage_skype_msg( airpe_interface_t *airpe, const char *msg ) {
+ char *buf = NULL;
+ int argc = 0;
+ char *argv[9] = { 0 };
+
+ assert(airpe);
+ assert(msg);
+
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "airpe client %s: %s\n", airpe->name, msg);
+
+ buf = strdup(msg);
+ argc = switch_separate_string(buf, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+ if ( argc == 0 ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: %s - Message without arguments? uh?\n", airpe->name, msg);
+ free(buf);
+ return SWITCH_STATUS_FALSE;
+ }
+
+
+
+ if ( !strncmp( buf, "CURRENTUSERHANDLE", strlen("CURRENTUSERHANDLE")) ) {
+ /* The username that the client is using. */
+ // TODO ... if the user handle mismatches, disconnect the channel or simply disable
+ // all operations
+ }
+ else if ( !strncmp( buf, "USERSTATUS", strlen("USERSTATUS")) && argc > 1 ) {
+ /* The status of the user of the client (ex: NA, ONLINE) */
+ airpe->user_status = skype_user_status(argv[1]);
+ }
+ else if ( !strncmp( buf, "PROTOCOL", strlen("PROTOCOL")) && argc > 1 ) {
+ /* The protocol of the client */
+ airpe->protocol = atoi(argv[1]);
+ }
+ else if ( !strncmp( buf, "CLEAR", strlen("CLEAR")) ) {
+ /* something has been cleared in the UI - Ignored */
+ }
+ else if ( !strncmp( buf, "PONG", strlen("PONG")) ) {
+ /* keepalive */
+ airpe_skype_watchdog_reset(airpe->skype_window);
+ }
+ else if ( !strncmp( buf, "CONNSTATUS", strlen("CONNSTATUS")) && argc >= 2 ) {
+ /* The connection status of the client (ex: ONLINE) */
+ airpe->conn_status = skype_conn_status( argv[1] );
+ }
+ else if ( !strncmp( buf, "USER", strlen("USER")) ) {
+ /* Updates about the users of our list - ignored */
+ }
+ else if ( !strncmp( buf, "GROUP", strlen("GROUP")) ) {
+ /* Updates about the groups of our list - ignored */
+ }
+ else if ( !strncmp( buf, "CONTACTS", strlen("CONTACTS")) ) {
+ /* Other messages referring to the contact list - ignored */
+ }
+ else if ( !strncmp( buf, "OK", strlen("OK")) ) {
+ /* Acknowledge - ignored */
+ }
+ else if ( !strncmp( buf, "AUTOAWAY", strlen("AUTOAWAY")) ) {
+ /* Autoaway - ignored */
+ }
+//TODO: RECEIVEDAUTHREQUEST - Add a config option to authorize or forget about it.
+ else if ( !strncmp( buf, "MUTE", strlen("MUTE")) && argc >= 2 ) {
+ if ( !strncmp(argv[1], "ON", 2) ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: I don't like to be muted...\n", airpe->name);
+ airpe_cmd_write(airpe, "MUTE OFF");
+ }
+ }
+ else if ( !strncmp( buf, "CHATMESSAGE", strlen("CHATMESSAGE")) ) {
+ /* a message has been received (unknown content) - ignored */
+ }
+ else if ( !strncmp( buf, "CHAT", strlen("CHAT")) && argc >=2 ) {
+ /* Chat status - ignored. */
+ if ( airpe->protocol > 6 ) {
+ //TODO : ALTER CHAT <chat_id> DISBAND - Doesn't seems to work on linux
+ char buf[SKYPE_MSG_LEN] = "";
+ snprintf(buf, sizeof(buf), "ALTER CHAT %s DISBAND", argv[1]);
+ airpe_cmd_write(airpe, buf);
+ }
+ }
+ else if ( !strncmp( buf, "CHATMEMBER", strlen("CHATMEMBER")) ) {
+ /* Informations about the chat members - ignored */
+ }
+ else if ( !strncmp( buf, "PROFILE", strlen("PROFILE")) && argc >= 2 ) {
+ if ( !strncmp(argv[1], "MOOD_TEXT", strlen("MOOD_TEXT")) ) {
+ char *tmp = NULL;
+ char *mood;
+ tmp = strdup(msg);
+ if ( tmp ) {
+ mood = strstr(tmp, "PROFILE MOOD_TEXT ");
+ if ( mood ) {
+ mood += strlen("PROFILE MOOD_TEXT ");
+ airpe_set_mood_text(airpe, mood);
+ }
+ switch_safe_free(tmp);
+ }
+ }
+ }
+ else if ( !strncmp( buf, "SKYPEVERSION", strlen("SKYPEVERSION")) ) {
+ airpe_set_version(airpe, argv[1]);
+ }
+ else if ( !strncmp( buf, "CALL", strlen("CALL")) && argc >= 3 ) {
+ char *cmd = argv[2];
+ int callid = atoi(argv[1]);
+
+ if ( !strncmp(cmd, "DURATION", strlen("DURATION")) ) {
+ /* Ignore the duration that is updated every second */
+ if ( callid != airpe->active_call_id ) {
+ char buf[SKYPE_MSG_LEN] = "";
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: hanging up unknown call id %d\n", airpe->name, callid);
+ snprintf(buf, sizeof(buf), "SET CALL %d STATUS FINISHED", callid);
+ airpe_cmd_write(airpe, buf);
+ }
+ //TODO: maybe we could consider this message as a keepalive signal
+ }
+ else if ( !strncmp(cmd, "STATUS", strlen("STATUS")) && argc >=4 ) {
+ char *callstatus = argv[3];
+ airpe_manage_call_status( airpe, callid, callstatus );
+ }
+ else if ( !strncmp(cmd, "CONF_ID", strlen("CONF_ID")) ) {
+ char buf[SKYPE_MSG_LEN];
+
+ if ( !airpe->active_call_id ) {
+ airpe_set_partner_displayname(airpe, NULL);
+ airpe_set_partner_handle(airpe, NULL);
+
+ snprintf(buf, sizeof(buf), "GET CALL %d PARTNER_DISPNAME", callid);
+ airpe_cmd_write(airpe, buf);
+
+ snprintf(buf, sizeof(buf), "GET CALL %d PARTNER_HANDLE", callid);
+ airpe_cmd_write(airpe, buf);
+
+ airpe_cmd_write(airpe, "PING");
+ }
+ else {
+ snprintf(buf, sizeof(buf), "ALTER CALL %d END HANGUP", callid );
+ airpe_cmd_write(airpe, buf);
+ }
+ }
+ else if ( !strncmp(cmd, "VAA_INPUT_STATUS", strlen("VAA_INPUT_STATUS")) ) {
+ /* Let's ignore */
+ }
+ else if ( !strncmp(cmd, "DTMF", strlen("DTMF")) ) {
+ /* This is an incoming DTMF */
+ switch_core_session_t *session;
+ switch_channel_t *channel;
+ switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) };
+ const char *signal_ptr;
+ int tmp;
+
+ assert(airpe->tech_pvt);
+ session = airpe->tech_pvt->session;
+ assert(session);
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ signal_ptr = argv[3];
+
+ if (*signal_ptr && (*signal_ptr == '*' || *signal_ptr == '#' || *signal_ptr == 'A' || *signal_ptr == 'B' || *signal_ptr == 'C' || *signal_ptr == 'D')) {
+ dtmf.digit = *signal_ptr;
+ } else {
+ tmp = atoi(signal_ptr);
+ dtmf.digit = switch_rfc2833_to_char(tmp);
+ }
+
+ switch_mutex_lock(airpe->tech_pvt->flag_mutex);
+ switch_channel_queue_dtmf(channel, &dtmf);
+ switch_mutex_unlock(airpe->tech_pvt->flag_mutex);
+ }
+ else if ( !strncmp(cmd, "FAILUREREASON", strlen("FAILUREREASON")) && argc >=2 ) {
+ airpe->last_fail_reason = atoi(argv[1]);
+ airpe_cmd_write(airpe, "CLEAR CALLHISTORY ALL");
+ }
+ else if ( !strncmp(cmd, "SEEN", strlen("SEEN")) && argc >=4 ) {
+ /*
+ char buf[SKYPE_MSG_LEN] = "";
+ char *seenstatus = argv[3];
+ if ( !strncmp(seenstatus, "FALSE", strlen("FALSE")) ) {
+ snprintf(buf, sizeof(buf), "SET CALL %d SEEN", callid);
+ airpe_cmd_write(airpe, buf);
+ }
+ */
+ airpe_cmd_write(airpe, "CLEAR CALLHISTORY ALL");
+ }
+ else if ( !strncmp(cmd, "PARTNER_DISPNAME", strlen("PARTNER_DISPNAME")) && argc >=2 ) {
+ char *data, *tmp = NULL;
+ tmp = strdup(msg);
+ if ( tmp && (callid == airpe->active_call_id) ) {
+ data = strstr(tmp, "PARTNER_DISPNAME ");
+ if ( data ) {
+ data += strlen("PARTNER_DISPNAME ");
+ airpe_set_partner_displayname(airpe, data);
+ }
+ }
+ switch_safe_free(tmp);
+ }
+ else if ( !strncmp(cmd, "PARTNER_HANDLE", strlen("PARTNER_HANDLE")) && argc >=2 ) {
+ char *data, *tmp = NULL;
+ tmp = strdup(msg);
+ if ( tmp && (callid == airpe->active_call_id) ) {
+ data = strstr(tmp, "PARTNER_HANDLE ");
+ if ( data ) {
+ data += strlen("PARTNER_HANDLE ");
+ airpe_set_partner_handle(airpe, data);
+ }
+ switch_safe_free(tmp);
+ }
+ }
+ else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CALL ID %d\n", callid);
+ }
+ }
+ else if ( !strncmp( buf, "DTMF", strlen("DTMF")) && argc>3 ) {
+ /* We are alerted that a DTMF we was sent to the other party - Ignored */
+ }
+ else if ( !strncmp( msg, "ERROR 68", strlen("ERROR 68")) ) {
+ /* The client needs authorization. Probably we reconnected to a new skype window. */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Airpe client %s needs authorization.\n", airpe->name);
+ switch_sleep(1000000);
+ airpe_on_connect_messages(airpe, airpe->protocol);
+ }
+ else if ( !strncmp( msg, "ALTER CALL", strlen("ALTER CALL")) ) {
+ /* The response to our hangup - Ignored */
+ }
+ else if ( !strncmp( msg, "SET CALL", strlen("SET CALL")) ) {
+ /* Ignoring by now */
+ }
+ else if ( !strncmp( buf, "ERROR", strlen("ERROR")) ) {
+ //TODO If we are in the middle of a call, hangup
+ }
+ else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unmanaged message\n");
+ }
+
+ switch_safe_free(buf);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_on_connect_messages( airpe_interface_t *airpe, int protocol ) {
+ char buf[SKYPE_MSG_LEN] = "";
+
+ snprintf(buf, sizeof(buf), "NAME airpe");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "PROTOCOL %d", protocol);
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "CLEAR CALLHISTORY ALL");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "CLEAR CHATHISTORY");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "GET SKYPEVERSION");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "GET PROFILE MOOD_TEXT");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "GET PROFILE FULLNAME");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "GET CONNSTATUS");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "SET AUTOAWAY OFF");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "SET MUTE OFF");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+
+ /*
+ The following two raise an error on linux, even if are supported from protocol 6 upwards.
+ That's not a big problem so we'll send them.
+ */
+
+ snprintf(buf, sizeof(buf), "SET PCSPEAKER OFF");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "SET SILENT_MODE ON");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/airpe_if_osx.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_osx.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,19 @@
+
+#include "mod_airpe.h"
+
+#if defined (MACOSX) || defined(DARWIN)
+
+#error OSX Not yet supported
+
+#endif
+
+/* 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/airpe_if_win32.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_win32.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,19 @@
+
+#include "mod_airpe.h"
+
+#ifdef WIN32
+
+#error WIN32 Not yet supported
+
+#endif
+
+/* 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,355 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#if defined (__GNUC__) && !(defined (MACOSX) || defined(DARWIN) )
+
+#include "mod_airpe.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#include <X11/Xatom.h>
+
+#define X11_MSG_LEN 20
+
+struct skype_window_handler_s {
+ Display *disp;
+ Window win;
+ uint8_t api_connected;
+ int fdesc[2];
+ Window skype_win;
+ int watchdog;
+};
+
+
+
+
+static XErrorHandler old_handler = 0;
+static int xerror = 0;
+
+static int xerrhandler(Display *dpy, XErrorEvent *err)
+{
+ xerror = err->error_code;
+ /* Return 0 so that the error is ignored */
+ return 0;
+}
+
+static void trap_errors()
+{
+ xerror = 0;
+ old_handler = XSetErrorHandler(xerrhandler);
+}
+
+static int untrap_errors()
+{
+ XSetErrorHandler(old_handler);
+ return (xerror != BadValue) && (xerror != BadWindow);
+}
+
+switch_status_t airpe_skype_watchdog_reset(skype_window_handler_t *window) {
+ window->watchdog = 0;
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_skype_watchdog_increment(skype_window_handler_t *window) {
+ window->watchdog++;
+
+ if ( window->watchdog >= 5 ) {
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+skype_window_handler_t *skype_window_alloc( switch_memory_pool_t *pool) {
+ return switch_core_alloc( pool, sizeof(skype_window_handler_t));
+}
+
+switch_status_t skype_restart( skype_window_handler_t *window, const char *params ) {
+
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
+ "HEY! where is my skype window gone ? Restarting skype for client...\n");
+/*
+
+ TODO AND TO USE
+
+ int fid;
+ const char *args[] = { "skype", "--actiondispatch", params, 0 };
+
+ if((fid = fork()) == 0) {
+ if(execvp("skype", (char *const*)args) == -1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client: cannot launch Skype, error %d: %s.\n", errno, strerror(errno) );
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+ else if(fid == -1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client: cannot launch Skype.\n");
+ return SWITCH_STATUS_FALSE;
+ }
+*/
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_skype_send_message(skype_window_handler_t *window, const char *message_P) {
+ Window w_P;
+ Display *disp;
+ Window handle_P;
+ Atom atom1;
+ Atom atom2;
+ unsigned int pos;
+ unsigned int len;
+ XEvent xev;
+ int ok;
+
+ w_P = window->skype_win;
+ disp = window->disp;
+ handle_P = window->win;
+
+ atom1 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+ atom2 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
+ pos = 0;
+ len = strlen(message_P);
+
+ memset(&xev, 0, sizeof(XEvent));
+ xev.xclient.type = ClientMessage;
+ xev.xclient.message_type = atom1;
+ xev.xclient.display = disp;
+ xev.xclient.window = handle_P;
+ xev.xclient.format = 8;
+
+ trap_errors();
+ do {
+ unsigned int i;
+ for (i = 0; i < 20 && i + pos <= len; ++i)
+ xev.xclient.data.b[i] = message_P[i + pos];
+ XSendEvent(disp, w_P, False, 0, &xev);
+
+ xev.xclient.message_type = atom2;
+ pos += i;
+ } while (pos <= len);
+
+ XSync(disp, False);
+ ok = untrap_errors();
+ if (!ok) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client X11 error.\n");
+ airpe_skype_avalaible(window);
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_skype_avalaible(skype_window_handler_t *window)
+{
+
+ Atom skype_inst;
+ Atom type_ret;
+ int format_ret;
+ unsigned long nitems_ret;
+ unsigned long bytes_after_ret;
+ unsigned char *prop;
+ int status, ok;
+
+ skype_inst = XInternAtom(window->disp, "_SKYPE_INSTANCE", True);
+
+ trap_errors();
+ status = XGetWindowProperty(
+ window->disp,
+ DefaultRootWindow(window->disp),
+ skype_inst,
+ 0,
+ 1,
+ False,
+ XA_WINDOW,
+ &type_ret,
+ &format_ret,
+ &nitems_ret,
+ &bytes_after_ret, &prop);
+
+ ok = untrap_errors();
+ if (!ok) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client X11 error.\n");
+ airpe_skype_avalaible(window);
+ }
+
+ /* sanity check */
+ if (status != Success || format_ret != 32 || nitems_ret != 1) {
+ window->skype_win = (Window) - 1;
+ return SWITCH_STATUS_FALSE;
+ }
+
+ window->skype_win = *(const unsigned long *) prop & 0xffffffff;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+
+/*****************************************************************************
+ THREADS
+ *****************************************************************************/
+
+void *SWITCH_THREAD_FUNC airpe_skype_thread(switch_thread_t * thread, void *obj) {
+
+ skype_window_handler_t *skype_window = NULL;
+ airpe_interface_t *airpe = NULL;
+ Display *disp = NULL;
+ Window root = -1;
+ Window win = -1;
+ int xfd;
+
+ assert(obj);
+
+ airpe = obj;
+
+ skype_window = airpe->skype_window;
+ assert(skype_window);
+
+ disp = XOpenDisplay(airpe->X11_display);
+ if (!disp) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client %s: cannot open display %s\n", airpe->name, airpe->X11_display);
+ return NULL;
+ }
+
+ xfd = XConnectionNumber(disp);
+ fcntl(xfd, F_SETFD, FD_CLOEXEC);
+
+ skype_window->disp = disp;
+
+ if ( airpe_skype_avalaible(skype_window) == SWITCH_STATUS_SUCCESS ) {
+ root = DefaultRootWindow(disp);
+ win = XCreateSimpleWindow(
+ disp,
+ root,
+ 0, 0, 1, 1, 0,
+ BlackPixel(disp, DefaultScreen(disp)),
+ BlackPixel(disp, DefaultScreen(disp))
+ );
+
+ skype_window->win = win;
+
+ if ( airpe_on_connect_messages( airpe, 6 ) != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "airpe client %s. Failed to send handshake messages\n",
+ airpe->name);
+ return NULL;
+ }
+
+ // perform an events loop
+ XEvent an_event;
+ char buf[X11_MSG_LEN + 2] = "";
+ char buffer[SKYPE_MSG_LEN] = "";
+ int i;
+ fd_set rset;
+ int x11_fd;
+ int empty_loops = 0;
+
+ airpe->running = 1;
+ XFlush(disp);
+ x11_fd = ConnectionNumber(disp);
+
+ while ( airpe->running ) {
+ FD_ZERO(&rset);
+ FD_SET( x11_fd, &rset);
+
+ struct timeval timeout;
+ int ret;
+
+ timeout.tv_usec = 10 * 1000;
+ ret = select(x11_fd+1, &rset, 0, 0, &timeout);
+
+ if ( !airpe->running ) /* Quick way to skip the loop when we are signaled to exit. */
+ break;
+
+ if ( ret <=0 ) {
+ empty_loops ++;
+ if ( empty_loops >= 250 ) {
+ airpe_cmd_write(airpe, "PING");
+ airpe_skype_watchdog_increment(skype_window);
+ empty_loops = 0;
+ }
+ continue;
+ }
+
+ airpe_skype_watchdog_reset(skype_window);
+
+ /* Process all the pending messages queued (not only one) */
+ while ( XPending(disp) )
+ {
+ XNextEvent(disp, &an_event);
+
+ switch (an_event.type)
+ {
+ case ClientMessage:
+ if (an_event.xclient.format != 8)
+ break;
+
+ for (i = 0; i < X11_MSG_LEN && an_event.xclient.data.b[i] != '\0'; ++i) {
+ buf[i] = an_event.xclient.data.b[i];
+ }
+ buf[i] = '\0';
+
+ strcat(buffer, buf);
+
+ if (i < X11_MSG_LEN) {
+ unsigned int howmany;
+ howmany = strlen(buffer) + 1;
+ airpe_manage_skype_msg( airpe, buffer);
+ memset(&buffer, 0, sizeof(buffer));
+ }
+ break;
+ default:
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "airpe client %s: unknown event\n", airpe->name);
+ break;
+ }
+ }
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "airpe client %s: exiting thread\n", airpe->name);
+
+ /* Hangup our call, if we have one */
+ airpe_explicit_hangup(airpe);
+
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client %s: skype not running on display %s\n", airpe->name, airpe->X11_display);
+ }
+
+ return NULL;
+}
+
+#endif
+
+/* 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml Mon Jan 12 17:24:44 2009
@@ -0,0 +1,36 @@
+<configuration name="airpe.conf" description="Airpe Configuration">
+ <globals>
+ <param name="audio-tcp-port_start" value="21000"/>
+
+ <!-- Those params are used for all clients if not explicitly set for each one -->
+ <param name="context" value="public"/>
+ <param name="dialplan" value="XML"/>
+ <param name="destination" value="5000"/>
+ </globals>
+
+ <!-- one entry here per airpe client -->
+ <clients>
+ <client name="airpe1">
+ <!-- Print out as notices the client messages -->
+ <param name="debug" value="1"/>
+
+ <!-- Where our calls will land -->
+ <param name="dialplan" value="XML"/>
+ <param name="context" value="default"/>
+ <param name="destination" value="4321"/>
+
+ <!-- Linux only -->
+ <param name="X11-display" value=":101"/>
+
+ <!-- Not used yet -->
+ <param name="cid-name" value="Skype 1"/>
+ <param name="cid-num" value="0000001"/>
+
+ <!-- Not used... maybe should be removed.
+ The purpose is restarting the client with those credentials -->
+ <param name="skype-user" value="username"/>
+ <param name="skype-password" value="password"/>
+ </client>
+ </clients>
+
+</configuration>
Added: freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,868 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#include "mod_airpe.h"
+
+/*****************************************************************************
+ MODULE PRIVATE STRUCTS && FUNCTIONS
+ *****************************************************************************/
+
+static switch_endpoint_interface_t *airpe_endpoint_interface;
+
+static struct {
+ char *dialplan;
+ char *context;
+ char *destination;
+ int audio_tcp_port_start;
+
+ switch_mutex_t *mutex;
+ switch_hash_t *interfaces_hash;
+ int last_port_used;
+} globals;
+
+static switch_memory_pool_t *airpe_module_pool = NULL;
+
+
+airpe_interface_t *airpe_find_interface( const char *name) {
+ return switch_core_hash_find(globals.interfaces_hash, name);
+}
+
+
+/*****************************************************************************
+ TECH STUFF
+ *****************************************************************************/
+
+static switch_status_t airpe_codec_init(private_object_t * tech_pvt, int sample_rate, int codec_ms) {
+ airpe_interface_t *airpe = NULL;
+
+ if ( switch_core_codec_init(&tech_pvt->read_codec, "L16", NULL, sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client: %s - Cannot init read codec.\n", airpe->name);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if ( switch_core_codec_init(&tech_pvt->write_codec, "L16", NULL, sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client: %s - Cannot init write codec.\n", airpe->name);
+ switch_core_codec_destroy(&tech_pvt->read_codec);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ tech_pvt->read_frame.rate = sample_rate;
+ tech_pvt->read_frame.codec = &tech_pvt->read_codec;
+
+ switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
+ switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_tech_init( private_object_t * tech_pvt, switch_core_session_t * session ) {
+
+ tech_pvt->read_frame.data = tech_pvt->databuf;
+ tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
+
+ switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+ switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+
+ switch_core_session_set_private(session, tech_pvt);
+ tech_pvt->session = session;
+ return airpe_codec_init(tech_pvt, CODEC_SAMPLE_RATE, CODEC_INTERVAL_MS);
+}
+
+static switch_socket_t *airpe_socket_create( const char *host, int port ) {
+ switch_status_t rv;
+ switch_socket_t *new_sock = NULL;
+ switch_sockaddr_t *sa;
+
+ rv = switch_sockaddr_info_get(&sa, host, AF_INET, port, 0, airpe_module_pool);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (1)\n");
+ return NULL;
+ }
+
+ rv = switch_socket_create(&new_sock, AF_INET, SOCK_STREAM, SWITCH_PROTO_TCP, airpe_module_pool);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (2)\n");
+ return NULL;
+ }
+
+ rv = switch_socket_opt_set(new_sock, SWITCH_SO_REUSEADDR, 1);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (3)\n");
+ return NULL;
+ }
+
+ rv = switch_socket_opt_set(new_sock, SWITCH_SO_NONBLOCK, 1);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (3)\n");
+ return NULL;
+ }
+
+ rv = switch_socket_bind(new_sock, sa);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (4)\n");
+ return NULL;
+ }
+
+ rv = switch_socket_listen(new_sock, 5);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (5)\n");
+ return NULL;
+ }
+
+ return new_sock;
+}
+
+static int fetch_next_port(void) {
+ int port = 0;
+
+ if ( !globals.last_port_used )
+ globals.last_port_used = globals.audio_tcp_port_start;
+
+ switch_mutex_lock(globals.mutex);
+ port = globals.last_port_used;
+ globals.last_port_used++;
+ switch_mutex_unlock(globals.mutex);
+
+ return port;
+}
+
+static switch_status_t airpe_audio_sockets_create( airpe_interface_t *airpe ) {
+ switch_socket_t *new_sock;
+ int port;
+
+ new_sock = NULL;
+ while ( !new_sock ) {
+ port = fetch_next_port();
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Assigning in port %d for client %s\n", port, airpe->name);
+ new_sock = airpe_socket_create("127.0.0.1", port);
+ if ( new_sock ) {
+ airpe->audio_in_socket = new_sock;
+ airpe->audio_in_port = port;
+ }
+ }
+
+ new_sock = NULL;
+ while ( !new_sock ) {
+ port = fetch_next_port();
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Assigning out port %d for client %s\n", port, airpe->name);
+ new_sock = airpe_socket_create("127.0.0.1", port);
+ if ( new_sock ) {
+ airpe->audio_out_socket = new_sock;
+ airpe->audio_out_port = port;
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+static switch_status_t airpe_start_client(airpe_interface_t *airpe) {
+
+ switch_threadattr_t *attr_skype = NULL;
+
+ airpe->user_status = USER_STATUS_UNKNOWN;
+ airpe->conn_status = CONN_STATUS_UNKNOWN;
+ airpe->call_status = CALL_STATUS_UNKNOWN;
+
+ airpe_audio_sockets_create(airpe);
+
+ switch_threadattr_create(&attr_skype, airpe_module_pool);
+ //switch_threadattr_detach_set(attr_skype, 1);
+ switch_threadattr_stacksize_set(attr_skype, SWITCH_THREAD_STACKSIZE);
+
+ switch_thread_create(&airpe->airpe_thread_skype,
+ attr_skype,
+ airpe_skype_thread,
+ airpe,
+ airpe_module_pool);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t airpe_stop_client(airpe_interface_t *airpe) {
+
+ if ( airpe->audio_in_socket ) {
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting down socket on port %d for client %s\n", airpe->audio_in_port, airpe->name);
+ airpe->audio_in_port = 0;
+ switch_socket_shutdown(airpe->audio_in_socket, SWITCH_SHUTDOWN_READWRITE);
+ switch_socket_close(airpe->audio_in_socket);
+ }
+
+ if ( airpe->audio_out_socket ) {
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting down socket on port %d for client %s\n", airpe->audio_out_port, airpe->name);
+ airpe->audio_out_port = 0;
+ switch_socket_shutdown(airpe->audio_out_socket, SWITCH_SHUTDOWN_READWRITE);
+ switch_socket_close(airpe->audio_out_socket);
+ }
+
+ airpe_set_version(airpe, NULL);
+ airpe_set_mood_text(airpe, NULL);
+ airpe_set_partner_displayname(airpe, NULL);
+ airpe_set_partner_handle(airpe, NULL);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_core_session_t *airpe_request_session( switch_memory_pool_t **pool ) {
+ /* I prefer not to expose airpe_endpoint_interface out of this file. */
+ return switch_core_session_request(airpe_endpoint_interface, pool);
+}
+
+
+/*****************************************************************************
+ CHANNEL STATE HANDLERS
+ *****************************************************************************/
+
+static switch_status_t channel_on_init(switch_core_session_t * session)
+{
+ switch_channel_t *channel;
+ private_object_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+ assert(tech_pvt->airpe);
+
+ tech_pvt->airpe->tech_pvt = tech_pvt;
+
+ if ( switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ) {
+ airpe_originate(tech_pvt->airpe, tech_pvt->destination );
+ // TODO if fail switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ }
+
+ if ( switch_test_flag(tech_pvt, TFLAG_INBOUND) ) {
+ char buf[SKYPE_MSG_LEN];
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_INPUT PORT=\"%d\"", tech_pvt->airpe->active_call_id, tech_pvt->airpe->audio_in_port);
+ airpe_cmd_write(tech_pvt->airpe, buf);
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_OUTPUT PORT=\"%d\"", tech_pvt->airpe->active_call_id, tech_pvt->airpe->audio_out_port);
+ airpe_cmd_write(tech_pvt->airpe, buf);
+
+ switch_channel_set_state(channel, CS_ROUTING);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_routing(switch_core_session_t * session) {
+ char buf[SKYPE_MSG_LEN];
+ switch_channel_t *channel = NULL;
+ private_object_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ if ( switch_test_flag(tech_pvt, TFLAG_INBOUND) ) {
+ snprintf(buf, sizeof(buf), "ALTER CALL %d ANSWER", tech_pvt->airpe->active_call_id);
+ airpe_cmd_write(tech_pvt->airpe, buf);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_execute(switch_core_session_t * session) {
+ switch_channel_t *channel = NULL;
+ private_object_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_hangup(switch_core_session_t * session)
+{
+ switch_channel_t *channel = NULL;
+ private_object_t *tech_pvt = NULL;
+ airpe_interface_t *airpe = NULL;
+ char msg[SKYPE_MSG_LEN];
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ airpe = tech_pvt->airpe;
+ assert(airpe);
+
+ if ( airpe->active_call_id ) {
+ snprintf(msg, sizeof(msg), "ALTER CALL %d HANGUP", airpe->active_call_id);
+ airpe_cmd_write(airpe, msg);
+// airpe->active_call_id = 0;
+// airpe->tech_pvt = NULL;
+ }
+
+ airpe_hangup( tech_pvt );
+
+ if (tech_pvt->read_codec.implementation) {
+ switch_core_codec_destroy(&tech_pvt->read_codec);
+ }
+
+ if (tech_pvt->write_codec.implementation) {
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_exchange_media(switch_core_session_t * session) {
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/*****************************************************************************
+ CHANNEL IO INTERFACE / ROUTINES
+ *****************************************************************************/
+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)
+{
+ switch_caller_profile_t *caller_profile = NULL;
+ private_object_t *tech_pvt = NULL;
+ switch_channel_t *channel = NULL;
+
+ assert(outbound_profile);
+
+ /* New session creation */
+ *new_session = airpe_request_session(pool);
+ if ( *new_session )
+ {
+ char *chan_interface = NULL;
+ char *chan_destination = NULL;
+
+ switch_core_session_add_stream(*new_session, NULL);
+
+ tech_pvt = (private_object_t *) switch_core_session_alloc(*new_session, sizeof(private_object_t));
+
+ if ( tech_pvt ) {
+ channel = switch_core_session_get_channel(*new_session);
+ if ( airpe_tech_init( tech_pvt, *new_session ) != SWITCH_STATUS_SUCCESS ) {
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+ } else {
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+
+
+ chan_interface = switch_core_session_strdup( *new_session, outbound_profile->destination_number);
+ if (( chan_destination = strchr(chan_interface, '/'))) {
+ *chan_destination++ = '\0';
+ }
+ if ( !chan_interface || !chan_destination ) {
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
+ }
+
+ if ( (tech_pvt->airpe = airpe_find_interface(chan_interface))==NULL ) {
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+ tech_pvt->destination = chan_destination;
+
+ if ( tech_pvt->airpe->active_call_id != 0 ) {
+ /* We're busy, man! */
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL;
+ }
+
+ if (outbound_profile) {
+ char name[128];
+ snprintf(name, sizeof(name), "airpe/%s", outbound_profile->destination_number);
+ switch_channel_set_name(channel, name);
+ caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+ switch_channel_set_caller_profile(channel, caller_profile);
+ tech_pvt->caller_profile = caller_profile;
+ }
+ else
+ {
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+
+ switch_channel_set_flag(channel, CF_OUTBOUND);
+ switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
+ switch_channel_set_state(channel, CS_INIT);
+ return SWITCH_CAUSE_SUCCESS;
+ }
+ else
+ {
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+}
+
+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_object_t *tech_pvt = NULL;
+ switch_byte_t *data;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ tech_pvt->read_frame.flags = SFF_NONE;
+ *frame = NULL;
+
+ if ( airpe_audio_read(tech_pvt) != SWITCH_STATUS_SUCCESS) {
+ ADEBUG("airpe_audio_read ERROR\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!tech_pvt->read_frame.datalen) {
+ goto cng;
+ }
+
+ *frame = &tech_pvt->read_frame;
+
+ return SWITCH_STATUS_SUCCESS;
+
+cng:
+ data = (switch_byte_t *) tech_pvt->read_frame.data;
+ data[0] = 65;
+ data[1] = 0;
+ tech_pvt->read_frame.datalen = 2;
+ tech_pvt->read_frame.flags = SFF_CNG;
+ *frame = &tech_pvt->read_frame;
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_write_frame(switch_core_session_t * session,
+ switch_frame_t * frame,
+ switch_io_flag_t flags,
+ int stream_id)
+{
+ switch_channel_t *channel = NULL;
+ private_object_t *tech_pvt = NULL;
+ airpe_interface_t *airpe = NULL;
+ switch_status_t rv;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ if ( !tech_pvt->airpe ) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ airpe = tech_pvt->airpe;
+
+ rv = airpe_audio_write(tech_pvt, frame);
+ return rv;
+}
+
+static switch_status_t channel_kill_channel(switch_core_session_t * session, int sig)
+{
+ switch_channel_t *channel = NULL;
+ private_object_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ switch (sig) {
+ case SWITCH_SIG_KILL:
+ break;
+ case SWITCH_SIG_BREAK:
+ break;
+ default:
+ //TODO Log unhandled signal
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_send_dtmf(switch_core_session_t * session, const switch_dtmf_t * dtmf) {
+ private_object_t *tech_pvt = switch_core_session_get_private(session);
+ airpe_interface_t *airpe;
+ char buf[SKYPE_MSG_LEN];
+
+ switch_assert(tech_pvt);
+
+ airpe = tech_pvt->airpe;
+
+ if ( airpe->active_call_id ) {
+ snprintf(buf, sizeof(buf), "SET CALL %d DTMF %c", airpe->active_call_id, dtmf->digit);
+ airpe_cmd_write(airpe, buf);
+ }
+
+ 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_object_t *tech_pvt;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = (private_object_t *) switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_ANSWER:
+ ADEBUG("received message indicate answer...\n");
+/*
+ //switch_answer_channel(session);
+ char buf[SKYPE_MSG_LEN];
+ snprintf(buf, sizeof(buf), "ALTER CALL %d ANSWER", tech_pvt->airpe->active_call_id );
+ airpe_cmd_write(tech_pvt->airpe, buf);
+*/
+ break;
+ case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
+ ADEBUG("received message indicate unbridge...\n");
+ break;
+ case SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY:
+ ADEBUG("received message indicate transcode necessary...\n");
+ break;
+ case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC:
+ ADEBUG("received message indicate audio sync...\n");
+ break;
+ case SWITCH_MESSAGE_INDICATE_TRANSFER:
+ ADEBUG("received message indicate transfer...\n");
+ break;
+ default:
+ ADEBUG("Unmanaged received message... %d\n", msg->message_id);
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_event(switch_core_session_t * session, switch_event_t * event)
+{
+ char *body = NULL;
+ switch_channel_t *channel;
+ private_object_t *tech_pvt;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = (private_object_t *) switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ body = switch_event_get_body(event);
+
+ if (!body) {
+ body = "";
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+/*****************************************************************************
+ CONFIGURATION
+ *****************************************************************************/
+
+static switch_status_t load_config(void) {
+ switch_xml_t cfg,
+ xml,
+ global_settings,
+ param,
+ clients,
+ client;
+ switch_memory_pool_t *pool;
+
+ pool = airpe_module_pool;
+
+ if (!(xml = switch_xml_open_cfg("airpe.conf", &cfg, NULL))) {
+ return SWITCH_STATUS_TERM;
+ }
+
+ if ( (global_settings = switch_xml_child(cfg, "globals") ) ) {
+ for (param = switch_xml_child(global_settings, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcmp(var, "dialplan")) {
+ globals.dialplan = switch_core_strdup(pool, val);
+ } else if (!strcmp(var, "context")) {
+ globals.context = switch_core_strdup(pool, val);
+ } else if (!strcmp(var, "destination")) {
+ globals.destination = switch_core_strdup(pool, val);
+ } else if (!strcmp(var, "audio-tcp-port_start")) {
+ globals.audio_tcp_port_start = atoi(val);
+ }
+ }
+ }
+
+ if ( globals.audio_tcp_port_start <= 0 ) {
+ globals.audio_tcp_port_start = 21000;
+ }
+
+ if ( !globals.dialplan )
+ globals.dialplan = switch_core_strdup(pool, "XML");
+ if ( !globals.context )
+ globals.context = switch_core_strdup(pool, "default");
+ if ( !globals.destination )
+ globals.destination = switch_core_strdup(pool, "4321");
+
+ if ((clients = switch_xml_child(cfg, "clients"))) {
+
+ for (client = switch_xml_child(clients, "client"); client; client = client->next)
+ {
+ char *name = (char *) switch_xml_attr(client, "name");
+ char *context = NULL;
+ char *dialplan = NULL;
+ char *destination = NULL;
+ char *X11_display = NULL;
+ char *skype_user = NULL;
+ char *skype_password= NULL;
+ char *cid_name = NULL;
+ char *cid_num = NULL;
+ int debug = 0;
+
+ airpe_interface_t *newconf = NULL;
+
+ if (!name) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No name attribute. Skipping unnamed client.\n");
+ continue;
+ }
+
+ if ( (newconf = switch_core_hash_find(globals.interfaces_hash, name)) ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Duplicated client %s. Skipping\n", name);
+ continue;
+ }
+
+ for (param = switch_xml_child(client, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcasecmp(var, "debug")) {
+ debug = switch_true(val) ? 1 : 0;
+ } else if (!strcasecmp(var, "context")) {
+ context = val;
+ } else if (!strcasecmp(var, "dialplan")) {
+ dialplan = val;
+ } else if (!strcasecmp(var, "destination")) {
+ destination = val;
+ } else if (!strcasecmp(var, "skype-user")) {
+ skype_user = val;
+ } else if (!strcasecmp(var, "skype-password")) {
+ skype_password = val;
+ } else if (!strcasecmp(var, "X11-display")) {
+ X11_display = val;
+ } else if (!strcasecmp(var, "cid-name")) {
+ cid_name = val;
+ } else if (!strcasecmp(var, "cid-num")) {
+ cid_num = val;
+ }
+ else
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown config param %s\n", var);
+ }
+ if (!skype_user) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No skype-user param for client %s. Skipping\n", name);
+ continue;
+ }
+ if (!skype_password) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No skype-password param for client %s. Skipping\n", name);
+ continue;
+ }
+ if (!X11_display) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No X11-display param for client %s. Skipping\n", name);
+ continue;
+ }
+
+ if ( !dialplan )
+ dialplan = globals.dialplan;
+ if ( !context )
+ context = globals.context;
+ if ( !destination )
+ destination = globals.destination;
+
+ newconf = (airpe_interface_t *) switch_core_alloc( pool, sizeof(airpe_interface_t) );
+
+ if ( newconf ) {
+ switch_status_t status;
+
+ memset(newconf, 0, sizeof(airpe_interface_t));
+
+ newconf->name = switch_core_strdup(pool, name);
+ newconf->dialplan = switch_core_strdup(pool, dialplan);
+ newconf->context = switch_core_strdup(pool, context);
+ newconf->destination = switch_core_strdup(pool, destination);
+ newconf->skype_user = switch_core_strdup(pool, skype_user);
+ newconf->skype_password = switch_core_strdup(pool, skype_password);
+ newconf->X11_display = switch_core_strdup(pool, X11_display);
+ newconf->audio_in_port = 0;
+ newconf->audio_in_port = 0;
+ newconf->debug = debug;
+
+ newconf->skype_window = skype_window_alloc(pool);
+
+ if ( newconf->skype_window ) {
+ status = airpe_start_client(newconf);
+
+ if ( status == SWITCH_STATUS_SUCCESS ) {
+ switch_core_hash_insert(globals.interfaces_hash, name, newconf);
+ }
+ else {
+ // LOG OUR ERROR
+ }
+ }
+ else {
+ // LOG OUR ERROR
+ }
+
+ }
+ else {
+ //TODO LOG ERROR ABOUT CREATING INTERFACE
+ }
+ }
+
+ }
+
+ switch_xml_free(xml);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+/*****************************************************************************
+ MODULE INITIALIZATION FUNCTIONS
+ *****************************************************************************/
+
+static switch_state_handler_table_t airpe_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 */ NULL
+};
+
+static switch_io_routines_t airpe_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
+};
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_airpe_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_airpe_shutdown);
+SWITCH_MODULE_DEFINITION(mod_airpe, mod_airpe_load, mod_airpe_shutdown, NULL);
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_airpe_load)
+{
+ airpe_module_pool = pool;
+
+ memset(&globals, 0, sizeof(globals));
+
+ switch_core_hash_init(&globals.interfaces_hash, pool);
+ switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, pool);
+
+ load_config();
+
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+ airpe_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
+
+ airpe_endpoint_interface->interface_name = "airpe";
+ airpe_endpoint_interface->io_routines = &airpe_io_routines;
+ airpe_endpoint_interface->state_handler = &airpe_state_handlers;
+
+ airpe_register_api( &*module_interface );
+ airpe_register_apps( &*module_interface );
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_airpe_shutdown)
+{
+ switch_memory_pool_t *pool;
+ airpe_interface_t *airpe;
+ switch_hash_index_t *hi;
+ void *val;
+
+ pool = airpe_module_pool;
+
+ for (hi = switch_hash_first(NULL, globals.interfaces_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, NULL, NULL, &val);
+ airpe = ( airpe_interface_t *) val;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting down airpe client: %s\n", airpe->name);
+ airpe->running = 0;
+ /* Wake up the socket */
+ airpe_cmd_write(airpe, "PING");
+ airpe_stop_client(airpe);
+ /*
+ we won't delete the hash element. we're going to destroy the whole pool
+ switch_core_hash_delete(globals.interfaces_hash, airpe->name);
+ */
+ }
+ switch_yield(500000);
+
+ /* TODO... should we check that all interfaces has been switched off ? */
+
+ switch_core_hash_destroy(&globals.interfaces_hash);
+ switch_core_destroy_memory_pool(&pool);
+ return SWITCH_STATUS_UNLOAD;
+}
+
+/* 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.h Mon Jan 12 17:24:44 2009
@@ -0,0 +1,235 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#include <switch.h>
+#include <switch_version.h>
+
+#define MODNAME "airpe"
+
+#define SKYPE_MSG_LEN 1024
+
+#define CODEC_SAMPLE_RATE 16000
+#define CODEC_INTERVAL_MS 20
+#define FRAMES_PER_SECOND 1000 / CODEC_INTERVAL_MS
+#define SAMPLES_PER_FRAME CODEC_SAMPLE_RATE / FRAMES_PER_SECOND
+
+#define ADEBUG(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, __VA_ARGS__ );
+
+typedef enum {
+ CONN_STATUS_UNKNOWN,
+ CONN_STATUS_OFFLINE,
+ CONN_STATUS_CONNECTING,
+ CONN_STATUS_PAUSING,
+ CONN_STATUS_ONLINE,
+} CONN_STATUS;
+
+typedef enum {
+ USER_STATUS_UNKNOWN,
+ USER_STATUS_ONLINE,
+ USER_STATUS_OFFLINE,
+ USER_STATUS_SKYPEME,
+ USER_STATUS_AWAY,
+ USER_STATUS_NA,
+ USER_STATUS_DND,
+ USER_STATUS_INVISIBLE,
+ USER_STATUS_LOGGEDOUT
+} USER_STATUS;
+
+typedef enum {
+ CALL_STATUS_UNKNOWN,
+ CALL_STATUS_UNPLACED,
+ CALL_STATUS_ROUTING,
+ CALL_STATUS_EARLYMEDIA,
+ CALL_STATUS_FAILED,
+ CALL_STATUS_RINGING,
+ CALL_STATUS_INPROGRESS,
+ CALL_STATUS_ONHOLD,
+ CALL_STATUS_LOCALHOLD,
+ CALL_STATUS_REMOTEHOLD,
+ CALL_STATUS_FINISHED,
+ CALL_STATUS_MISSED,
+ CALL_STATUS_REFUSED,
+ CALL_STATUS_BUSY,
+ CALL_STATUS_CANCELLED,
+ CALL_STATUS_TRANSFERRING, /* Protocol 7 */
+ CALL_STATUS_TRANSFERRED, /* Protocol 7 */
+
+ CALL_STATUS_VM_BUFFERING_GREETING,
+ CALL_STATUS_VM_PLAYING_GREETING,
+ CALL_STATUS_VM_RECORDING,
+ CALL_STATUS_VM_UPLOADING,
+ CALL_STATUS_VM_SENT,
+ CALL_STATUS_VM_CANCELLED ,
+ CALL_STATUS_VM_FAILED,
+ CALL_STATUS_WAITING_REDIAL_COMMAND,
+ CALL_STATUS_REDIAL_PENDING, /* Protocol 8 */
+
+} CALL_STATUS;
+
+typedef enum {
+ FAILURE_CODE_MISC = 1,
+ FAILURE_CODE_BAD_DESTINATION_NUM = 2,
+ FAILURE_CODE_USER_OFFLINE = 3,
+ FAILURE_CODE_NO_PROXY_FOUND = 4,
+ FAILURE_CODE_SESSION_TERMINATED = 5,
+ FAILURE_CODE_NO_CODEC_FOUND = 6,
+ FAILURE_CODE_LOCAL_SOUND_ERR = 7,
+ FAILURE_CODE_REMOTE_SOUND_ERR = 8,
+ FAILURE_CODE_CALL_BLOCKED = 9,
+ FAILURE_CODE_RECIPIENT_NOT_FRIEND = 10,
+ FAILURE_CODE_CALL_UNAUTHORIZED = 11,
+ FAILURE_CODE_SOUND_REC_ERR = 12,
+} FAILURE_CODES;
+
+
+typedef enum {
+ TFLAG_INBOUND = (1 << 1),
+ TFLAG_OUTBOUND = (1 << 2),
+/*
+ TFLAG_IO = (1 << 0),
+ TFLAG_DTMF = (1 << 3),
+ TFLAG_VOICE = (1 << 4),
+ TFLAG_HANGUP = (1 << 5),
+ TFLAG_LINEAR = (1 << 6),
+ TFLAG_CODEC = (1 << 7),
+ TFLAG_BREAK = (1 << 8),
+ TFLAG_ANSWER = (1 << 9)
+*/
+} TFLAGS;
+
+typedef struct skype_window_handler_s skype_window_handler_t;
+
+typedef struct airpe_interface_s airpe_interface_t;
+typedef struct private_object_s private_object_t;
+
+struct airpe_interface_s {
+ char *name;
+ int debug;
+ char *dialplan;
+ char *context;
+ char *destination;
+ char *X11_display;
+ char *skype_user;
+ char *skype_password;
+
+ int audio_in_port;
+ int audio_out_port;
+ switch_socket_t *audio_in_socket;
+ switch_socket_t *audio_out_socket;
+ switch_socket_t *audio_in_active_socket;
+ switch_socket_t *audio_out_active_socket;
+
+ switch_thread_t *airpe_thread_skype;
+ skype_window_handler_t *skype_window;
+
+ int protocol;
+ USER_STATUS user_status;
+ CALL_STATUS call_status;
+ CONN_STATUS conn_status;
+
+ char *skype_version;
+ char *mood_text;
+ int active_call_id;
+ int last_fail_reason;
+ int running;
+ private_object_t *tech_pvt;
+ char *partner_displayname;
+ char *partner_handle;
+};
+
+struct private_object_s {
+ unsigned int flags;
+ switch_mutex_t *flag_mutex;
+ switch_mutex_t *mutex;
+
+ airpe_interface_t *airpe;
+ switch_core_session_t *session;
+ switch_caller_profile_t *caller_profile;
+ char *destination;
+
+ switch_codec_t read_codec;
+ switch_codec_t write_codec;
+ switch_frame_t read_frame;
+ uint8_t databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+};
+
+
+/* CORE */
+airpe_interface_t *airpe_find_interface( const char *name);
+switch_core_session_t *airpe_request_session( switch_memory_pool_t **pool );
+switch_status_t airpe_tech_init( private_object_t * tech_pvt, switch_core_session_t * session );
+
+/* API */
+switch_status_t airpe_register_api( switch_loadable_module_interface_t **module_interface );
+
+/* APPS */
+switch_status_t airpe_register_apps( switch_loadable_module_interface_t **module_interface );
+
+/* INTERFACE - COMMON FUNCTIONS */
+const char *skype_user_status_string(USER_STATUS st);
+USER_STATUS skype_user_status(const char *str);
+const char *skype_conn_status_string(CONN_STATUS st);
+CONN_STATUS skype_conn_status(const char *str);
+
+switch_status_t airpe_set_version(airpe_interface_t *airpe, char *string);
+switch_status_t airpe_set_mood_text(airpe_interface_t *airpe, char *string);
+switch_status_t airpe_set_partner_displayname(airpe_interface_t *airpe, char *string);
+switch_status_t airpe_set_partner_handle(airpe_interface_t *airpe, char *string);
+
+switch_status_t airpe_hangup( private_object_t *pvt );
+switch_status_t airpe_audio_read( private_object_t *pvt );
+switch_status_t airpe_audio_write( private_object_t *pvt, switch_frame_t *frame );
+
+switch_status_t airpe_cmd_write(airpe_interface_t *p, char *msg);
+switch_status_t airpe_originate(airpe_interface_t *p, char *dest);
+switch_status_t airpe_explicit_hangup(airpe_interface_t *airpe);
+switch_status_t airpe_manage_skype_msg( airpe_interface_t *airpe, const char *msg );
+
+switch_status_t airpe_on_connect_messages( airpe_interface_t *airpe, int protocol );
+
+/* INTERFACE - PLATFORM DEPENDANT FUNCTIONS */
+switch_status_t airpe_skype_watchdog_reset(skype_window_handler_t *window);
+switch_status_t airpe_skype_watchdog_increment(skype_window_handler_t *window);
+skype_window_handler_t *skype_window_alloc( switch_memory_pool_t *pool);
+switch_status_t airpe_skype_avalaible(skype_window_handler_t *window);
+switch_status_t skype_restart( skype_window_handler_t *airpe, const char *params );
+switch_status_t airpe_skype_send_message(skype_window_handler_t *window, const char *message_P);
+void *SWITCH_THREAD_FUNC airpe_skype_thread(switch_thread_t * thread, void *obj);
+
+/* 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:
+ */
1
0