emulab_proxy.cc 3.5 KB
Newer Older
1 2 3
/*
 * emulab_proxy.cpp
 *
Mike Hibler's avatar
Mike Hibler committed
4
 * Copyright (c) 2004-2014 The University of Utah and the Flux Group.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 * All rights reserved.
 *
 * This file is licensed under the terms of the GNU Public License.  
 * See the file "license.terms" for restrictions on redistribution 
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/client.hpp>

#include <assert.h>

#include <xmlrpc-c/girerr.hpp>
#include <map>
#include <iostream>

#include "emulab_proxy.h"

using namespace emulab;

/**
 * The Emulab XML-RPC protocol version number.
 */
static const double PROTOCOL_VERSION = 0.1;

EmulabResponse::EmulabResponse(const er_code_t code,
			       const xmlrpc_c::value value,
			       const xmlrpc_c::value output)
    : er_Code(code), er_Value(value), er_Output(output)
{
}

EmulabResponse::EmulabResponse(xmlrpc_c::value result)
{
	std::map<std::string, xmlrpc_c::value> result_map;
	std::map<std::string, xmlrpc_c::value>::iterator p;

Mike Hibler's avatar
Mike Hibler committed
42
	if (result.type() != xmlrpc_c::value::TYPE_STRUCT)
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
	{
		throw girerr::error("Invalid response from server");
	}

	result_map = (xmlrpc_c::value_struct)result;

	/* Make sure the result has what we expect before */
	p = result_map.find("code");
	if (p == result_map.end()) {
		throw girerr::error("Invalid response from server");
	}

	/* ... decoding its contents. */
	this->er_Code = (er_code_t)(int)(xmlrpc_c::value_int)result_map["code"];
	this->er_Value = result_map["value"];
	this->er_Output = result_map["output"];
}

EmulabResponse::~EmulabResponse()
{
}


66
ServerProxy::ServerProxy(xmlrpc_c::clientXmlTransport *transport,
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
			 bool wbxml_mode,
			 const char *url)
{
	this->transport = transport;
	this->server_url = url;
}

ServerProxy::~ServerProxy()
{
}

xmlrpc_c::value ServerProxy::call(xmlrpc_c::rpcPtr rpc)
{
	xmlrpc_c::client_xml client(this->transport);
	xmlrpc_c::carriageParm_curl0 carriage_parm(this->server_url);

	rpc->call(&client, &carriage_parm);

	assert(rpc->isFinished());

	/* This will throw an exception if the RPC call failed */
	return rpc->getResult();
}

EmulabResponse ServerProxy::invoke(const char *method_name,
				   spa_attr_t tag,
				   ...)
{
    va_list args;

    va_start(args, tag);
    EmulabResponse retval = this->invoke(method_name, tag, args);
    va_end(args);

    return( retval );
}

EmulabResponse ServerProxy::invoke(const char *method_name,
				   spa_attr_t tag,
				   va_list args)
{
    xmlrpc_c::paramList params;
    std::map <std::string, xmlrpc_c::value> struct_data;
    
    /* Iterate over the tag list to build the argument structure, */
    while( tag != SPA_TAG_DONE )
    {
	    std::string key;

	    key = std::string(va_arg(args, const char *));
	    switch( tag )
	    {
	    case SPA_Boolean:
		    struct_data[key] =
			    xmlrpc_c::value_boolean((bool)va_arg(args, int));
		    break;
	    case SPA_Integer:
		    struct_data[key] =
			    xmlrpc_c::value_int(va_arg(args, int));
		    break;
	    case SPA_Double:
		    struct_data[key] =
			    xmlrpc_c::value_double(va_arg(args, double));
		break;
	    case SPA_String:
		    struct_data[key] =
			    xmlrpc_c::value_string(
				    std::string(va_arg(args, const char *)));
		break;
	    default:
		    break;
	    }

	    tag = (spa_attr_t)va_arg(args, int);
    }
    
    /* ... add the parameters, and */
    params.add(xmlrpc_c::value_double(PROTOCOL_VERSION));
    params.add(xmlrpc_c::value_struct(struct_data));
    xmlrpc_c::rpcPtr rpc(std::string(method_name), params);
    
    /* ... call the method. */
    return EmulabResponse(this->call(rpc));
}