Monday, November 08, 2010 at 12:06 AM.

system.verbs.builtins.tcp.im.builtinDrivers.jabber.code.examples.rpc.rpc

on rpc (dest, procedureName = "", adrParamList = nil, flDebug = false, secondsToTimeOut = 60, flAsync = false, adrCallback = nil, extraInfo = nil, adrTimeoutCallback = nil, id = nil, adrErrorCallback = nil, connection = nil) {
	<<Changes
		<<5/14/02; 1:51:34 PM by JB
			<<Changelog created.
	<<This script implements the client end of Jabber RPC
	on addAtt ( XMLadr, name, value ) {
		if not defined ( XMLadr^.["/atts"] ) {
			new ( tableType, @XMLadr^.["/atts"] )};
		XMLadr^.["/atts"].[name] = value};
	
	if connection == nil {
		connection = @system.temp.jabber.connection};
	
	if not defined ( connection^ ) {
		scriptError ( "Can't make Jabber-RPC call because the Jabber connection doesn't exist." )};
	
	local ( idName, result, iqTag, queryTag, methodCall, params, param, value ); new ( tableType, @result );
	bundle { // step one... set up the idTable
		if id == nil {
			id = tcp.im.builtinDrivers.jabber.code.idTables.create()};
		idName = nameOf ( id^ );
		id^.expireTime = clock.now() + secondsToTimeOut; // when we forget about this call
		if adrCallback != nil { // remember the callback
			id^.jabberXMLRPCCallback = adrCallback};
		if adrTimeoutCallback != nil { // remember the cleanup script
			id^.cleanupScript = adrTimeoutCallback};
		if adrErrorCallback != nil {
			id^.jabberXMLRPCErrorCallback = adrErrorCallback};
		id^.jabberXMLRPCExtraInfo = extraInfo; // any extra info stored
		id^.jabberXMLRPCflAsync = flAsync};
	bundle { // set up the XML message
		bundle { // <iq type="set" from="me" to="username@host/resource" id="id">
			iqTag = xml.addTable ( @result, "iq" );
			addAtt ( iqTag, "from", connection^.username + "@" + connection^.host + "/" + connection^.resource );
			addAtt ( iqTag, "to", dest );
			addAtt ( iqTag, "type", "set" );
			addAtt ( iqTag, "id", nameOf ( id^ ) )};
		bundle { // <query xmlns="jabber:iq:rpc">
			queryTag = xml.addTable ( iqTag, "query" );
			addAtt(queryTag, "xmlns", "jabber:iq:rpc")};
		bundle { // <methodCall>...</methodCall>
			methodCall = xml.addTable ( queryTag, "methodCall" );
			xml.addValue ( methodCall, "methodName", procedureName );
			if adrParamList != nil and sizeOf ( adrParamList^ ) > 0 {
				params = xml.addTable ( methodCall, "params" );
				for item in adrParamList^ {
					param = xml.addTable ( params, "param" );
					value = xml.addTable ( param, "value" );
					xml.compile(xml.coercions.frontierValueToTaggedText(@item, 0), value)}}
			else {
				xml.addValue ( methodCall, "params", "" )}}};
	
	if flAsync { // if this is asynchronous, send the call and return true
		tcp.im.builtinDrivers.jabber.code.writeXML(iqTag, connection: connection);
		return true};
	
	tcp.im.builtinDrivers.jabber.code.writeXML(iqTag, connection: connection);
	try {
		tcp.im.builtinDrivers.jabber.code.waitForIqReply(id, secondsToTimeOut)}
	else {
		scriptError ( "Can't complete RPC call because the call timed out." )};
	if defined ( id^.JabberXMLRPCResult ) {
		return id^.JabberXMLRPCResult}
	else {
		scriptError ( "The server returned error code " + id^.JabberXMLRPCFaultCode + ": " + id^.JabberXMLRPCFaultString )}};
bundle { //test code
	local (params = {22});
	dialog.alert(rpc("Jeremy@jabber.xlogs.net/RadioUserland","examples.getStateName", @params))}



This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.