isbear@59: --[[ Copyright 2009-2016 Myhailo Danylenko isbear@23: isbear@23: This program is free software: you can redistribute it and/or modify isbear@23: it under the terms of the GNU General Public License as published by isbear@23: the Free Software Foundation, either version 2 of the License, or isbear@23: (at your option) any later version. isbear@23: isbear@23: This program is distributed in the hope that it will be useful, isbear@23: but WITHOUT ANY WARRANTY; without even the implied warranty of isbear@23: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the isbear@23: GNU General Public License for more details. isbear@23: isbear@23: You should have received a copy of the GNU General Public License isbear@23: along with this program. If not, see . ]] isbear@0: isbear@16: local lm = require 'loudmouth' isbear@0: isbear@59: -- Argument is a table with keys: isbear@59: -- * server - server name to connect to isbear@59: -- * port - port to connect to isbear@59: -- * type - proxy type isbear@59: -- * username - uername to authenticate on proxy isbear@59: -- * password - password to authenticate with isbear@0: function lm.proxy.create ( a ) isbear@0: if type ( a ) ~= "table" then isbear@6: error "arguments should be in a table" isbear@0: end isbear@0: local p = lm.proxy.new () isbear@0: if a.server then isbear@0: p:server ( a.server ) isbear@0: end isbear@0: if a.port then isbear@0: p:port ( a.port ) isbear@0: end isbear@0: if a['type'] then isbear@0: p:type ( a['type'] ) isbear@0: end isbear@0: if a.username then isbear@0: p:username ( a.username ) isbear@0: end isbear@0: if a.password then isbear@0: p:password ( a.password ) isbear@0: end isbear@0: return p isbear@0: end isbear@0: isbear@59: -- Argument is a table with keys: isbear@59: -- * fingerprint - fingerprint string isbear@59: -- * callback - ssl error callback isbear@59: -- * tls - string - one of "on", "required", "off" (default) isbear@59: -- * ca_path - path to trusted certificates isbear@59: -- * cipher_list - list of allowed ciphers to ues isbear@0: function lm.ssl.create ( a ) isbear@0: if not lm.ssl.supported () then isbear@0: -- XXX isbear@6: -- error "ssl is not supported by your loudmouth library" isbear@0: return nil isbear@0: end isbear@59: local fp, cb, ut, rt, ca, cl isbear@0: local st = type ( a ) isbear@0: if st == "table" then isbear@0: fp = a.fingerprint isbear@0: cb = a.callback isbear@59: ca = a.ca_path isbear@59: cl = a.cipher_list isbear@59: tl = a.tls isbear@59: if tl ~= nil then isbear@59: if tl == "on" then isbear@59: ut = true isbear@59: rt = false isbear@59: elseif tl == "required" then isbear@59: ut = true isbear@59: rt = true isbear@59: end isbear@59: end isbear@0: elseif st == "function" then isbear@0: cb = a isbear@0: elseif st == "string" then isbear@0: fp = a isbear@0: elseif st ~= "nil" then isbear@6: error "unexpected type of argument" isbear@0: end isbear@42: local ssl isbear@0: if fp then isbear@0: if cb then isbear@42: ssl = lm.ssl.new ( fp, cb ) isbear@0: else isbear@42: ssl = lm.ssl.new ( fp ) isbear@0: end isbear@0: else isbear@0: if cb then isbear@42: ssl = lm.ssl.new ( cb ) isbear@0: else isbear@42: ssl = lm.ssl.new () isbear@0: end isbear@0: end isbear@59: if ca ~= nil then isbear@59: ssl:ca_path ( ca ) isbear@59: end isbear@59: if cl ~= nil then isbear@59: ssl:cipher_list ( cl ) isbear@59: end isbear@42: if ut ~= nil then isbear@42: ssl:tls ( ut, rt ) isbear@42: end isbear@42: return ssl isbear@0: end isbear@0: isbear@59: -- Argument is a table with keys: isbear@59: -- * server - server name isbear@59: -- * context - glib main context isbear@59: -- * port - server port isbear@59: -- * jid - jid to connect with isbear@59: -- * keep_alive_rate - rate of keep alive packets isbear@59: -- * proxy - lm.proxy object or table isbear@59: -- * ssl - lm.ssl object or table isbear@59: -- * ondisconnect - disconnect callback isbear@59: -- * handlers - table with { "type/priority" = function/object } mapping isbear@0: function lm.connection.create ( a ) isbear@0: local at = type (a) isbear@0: if at == "string" then isbear@0: return lm.connection.new ( a ) isbear@0: elseif at == "table" then isbear@0: local server = a.server isbear@0: if not server then isbear@6: error "server name parameter required" isbear@0: end isbear@0: isbear@0: -- create connection object isbear@0: local c isbear@0: if a.context then isbear@0: c = lm.connection.new ( server, a.context ) isbear@0: else isbear@0: c = lm.connection.new ( server ) isbear@0: end isbear@0: isbear@0: -- connection parameters isbear@0: if a.port then isbear@0: c:port ( a.port ) isbear@0: end isbear@0: if a.jid then isbear@0: c:jid ( a.jid ) isbear@0: end isbear@0: if a.keep_alive_rate then isbear@0: c:keep_alive_rate ( a.keep_alive_rate ) isbear@0: end isbear@0: isbear@0: -- proxy isbear@0: if a.proxy then isbear@0: local pt = type ( a.proxy ) isbear@0: if pt == "userdata" then isbear@0: c:proxy ( a.proxy ) isbear@0: else isbear@0: local proxy = lm.proxy.create ( a.proxy ) isbear@0: c:proxy ( proxy ) isbear@0: end isbear@0: end isbear@0: isbear@0: -- ssl isbear@0: if a.ssl then isbear@0: local st = type ( a.ssl ) isbear@0: if st == "userdata" then isbear@0: c:ssl ( a.ssl ) isbear@0: else isbear@0: local ssl = lm.ssl.create ( a.ssl ) isbear@0: c:ssl ( ssl ) isbear@0: end isbear@0: end isbear@0: isbear@0: -- disconnect callback isbear@0: if a.ondisconnect then isbear@0: c:ondisconnect ( a.ondisconnect ) isbear@0: end isbear@0: isbear@0: -- message handlers isbear@0: if a.handlers then isbear@0: if type ( a.handlers ) ~= "table" then isbear@0: error ( "handlers parameter expected to be a table " .. isbear@0: "of the form { \"type/priority\" = function/object }" ) isbear@0: end isbear@0: for mhtype, handler in pairs ( a.handlers ) do isbear@0: local mtype, prio = mhtype:match ( "(.-)/(%d+)" ) isbear@0: if not mtype then isbear@0: mtype = mhtype isbear@0: prio = 0 isbear@0: else isbear@0: prio = tonumber ( prio ) isbear@0: end isbear@0: c:handler ( handler, mtype, prio ) isbear@0: end isbear@0: end isbear@0: isbear@0: return c isbear@0: else isbear@7: error "at least server name parameter required" isbear@0: end isbear@0: end isbear@0: isbear@0: -- TODO: multiple nodes with same name isbear@0: function lm.message_node.parse ( node, r ) isbear@18: local n = node:child () isbear@0: while n do isbear@0: local name = n:name () isbear@0: r[name] = { } isbear@0: local value = n:value () isbear@0: if value then isbear@0: r[name][1] = value isbear@0: end isbear@0: lm.message_node.parse ( n, r[name] ) isbear@0: n = n:next () isbear@0: end isbear@0: end isbear@0: isbear@0: -- There are NO WAY to get a list of node attributes, isbear@0: -- except brute force... isbear@0: function lm.message.parse ( message ) isbear@0: local mtype, subtype = message:type () isbear@0: if subtype then isbear@0: mtype = mtype .. '-' .. subtype isbear@0: end isbear@0: local r = { mtype = mtype } isbear@7: local value = message:value () isbear@0: if value then isbear@0: r[1] = value isbear@0: end isbear@7: lm.message_node.parse ( message, r ) isbear@0: return r isbear@0: end isbear@0: isbear@59: -- The same table, as for lm.connection.create, but with few more fields: isbear@59: -- * ssl.validate - boolean isbear@59: -- * preopen - callback to call after connection creation but before opening (to install log handler, for example) isbear@59: -- * onopen - callback to call after connection is established, but before authentication isbear@59: -- * onconnect - callback to call after connection will be established isbear@59: -- * username - username to authenticate with isbear@59: -- * password - password to authenticate with isbear@59: -- * resource - jabber resource to use isbear@0: function lm.connect ( a ) isbear@0: if type ( a ) ~= "table" then isbear@6: error "table expected as argument" isbear@0: end isbear@0: if a.ssl then isbear@0: if a.ssl.validate and not a.ssl.callback then isbear@0: a.ssl.callback = isbear@0: function ( obj, status ) isbear@0: return false isbear@0: end isbear@0: end isbear@0: end isbear@0: local c = lm.connection.create ( a ) isbear@36: if type ( a.preopen ) == "function" then isbear@36: a.preopen ( c ) -- XXX isbear@36: end isbear@0: c:open ( isbear@0: function ( obj, status ) isbear@0: if status then isbear@0: if type ( a.onopen ) == "function" then isbear@0: a.onopen ( obj ) isbear@0: end isbear@0: c:authenticate ( a.username, a.password, a.resource, isbear@0: function ( obj, status ) isbear@0: if type ( a.onconnect ) == "function" then isbear@0: a.onconnect ( obj ) isbear@0: end isbear@0: end ) isbear@0: end isbear@0: end ) isbear@0: return c isbear@0: end isbear@0: isbear@16: return lm isbear@16: isbear@36: -- vim: se ts=4 sw=4: --