require 'xmlrpc/server'
require 'xmlrpc/parser'
require 'xmlrpc/create'
require 'xmlrpc/config'
require 'xmlrpc/utils' # ParserWriterChooseMixin
require 'xmpp4r/dataforms/x/data'
require 'xmpp4r/rpc/iq/rpc'
require 'xmpp4r/rpc/helper/xmlrpcaddons'
module Jabber
module RPC
##
# XMLRPC Client
class Client
include XMLRPC::ParserWriterChooseMixin
include XMLRPC::ParseContentType
attr_accessor :my_jid
##
# xmppstream
# stream:: [Stream]
# jid where you want to send the rpc requests to
# jid:: [JID] rpcserver@jabberserver/ressource
def initialize(stream,jid)
@jid = JID.new(jid)
@my_jid = stream.jid
@stream = stream
@parser = nil
@create = XMLRPC::Create.new
end
##
# automatically trys to find a method
# thanx to eric cestari :)
def method_missing(methodname, *args)
send("call", methodname,*args)
end
def call(method, *args)
ok, param = call2(method, *args)
if ok
param
else
raise param
end
end
def call2(method, *args)
request = @create.methodCall(method, *args)
data = do_rpc(request)
parser().parseMethodResponse(data)
end
##
# adds multi rpcalls to the query
# methods:: [Array]
def multicall(*methods)
ok, params = multicall2(*methods)
if ok
params
else
raise params
end
end
##
# generate a multicall
# methods:: [Array]
def multicall2(*methods)
gen_multicall(methods)
end
def do_rpc(xmlrpc)
iq = Iq.new(:set, @jid)
iq.from = @my_jid
iq.id = IdGenerator::generate_id
rpcquery = iq.add(IqQueryRPC.new)
rpcquery.typed_add(xmlrpc)
result = nil
@stream.send_with_id(iq) do |iqreply|
if iqreply.query.kind_of?(IqQueryRPC)
result = iqreply.query.to_s
end
end
result
end
private
def gen_multicall(methods=[])
ok, params = call2("system.multicall",
methods.collect { |m|
{
'methodName' => m[0],
'params' => m[1..-1]
}
}
)
if ok
params = params.collect{ |param|
if param.is_a? Array
param[0]
elsif param.is_a? Hash
XMLRPC::FaultException.new(param["faultCode"], param["faultString"])
else
raise "Wrong multicall return value"
end
}
end
return ok, params
end
end
end # Helpers
end # Jabber