#include <termios.h>
-#include <xmlrpc-c/base.h>
#include <xmlrpc-c/client.h>
#include <libvscmisc/assert.h>
#include "../include/libvscremote/libvscremote.h"
static int _initialized = FALSE;
-static VscRemoteMethodNameLookupFunction _method_name_lookup_function = NULL;
-static VscRemoteArgumentNameLookupFunction _argument_name_lookup_function = NULL;
+static VscRemoteMethodLookupFunction _method_lookup_function = NULL;
+static VscRemoteParameterNameLookupFunction _parameter_name_lookup_function = NULL;
static char *_remote_url = NULL;
static char *_username = NULL;
static char *_cookie = NULL;
return password;
}
-static const char *
-_lookup_method_name (struct VscError *error, const char *command_name)
+static const char * /* method_name */
+_lookup_method (struct VscError *error, const char *command_name,
+ VscRemotePackFunction *pack_function,
+ VscRemoteUnpackFunction *unpack_function, void *user_data)
{
const char *method_name = NULL;
VSC__ASSERT (error != NULL);
VSC__ASSERT (! error->occured);
- VSC__ASSERT (_method_name_lookup_function != NULL);
+ VSC__ASSERT (_method_lookup_function != NULL);
+ VSC__ASSERT (pack_function != NULL);
+ VSC__ASSERT (unpack_function != NULL);
- method_name = _method_name_lookup_function (error, command_name);
+ method_name = _method_lookup_function (error, command_name, pack_function,
+ unpack_function, user_data);
if (error->occured) {
VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
return NULL;
}
+ if (strcmp (command_name, "login") != 0 &&
+ strcmp (command_name, "logout") != 0) {
+ if (*pack_function == NULL) {
+ VSC__ERROR1 (error, VSC__ERROR_CODE__INTERNAL_ERROR,
+ "Internal error");
+ return NULL;
+ }
+
+ if (*unpack_function == NULL) {
+ VSC__ERROR1 (error, VSC__ERROR_CODE__INTERNAL_ERROR,
+ "Internal error");
+ return NULL;
+ }
+ }
+
return method_name;
}
static const char *
-_lookup_argument_name (struct VscError *error, const char *command_name,
- const char *option_long_name)
+_lookup_parameter_name (struct VscError *error, const char *command_name,
+ const char *option_long_name, void *user_data)
{
const char *argument_name = NULL;
VSC__ASSERT (error != NULL);
VSC__ASSERT (! error->occured);
- VSC__ASSERT (_argument_name_lookup_function != NULL);
+ VSC__ASSERT (_parameter_name_lookup_function != NULL);
- argument_name = _argument_name_lookup_function (error, command_name,
- option_long_name);
+ argument_name = _parameter_name_lookup_function
+ (error, command_name, option_long_name, user_data);
if (error->occured) {
VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
return argument_name;
}
+static void
+_decompose_response (struct VscError *error, xmlrpc_value *response, int *code,
+ char **message, xmlrpc_value **value)
+{
+ xmlrpc_env env;
+ xmlrpc_value *struct_value = NULL;
+ xmlrpc_value *temp_value = NULL;
+
+ VSC__ASSERT (error != NULL);
+ VSC__ASSERT (! error->occured);
+ VSC__ASSERT (response != NULL);
+ VSC__ASSERT (code != NULL);
+ VSC__ASSERT (message != NULL);
+
+ xmlrpc_env_init (&env);
+
+ xmlrpc_decompose_value (&env, response, "S", &struct_value);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ goto cleanup;
+ }
+
+ xmlrpc_struct_find_value (&env, struct_value, "code", &temp_value);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ goto cleanup;
+ }
+
+ if (temp_value == NULL) {
+ VSC__ERROR1 (error, VSC__ERROR_CODE__INTERNAL_ERROR,
+ "Expecting XML-RPC response to contain a 'code' element");
+ goto cleanup;
+ }
+
+ xmlrpc_read_int (&env, temp_value, code);
+ xmlrpc_DECREF (temp_value);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ goto cleanup;
+ }
+
+ if (code != 0) {
+ xmlrpc_struct_find_value (&env, struct_value, "message", &temp_value);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ goto cleanup;
+ }
+
+ if (temp_value == NULL) {
+ VSC__ERROR1 (error, VSC__ERROR_CODE__INTERNAL_ERROR,
+ "Expecting XML-RPC response to contain a 'message' "
+ "element, because 'code' is non-zero");
+ goto cleanup;
+ }
+
+ xmlrpc_read_string (&env, temp_value, (const char **) message);
+ xmlrpc_DECREF (temp_value);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ goto cleanup;
+ }
+ }
+
+ if (value != NULL) {
+ xmlrpc_struct_find_value (&env, struct_value, "value", value);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (struct_value != NULL) {
+ xmlrpc_DECREF (struct_value);
+ }
+
+ xmlrpc_env_clean (&env);
+}
+
/*
* Login
*/
const struct VscCliOption *option_list, void *user_data);
static const struct VscCliOptionInfo _login_option_infos[] = {
- { -1, "username", "username for the remote system",
+ { -1, "username", "Username for the remote system",
VSC_CLI__OPTION_TYPE__STRING, FALSE, TRUE },
- { -1, "password", "password for the remote system",
+ { -1, "password", "Password for the remote system",
VSC_CLI__OPTION_TYPE__STRING, FALSE, FALSE },
VSC_CLI__NULL__OPTION_INFO,
};
const struct VscCliCommandInfo vsc_remote_login_command_info = {
"login",
- "login to the remote system",
+ "Login to the remote system",
"",
_login,
_login_option_infos,
static void
_login (struct VscError *error,
const struct VscCliCommandInfo *command_info VSC__ATTR__UNUSED,
- const struct VscCliOption *option_list,
- void *user_data VSC__ATTR__UNUSED)
+ const struct VscCliOption *option_list, void *user_data)
{
const char *method_name;
+ VscRemotePackFunction pack_function = NULL;
+ VscRemoteUnpackFunction unpack_function = NULL;
const char *username_name;
const char *password_name;
const char *username;
const char *password;
char *password_;
xmlrpc_env env;
- xmlrpc_value *result = NULL;
+ xmlrpc_value *response = NULL;
int code;
char *message = NULL;
+ xmlrpc_value *cookie_value = NULL;
VSC__ASSERT (error != NULL);
VSC__ASSERT (! error->occured);
return;
}
- method_name = _lookup_method_name (error, "login");
+ method_name = _lookup_method (error, command_info->name, &pack_function,
+ &unpack_function, user_data);
if (error->occured) {
VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
return;
}
- username_name = _lookup_argument_name (error, "login", "username");
+ username_name = _lookup_parameter_name (error, command_info->name,
+ _login_option_infos[0].long_name,
+ user_data);
if (error->occured) {
VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
return;
}
- password_name = _lookup_argument_name (error, "login", "password");
+ password_name = _lookup_parameter_name (error, command_info->name,
+ _login_option_infos[1].long_name,
+ user_data);
if (error->occured) {
VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
VSC__ASSERT (_username == NULL);
- username = vsc_cli_option_get_string (option_list, "username");
- password = vsc_cli_option_get_string (option_list, "password");
+ username = vsc_cli_option_list_lookup_string
+ (option_list, _login_option_infos[0].long_name);
+ password = vsc_cli_option_list_lookup_string
+ (option_list, _login_option_infos[1].long_name);
VSC__ASSERT (username != NULL);
xmlrpc_env_init (&env);
- result = xmlrpc_client_call (&env, _remote_url, method_name,
- "({s:s,s:s})",
- username_name, username,
- password_name, password_);
+ response = xmlrpc_client_call (&env, _remote_url, method_name,
+ "({s:s,s:s})",
+ username_name, username,
+ password_name, password_);
if (env.fault_occurred) {
_ERROR_FROM_XMLRPC (error, &env);
- result = NULL;
+ response = NULL;
goto cleanup;
}
- xmlrpc_decompose_value (&env, result, "{s:i,s:s,s:s,*}",
- "code", &code,
- "message", &message,
- "value", &_cookie);
+ _decompose_response (error, response, &code, &message, &cookie_value);
- if (env.fault_occurred) {
- _ERROR_FROM_XMLRPC (error, &env);
- message = NULL;
+ if (error->occured) {
+ VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
goto cleanup;
}
goto cleanup;
}
+ xmlrpc_read_string (&env, cookie_value, (const char **) &_cookie);
+ xmlrpc_DECREF (cookie_value);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ _cookie = NULL;
+ goto cleanup;
+ }
+
_username = vsc_strdup (error, username);
if (error->occured) {
}
cleanup:
- if (result != NULL) {
- xmlrpc_DECREF (result);
+ if (response != NULL) {
+ xmlrpc_DECREF (response);
}
vsc_free (&password_);
const struct VscCliCommandInfo vsc_remote_logout_command_info = {
"logout",
- "logout from the remote system",
+ "Logout from the remote system",
"",
_logout,
_logout_option_infos,
void *user_data VSC__ATTR__UNUSED)
{
const char *method_name = NULL;
+ VscRemotePackFunction pack_function = NULL;
+ VscRemoteUnpackFunction unpack_function = NULL;
const char *cookie_name = NULL;
xmlrpc_env env;
- xmlrpc_value *result = NULL;
+ xmlrpc_value *response = NULL;
int code;
char *message = NULL;
return;
}
- method_name = _lookup_method_name (error, "logout");
+ method_name = _lookup_method (error, command_info->name, &pack_function,
+ &unpack_function, user_data);
if (error->occured) {
VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
return;
}
- cookie_name = _lookup_argument_name (error, "logout", "cookie");
+ cookie_name = _lookup_parameter_name (error, command_info->name, "cookie",
+ user_data);
if (error->occured) {
VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
xmlrpc_env_init (&env);
- result = xmlrpc_client_call (&env, _remote_url, method_name,
- "({s:s})",
- cookie_name, _cookie);
+ response = xmlrpc_client_call (&env, _remote_url, method_name,
+ "({s:s})",
+ cookie_name, _cookie);
if (env.fault_occurred) {
_ERROR_FROM_XMLRPC (error, &env);
- result = NULL;
+ response = NULL;
goto cleanup;
}
- xmlrpc_decompose_value (&env, result, "{s:i,s:s,*}",
- "code", &code,
- "message", &message);
+ _decompose_response (error, response, &code, &message, NULL);
- if (env.fault_occurred) {
- _ERROR_FROM_XMLRPC (error, &env);
- message = NULL;
+ if (error->occured) {
+ VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
goto cleanup;
}
vsc_free (&_username);
cleanup:
- if (result != NULL) {
- xmlrpc_DECREF (result);
+ if (response != NULL) {
+ xmlrpc_DECREF (response);
}
vsc_free (&message);
void
vsc_remote_init (struct VscError *error, const char *name, const char *version,
const char *remote_url,
- VscRemoteMethodNameLookupFunction method_name_lookup_function,
- VscRemoteArgumentNameLookupFunction argument_name_lookup_function)
+ VscRemoteMethodLookupFunction method_lookup_function,
+ VscRemoteParameterNameLookupFunction parameter_name_lookup_function)
{
xmlrpc_env env;
char user_agent[256];
VSC__ASSERT (error != NULL);
VSC__ASSERT (! error->occured);
- VSC__ASSERT (method_name_lookup_function != NULL);
- VSC__ASSERT (argument_name_lookup_function != NULL);
+ VSC__ASSERT (method_lookup_function != NULL);
+ VSC__ASSERT (parameter_name_lookup_function != NULL);
if (_initialized) {
VSC__ERROR1 (error, VSC__ERROR_CODE__INVALID_CALL,
return;
}
- _method_name_lookup_function = method_name_lookup_function;
- _argument_name_lookup_function = argument_name_lookup_function;
+ _method_lookup_function = method_lookup_function;
+ _parameter_name_lookup_function = parameter_name_lookup_function;
if (remote_url != NULL) {
_remote_url = vsc_strdup (error, remote_url);
if (_cookie != NULL) {
vsc_error_init (&error);
- _logout (&error, NULL, NULL, NULL);
+ _logout (&error, &vsc_remote_logout_command_info, NULL, NULL);
vsc_error_cleanup (&error);
}
vsc_free (&_cookie);
vsc_free (&_username);
- _method_name_lookup_function = NULL;
- _argument_name_lookup_function = NULL;
+ _method_lookup_function = NULL;
+ _parameter_name_lookup_function = NULL;
_initialized = FALSE;
}
return _username;
}
+
+/*
+ * Command
+ */
+
+void
+vsc_remote_default_pack (struct VscError *error,
+ const struct VscCliCommandInfo *command_info,
+ const struct VscCliOption *option_list,
+ const char *cookie, xmlrpc_value *struct_value,
+ void *user_data)
+{
+ int i;
+ xmlrpc_env env;
+ const struct VscCliOption *option;
+ const struct VscCliOptionInfo *option_info;
+ const char *name;
+ xmlrpc_value *value = NULL;
+
+ VSC__ASSERT (error != NULL);
+ VSC__ASSERT (! error->occured);
+
+ name = _lookup_parameter_name (error, command_info->name, "cookie",
+ user_data);
+
+ if (error->occured) {
+ VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
+ return;
+ }
+
+ xmlrpc_env_init (&env);
+
+ value = xmlrpc_string_new (&env, cookie);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ goto cleanup;
+ }
+
+ xmlrpc_struct_set_value (&env, struct_value, name, value);
+
+ xmlrpc_DECREF (value);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ goto cleanup;
+ }
+
+ for (i = 0; command_info->option_infos[i].long_name != NULL; i++) {
+ option_info = &command_info->option_infos[i];
+ option = vsc_cli_option_list_lookup (option_list,
+ option_info->long_name);
+ name = _lookup_parameter_name (error, command_info->name,
+ option_info->long_name, user_data);
+
+ if (error->occured) {
+ VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
+ goto cleanup;
+ }
+
+ if (option != NULL) {
+ switch (option_info->type) {
+ case VSC_CLI__OPTION_TYPE__BOOLEAN:
+ value = xmlrpc_bool_new (&env, TRUE);
+ break;
+
+ case VSC_CLI__OPTION_TYPE__NUMBER:
+ value = xmlrpc_int_new (&env, option->number);
+ break;
+
+ case VSC_CLI__OPTION_TYPE__STRING:
+ value = xmlrpc_string_new (&env, option->string);
+ break;
+
+ default:
+ VSC__ERROR1 (error, VSC__ERROR_CODE__INTERNAL_ERROR,
+ "Internal error");
+ goto cleanup;
+ }
+ } else if (option_info->type == VSC_CLI__OPTION_TYPE__BOOLEAN &&
+ option_info->required) {
+ value = xmlrpc_bool_new (&env, FALSE);
+ } else {
+ continue;
+ }
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ goto cleanup;
+ }
+
+ xmlrpc_struct_set_value (&env, struct_value, name, value);
+
+ xmlrpc_DECREF (value);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ xmlrpc_env_clean (&env);
+}
+
+void
+vsc_remote_default_command (struct VscError *error,
+ const struct VscCliCommandInfo *command_info,
+ const struct VscCliOption *option_list,
+ void *user_data)
+{
+ xmlrpc_env env;
+ const char *method_name = NULL;
+ VscRemotePackFunction pack_function = NULL;
+ VscRemoteUnpackFunction unpack_function = NULL;
+ xmlrpc_value *struct_value = NULL;
+ xmlrpc_value *value = NULL;
+ xmlrpc_value *response = NULL;
+ int code = 0;
+ char *message = NULL;
+
+ VSC__ASSERT (error != NULL);
+ VSC__ASSERT (! error->occured);
+
+ vsc_remote_check (error, TRUE);
+
+ if (error->occured) {
+ VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
+ return;
+ }
+
+ method_name = _lookup_method (error, command_info->name, &pack_function,
+ &unpack_function, user_data);
+
+ if (error->occured) {
+ VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
+ return;
+ }
+
+ xmlrpc_env_init (&env);
+
+ struct_value = xmlrpc_struct_new (&env);
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ struct_value = NULL;
+ goto cleanup;
+ }
+
+ /*
+ * Pack
+ */
+ pack_function (error, command_info, option_list, _cookie, struct_value,
+ user_data);
+
+ if (error->occured) {
+ VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
+ goto cleanup;
+ }
+
+ /*
+ * Call
+ */
+ response = xmlrpc_client_call (&env, _remote_url, method_name,
+ "(S)", struct_value);
+
+ xmlrpc_DECREF (struct_value);
+ struct_value = NULL;
+
+ if (env.fault_occurred) {
+ _ERROR_FROM_XMLRPC (error, &env);
+ response = NULL;
+ goto cleanup;
+ }
+
+ /*
+ * Decompose
+ */
+ _decompose_response (error, response, &code, &message, &value);
+
+ if (error->occured) {
+ VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
+ goto cleanup;
+ }
+
+ /*
+ * Unpack
+ */
+ unpack_function (error, command_info, option_list, code, message, value,
+ user_data);
+ xmlrpc_DECREF (value);
+
+ if (error->occured) {
+ VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
+ goto cleanup;
+ }
+
+cleanup:
+ if (struct_value != NULL) {
+ xmlrpc_DECREF (struct_value);
+ }
+
+ if (response != NULL) {
+ xmlrpc_DECREF (response);
+ }
+
+ vsc_free (&message);
+
+ xmlrpc_env_clean (&env);
+}