Commit 16eba02e authored by Ghislain MARY's avatar Ghislain MARY

Handle XML-RPC request in liblinphone directly instead of using libsoup.

parent a4666bd1
......@@ -92,6 +92,8 @@ set(SOURCE_FILES
xml2lpc.c
xml2lpc.h
xml.c
xmlrpc.c
xmlrpc.h
vtables.c
)
if(ENABLE_TUNNEL)
......
......@@ -373,6 +373,7 @@ LINPHONE_PUBLIC const char* linphone_privacy_to_string(LinphonePrivacy privacy);
#include "content.h"
#include "event.h"
#include "linphonefriend.h"
#include "xmlrpc.h"
#else
#include "linphone/buffer.h"
#include "linphone/call_log.h"
......@@ -380,6 +381,7 @@ LINPHONE_PUBLIC const char* linphone_privacy_to_string(LinphonePrivacy privacy);
#include "linphone/content.h"
#include "linphone/event.h"
#include "linphone/linphonefriend.h"
#include "linphone/xmlrpc.h"
#endif
LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr);
......
......@@ -979,6 +979,38 @@ struct _LinphoneBuffer {
BELLE_SIP_DECLARE_VPTR(LinphoneBuffer);
/*****************************************************************************
* XML-RPC interface *
****************************************************************************/
struct _LinphoneXmlRpcRequest {
belle_sip_object_t base;
void *user_data;
belle_sip_list_t *arg_list;
char *content; /**< The string representation of the XML-RPC request */
char *method;
LinphoneXmlRpcStatus status;
int response;
};
BELLE_SIP_DECLARE_VPTR(LinphoneXmlRpcRequest);
struct _LinphoneXmlRpcSession {
belle_sip_object_t base;
void *user_data;
belle_sip_list_t *arg_list;
LinphoneCore *core;
LinphoneXmlRpcRequest *request;
LinphoneContent *content;
char *url;
ms_cond_t cond;
ms_mutex_t cond_mutex;
ms_mutex_t mutex;
};
BELLE_SIP_DECLARE_VPTR(LinphoneXmlRpcSession);
/*****************************************************************************
* REMOTE PROVISIONING FUNCTIONS *
****************************************************************************/
......@@ -1083,7 +1115,9 @@ BELLE_SIP_TYPE_ID(LinphoneContent),
BELLE_SIP_TYPE_ID(LinphoneLDAPContactProvider),
BELLE_SIP_TYPE_ID(LinphoneLDAPContactSearch),
BELLE_SIP_TYPE_ID(LinphoneProxyConfig),
BELLE_SIP_TYPE_ID(LinphoneFriend)
BELLE_SIP_TYPE_ID(LinphoneFriend),
BELLE_SIP_TYPE_ID(LinphoneXmlRpcRequest),
BELLE_SIP_TYPE_ID(LinphoneXmlRpcSession)
BELLE_SIP_DECLARE_TYPES_END
......
......@@ -1517,7 +1517,7 @@ LinphoneAccountCreator *linphone_account_creator_new(struct _LinphoneCore *core,
return NULL;
}
obj=ms_new0(LinphoneAccountCreator,1);
cfg=linphone_proxy_config_new();
cfg=linphone_core_create_proxy_config(core);
ssctx=sip_setup_context_new(ss,cfg);
obj->lc=core;
obj->ssctx=ssctx;
......
......@@ -31,10 +31,13 @@ struct _SipSetup;
struct _BuddyInfo;
struct _LinphoneXmlRpcSession;
struct _SipSetupContext{
struct _SipSetup *funcs;
struct _LinphoneProxyConfig *cfg;
struct _LinphoneXmlRpcSession *xmlrpc_session;
char domain[128];
char username[128];
void *data;
......
......@@ -20,18 +20,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "linphonecore.h"
#include "private.h"
#include <ctype.h>
#include <libsoup/soup.h>
typedef struct _BLReq{
int status;
int result;
SoupMessage *msg;
SoupSession *session;
ortp_thread_t th;
}BLReq;
static const int XMLRPC_FAILED = -1;
static const int XMLRPC_OK = 0;
static const char *XMLRPC_URL = "https://www.linphone.org/wizard.php";
static void sip_wizard_init_instance(SipSetupContext *ctx){
......@@ -40,6 +30,13 @@ static void sip_wizard_init_instance(SipSetupContext *ctx){
linphone_proxy_config_enable_register(cfg,FALSE);
}
static void sip_wizard_uninit_instance(SipSetupContext *ctx) {
if (ctx->xmlrpc_session != NULL) {
linphone_xml_rpc_session_unref(ctx->xmlrpc_session);
ctx->xmlrpc_session = NULL;
}
}
static const char ** sip_wizard_get_domains(SipSetupContext *ctx) {
LinphoneProxyConfig *cfg=sip_setup_context_get_proxy_config(ctx);
const char **domains = (const char**) &cfg->reg_proxy;
......@@ -47,94 +44,23 @@ static const char ** sip_wizard_get_domains(SipSetupContext *ctx) {
}
static int xml_rpc_parse_response(BLReq *blreq, SoupMessage *sm){
SoupBuffer *sb;
GValue retval;
GError *error=NULL;
sb=soup_message_body_flatten(sm->response_body);
ms_message("This the xml-rpc response:\n%s\n",sb->data);
if (soup_xmlrpc_parse_method_response(sb->data,sb->length,&retval,&error)==FALSE){
if (error!=NULL){
ms_error("xmlrpc fault: %s",error->message);
g_error_free(error);
}else{
ms_error("Could not parse xml-rpc response !");
}
blreq->status=XMLRPC_FAILED;
}else{
ms_message("Extracting values from return type...");
blreq->result = g_value_get_int(&retval);
g_value_unset(&retval);
blreq->status=XMLRPC_OK;
}
soup_buffer_free(sb);
return blreq->status;
}
static void got_headers(BLReq *blreq, SoupMessage*msg){
ms_message("Got headers !");
blreq->status=XMLRPC_OK;
}
#if SERIALIZE_HTTPS
/*on windows libsoup support for threads with gnutls is not yet functionnal (only in git)
This will come in next release of libsoup, probably.
In the meantime, we are forced to serialize all soup https processing with a big
ugly global mutex...*/
static GStaticMutex big_mutex = G_STATIC_MUTEX_INIT;
#endif
static void * process_xml_rpc_request(void *up){
BLReq *blreq=(BLReq*)up;
SoupMessage *sm=blreq->msg;
int code;
g_signal_connect_swapped(G_OBJECT(sm),"got-headers",(GCallback)got_headers,blreq);
blreq->status=XMLRPC_OK;
#if SERIALIZE_HTTPS
g_static_mutex_lock(&big_mutex);
#endif
code=soup_session_send_message(blreq->session,sm);
if (code==200){
xml_rpc_parse_response(blreq,sm);
}else{
ms_error("request failed, error-code=%i (%s)",code,soup_status_get_phrase(code));
blreq->status=XMLRPC_FAILED;
}
#if SERIALIZE_HTTPS
g_static_mutex_unlock(&big_mutex);
#endif
return NULL;
}
static int do_simple_xmlrpc_request(SoupMessage *msg) {
int ret=-1;
BLReq *req;
static int do_simple_xmlrpc_request(SipSetupContext *ctx, LinphoneXmlRpcRequest *request) {
int ret = -1;
if (!msg){
ms_error("Fail to create SoupMessage !");
if (!request) {
ms_error("Fail to create XML-RPC request!");
return -1;
}else{
SoupBuffer *sb=soup_message_body_flatten(msg->request_body);
ms_message("This is the XML-RPC request we are going to send:\n%s\n",sb->data);
soup_buffer_free(sb);
} else {
ms_message("This is the XML-RPC request we are going to send:\n%s\n", linphone_xml_rpc_request_get_content(request));
}
req=ms_new0(BLReq, 1);
req->session=soup_session_sync_new();
req->msg=msg;
process_xml_rpc_request(req);
if (req->status == XMLRPC_OK) {
ret=req->result;
}
// Freeing allocated structures lead to a crash (why?)
//g_free(req->session);
//g_free(msg);
ms_free(req);
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);
}
linphone_xml_rpc_request_unref(request);
return ret;
}
......@@ -145,30 +71,27 @@ static int do_simple_xmlrpc_request(SoupMessage *msg) {
* -1 if information isn't available
*/
static int sip_wizard_account_exists(SipSetupContext *ctx, const char *identity) {
SoupMessage *msg=soup_xmlrpc_request_new(XMLRPC_URL,
"check_account",
G_TYPE_STRING, identity,
G_TYPE_INVALID);
return do_simple_xmlrpc_request(msg);
LinphoneXmlRpcRequest *request = linphone_xml_rpc_request_new("check_account",
LinphoneXmlRpcArgString, identity,
LinphoneXmlRpcArgNone);
return do_simple_xmlrpc_request(ctx, request);
}
static int sip_wizard_account_validated(SipSetupContext *ctx, const char *identity) {
SoupMessage *msg=soup_xmlrpc_request_new(XMLRPC_URL,
"check_account_validated",
G_TYPE_STRING, identity,
G_TYPE_INVALID);
return do_simple_xmlrpc_request(msg);
LinphoneXmlRpcRequest *request = linphone_xml_rpc_request_new("check_account_validated",
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 suscribe) {
SoupMessage *msg=soup_xmlrpc_request_new(XMLRPC_URL,
"create_account",
G_TYPE_STRING, identity,
G_TYPE_STRING, passwd,
G_TYPE_STRING, email,
G_TYPE_INT, suscribe,
G_TYPE_INVALID);
return do_simple_xmlrpc_request(msg);
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",
LinphoneXmlRpcArgString, identity,
LinphoneXmlRpcArgString, passwd,
LinphoneXmlRpcArgString, email,
LinphoneXmlRpcArgInt, subscribe,
LinphoneXmlRpcArgNone);
return do_simple_xmlrpc_request(ctx, request);
}
static void guess_display_name(LinphoneAddress *from){
......@@ -232,6 +155,7 @@ SipSetup linphone_sip_wizard={
.name="SipWizard",
.capabilities=SIP_SETUP_CAP_ACCOUNT_MANAGER,
.init_instance=sip_wizard_init_instance,
.uninit_instance=sip_wizard_uninit_instance,
.account_exists=sip_wizard_account_exists,
.create_account=sip_wizard_create_account,
.login_account=sip_wizard_do_login,
......@@ -247,7 +171,7 @@ SipSetup linphone_sip_wizard={
NULL,
NULL,
sip_wizard_init_instance,
NULL,
sip_wizard_uninit_instance,
sip_wizard_account_exists,
sip_wizard_create_account,
sip_wizard_do_login,
......@@ -261,6 +185,4 @@ SipSetup linphone_sip_wizard={
sip_wizard_account_validated
};
#endif
This diff is collapsed.
/*
buffer.h
Copyright (C) 2010-2015 Belledonne Communications SARL
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef LINPHONE_XMLRPC_H_
#define LINPHONE_XMLRPC_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup misc
* @{
*/
typedef enum _LinphoneXmlRpcArgType {
LinphoneXmlRpcArgNone,
LinphoneXmlRpcArgInt,
LinphoneXmlRpcArgString
} LinphoneXmlRpcArgType;
typedef enum _LinphoneXmlRpcStatus {
LinphoneXmlRpcStatusPending,
LinphoneXmlRpcStatusOk,
LinphoneXmlRpcStatusFailed
} LinphoneXmlRpcStatus;
/**
* The LinphoneXmlRpcRequest object representing a XML-RPC request to be sent.
**/
typedef struct _LinphoneXmlRpcRequest LinphoneXmlRpcRequest;
/**
* The LinphoneXmlRpcSession object used to send XML-RPC requests and handle their responses.
**/
typedef struct _LinphoneXmlRpcSession LinphoneXmlRpcSession;
/**
* Create a new LinphoneXmlRpcRequest object.
* @param[in] method The XML-RPC method to call.
* @return A new LinphoneXmlRpcRequest object.
*/
LINPHONE_PUBLIC LinphoneXmlRpcRequest * linphone_xml_rpc_request_new(const char *method, ...);
/**
* Acquire a reference to the XML-RPC request.
* @param[in] request LinphoneXmlRpcRequest object.
* @return The same LinphoneXmlRpcRequest object.
**/
LINPHONE_PUBLIC LinphoneXmlRpcRequest * linphone_xml_rpc_request_ref(LinphoneXmlRpcRequest *request);
/**
* Release reference to the XML-RPC request.
* @param[in] request LinphoneXmlRpcRequest object.
**/
LINPHONE_PUBLIC void linphone_xml_rpc_request_unref(LinphoneXmlRpcRequest *request);
/**
* Retrieve the user pointer associated with the XML-RPC request.
* @param[in] request LinphoneXmlRpcRequest object.
* @return The user pointer associated with the XML-RPC request.
**/
LINPHONE_PUBLIC void *linphone_xml_rpc_request_get_user_data(const LinphoneXmlRpcRequest *request);
/**
* Assign a user pointer to the XML-RPC request.
* @param[in] request LinphoneXmlRpcRequest object.
* @param[in] ud The user pointer to associate with the XML-RPC request.
**/
LINPHONE_PUBLIC void linphone_xml_rpc_request_set_user_data(LinphoneXmlRpcRequest *request, void *ud);
/**
* Get the content of the XML-RPC request.
* @param[in] request LinphoneXmlRpcRequest object.
* @return The string representation of the content of the XML-RPC request.
*/
LINPHONE_PUBLIC const char * linphone_xml_rpc_request_get_content(const LinphoneXmlRpcRequest *request);
/**
* Get the status of the XML-RPC request.
* @param[in] request LinphoneXmlRpcRequest object.
* @return The status of the XML-RPC request.
**/
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().
* @param[in] request LinphoneXmlRpcRequest object.
* @return The response to the XML-RPC request.
**/
LINPHONE_PUBLIC int linphone_xml_rpc_request_get_response(const LinphoneXmlRpcRequest *request);
/**
* Create a new LinphoneXmlRpcSession object.
* @param[in] core The LinphoneCore object used to send the XML-RPC requests.
* @param[in] url The URL of the XML-RPC server to send the XML-RPC requests to.
* @return A new LinphoneXmlRpcSession object.
*/
LINPHONE_PUBLIC LinphoneXmlRpcSession * linphone_xml_rpc_session_new(LinphoneCore *core, const char *url);
/**
* Acquire a reference to the XML-RPC session.
* @param[in] session LinphoneXmlRpcSession object.
* @return The same LinphoneXmlRpcSession object.
**/
LINPHONE_PUBLIC LinphoneXmlRpcSession * linphone_xml_rpc_session_ref(LinphoneXmlRpcSession *session);
/**
* Release reference to the XML-RPC session.
* @param[in] session LinphoneXmlRpcSession object.
**/
LINPHONE_PUBLIC void linphone_xml_rpc_session_unref(LinphoneXmlRpcSession *session);
/**
* Retrieve the user pointer associated with the XML-RPC session.
* @param[in] session LinphoneXmlRpcSession object.
* @return The user pointer associated with the XML-RPC session.
**/
LINPHONE_PUBLIC void *linphone_xml_rpc_session_get_user_data(const LinphoneXmlRpcSession *session);
/**
* Assign a user pointer to the XML-RPC session.
* @param[in] session LinphoneXmlRpcSession object.
* @param[in] ud The user pointer to associate with the XML-RPC session.
**/
LINPHONE_PUBLIC void linphone_xml_rpc_session_set_user_data(LinphoneXmlRpcSession *session, void *ud);
/**
* Send an XML-RPC request.
* @param[in] session LinphoneXmlRpcSession object.
* @param[in] request The LinphoneXmlRpcRequest to be sent.
* @return The status of the XML-RPC request sending. If it is LinphoneXmlRpcStatusOk, use linphone_xml_rpc_session_get_response() to get the XML-RPC response.
**/
LINPHONE_PUBLIC LinphoneXmlRpcStatus linphone_xml_rpc_session_send_request(LinphoneXmlRpcSession *session, LinphoneXmlRpcRequest *request);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* LINPHONE_XMLRPC_H_ */
......@@ -292,6 +292,7 @@ static void account_username_changed(GtkEntry *entry, GtkWidget *w) {
LinphoneAccountCreator *creator=linphone_gtk_assistant_get_creator(assistant);
linphone_account_creator_set_username(creator, gtk_entry_get_text(username));
linphone_account_creator_set_domain(creator, "sip.linphone.org");
if (g_regex_match_simple("^[a-zA-Z]+[a-zA-Z0-9.\\-_]{3,}$", gtk_entry_get_text(username), 0, 0)) {
#if !GLIB_CHECK_VERSION(2, 31, 0)
......
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