<!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][14500] </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=14500">14500</a></dd>
<dt>Author</dt> <dd>seven</dd>
<dt>Date</dt> <dd>2009-08-12 11:37:28 -0500 (Wed, 12 Aug 2009)</dd>
</dl>

<h3>Log Message</h3>
<pre>add lua script</pre>

<h3>Added Paths</h3>
<ul>
<li>freeswitch/trunk/contrib/seven/lua/</li>
<li><a href="#freeswitchtrunkcontribsevenluagateway_reportlua">freeswitch/trunk/contrib/seven/lua/gateway_report.lua</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunkcontribsevenluagateway_reportlua"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/seven/lua/gateway_report.lua (0 => 14500)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/seven/lua/gateway_report.lua                                (rev 0)
+++ freeswitch/trunk/contrib/seven/lua/gateway_report.lua        2009-08-12 16:37:28 UTC (rev 14500)
</span><span class="lines">@@ -0,0 +1,366 @@
</span><ins>+--- Lua gateway report - Monitor and report gateway status by catching events
+--- Seven AT idapted.com
+  
+--[[
+  Listen to FreeSWITCH events and report to
+        1) fire an event
+        2) post to a http server
+        3) write to db (not yet implemented)
+        
+  Report when:                                                           
+        1) more than 1 continues failed calls
+        2) a successful call flowed by failed calls
+
+  Params:        
+        Total-Failed-Calls: Count of faied calls from init of the lua script
+        Continue-Failed-Calls: counts till a succeful call detected
+        Last-Failed-Calls: count of failed calls from the last report
+        Last-Failed-Calls[x]: count of the last Sample-Time minutes
+        Sample-Time[x]: not a continuouse time. Say if it's value is 5, and we catch an event once a minute, that would be 5 minutes. But if we catch an event once a day, can be five days.            
+        
+  Usage: in FreeSWITCH console or fs_cli,
+        luarun gw.lua &lt;http_post | fire_event | db &gt;
+        luarun gw.lua db [odbc | mysql | sqlite3 | psql | ... ]
+        luarun gw.lua debug
+        luarun gw.lua stop
+        
+        in lua.conf.xml:
+        &lt;param name=&quot;startup-script&quot; value=&quot;gateway_report.lua&quot;/&gt;
+        
+  A sample event:
+
+&lt;event&gt;
+  &lt;headers&gt;
+    &lt;Event-Name&gt;CUSTOM&lt;/Event-Name&gt;
+    &lt;Core-UUID&gt;94a01890-3e62-4758-b1a5-f2cbe0d7b4b3&lt;/Core-UUID&gt;
+    &lt;FreeSWITCH-Hostname&gt;localhost&lt;/FreeSWITCH-Hostname&gt;
+    &lt;FreeSWITCH-IPv4&gt;192.168.1.27&lt;/FreeSWITCH-IPv4&gt;
+    &lt;FreeSWITCH-IPv6&gt;%3A%3A1&lt;/FreeSWITCH-IPv6&gt;
+    &lt;Event-Date-Local&gt;2009-08-12%2010%3A38%3A05&lt;/Event-Date-Local&gt;
+    &lt;Event-Date-GMT&gt;Wed,%2012%20Aug%202009%2002%3A38%3A05%20GMT&lt;/Event-Date-GMT&gt;
+    &lt;Event-Date-Timestamp&gt;1250044685793509&lt;/Event-Date-Timestamp&gt;
+    &lt;Event-Calling-File&gt;switch_cpp.cpp&lt;/Event-Calling-File&gt;
+    &lt;Event-Calling-Function&gt;Event&lt;/Event-Calling-Function&gt;
+    &lt;Event-Calling-Line-Number&gt;235&lt;/Event-Calling-Line-Number&gt;
+    &lt;Event-Subclass&gt;luagw%3A%3Areport&lt;/Event-Subclass&gt;
+    &lt;Sip-Gateway-Name&gt;officepbx&lt;/Sip-Gateway-Name&gt;
+    &lt;Sip-Gateway-Total-Calls&gt;6&lt;/Sip-Gateway-Total-Calls&gt;
+    &lt;Sip-Gateway-Last-Calls&gt;6&lt;/Sip-Gateway-Last-Calls&gt;
+    &lt;Sip-Gateway-Total-Failed-Calls&gt;6&lt;/Sip-Gateway-Total-Failed-Calls&gt;
+    &lt;Sip-Gateway-Continue-Failed-Calls&gt;0&lt;/Sip-Gateway-Continue-Failed-Calls&gt;
+    &lt;Sip-Gateway-Last-Failed-Calls&gt;0&lt;/Sip-Gateway-Last-Failed-Calls&gt;
+    &lt;Sip-Gateway-Last-Failed-Calls1&gt;6&lt;/Sip-Gateway-Last-Failed-Calls1&gt;
+    &lt;Sip-Gateway-Last-Failed-Calls2&gt;6&lt;/Sip-Gateway-Last-Failed-Calls2&gt;
+    &lt;Sip-Gateway-Sample-Time1&gt;5&lt;/Sip-Gateway-Sample-Time1&gt;
+    &lt;Sip-Gateway-Sample-Time2&gt;10&lt;/Sip-Gateway-Sample-Time2&gt;
+  &lt;/headers&gt;
+&lt;/event&gt;
+]]
+
+-- Standard FreeSWITCH doesn't has argv[0]
+argv[0] = &quot;gateway_report.lua&quot;
+
+script_name = argv[0]
+report_type = argv[1] or &quot;http_post&quot;
+
+debug = {} 
+
+function debug.var(k, v)
+        v = v or 'nil'
+        freeswitch.consoleLog(&quot;notice&quot;, &quot;==DebugVar== &quot; .. k .. &quot;: &quot; .. v .. &quot;\n&quot;)
+end
+function debug.info(s)
+        freeswitch.consoleLog(&quot;info&quot;, s .. &quot;\n&quot;)
+end
+function debug.notice(s)
+        freeswitch.consoleLog(&quot;notice&quot;, s .. &quot;\n&quot;)
+end
+
+if argv[1] == &quot;stop&quot; then
+        local event = freeswitch.Event(&quot;custom&quot;, &quot;lua::stopscript&quot;);
+        event:addHeader(&quot;Seven&quot;, &quot;7777777&quot;);
+        event:fire();
+        debug.info(&quot;Sent stop message to lua script[&quot; .. argv[0] .. &quot;]&quot;)
+        return;
+end
+
+if argv[1] == &quot;debug&quot; then
+        local event = freeswitch.Event(&quot;custom&quot;, &quot;lua::debugscript&quot;);
+        event:addHeader(&quot;Seven&quot;, &quot;7777777&quot;);
+        event:fire();
+        debug.info(&quot;Sent debug message to lua script[&quot; .. argv[0] .. &quot;]&quot;)
+        return;
+end
+
+if report_type == &quot;http_post&quot; then
+        require 'socket'
+        local host = &quot;127.0.0.1&quot;
+        local port = 3003
+        local path = '/test.xml'
+
+        function http_post(params)
+                                   
+                -- print(&quot;sending &quot; .. params) 
+                -- params = &quot;&lt;?xml version='1.0' encoding='UTF-8'?&gt;\n&quot; .. params .. &quot;\n&quot;
+                local http_header = &quot;POST &quot; .. path .. &quot; HTTP/1.1\r\n&quot;
+                        .. &quot;User-Agent: FreeSWITCH-Lua\r\n&quot;
+                        .. &quot;Host: &quot; .. host .. &quot;:&quot; .. port .. &quot;\r\n&quot;
+                        .. &quot;Accept: */*\r\n&quot;
+                        .. &quot;Connection: close\r\n&quot;
+                        .. &quot;Content-Length: &quot; .. #params .. &quot;\r\n&quot;
+                        .. &quot;Content-Type: application/xml\r\n\r\n&quot;
+        --                .. &quot;Content-Type: application/x-www-form-urlencoded\r\n\r\n&quot; .. params
+                        .. params
+
+                -- print(http_header)
+
+                local conn = socket.connect(host, port)
+                if (conn) then
+                        conn:send(http_header)
+                        conn:close()
+                        return true
+                else
+                        debug.notice(&quot;Error posting to server: &quot; .. host .. &quot;:&quot; .. port )
+                end            
+                return false
+        
+        end
+end
+
+
+if report_type == &quot;db&quot; then
+    
+        TABLE_NAME = &quot;voip_outbound_gateways&quot;
+    
+    local db_adapter = argv[2] or 'sqlite3'
+
+        if (db_adapter ~= &quot;sqlite3&quot; ) then
+                debug.info( &quot;db_adapter &quot; .. db_adapter .. &quot;not implemented yet!&quot;)
+                return
+        end
+
+        require 'luasql.sqlite3'
+        env = assert(luasql.sqlite3())
+        db_conn = assert(env:connect (&quot;test.sqlite3&quot;, &quot;root&quot;, &quot;&quot;, &quot;localhost&quot;))
+
+        -- local sql = &quot;CREATE TABLE &quot; .. TABLE_NAME .. [[
+        --         (   id integer pramary_key,
+        --                 gateway_name varchar(255), 
+        --                 total_calls integer default 0,
+        --                 total_failed_calls integer default 0,
+        --                 continue_failed_calls integer default 0,
+        --                 last_failed_calls1 integer default 0,
+        --                 last_failed_calls2 integer default 0 ); ]]
+        -- print(sql)
+        -- conn:execute(sql)
+end
+
+--Main function starts here                                                                   
+freeswitch.consoleLog(&quot;info&quot;, &quot;-- Lua Script [&quot; .. argv[0] .. &quot;] Starting --\n&quot;);
+                      
+local all_events = 0
+local processed_events = 0
+local event_name
+local event_subclass
+local gateways = {}
+local SAMPLE_TIME1 = 5
+local SAMPLE_TIME2 = 10            
+local mt = {__index = function() return 0 end}
+
+function ensure_gateway(gateway)
+        -- ensure values not nil and numeric value default to 0
+        if gateways[gateway] then return end
+        
+        gateways[gateway] = {last_failed_calls1 = {}, last_failed_calls2 = {}}
+        setmetatable(gateways[gateway], mt)
+        setmetatable(gateways[gateway].last_failed_calls1, mt)
+        setmetatable(gateways[gateway].last_failed_calls2, mt)
+end                                                              
+
+function prepare_event(gateway)
+
+        local count1 = 0;
+        local count2 = 0;
+        
+        for k,v in ipairs(gateways[gateway].last_failed_calls1) do
+                count1 = count1 + v
+        end
+        for k,v in ipairs(gateways[gateway].last_failed_calls2) do
+                count2 = count2 + v
+        end
+        
+        local event = freeswitch.Event(&quot;custom&quot;, &quot;luagw::report&quot;);
+        event:addHeader(&quot;Sip-Gateway-Name&quot;, gateway)
+        event:addHeader(&quot;Sip-Gateway-Total-Calls&quot;, gateways[gateway].total_calls)
+        event:addHeader(&quot;Sip-Gateway-Last-Calls&quot;, gateways[gateway].last_calls)
+        event:addHeader(&quot;Sip-Gateway-Total-Failed-Calls&quot;, gateways[gateway].total_failed_calls)
+        event:addHeader(&quot;Sip-Gateway-Continue-Failed-Calls&quot;, gateways[gateway].continue_failed_calls)
+        event:addHeader(&quot;Sip-Gateway-Last-Failed-Calls&quot;, gateways[gateway].last_failed_calls)
+        event:addHeader(&quot;Sip-Gateway-Last-Failed-Calls1&quot;, count1)
+        event:addHeader(&quot;Sip-Gateway-Last-Failed-Calls2&quot;, count2)
+        event:addHeader(&quot;Sip-Gateway-Sample-Time1&quot;, SAMPLE_TIME1)
+        event:addHeader(&quot;Sip-Gateway-Sample-Time2&quot;, SAMPLE_TIME2)
+        return event
+                         
+end        
+
+function reset_gateway_values(gateway)
+        gateways[gateway].last_failed_calls = 0
+        gateways[gateway].last_calls = 0
+end
+
+function do_fire_gateway_event(gateway)
+        local event = prepare_event(gateway)
+        event:fire();
+        reset_gateway_values(gateway)
+end
+
+function do_http_post(gateway)
+        local event = prepare_event(gateway)
+        if (http_post(event:serialize(&quot;xml&quot;))) then
+                reset_gateway_values(gateway)
+        end
+end        
+
+function do_db_update(gateway)
+        local count1 = 0;
+        local count2 = 0;
+
+        for k,v in ipairs(gateways[gateway].last_failed_calls1) do
+                count1 = count1 + v
+        end
+        for k,v in ipairs(gateways[gateway].last_failed_calls2) do
+                count2 = count2 + v
+        end
+
+        local sql = &quot;UPDATE &quot; .. TABLE_NAME
+                .. &quot; SET total_calls = total_calls + &quot; .. gateways[gateway].last_calls
+                .. &quot;,    total_failed_calls = total_failed_calls + &quot; .. gateways[gateway].last_failed_calls
+                .. &quot;,    last_failed_calls1 = &quot; .. count1
+                .. &quot;,    last_failed_calls2 = &quot; .. count2
+                .. &quot;,    continue_failed_calls = &quot; .. gateways[gateway].continue_failed_calls
+                .. &quot; WHERE gateway_name = '&quot; .. gateway .. &quot;'&quot;
+        print(sql)
+        local result = db_conn:execute(sql)
+        if result and result &gt; 0 then
+                reset_gateway_values(gateway)
+        end
+end
+
+function do_gateway_report(gateway)
+        if (report_type == &quot;fire_event&quot;) then
+                do_fire_gateway_event(gateway)
+        elseif (report_type == &quot;http_post&quot;) then
+                do_http_post(gateway) 
+        elseif (report_type == &quot;db&quot;) then
+                do_db_update(gateway)
+        else
+                debug.notice(&quot;report_type &quot; .. report_type .. &quot; not yet implemented!&quot;)
+        end
+end
+                                              
+local index1 = 0;
+local index2 = 0;                           
+
+con = freeswitch.EventConsumer(&quot;all&quot;);                                                                         
+for e in (function() return con:pop(1) end) do
+  -- freeswitch.consoleLog(&quot;info&quot;, &quot;event\n&quot; .. e:serialize(&quot;xml&quot;));
+          all_events = all_events + 1;
+        
+        event_name = e:getHeader(&quot;Event-Name&quot;) or &quot;&quot;
+        event_subclass = e:getHeader(&quot;Event-Subclass&quot;) or &quot;&quot;
+        
+        if (event_name == &quot;CHANNEL_HANGUP&quot;) then
+                processed_events = processed_events + 1;
+
+                local gateway = e:getHeader(&quot;variable_sip_gateway_name&quot;)
+                debug.var(&quot;gateway_name&quot;, gateway)
+                
+                if (gateway) then       
+
+                        ensure_gateway(gateway)
+
+                        local hangup_cause = e:getHeader(&quot;Hangup-Cause&quot;)
+                        -- debug.var(&quot;hangup-cause&quot;, hangup_cause)
+                        gateways[gateway].total_calls =  gateways[gateway].total_calls + 1
+                        gateways[gateway].last_calls =  gateways[gateway].last_calls + 1
+
+                        if (e:getHeader(&quot;Answer-State&quot;) ~= &quot;answered&quot; and hangup_cause ~= &quot;USER_BUSY&quot;) then
+                        
+                                gateways[gateway].total_failed_calls =  gateways[gateway].total_failed_calls + 1
+                                gateways[gateway].last_failed_calls =  gateways[gateway].last_failed_calls + 1
+                                gateways[gateway].continue_failed_calls =  gateways[gateway].continue_failed_calls + 1
+                                                       
+                                -- drop count values into a loop queue
+                                curr_timestamp = math.floor(tonumber(e:getHeader(&quot;Event-Date-Timestamp&quot;)) / 60000000)
+                                
+                                if (curr_timestamp == last_timestamp1) then
+                                        gateways[gateway].last_failed_calls1[index1] = gateways[gateway].last_failed_calls1[index1] + 1
+                                else                                
+                                        last_timestamp1 = curr_timestamp
+                                        index1 = index1 &lt; SAMPLE_TIME1 and (index1 + 1) or 1
+                                        gateways[gateway].last_failed_calls1[index1] = 1
+                                end
+
+                                if (curr_timestamp == last_timestamp2) then
+                                        gateways[gateway].last_failed_calls2[index2] = gateways[gateway].last_failed_calls2[index2] + 1
+                                else                                
+                                        last_timestamp2 = curr_timestamp
+                                        index2 = index2 &lt; SAMPLE_TIME2 and (index2 + 1) or 1
+                                        gateways[gateway].last_failed_calls2[index2] = 1
+                                end
+                                                                
+                                if (gateways[gateway].continue_failed_calls &gt; 1) then
+                                        do_gateway_report(gateway)
+                                end
+                        end
+                end
+                
+        elseif (event_name == &quot;CHANNEL_ANSWER&quot;) then
+                processed_events = processed_events + 1;
+        
+                local gateway = e:getHeader(&quot;variable_sip_gateway_name&quot;)
+                debug.var(&quot;gateway_name&quot;, gateway)
+                
+                if (gateway) then             
+                        ensure_gateway(gateway)
+
+                        if (gateways[gateway].continue_failed_calls &gt; 0)  then
+                                gateways[gateway].continue_failed_calls = 0
+                                  do_gateway_report(gateway)
+                        end
+                end
+                
+        end     
+                                                                                         
+        if (event_name == &quot;CUSTOM&quot; and event_subclass == &quot;lua::stopscript&quot;) then
+                freeswitch.consoleLog(&quot;info&quot;, &quot;--lua Script [&quot; .. argv[0] .. &quot;] got stop message, Exiting--\n&quot;)
+                break
+        end
+        
+        if (event_name == &quot;CUSTOM&quot; and event_subclass == &quot;lua::debugscript&quot;) then
+                local message = &quot;--lua Script [&quot; .. argv[0] .. &quot;] got debug message, Reporting--\n&quot;
+                                   
+                message = message .. &quot;all_events: &quot; .. all_events .. &quot;\n&quot;
+                        .. &quot;processed_events: &quot; .. processed_events .. &quot;\n&quot;
+                for g, gv in pairs(gateways) do 
+                        message = message .. &quot;gateway: &quot; .. g .. &quot;\n&quot;
+                                .. &quot;total_failed_calls: &quot; .. gv.total_failed_calls .. &quot;\n&quot;
+                                .. &quot;continue_failed_calls: &quot; .. gv.continue_failed_calls .. &quot;\n&quot;
+                                .. &quot;last_failed_calls: &quot; .. gv.last_failed_calls .. &quot;\n&quot;
+                                .. &quot;index1: &quot; .. index1 .. &quot;\n&quot;
+                                .. &quot;index2: &quot; .. index2 .. &quot;\n&quot;
+                        
+                        for k,v in ipairs(gv.last_failed_calls1) do
+                                message = message .. &quot;last_failed_calls1[&quot; .. k .. &quot;]: &quot; .. v .. &quot;\n&quot;
+                        end
+                        for k,v in ipairs(gv.last_failed_calls2) do
+                                message = message .. &quot;last_failed_calls2[&quot; .. k .. &quot;]: &quot; .. v .. &quot;\n&quot;
+                        end
+
+                end
+                debug.info(message)
+        end
+        
+end 
+
</ins></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>

</body>
</html>