Commit 067bbef1 authored by Ghislain MARY's avatar Ghislain MARY
Browse files

Improve XML-RPC API.

- Handle XML-RPC request returning a string response
- Allow creating a request adding the arguments one at a time (useful for
  automatically generated wrappers where variable args functions can be an
  issue)
parent a152132b
......@@ -983,6 +983,14 @@ BELLE_SIP_DECLARE_VPTR(LinphoneBuffer);
* XML-RPC interface *
****************************************************************************/
typedef struct _LinphoneXmlRpcArg {
LinphoneXmlRpcArgType type;
union {
int i;
char *s;
} data;
} LinphoneXmlRpcArg;
struct _LinphoneXmlRpcRequest {
belle_sip_object_t base;
void *user_data;
......@@ -990,7 +998,7 @@ struct _LinphoneXmlRpcRequest {
char *content; /**< The string representation of the XML-RPC request */
char *method;
LinphoneXmlRpcStatus status;
int response;
LinphoneXmlRpcArg response;
};
BELLE_SIP_DECLARE_VPTR(LinphoneXmlRpcRequest);
......
......@@ -50,19 +50,17 @@ static int do_simple_xmlrpc_request(SipSetupContext *ctx, LinphoneXmlRpcRequest
if (!request) {
ms_error("Fail to create XML-RPC request!");
return -1;
} else {
ms_message("This is the XML-RPC request we are going to send:\n%s\n", linphone_xml_rpc_request_get_content(request));
}
if (ctx->xmlrpc_session == NULL) {
ctx->xmlrpc_session = linphone_xml_rpc_session_new(ctx->cfg->lc, XMLRPC_URL);
}
if (linphone_xml_rpc_session_send_request(ctx->xmlrpc_session, request) == LinphoneXmlRpcStatusOk) {
ret = linphone_xml_rpc_request_get_response(request);
ret = linphone_xml_rpc_request_get_int_response(request);
}
linphone_xml_rpc_request_unref(request);
return ret;
return ret;
}
/*
......@@ -71,21 +69,24 @@ static int do_simple_xmlrpc_request(SipSetupContext *ctx, LinphoneXmlRpcRequest
* -1 if information isn't available
*/
static int sip_wizard_account_exists(SipSetupContext *ctx, const char *identity) {
LinphoneXmlRpcRequest *request = linphone_xml_rpc_request_new("check_account",
LinphoneXmlRpcRequest *request = linphone_xml_rpc_request_new_with_args("check_account",
LinphoneXmlRpcArgInt,
LinphoneXmlRpcArgString, identity,
LinphoneXmlRpcArgNone);
return do_simple_xmlrpc_request(ctx, request);
}
static int sip_wizard_account_validated(SipSetupContext *ctx, const char *identity) {
LinphoneXmlRpcRequest *request = linphone_xml_rpc_request_new("check_account_validated",
LinphoneXmlRpcRequest *request = linphone_xml_rpc_request_new_with_args("check_account_validated",
LinphoneXmlRpcArgInt,
LinphoneXmlRpcArgString, identity,
LinphoneXmlRpcArgNone);
return do_simple_xmlrpc_request(ctx, request);
}
static int sip_wizard_create_account(SipSetupContext *ctx, const char *identity, const char *passwd, const char *email, int subscribe) {
LinphoneXmlRpcRequest *request = linphone_xml_rpc_request_new("create_account",
LinphoneXmlRpcRequest *request = linphone_xml_rpc_request_new_with_args("create_account",
LinphoneXmlRpcArgInt,
LinphoneXmlRpcArgString, identity,
LinphoneXmlRpcArgString, passwd,
LinphoneXmlRpcArgString, email,
......
......@@ -26,14 +26,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
typedef struct _LinphoneXmlRpcArg {
LinphoneXmlRpcArgType type;
union {
int i;
char *s;
} data;
} LinphoneXmlRpcArg;
static void format_request(LinphoneXmlRpcRequest *request) {
char si[64];
belle_sip_list_t *arg_ptr = request->arg_list;
......@@ -41,6 +33,11 @@ static void format_request(LinphoneXmlRpcRequest *request) {
xmlTextWriterPtr writer;
int err;
if (request->content != NULL) {
belle_sip_free(request->content);
request->content = NULL;
}
buf = xmlBufferCreate();
if (buf == NULL) {
ms_error("Error creating the XML buffer");
......@@ -140,10 +137,23 @@ static void parse_valid_xml_rpc_response(LinphoneXmlRpcSession *session, const c
if (xml_ctx->doc != NULL) {
const char *response_str;
if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end;
response_str = linphone_get_xml_text_content(xml_ctx, "/methodResponse/params/param/value/int");
if (response_str != NULL) {
session->request->response = atoi(response_str);
session->request->status = LinphoneXmlRpcStatusOk;
switch (session->request->response.type) {
case LinphoneXmlRpcArgInt:
response_str = linphone_get_xml_text_content(xml_ctx, "/methodResponse/params/param/value/int");
if (response_str != NULL) {
session->request->response.data.i = atoi(response_str);
session->request->status = LinphoneXmlRpcStatusOk;
}
break;
case LinphoneXmlRpcArgString:
response_str = linphone_get_xml_text_content(xml_ctx, "/methodResponse/params/param/value/string");
if (response_str != NULL) {
session->request->response.data.s = belle_sip_strdup(response_str);
session->request->status = LinphoneXmlRpcStatusOk;
}
break;
default:
break;
}
linphone_free_xml_text_content(response_str);
} else {
......@@ -182,13 +192,39 @@ static void process_response_from_post_xml_rpc_request(void *data, const belle_h
}
static void linphone_xml_rpc_request_destroy(LinphoneXmlRpcRequest *request) {
static LinphoneXmlRpcRequest * _linphone_xml_rpc_request_new(const char *method, LinphoneXmlRpcArgType return_type) {
LinphoneXmlRpcRequest *request = belle_sip_object_new(LinphoneXmlRpcRequest);
belle_sip_object_ref(request);
request->status = LinphoneXmlRpcStatusPending;
request->response.type = return_type;
request->method = belle_sip_strdup(method);
return request;
}
static void _linphone_xml_rpc_request_add_int_arg(LinphoneXmlRpcRequest *request, int value) {
LinphoneXmlRpcArg *arg = belle_sip_malloc0(sizeof(LinphoneXmlRpcArg));
arg->type = LinphoneXmlRpcArgInt;
arg->data.i = value;
request->arg_list = belle_sip_list_append(request->arg_list, arg);
}
static void _linphone_xml_rpc_request_add_string_arg(LinphoneXmlRpcRequest *request, const char *value) {
LinphoneXmlRpcArg *arg = belle_sip_malloc0(sizeof(LinphoneXmlRpcArg));
arg->type = LinphoneXmlRpcArgString;
arg->data.s = belle_sip_strdup(value);
request->arg_list = belle_sip_list_append(request->arg_list, arg);
}
static void _linphone_xml_rpc_request_destroy(LinphoneXmlRpcRequest *request) {
belle_sip_list_free_with_data(request->arg_list, (void (*)(void*))free_arg);
if ((request->response.type == LinphoneXmlRpcArgString) && (request->response.data.s != NULL)) {
belle_sip_free(request->response.data.s);
}
if (request->content) belle_sip_free(request->content);
belle_sip_free(request->method);
}
static void linphone_xml_rpc_session_destroy(LinphoneXmlRpcSession *session) {
static void _linphone_xml_rpc_session_destroy(LinphoneXmlRpcSession *session) {
belle_sip_free(session->url);
ms_cond_destroy(&session->cond);
ms_mutex_destroy(&session->cond_mutex);
......@@ -199,31 +235,33 @@ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneXmlRpcRequest);
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneXmlRpcSession);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneXmlRpcRequest, belle_sip_object_t,
(belle_sip_object_destroy_t)linphone_xml_rpc_request_destroy,
(belle_sip_object_destroy_t)_linphone_xml_rpc_request_destroy,
NULL, // clone
NULL, // marshal
TRUE
);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneXmlRpcSession, belle_sip_object_t,
(belle_sip_object_destroy_t)linphone_xml_rpc_session_destroy,
(belle_sip_object_destroy_t)_linphone_xml_rpc_session_destroy,
NULL, // clone
NULL, // marshal
TRUE
);
LinphoneXmlRpcRequest * linphone_xml_rpc_request_new(const char *method, ...) {
LinphoneXmlRpcRequest * linphone_xml_rpc_request_new(const char *method, LinphoneXmlRpcArgType return_type) {
LinphoneXmlRpcRequest *request = _linphone_xml_rpc_request_new(method, return_type);
format_request(request);
return request;
}
LinphoneXmlRpcRequest * linphone_xml_rpc_request_new_with_args(const char *method, LinphoneXmlRpcArgType return_type, ...) {
bool_t cont = TRUE;
va_list args;
LinphoneXmlRpcArgType arg_type;
LinphoneXmlRpcArg *arg = NULL;
LinphoneXmlRpcRequest *request = belle_sip_object_new(LinphoneXmlRpcRequest);
belle_sip_object_ref(request);
request->status = LinphoneXmlRpcStatusPending;
request->response = -1;
request->method = belle_sip_strdup(method);
va_start(args, method);
LinphoneXmlRpcRequest *request = _linphone_xml_rpc_request_new(method, return_type);
va_start(args, return_type);
while (cont) {
arg_type = va_arg(args, LinphoneXmlRpcArgType);
switch (arg_type) {
......@@ -231,16 +269,10 @@ LinphoneXmlRpcRequest * linphone_xml_rpc_request_new(const char *method, ...) {
cont = FALSE;
break;
case LinphoneXmlRpcArgInt:
arg = belle_sip_malloc0(sizeof(LinphoneXmlRpcArg));
arg->type = LinphoneXmlRpcArgInt;
arg->data.i = va_arg(args, int);
request->arg_list = belle_sip_list_append(request->arg_list, arg);
_linphone_xml_rpc_request_add_int_arg(request, va_arg(args, int));
break;
case LinphoneXmlRpcArgString:
arg = belle_sip_malloc0(sizeof(LinphoneXmlRpcArg));
arg->type = LinphoneXmlRpcArgString;
arg->data.s = belle_sip_strdup(va_arg(args, char *));
request->arg_list = belle_sip_list_append(request->arg_list, arg);
_linphone_xml_rpc_request_add_string_arg(request, va_arg(args, char *));
break;
}
}
......@@ -266,6 +298,16 @@ void linphone_xml_rpc_request_set_user_data(LinphoneXmlRpcRequest *request, void
request->user_data = ud;
}
void linphone_xml_rpc_request_add_int_arg(LinphoneXmlRpcRequest *request, int value) {
_linphone_xml_rpc_request_add_int_arg(request, value);
format_request(request);
}
void linphone_xml_rpc_request_add_string_arg(LinphoneXmlRpcRequest *request, const char *value) {
_linphone_xml_rpc_request_add_string_arg(request, value);
format_request(request);
}
const char * linphone_xml_rpc_request_get_content(const LinphoneXmlRpcRequest *request) {
return request->content;
}
......@@ -274,8 +316,12 @@ LinphoneXmlRpcStatus linphone_xml_rpc_request_get_status(const LinphoneXmlRpcReq
return request->status;
}
int linphone_xml_rpc_request_get_response(const LinphoneXmlRpcRequest *request) {
return request->response;
int linphone_xml_rpc_request_get_int_response(const LinphoneXmlRpcRequest *request) {
return request->response.data.i;
}
const char * linphone_xml_rpc_request_get_string_response(const LinphoneXmlRpcRequest *request) {
return request->response.data.s;
}
......
......@@ -31,12 +31,18 @@ extern "C" {
* @{
*/
/**
* Enum describing the types of argument for LinphoneXmlRpcRequest.
**/
typedef enum _LinphoneXmlRpcArgType {
LinphoneXmlRpcArgNone,
LinphoneXmlRpcArgInt,
LinphoneXmlRpcArgString
} LinphoneXmlRpcArgType;
/**
* Enum describing the status of a LinphoneXmlRpcRequest.
**/
typedef enum _LinphoneXmlRpcStatus {
LinphoneXmlRpcStatusPending,
LinphoneXmlRpcStatusOk,
......@@ -55,11 +61,20 @@ typedef struct _LinphoneXmlRpcSession LinphoneXmlRpcSession;
/**
* Create a new LinphoneXmlRpcRequest object.
* Create a new LinphoneXmlRpcRequest object.
* @param[in] method The XML-RPC method to call.
* @param[in] return_type The expected XML-RPC response type.
* @return A new LinphoneXmlRpcRequest object.
**/
LINPHONE_PUBLIC LinphoneXmlRpcRequest * linphone_xml_rpc_request_new(const char *method, LinphoneXmlRpcArgType return_type);
/**
* Create a new LinphoneXmlRpcRequest object giving the arguments to the method call.
* @param[in] method The XML-RPC method to call.
* @param[in] return_type The expected XML-RPC response type.
* @return A new LinphoneXmlRpcRequest object.
*/
LINPHONE_PUBLIC LinphoneXmlRpcRequest * linphone_xml_rpc_request_new(const char *method, ...);
**/
LINPHONE_PUBLIC LinphoneXmlRpcRequest * linphone_xml_rpc_request_new_with_args(const char *method, LinphoneXmlRpcArgType return_type, ...);
/**
* Acquire a reference to the XML-RPC request.
......@@ -88,6 +103,20 @@ LINPHONE_PUBLIC void *linphone_xml_rpc_request_get_user_data(const LinphoneXmlRp
**/
LINPHONE_PUBLIC void linphone_xml_rpc_request_set_user_data(LinphoneXmlRpcRequest *request, void *ud);
/**
* Add an integer argument to an XML-RPC request.
* @param[in] request LinphoneXmlRpcRequest object.
* @param[in] value The integer value of the added argument.
**/
LINPHONE_PUBLIC void linphone_xml_rpc_request_add_int_arg(LinphoneXmlRpcRequest *request, int value);
/**
* Add a string argument to an XML-RPC request.
* @param[in] request LinphoneXmlRpcRequest object.
* @param[in] value The string value of the added argument.
**/
LINPHONE_PUBLIC void linphone_xml_rpc_request_add_string_arg(LinphoneXmlRpcRequest *request, const char *value);
/**
* Get the content of the XML-RPC request.
* @param[in] request LinphoneXmlRpcRequest object.
......@@ -103,11 +132,18 @@ LINPHONE_PUBLIC const char * linphone_xml_rpc_request_get_content(const Linphone
LINPHONE_PUBLIC LinphoneXmlRpcStatus linphone_xml_rpc_request_get_status(const LinphoneXmlRpcRequest *request);
/**
* Get the response to an XML-RPC request sent with linphone_xml_rpc_session_send_request().
* Get the response to an XML-RPC request sent with linphone_xml_rpc_session_send_request() and returning an integer response.
* @param[in] request LinphoneXmlRpcRequest object.
* @return The response to the XML-RPC request.
* @return The integer response to the XML-RPC request.
**/
LINPHONE_PUBLIC int linphone_xml_rpc_request_get_int_response(const LinphoneXmlRpcRequest *request);
/**
* Get the response to an XML-RPC request sent with linphone_xml_rpc_session_send_request() and returning a string response.
* @param[in] request LinphoneXmlRpcRequest object.
* @return The string response to the XML-RPC request.
**/
LINPHONE_PUBLIC int linphone_xml_rpc_request_get_response(const LinphoneXmlRpcRequest *request);
LINPHONE_PUBLIC const char * linphone_xml_rpc_request_get_string_response(const LinphoneXmlRpcRequest *request);
/**
* Create a new LinphoneXmlRpcSession object.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment