summaryrefslogtreecommitdiff
path: root/sleekxmpp/plugins/xep_0009/rpc.py
diff options
context:
space:
mode:
Diffstat (limited to 'sleekxmpp/plugins/xep_0009/rpc.py')
-rw-r--r--sleekxmpp/plugins/xep_0009/rpc.py221
1 files changed, 221 insertions, 0 deletions
diff --git a/sleekxmpp/plugins/xep_0009/rpc.py b/sleekxmpp/plugins/xep_0009/rpc.py
new file mode 100644
index 00000000..4f749f30
--- /dev/null
+++ b/sleekxmpp/plugins/xep_0009/rpc.py
@@ -0,0 +1,221 @@
+"""
+ SleekXMPP: The Sleek XMPP Library
+ Copyright (C) 2011 Nathanael C. Fritz, Dann Martens (TOMOTON).
+ This file is part of SleekXMPP.
+
+ See the file LICENSE for copying permission.
+"""
+
+from sleekxmpp.plugins import base
+from sleekxmpp.plugins.xep_0009.stanza.RPC import RPCQuery, MethodCall, MethodResponse
+from sleekxmpp.stanza.iq import Iq
+from sleekxmpp.xmlstream.handler.callback import Callback
+from sleekxmpp.xmlstream.matcher.xpath import MatchXPath
+from sleekxmpp.xmlstream.stanzabase import register_stanza_plugin
+from xml.etree import cElementTree as ET
+import logging
+
+
+
+log = logging.getLogger(__name__)
+
+
+
+class xep_0009(base.base_plugin):
+
+ def plugin_init(self):
+ self.xep = '0009'
+ self.description = 'Jabber-RPC'
+ #self.stanza = sleekxmpp.plugins.xep_0009.stanza
+
+ register_stanza_plugin(Iq, RPCQuery)
+ register_stanza_plugin(RPCQuery, MethodCall)
+ register_stanza_plugin(RPCQuery, MethodResponse)
+
+ self.xmpp.registerHandler(
+ Callback('RPC Call', MatchXPath('{%s}iq/{%s}query/{%s}methodCall' % (self.xmpp.default_ns, RPCQuery.namespace, RPCQuery.namespace)),
+ self._handle_method_call)
+ )
+ self.xmpp.registerHandler(
+ Callback('RPC Call', MatchXPath('{%s}iq/{%s}query/{%s}methodResponse' % (self.xmpp.default_ns, RPCQuery.namespace, RPCQuery.namespace)),
+ self._handle_method_response)
+ )
+ self.xmpp.registerHandler(
+ Callback('RPC Call', MatchXPath('{%s}iq/{%s}error' % (self.xmpp.default_ns, self.xmpp.default_ns)),
+ self._handle_error)
+ )
+ self.xmpp.add_event_handler('jabber_rpc_method_call', self._on_jabber_rpc_method_call)
+ self.xmpp.add_event_handler('jabber_rpc_method_response', self._on_jabber_rpc_method_response)
+ self.xmpp.add_event_handler('jabber_rpc_method_fault', self._on_jabber_rpc_method_fault)
+ self.xmpp.add_event_handler('jabber_rpc_error', self._on_jabber_rpc_error)
+ self.xmpp.add_event_handler('error', self._handle_error)
+ #self.activeCalls = []
+
+ def post_init(self):
+ base.base_plugin.post_init(self)
+ self.xmpp.plugin['xep_0030'].add_feature('jabber:iq:rpc')
+ self.xmpp.plugin['xep_0030'].add_identity('automation','rpc')
+
+ def make_iq_method_call(self, pto, pmethod, params):
+ iq = self.xmpp.makeIqSet()
+ iq.attrib['to'] = pto
+ iq.attrib['from'] = self.xmpp.boundjid.full
+ iq.enable('rpc_query')
+ iq['rpc_query']['method_call']['method_name'] = pmethod
+ iq['rpc_query']['method_call']['params'] = params
+ return iq;
+
+ def make_iq_method_response(self, pid, pto, params):
+ iq = self.xmpp.makeIqResult(pid)
+ iq.attrib['to'] = pto
+ iq.attrib['from'] = self.xmpp.boundjid.full
+ iq.enable('rpc_query')
+ iq['rpc_query']['method_response']['params'] = params
+ return iq
+
+ def make_iq_method_response_fault(self, pid, pto, params):
+ iq = self.xmpp.makeIqResult(pid)
+ iq.attrib['to'] = pto
+ iq.attrib['from'] = self.xmpp.boundjid.full
+ iq.enable('rpc_query')
+ iq['rpc_query']['method_response']['params'] = None
+ iq['rpc_query']['method_response']['fault'] = params
+ return iq
+
+# def make_iq_method_error(self, pto, pid, pmethod, params, code, type, condition):
+# iq = self.xmpp.makeIqError(pid)
+# iq.attrib['to'] = pto
+# iq.attrib['from'] = self.xmpp.boundjid.full
+# iq['error']['code'] = code
+# iq['error']['type'] = type
+# iq['error']['condition'] = condition
+# iq['rpc_query']['method_call']['method_name'] = pmethod
+# iq['rpc_query']['method_call']['params'] = params
+# return iq
+
+ def _item_not_found(self, iq):
+ payload = iq.get_payload()
+ iq.reply().error().set_payload(payload);
+ iq['error']['code'] = '404'
+ iq['error']['type'] = 'cancel'
+ iq['error']['condition'] = 'item-not-found'
+ return iq
+
+ def _undefined_condition(self, iq):
+ payload = iq.get_payload()
+ iq.reply().error().set_payload(payload)
+ iq['error']['code'] = '500'
+ iq['error']['type'] = 'cancel'
+ iq['error']['condition'] = 'undefined-condition'
+ return iq
+
+ def _forbidden(self, iq):
+ payload = iq.get_payload()
+ iq.reply().error().set_payload(payload)
+ iq['error']['code'] = '403'
+ iq['error']['type'] = 'auth'
+ iq['error']['condition'] = 'forbidden'
+ return iq
+
+ def _recipient_unvailable(self, iq):
+ payload = iq.get_payload()
+ iq.reply().error().set_payload(payload)
+ iq['error']['code'] = '404'
+ iq['error']['type'] = 'wait'
+ iq['error']['condition'] = 'recipient-unavailable'
+ return iq
+
+ def _handle_method_call(self, iq):
+ type = iq['type']
+ if type == 'set':
+ log.debug("Incoming Jabber-RPC call from %s", iq['from'])
+ self.xmpp.event('jabber_rpc_method_call', iq)
+ else:
+ if type == 'error' and ['rpc_query'] is None:
+ self.handle_error(iq)
+ else:
+ log.debug("Incoming Jabber-RPC error from %s", iq['from'])
+ self.xmpp.event('jabber_rpc_error', iq)
+
+ def _handle_method_response(self, iq):
+ if iq['rpc_query']['method_response']['fault'] is not None:
+ log.debug("Incoming Jabber-RPC fault from %s", iq['from'])
+ #self._on_jabber_rpc_method_fault(iq)
+ self.xmpp.event('jabber_rpc_method_fault', iq)
+ else:
+ log.debug("Incoming Jabber-RPC response from %s", iq['from'])
+ self.xmpp.event('jabber_rpc_method_response', iq)
+
+ def _handle_error(self, iq):
+ print("['XEP-0009']._handle_error -> ERROR! Iq is '%s'" % iq)
+ print("#######################")
+ print("### NOT IMPLEMENTED ###")
+ print("#######################")
+
+ def _on_jabber_rpc_method_call(self, iq, forwarded=False):
+ """
+ A default handler for Jabber-RPC method call. If another
+ handler is registered, this one will defer and not run.
+
+ If this handler is called by your own custom handler with
+ forwarded set to True, then it will run as normal.
+ """
+ if not forwarded and self.xmpp.event_handled('jabber_rpc_method_call') > 1:
+ return
+ # Reply with error by default
+ error = self.client.plugin['xep_0009']._item_not_found(iq)
+ error.send()
+
+ def _on_jabber_rpc_method_response(self, iq, forwarded=False):
+ """
+ A default handler for Jabber-RPC method response. If another
+ handler is registered, this one will defer and not run.
+
+ If this handler is called by your own custom handler with
+ forwarded set to True, then it will run as normal.
+ """
+ if not forwarded and self.xmpp.event_handled('jabber_rpc_method_response') > 1:
+ return
+ error = self.client.plugin['xep_0009']._recpient_unavailable(iq)
+ error.send()
+
+ def _on_jabber_rpc_method_fault(self, iq, forwarded=False):
+ """
+ A default handler for Jabber-RPC fault response. If another
+ handler is registered, this one will defer and not run.
+
+ If this handler is called by your own custom handler with
+ forwarded set to True, then it will run as normal.
+ """
+ if not forwarded and self.xmpp.event_handled('jabber_rpc_method_fault') > 1:
+ return
+ error = self.client.plugin['xep_0009']._recpient_unavailable(iq)
+ error.send()
+
+ def _on_jabber_rpc_error(self, iq, forwarded=False):
+ """
+ A default handler for Jabber-RPC error response. If another
+ handler is registered, this one will defer and not run.
+
+ If this handler is called by your own custom handler with
+ forwarded set to True, then it will run as normal.
+ """
+ if not forwarded and self.xmpp.event_handled('jabber_rpc_error') > 1:
+ return
+ error = self.client.plugin['xep_0009']._recpient_unavailable(iq, iq.get_payload())
+ error.send()
+
+ def _send_fault(self, iq, fault_xml): #
+ fault = self.make_iq_method_response_fault(iq['id'], iq['from'], fault_xml)
+ fault.send()
+
+ def _send_error(self, iq):
+ print("['XEP-0009']._send_error -> ERROR! Iq is '%s'" % iq)
+ print("#######################")
+ print("### NOT IMPLEMENTED ###")
+ print("#######################")
+
+ def _extract_method(self, stanza):
+ xml = ET.fromstring("%s" % stanza)
+ return xml.find("./methodCall/methodName").text
+