diff --git a/debian/ngcp-prosody-modules.install b/debian/ngcp-prosody-modules.install index addb199..0c09054 100644 --- a/debian/ngcp-prosody-modules.install +++ b/debian/ngcp-prosody-modules.install @@ -1 +1,2 @@ plugins/* /usr/lib/prosody/modules/ +util/* /usr/lib/prosody/util/ diff --git a/plugins/mod_sipwise_redis_sessions.lua b/plugins/mod_sipwise_redis_sessions.lua index 00fc467..4edf919 100644 --- a/plugins/mod_sipwise_redis_sessions.lua +++ b/plugins/mod_sipwise_redis_sessions.lua @@ -6,7 +6,9 @@ -- module:set_global(); - +require "util.table"; +local jid = require "util.jid"; +local array = require "util.array"; local redis = require 'redis'; local redis_config = { port = 6739, host = "127.0.0.1", @@ -14,6 +16,8 @@ local redis_config = { }; local redis_client; +local redis_sessions = module:shared("redis_sessions"); + local function test_connection() if not redis_client then return nil end; local ok, err = pcall(redis_client.ping, redis_client); @@ -33,18 +37,54 @@ end local function resource_bind(event) local session = event.session; + local node, domain, resource = jid.split(session.full_jid); + local full_jid, bare_jid = session.full_jid, node.."@"..domain; + module:log("debug", "resource-bind from %s", session.host); - module:log("debug", "save %s", session.full_jid); + module:log("debug", "save [%s]=%s", full_jid, redis_config.server_id); if not test_connection() then client_connect() end - redis_client:set(session.full_jid, redis_config.server_id); + redis_client:set(full_jid, redis_config.server_id); + module:log("debug", "append [%s]=>%s:%s", bare_jid, redis_config.server_id, resource); + redis_client:sadd(bare_jid, redis_config.server_id..":"..resource); + module:log("debug", "done"); end local function resource_unbind(event) local session, err = event.session, event.error; + local node, domain, resource = jid.split(session.full_jid); + local full_jid, bare_jid = session.full_jid, node.."@"..domain; + module:log("debug", "resource-unbind from %s", session.host); - module:log("debug", "remove %s", session.full_jid); + module:log("debug", "remove [%s]=%s", full_jid, redis_config.server_id); if not test_connection() then client_connect() end - redis_client:del(session.full_jid); + redis_client:del(full_jid); + module:log("debug", "remove [%s]=>%s:%s", bare_jid, redis_config.server_id, resource); + redis_client:srem(bare_jid, redis_config.server_id..":"..resource); + module:log("debug", "done"); +end + +local function split_key(key) + local t = explode(':', key); + return t[1], t[2]; +end + +function redis_sessions.get_hosts(j) + local node, domain, resource = jid.split(j); + local bare_jid = node.."@"..domain; + local res = {}; + local l, h, r; + + module:log("debug", "search session:%s host", bare_jid); + if not test_connection() then client_connect() end + l = redis_client:smembers(bare_jid); + module:log("debug", "l:%s", table.tostring(l)); + for _,v in pairs(l) do + h, r = split_key(v); + module:log("debug", "h:%s r:%s", tostring(h), tostring(r)); + if not res[h] then res[h] = array() end + res[h]:push(r); + end + return res; end function module.load() diff --git a/util/table.lua b/util/table.lua new file mode 100644 index 0000000..c131ae3 --- /dev/null +++ b/util/table.lua @@ -0,0 +1,154 @@ +-- +-- Copyright 2013 SipWise Team +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This package is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- . +-- On Debian systems, the complete text of the GNU General +-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". +-- +-- Lua utils + +-- copy a table +function table.deepcopy(object) + local lookup_table = {} + local function _copy(object) + if type(object) ~= "table" then + return object + elseif lookup_table[object] then + return lookup_table[object] + end + local new_table = {} + lookup_table[object] = new_table + for index, value in pairs(object) do + new_table[_copy(index)] = _copy(value) + end + return setmetatable(new_table, getmetatable(object)) + end + return _copy(object) +end + +function table.contains(table, element) + if table then + for _, value in pairs(table) do + if value == element then + return true + end + end --for + end --if + return false +end + +-- add if element is not in table +function table.add(t, element) + if not table.contains(t, element) then + table.insert(t, element) + end +end + +function table.val_to_str ( v ) + if "string" == type( v ) then + v = string.gsub( v, "\n", "\\n" ) + if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then + return "'" .. v .. "'" + end + return '"' .. string.gsub(v,'"', '\\"' ) .. '"' + else + return "table" == type( v ) and table.tostring( v ) or + tostring( v ) + end +end + +function table.key_to_str ( k ) + if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then + return k + else + return "[" .. table.val_to_str( k ) .. "]" + end +end + +function table.tostring( tbl ) + local result, done = {}, {} + for k, v in ipairs( tbl ) do + table.insert( result, table.val_to_str( v ) ) + done[ k ] = true + end + for k, v in pairs( tbl ) do + if not done[ k ] then + table.insert( result, + table.key_to_str( k ) .. "=" .. table.val_to_str( v ) ) + end + end + return "{" .. table.concat( result, "," ) .. "}" +end + +-- from table to string +-- t = {'a','b'} +-- implode(",",t,"'") +-- "'a','b'" +-- implode("#",t) +-- "a#b" +function implode(delimiter, list, quoter) + local len = #list + if not delimiter then + error("delimiter is nil") + end + if len == 0 then + return nil + end + if not quoter then + quoter = "" + end + local string = quoter .. list[1] .. quoter + for i = 2, len do + string = string .. delimiter .. quoter .. list[i] .. quoter + end + return string +end + +-- from string to table +function explode(delimiter, text) + local list = {} + local pos = 1 + + if not delimiter then + error("delimiter is nil") + end + if not text then + error("text is nil") + end + if string.find("", delimiter, 1) then + -- We'll look at error handling later! + error("delimiter matches empty string!") + end + while 1 do + local first, last = string.find(text, delimiter, pos) + -- print (first, last) + if first then + table.insert(list, string.sub(text, pos, first-1)) + pos = last+1 + else + table.insert(list, string.sub(text, pos)) + break + end + end + return list +end + +function string.starts(String,Start) + return string.sub(String,1,string.len(Start))==Start +end + +function string.ends(String,End) + return End=='' or string.sub(String,-string.len(End))==End +end