<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][16789] </title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=16789">16789</a></dd>
<dt>Author</dt> <dd>sathieu</dd>
<dt>Date</dt> <dd>2010-02-24 06:05:45 -0600 (Wed, 24 Feb 2010)</dd>
</dl>
<h3>Log Message</h3>
<pre>Skinny: Corrections
- Construct call_id based on simple increment per profile
- close RTP only if needed
- now hanging up while there is no other leg works
- better steps: create_session -> process_dest -> answer</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchtrunksrcmodendpointsmod_skinnymod_skinnyc">freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.c</a></li>
<li><a href="#freeswitchtrunksrcmodendpointsmod_skinnymod_skinnyh">freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.h</a></li>
<li><a href="#freeswitchtrunksrcmodendpointsmod_skinnyskinny_protocolc">freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.c</a></li>
<li><a href="#freeswitchtrunksrcmodendpointsmod_skinnyskinny_protocolh">freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunksrcmodendpointsmod_skinnymod_skinnyc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.c (16788 => 16789)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.c        2010-02-24 12:05:34 UTC (rev 16788)
+++ freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.c        2010-02-24 12:05:45 UTC (rev 16789)
</span><span class="lines">@@ -381,13 +381,19 @@
</span><span class="cx">         return status;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void tech_init(private_t *tech_pvt, switch_core_session_t *session)
</del><ins>+void tech_init(private_t *tech_pvt, switch_core_session_t *session, listener_t *listener, uint32_t line)
</ins><span class="cx"> {
</span><ins>+        switch_assert(tech_pvt);
+        switch_assert(session);
+        switch_assert(listener);
+        
</ins><span class="cx">         tech_pvt->read_frame.data = tech_pvt->databuf;
</span><span class="cx">         tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
</span><span class="cx">         switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
</span><span class="cx">         switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
</span><del>-        tech_pvt->call_id = 12345; /* TODO */
</del><ins>+        tech_pvt->call_id = listener->profile->next_call_id++;
+        tech_pvt->listener = listener;
+        tech_pvt->line = line;
</ins><span class="cx">         switch_core_session_set_private(session, tech_pvt);
</span><span class="cx">         tech_pvt->session = session;
</span><span class="cx"> }
</span><span class="lines">@@ -508,16 +514,25 @@
</span><span class="cx">         stop_tone(listener, tech_pvt->line, tech_pvt->call_id);
</span><span class="cx">         set_lamp(listener, SKINNY_BUTTON_LINE, tech_pvt->line, SKINNY_LAMP_OFF);
</span><span class="cx">         clear_prompt_status(listener, tech_pvt->line, tech_pvt->call_id);
</span><del>-        close_receive_channel(listener,
-                tech_pvt->call_id, /* uint32_t conference_id, */
-                tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
-                tech_pvt->call_id /* uint32_t conference_id2, */
-        );
-        stop_media_transmission(listener,
-                tech_pvt->call_id, /* uint32_t conference_id, */
-                tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
-                tech_pvt->call_id /* uint32_t conference_id2, */
-        );
</del><ins>+
+        if( skinny_line_get_state(tech_pvt->listener, tech_pvt->line) == SKINNY_KEY_SET_CONNECTED ) {
+                close_receive_channel(listener,
+                        tech_pvt->call_id, /* uint32_t conference_id, */
+                        tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
+                        tech_pvt->call_id /* uint32_t conference_id2, */
+                );
+                stop_media_transmission(listener,
+                        tech_pvt->call_id, /* uint32_t conference_id, */
+                        tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
+                        tech_pvt->call_id /* uint32_t conference_id2, */
+                );
+                switch_mutex_lock(globals.calls_mutex);
+                globals.calls--;
+                if (globals.calls < 0) {
+                        globals.calls = 0;
+                }
+                switch_mutex_unlock(globals.calls_mutex);
+        }
</ins><span class="cx">         send_call_state(listener,
</span><span class="cx">                 SKINNY_ON_HOOK,
</span><span class="cx">                 tech_pvt->line,
</span><span class="lines">@@ -526,15 +541,7 @@
</span><span class="cx">         /* TODO: DefineTimeDate */
</span><span class="cx">         set_speaker_mode(listener, SKINNY_SPEAKER_OFF);
</span><span class="cx">         set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0);
</span><del>-        
</del><span class="cx">
</span><del>-        switch_mutex_lock(globals.calls_mutex);
-        globals.calls--;
-        if (globals.calls < 0) {
-                globals.calls = 0;
-        }
-        switch_mutex_unlock(globals.calls_mutex);
-
</del><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -551,12 +558,12 @@
</span><span class="cx">
</span><span class="cx">         switch (sig) {
</span><span class="cx">         case SWITCH_SIG_KILL:
</span><del>-                switch_clear_flag_locked(tech_pvt, TFLAG_IO);
-                switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
</del><span class="cx">                 switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
</span><span class="cx">                 break;
</span><span class="cx">         case SWITCH_SIG_BREAK:
</span><del>-                switch_set_flag_locked(tech_pvt, TFLAG_BREAK);
</del><ins>+                if (switch_rtp_ready(tech_pvt->rtp_session)) {
+                        switch_rtp_break(tech_pvt->rtp_session);
+                }
</ins><span class="cx">                 break;
</span><span class="cx">         default:
</span><span class="cx">                 break;
</span><span class="lines">@@ -748,6 +755,8 @@
</span><span class="cx">         
</span><span class="cx">         char *profile_name, *dest;
</span><span class="cx">         skinny_profile_t *profile = NULL;
</span><ins>+        listener_t *listener = NULL;
+        uint32_t line = 0;
</ins><span class="cx">         char name[128];
</span><span class="cx">         switch_channel_t *channel;
</span><span class="cx">         switch_caller_profile_t *caller_profile;
</span><span class="lines">@@ -767,8 +776,6 @@
</span><span class="cx">                 goto error;
</span><span class="cx">         }
</span><span class="cx">
</span><del>-        tech_init(tech_pvt, nsession);
-
</del><span class="cx">         if(!(profile_name = switch_core_session_strdup(nsession, outbound_profile->destination_number))) {
</span><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error Creating Session Info\n");
</span><span class="cx">                 goto error;
</span><span class="lines">@@ -794,31 +801,33 @@
</span><span class="cx">         switch_channel_set_name(channel, name);
</span><span class="cx">         
</span><span class="cx">
</span><del>-        caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
-        switch_channel_set_caller_profile(channel, caller_profile);
-        tech_pvt->caller_profile = caller_profile;
-
-        switch_channel_set_flag(channel, CF_OUTBOUND);
-        switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
-
-        if ((skinny_profile_find_listener(profile, dest, &tech_pvt->listener, &tech_pvt->line) != SWITCH_STATUS_SUCCESS)) {
</del><ins>+        if ((skinny_profile_find_listener(profile, dest, &listener, &line) != SWITCH_STATUS_SUCCESS)) {
</ins><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Problem while retrieving listener and line for destination %s in profile %s\n", dest, profile_name);
</span><span class="cx">                 cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
</span><span class="cx">                 goto error;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        if (!tech_pvt->listener) {
</del><ins>+        if (!listener) {
</ins><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid destination or phone not registred %s in profile %s\n", dest, profile_name);
</span><span class="cx">                 cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
</span><span class="cx">                 goto error;
</span><span class="cx">         }
</span><span class="cx">
</span><del>-        if (tech_pvt->line == 0) {
</del><ins>+        if (line == 0) {
</ins><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid destination or phone not registred %s in profile %s\n", dest, profile_name);
</span><span class="cx">                 cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
</span><span class="cx">                 goto error;
</span><span class="cx">         }
</span><span class="cx">         
</span><ins>+        tech_init(tech_pvt, nsession, listener, line);
+
+        caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
+        switch_channel_set_caller_profile(channel, caller_profile);
+        tech_pvt->caller_profile = caller_profile;
+
+        switch_channel_set_flag(channel, CF_OUTBOUND);
+        switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
+
</ins><span class="cx">         if(tech_pvt->listener->session[tech_pvt->line]) { /* Line is busy */
</span><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Device line is busy %s in profile %s\n", dest, profile_name);
</span><span class="cx">                 cause = SWITCH_CAUSE_USER_BUSY;
</span><span class="lines">@@ -1424,8 +1433,6 @@
</span><span class="cx">                                 skinny_execute_sql_callback(profile, profile->listener_mutex, "DELETE FROM skinny_devices", NULL, NULL);
</span><span class="cx">                                 skinny_execute_sql_callback(profile, profile->listener_mutex, "DELETE FROM skinny_buttons", NULL, NULL);
</span><span class="cx">
</span><del>-                                switch_core_hash_init(&profile->session_hash, module_pool);
-                                
</del><span class="cx">                                 switch_core_hash_insert(globals.profile_hash, profile->name, profile);
</span><span class="cx">                                 profile = NULL;
</span><span class="cx">                         } else {
</span></span></pre></div>
<a id="freeswitchtrunksrcmodendpointsmod_skinnymod_skinnyh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.h (16788 => 16789)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.h        2010-02-24 12:05:34 UTC (rev 16788)
+++ freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.h        2010-02-24 12:05:45 UTC (rev 16789)
</span><span class="lines">@@ -92,9 +92,8 @@
</span><span class="cx">         switch_mutex_t *sock_mutex;
</span><span class="cx">         struct listener *listeners;
</span><span class="cx">         uint8_t listener_ready;
</span><del>-        /* sessions */
-        switch_hash_t *session_hash;
-        switch_mutex_t *sessions_mutex;
</del><ins>+        /* call id */
+        uint32_t next_call_id;
</ins><span class="cx"> };
</span><span class="cx"> typedef struct skinny_profile skinny_profile_t;
</span><span class="cx">
</span><span class="lines">@@ -143,7 +142,6 @@
</span><span class="cx">         TFLAG_HANGUP = (1 << 5),
</span><span class="cx">         TFLAG_LINEAR = (1 << 6),
</span><span class="cx">         TFLAG_CODEC = (1 << 7),
</span><del>-        TFLAG_BREAK = (1 << 8),
</del><span class="cx">         
</span><span class="cx">         TFLAG_READING = (1 << 9),
</span><span class="cx">         TFLAG_WRITING = (1 << 10)
</span><span class="lines">@@ -209,7 +207,7 @@
</span><span class="cx"> uint32_t skinny_line_get_state(listener_t *listener, uint32_t instance);
</span><span class="cx">
</span><span class="cx"> switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force);
</span><del>-void tech_init(private_t *tech_pvt, switch_core_session_t *session);
</del><ins>+void tech_init(private_t *tech_pvt, switch_core_session_t *session, listener_t *listener, uint32_t line);
</ins><span class="cx"> switch_status_t channel_on_init(switch_core_session_t *session);
</span><span class="cx"> switch_status_t channel_on_hangup(switch_core_session_t *session);
</span><span class="cx"> switch_status_t channel_on_destroy(switch_core_session_t *session);
</span></span></pre></div>
<a id="freeswitchtrunksrcmodendpointsmod_skinnyskinny_protocolc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.c (16788 => 16789)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.c        2010-02-24 12:05:34 UTC (rev 16788)
+++ freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.c        2010-02-24 12:05:45 UTC (rev 16789)
</span><span class="lines">@@ -272,6 +272,7 @@
</span><span class="cx">         }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+/*****************************************************************************/
</ins><span class="cx"> switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
</span><span class="cx"> {
</span><span class="cx">         skinny_message_t *request;
</span><span class="lines">@@ -355,6 +356,7 @@
</span><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+/*****************************************************************************/
</ins><span class="cx"> int skinny_device_event_callback(void *pArg, int argc, char **argv, char **columnNames)
</span><span class="cx"> {
</span><span class="cx">         switch_event_t *event = (switch_event_t *) pArg;
</span><span class="lines">@@ -399,6 +401,7 @@
</span><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+/*****************************************************************************/
</ins><span class="cx"> switch_status_t skinny_send_call_info(switch_core_session_t *session)
</span><span class="cx"> {
</span><span class="cx">         private_t *tech_pvt;
</span><span class="lines">@@ -435,11 +438,15 @@
</span><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-switch_status_t skinny_pick_up(listener_t *listener, uint32_t line)
</del><ins>+/*****************************************************************************/
+switch_status_t skinny_create_session(listener_t *listener, uint32_t line, uint32_t to_state)
</ins><span class="cx"> {
</span><span class="cx">         switch_core_session_t *session;
</span><span class="cx">         switch_channel_t *channel;
</span><span class="cx">         private_t *tech_pvt;
</span><ins>+        char *cid_name = "TODO-soft_key_event"; /* TODO set form the line*/
+        char *cid_num = "00000"; /* TODO set form the line */
+        char name[128];
</ins><span class="cx">
</span><span class="cx">         if (!(session = switch_core_session_request(skinny_get_endpoint_interface(), SWITCH_CALL_DIRECTION_INBOUND, NULL))) {
</span><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n");
</span><span class="lines">@@ -453,11 +460,26 @@
</span><span class="cx">
</span><span class="cx">         switch_core_session_add_stream(session, NULL);
</span><span class="cx">
</span><del>-        tech_pvt->listener = listener;
-        tech_pvt->line = line;
</del><ins>+        tech_init(tech_pvt, session, listener, line);
</ins><span class="cx">
</span><del>-        tech_init(tech_pvt, session);
</del><ins>+        channel = switch_core_session_get_channel(session);
</ins><span class="cx">
</span><ins>+        snprintf(name, sizeof(name), "SKINNY/%s/%s/%d", listener->profile->name, listener->device_name, tech_pvt->line);
+        switch_channel_set_name(channel, name);
+
+        if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
+                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error Creating Session thread\n");
+                goto error;
+        }
+
+        if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
+                                                                                                                         NULL, listener->profile->dialplan, cid_name, cid_num, listener->remote_ip, NULL, NULL, NULL, "skinny" /* modname */, listener->profile->context, tech_pvt->dest)) != 0) {
+                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error Creating Session caller profile\n");
+                goto error;
+        }
+
+        switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+
</ins><span class="cx">         set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0);
</span><span class="cx">         set_speaker_mode(listener, SKINNY_SPEAKER_ON);
</span><span class="cx">         set_lamp(listener, SKINNY_BUTTON_LINE, tech_pvt->line, SKINNY_LAMP_ON);
</span><span class="lines">@@ -465,7 +487,7 @@
</span><span class="cx">                 SKINNY_OFF_HOOK,
</span><span class="cx">                 tech_pvt->line,
</span><span class="cx">                 tech_pvt->call_id);
</span><del>-        skinny_line_set_state(listener, tech_pvt->line, SKINNY_KEY_SET_OFF_HOOK, tech_pvt->call_id);
</del><ins>+        skinny_line_set_state(listener, tech_pvt->line, to_state, tech_pvt->call_id);
</ins><span class="cx">         display_prompt_status(listener,
</span><span class="cx">                 0,
</span><span class="cx">                 "\200\000",
</span><span class="lines">@@ -474,7 +496,6 @@
</span><span class="cx">         activate_call_plane(listener, tech_pvt->line);
</span><span class="cx">         start_tone(listener, SKINNY_TONE_DIALTONE, 0, tech_pvt->line, tech_pvt->call_id);
</span><span class="cx">
</span><del>-        channel = switch_core_session_get_channel(session);
</del><span class="cx">         goto done;
</span><span class="cx"> error:
</span><span class="cx">         if (session) {
</span><span class="lines">@@ -488,6 +509,29 @@
</span><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+switch_status_t skinny_process_dest(listener_t *listener, uint32_t line)
+{
+        switch_channel_t *channel = NULL;
+        private_t *tech_pvt = NULL;
+
+        channel = switch_core_session_get_channel(listener->session[line]);
+        assert(channel != NULL);
+
+        tech_pvt = switch_core_session_get_private(listener->session[line]);
+        assert(tech_pvt != NULL);
+
+        tech_pvt->caller_profile->destination_number = switch_core_strdup(tech_pvt->caller_profile->pool, tech_pvt->dest);
+        if(strlen(tech_pvt->dest) >= 4) { /* TODO Number is complete -> check against dialplan */
+                if (switch_channel_get_state(channel) == CS_NEW) {
+                        switch_channel_set_state(channel, CS_INIT);
+                }
+
+                send_dialed_number(listener, tech_pvt->dest, tech_pvt->line, tech_pvt->call_id);
+                skinny_answer(listener->session[line]);
+        }
+        return SWITCH_STATUS_SUCCESS;
+}
+
</ins><span class="cx"> switch_status_t skinny_answer(switch_core_session_t *session)
</span><span class="cx"> {
</span><span class="cx">         private_t *tech_pvt;
</span><span class="lines">@@ -525,21 +569,40 @@
</span><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-switch_status_t skinny_hangup(listener_t *listener, uint32_t line)
</del><ins>+struct speed_dial_get_dest_helper {
+        uint32_t pos;
+        char dest[40];
+};
+
+int skinny_speed_dial_get_dest_callback(void *pArg, int argc, char **argv, char **columnNames)
</ins><span class="cx"> {
</span><del>-        switch_channel_t *channel = NULL;
-        private_t *tech_pvt = NULL;
</del><ins>+        struct speed_dial_get_dest_helper *helper = pArg;
</ins><span class="cx">
</span><del>-        channel = switch_core_session_get_channel(listener->session[line]);
-        assert(channel != NULL);
</del><ins>+        helper->pos++;
+        if (helper->pos == atoi(argv[0])) { /* wanted_position */
+                strncpy(helper->dest, argv[3], 40); /* value */
+        }
+        return 0;
+}
</ins><span class="cx">
</span><del>-        tech_pvt = switch_core_session_get_private(listener->session[line]);
-        assert(tech_pvt != NULL);
</del><ins>+void skinny_speed_dial_get_dest(skinny_profile_t *profile, const char *device_name, uint32_t instance, char *dest)
+{
+        struct speed_dial_get_dest_helper helper = {0};
+        char *sql;
</ins><span class="cx">
</span><del>-        switch_clear_flag_locked(tech_pvt, TFLAG_IO);
-        switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
-        switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
-        return SWITCH_STATUS_SUCCESS;
</del><ins>+        switch_assert(device_name);
+
+        if ((sql = switch_mprintf(
+                        "SELECT '%d' AS wanted_position, position, label, value, settings "
+                                "FROM skinny_buttons WHERE device_name='%s' AND type='speed-dial' "
+                                "ORDER BY position",
+                        instance,
+                        device_name
+                        ))) {
+                skinny_execute_sql_callback(profile, profile->listener_mutex, sql, skinny_speed_dial_get_dest_callback, &helper);
+                switch_safe_free(sql);
+        }
+        strncpy(dest, helper.dest, 40);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> /*****************************************************************************/
</span><span class="lines">@@ -1273,8 +1336,12 @@
</span><span class="cx">         message->data.soft_key_set.total_soft_key_set_count = 11;
</span><span class="cx">         
</span><span class="cx">         /* TODO fill the set */
</span><ins>+
</ins><span class="cx">         skinny_send_reply(listener, message);
</span><span class="cx">
</span><ins>+        /* Init the states */
+        skinny_line_set_state(listener, 0, SKINNY_KEY_SET_ON_HOOK, 0);
+        
</ins><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1420,6 +1487,7 @@
</span><span class="cx">         switch_status_t status = SWITCH_STATUS_SUCCESS;
</span><span class="cx">
</span><span class="cx">         skinny_profile_t *profile;
</span><ins>+        switch_channel_t *channel = NULL;
</ins><span class="cx">         uint32_t line;
</span><span class="cx">
</span><span class="cx">         switch_assert(listener->profile);
</span><span class="lines">@@ -1438,7 +1506,7 @@
</span><span class="cx">         if(!listener->session[line]) { /*the line is not busy */
</span><span class="cx">                 switch(request->data.soft_key_event.event) {
</span><span class="cx">                         case SOFTKEY_NEWCALL:
</span><del>-                                skinny_pick_up(listener, line);
</del><ins>+                                skinny_create_session(listener, line, SKINNY_KEY_SET_OFF_HOOK);
</ins><span class="cx">                                 break;
</span><span class="cx">                         default:
</span><span class="cx">                                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
</span><span class="lines">@@ -1447,7 +1515,11 @@
</span><span class="cx">         } else { /* the line is busy */
</span><span class="cx">                 switch(request->data.soft_key_event.event) {
</span><span class="cx">                         case SOFTKEY_ENDCALL:
</span><del>-                                skinny_hangup(listener, line);
</del><ins>+                                channel = switch_core_session_get_channel(listener->session[line]);
+                                assert(channel != NULL);
+
+                                switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+
</ins><span class="cx">                                 break;
</span><span class="cx">                         default:
</span><span class="cx">                                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
</span><span class="lines">@@ -1477,11 +1549,52 @@
</span><span class="cx">         if(listener->session[line]) { /*answering a call */
</span><span class="cx">                 skinny_answer(listener->session[line]);
</span><span class="cx">         } else { /* start a new call */
</span><del>-                skinny_pick_up(listener, line);
</del><ins>+                skinny_create_session(listener, line, SKINNY_KEY_SET_OFF_HOOK);
</ins><span class="cx">         }
</span><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_message_t *request)
+{
+        skinny_profile_t *profile;
+        uint32_t line = 1;
+        private_t *tech_pvt = NULL;
+        char dest[40] = "";
+
+        switch_assert(listener->profile);
+        switch_assert(listener->device_name);
+
+        profile = listener->profile;
+
+        skinny_check_data_length(request, sizeof(request->data.stimulus));
+
+        switch(request->data.stimulus.instance_type) {
+                case SKINNY_BUTTON_VOICEMAIL:
+                        skinny_create_session(listener, line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT);
+        
+                        tech_pvt = switch_core_session_get_private(listener->session[line]);
+                        assert(tech_pvt != NULL);
+                
+                        strcpy(tech_pvt->dest, "vmain");
+                        skinny_process_dest(listener, line);
+                        break;
+                case SKINNY_BUTTON_SPEED_DIAL:
+                        skinny_speed_dial_get_dest(listener->profile, listener->device_name, request->data.stimulus.instance, dest);
+                        if(strlen(dest) > 0) {
+                                skinny_create_session(listener, line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT);
+
+                                tech_pvt = switch_core_session_get_private(listener->session[line]);
+                                assert(tech_pvt != NULL);
+                
+                                strcpy(tech_pvt->dest, dest);
+                                skinny_process_dest(listener, line);
+                        }
+                default:
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown Stimulus Type Received [%d]\n", request->data.stimulus.instance_type);
+        }
+        return SWITCH_STATUS_SUCCESS;
+}
+
</ins><span class="cx"> switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *listener, skinny_message_t *request)
</span><span class="cx"> {
</span><span class="cx">         switch_status_t status = SWITCH_STATUS_SUCCESS;
</span><span class="lines">@@ -1581,7 +1694,7 @@
</span><span class="cx">
</span><span class="cx">         skinny_check_data_length(request, sizeof(request->data.keypad_button));
</span><span class="cx">
</span><del>-        if(request->data.keypad_button.line_instance) {
</del><ins>+        if(request->data.keypad_button.line_instance != 0) {
</ins><span class="cx">                 line = request->data.keypad_button.line_instance;
</span><span class="cx">         } else {
</span><span class="cx">                 /* Find first active line */
</span><span class="lines">@@ -1619,10 +1732,6 @@
</span><span class="cx">
</span><span class="cx">                 if((skinny_line_get_state(listener, tech_pvt->line) == SKINNY_KEY_SET_OFF_HOOK)
</span><span class="cx">                                 || (skinny_line_get_state(listener, tech_pvt->line) == SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT)) {
</span><del>-                        char name[128];
-                        switch_channel_t *channel;
-                        char *cid_name = "TODO-soft_key_event"; /* TODO */
-                        char *cid_num = "00000"; /* TODO */
</del><span class="cx">                         if(strlen(tech_pvt->dest) == 0) {/* first digit */
</span><span class="cx">                                 stop_tone(listener, tech_pvt->line, tech_pvt->call_id);
</span><span class="cx">                                 skinny_line_set_state(listener, tech_pvt->line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, tech_pvt->call_id);
</span><span class="lines">@@ -1630,38 +1739,7 @@
</span><span class="cx">                         
</span><span class="cx">                         tech_pvt->dest[strlen(tech_pvt->dest)] = digit;
</span><span class="cx">                         
</span><del>-                        if(strlen(tech_pvt->dest) >= 4) { /* TODO Number is complete */
-                                if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(listener->session[line]),
-                                                                                                                                                 NULL, listener->profile->dialplan, cid_name, cid_num, listener->remote_ip, NULL, NULL, NULL, "skinny" /* modname */, listener->profile->context, tech_pvt->dest)) != 0) {
-                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(listener->session[line]), SWITCH_LOG_CRIT, "Error Creating Session caller profile\n");
-                                        goto error;
-                                }
-
-                                channel = switch_core_session_get_channel(listener->session[line]);
-                                snprintf(name, sizeof(name), "SKINNY/%s/%s/%d", listener->profile->name, listener->device_name, line);
-                                switch_channel_set_name(channel, name);
-
-                                switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
-
-                                if (switch_channel_get_state(channel) == CS_NEW) {
-                                        switch_channel_set_state(channel, CS_INIT);
-                                }
-
-                                if (switch_core_session_thread_launch(listener->session[line]) != SWITCH_STATUS_SUCCESS) {
-                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(listener->session[line]), SWITCH_LOG_CRIT, "Error Creating Session thread\n");
-                                        goto error;
-                                }
-
-                                skinny_line_set_state(listener, tech_pvt->line, SKINNY_KEY_SET_CONNECTED, tech_pvt->call_id);
-                                send_dialed_number(listener, tech_pvt->dest, tech_pvt->line, tech_pvt->call_id);
-                                skinny_answer(listener->session[line]);
-
-                                goto done;
-error:
-                        return SWITCH_STATUS_FALSE;
-done:
-                        return SWITCH_STATUS_SUCCESS;
-                        }
</del><ins>+                        skinny_process_dest(listener, tech_pvt->line);
</ins><span class="cx">                 } else {
</span><span class="cx">                         if(digit != '\0') {
</span><span class="cx">                                 switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0)};
</span><span class="lines">@@ -1687,7 +1765,7 @@
</span><span class="cx">
</span><span class="cx">         skinny_check_data_length(request, sizeof(request->data.on_hook));
</span><span class="cx">
</span><del>-        if(request->data.on_hook.line_instance) {
</del><ins>+        if(request->data.on_hook.line_instance != 0) {
</ins><span class="cx">                 line = request->data.on_hook.line_instance;
</span><span class="cx">         } else {
</span><span class="cx">                 /* Find first active line */
</span><span class="lines">@@ -1700,7 +1778,12 @@
</span><span class="cx">         }
</span><span class="cx">
</span><span class="cx">         if(listener->session[line]) {
</span><del>-                skinny_hangup(listener, line);
</del><ins>+                switch_channel_t *channel = NULL;
+
+                channel = switch_core_session_get_channel(listener->session[line]);
+                assert(channel != NULL);
+
+                switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
</ins><span class="cx">         }
</span><span class="cx">         return status;
</span><span class="cx"> }
</span><span class="lines">@@ -1758,6 +1841,8 @@
</span><span class="cx">                         return skinny_handle_soft_key_event_message(listener, request);
</span><span class="cx">                 case OFF_HOOK_MESSAGE:
</span><span class="cx">                         return skinny_handle_off_hook_message(listener, request);
</span><ins>+                case STIMULUS_MESSAGE:
+                        return skinny_handle_stimulus_message(listener, request);
</ins><span class="cx">                 case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
</span><span class="cx">                         return skinny_handle_open_receive_channel_ack_message(listener, request);
</span><span class="cx">                 case KEYPAD_BUTTON_MESSAGE:
</span></span></pre></div>
<a id="freeswitchtrunksrcmodendpointsmod_skinnyskinny_protocolh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.h (16788 => 16789)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.h        2010-02-24 12:05:34 UTC (rev 16788)
+++ freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.h        2010-02-24 12:05:45 UTC (rev 16789)
</span><span class="lines">@@ -73,7 +73,7 @@
</span><span class="cx"> struct stimulus_message {
</span><span class="cx">         uint32_t instance_type; /* See enum skinny_button_definition */
</span><span class="cx">         uint32_t instance;
</span><del>-        uint32_t call_reference;
</del><ins>+        /* uint32_t call_reference; */
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> /* OffHookMessage */
</span><span class="lines">@@ -665,6 +665,10 @@
</span><span class="cx">
</span><span class="cx"> switch_status_t skinny_send_call_info(switch_core_session_t *session);
</span><span class="cx">
</span><ins>+switch_status_t skinny_create_session(listener_t *listener, uint32_t line, uint32_t to_state);
+switch_status_t skinny_process_dest(listener_t *listener, uint32_t line);
+switch_status_t skinny_answer(switch_core_session_t *session);
+
</ins><span class="cx"> switch_status_t skinny_perform_send_reply(listener_t *listener, const char *file, const char *func, int line, skinny_message_t *reply);
</span><span class="cx"> #define skinny_send_reply(listener, reply) skinny_perform_send_reply(listener, __FILE__, __SWITCH_FUNC__, __LINE__, reply)
</span><span class="cx">
</span></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>
</body>
</html>