--[[ Copyright 2009 Myhailo Danylenko
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 2 of the License, or
(at your option) any later version.
This program 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 <http://www.gnu.org/licenses/>. ]]
local lm = require 'loudmouth'
-- argument is a table with keys,
-- corresponding to method names.
function lm.proxy.create ( a )
if type ( a ) ~= "table" then
error "arguments should be in a table"
end
local p = lm.proxy.new ()
if a.server then
p:server ( a.server )
end
if a.port then
p:port ( a.port )
end
if a['type'] then
p:type ( a['type'] )
end
if a.username then
p:username ( a.username )
end
if a.password then
p:password ( a.password )
end
return p
end
-- argument is a table with two keys:
-- callback and fingerprint
function lm.ssl.create ( a )
if not lm.ssl.supported () then
-- XXX
-- error "ssl is not supported by your loudmouth library"
return nil
end
local fp, cb, ut, rt
local st = type ( a )
if st == "table" then
fp = a.fingerprint
cb = a.callback
ut = a.tls
rt = a.require_tls
elseif st == "function" then
cb = a
elseif st == "string" then
fp = a
elseif st ~= "nil" then
error "unexpected type of argument"
end
local ssl
if fp then
if cb then
ssl = lm.ssl.new ( fp, cb )
else
ssl = lm.ssl.new ( fp )
end
else
if cb then
ssl = lm.ssl.new ( cb )
else
ssl = lm.ssl.new ()
end
end
if ut ~= nil then
ssl:tls ( ut, rt )
end
return ssl
end
-- basically, it just provides a way
-- to initialize many parameters at once.
-- keys in a table correspond to methods
-- of connection object, except for handlers,
-- where format is {
-- "type/priority" = function/object,
-- ...
-- }
-- two extra keys - server and context.
-- ssl and proxy objects can either be objects
-- or tables, directly passed to corresponding
-- create routine.
function lm.connection.create ( a )
local at = type (a)
if at == "string" then
return lm.connection.new ( a )
elseif at == "table" then
local server = a.server
if not server then
error "server name parameter required"
end
-- create connection object
local c
if a.context then
c = lm.connection.new ( server, a.context )
else
c = lm.connection.new ( server )
end
-- connection parameters
if a.port then
c:port ( a.port )
end
if a.jid then
c:jid ( a.jid )
end
if a.keep_alive_rate then
c:keep_alive_rate ( a.keep_alive_rate )
end
-- proxy
if a.proxy then
local pt = type ( a.proxy )
if pt == "userdata" then
c:proxy ( a.proxy )
else
local proxy = lm.proxy.create ( a.proxy )
c:proxy ( proxy )
end
end
-- ssl
if a.ssl then
local st = type ( a.ssl )
if st == "userdata" then
c:ssl ( a.ssl )
else
local ssl = lm.ssl.create ( a.ssl )
c:ssl ( ssl )
end
end
-- disconnect callback
if a.ondisconnect then
c:ondisconnect ( a.ondisconnect )
end
-- message handlers
if a.handlers then
if type ( a.handlers ) ~= "table" then
error ( "handlers parameter expected to be a table " ..
"of the form { \"type/priority\" = function/object }" )
end
for mhtype, handler in pairs ( a.handlers ) do
local mtype, prio = mhtype:match ( "(.-)/(%d+)" )
if not mtype then
mtype = mhtype
prio = 0
else
prio = tonumber ( prio )
end
c:handler ( handler, mtype, prio )
end
end
return c
else
error "at least server name parameter required"
end
end
-- TODO: multiple nodes with same name
function lm.message_node.parse ( node, r )
local n = node:child ()
while n do
local name = n:name ()
r[name] = { }
local value = n:value ()
if value then
r[name][1] = value
end
lm.message_node.parse ( n, r[name] )
n = n:next ()
end
end
-- There are NO WAY to get a list of node attributes,
-- except brute force...
function lm.message.parse ( message )
local mtype, subtype = message:type ()
if subtype then
mtype = mtype .. '-' .. subtype
end
local r = { mtype = mtype }
local value = message:value ()
if value then
r[1] = value
end
lm.message_node.parse ( message, r )
return r
end
-- the same table, as for lm.connection.create, but with few more fields:
-- ssl.validate - boolean
-- preopen - callback to call after connection creation but before opening (to install log handler, for example)
-- onopen - callback to call after connection is established, but before authentication
-- onconnect - callback to call after connection will be established
-- username
-- password
-- resource
function lm.connect ( a )
if type ( a ) ~= "table" then
error "table expected as argument"
end
if a.ssl then
if a.ssl.validate and not a.ssl.callback then
a.ssl.callback =
function ( obj, status )
return false
end
end
end
local c = lm.connection.create ( a )
if type ( a.preopen ) == "function" then
a.preopen ( c ) -- XXX
end
c:open (
function ( obj, status )
if status then
if type ( a.onopen ) == "function" then
a.onopen ( obj )
end
c:authenticate ( a.username, a.password, a.resource,
function ( obj, status )
if type ( a.onconnect ) == "function" then
a.onconnect ( obj )
end
end )
end
end )
return c
end
return lm
-- vim: se ts=4 sw=4: --