diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index b8b6b27cbb6e263d9e2f90b24b00f7226a60fa67..ea1ccb0ea9ceefa18d189db6eca39756d8485a1c 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -92,6 +92,8 @@ set(SOURCE_FILES xml2lpc.c xml2lpc.h xml.c + xmlrpc.c + xmlrpc.h vtables.c ) if(ENABLE_TUNNEL) diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 53f8cbcfb353eed21052f2e4d7669fa09844e63a..20aa69aceab5f9d564ec6bc28f9a15b6620f5f3c 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -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); diff --git a/coreapi/private.h b/coreapi/private.h index 40fd9b2e49185f45d86deb0684f8f205dc249fe9..48b448f671868ca76892c2e20f1ecb43d3f58155 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -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 diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 26a2eb7f8787748a444b16891c9bafc462755a65..5b9705f9758ca6384e48c5b267896e00e35136e5 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -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; diff --git a/coreapi/sipsetup.h b/coreapi/sipsetup.h index 2cbe24036410c9d877309e1afc52579f89ea7042..63d71d5f1d67a5a139646b56a42659febd5446e8 100644 --- a/coreapi/sipsetup.h +++ b/coreapi/sipsetup.h @@ -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; diff --git a/coreapi/sipwizard.c b/coreapi/sipwizard.c index 879b9942a4af7ff3548b75e74a7e65936cbfa66d..7c1e4d1bb4fc0db422c654e70cedd825cca02cf0 100644 --- a/coreapi/sipwizard.c +++ b/coreapi/sipwizard.c @@ -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 diff --git a/coreapi/xmlrpc.c b/coreapi/xmlrpc.c new file mode 100644 index 0000000000000000000000000000000000000000..89f16f10d04d3fc4f15b0d626647c3eec23036f9 --- /dev/null +++ b/coreapi/xmlrpc.c @@ -0,0 +1,346 @@ +/* +linphone +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. +*/ + +#include "linphonecore.h" +#include "private.h" + +#include <string.h> +#include <libxml/tree.h> +#include <libxml/xmlwriter.h> + + + +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; + xmlBufferPtr buf; + xmlTextWriterPtr writer; + int err; + + buf = xmlBufferCreate(); + if (buf == NULL) { + ms_error("Error creating the XML buffer"); + return; + } + writer = xmlNewTextWriterMemory(buf, 0); + if (writer == NULL) { + ms_error("Error creating the XML writer"); + return; + } + + err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); + if (err >= 0) { + err = xmlTextWriterStartElement(writer, (const xmlChar *)"methodCall"); + } + if (err >= 0) { + err = xmlTextWriterWriteElement(writer, (const xmlChar *)"methodName", (const xmlChar *)request->method); + } + if (err >= 0) { + err = xmlTextWriterStartElement(writer, (const xmlChar *)"params"); + } + while (arg_ptr != NULL) { + LinphoneXmlRpcArg *arg = (LinphoneXmlRpcArg *)arg_ptr->data; + if (err >= 0) { + err = xmlTextWriterStartElement(writer, (const xmlChar *)"param"); + } + if (err >= 0) { + err = xmlTextWriterStartElement(writer, (const xmlChar *)"value"); + } + switch (arg->type) { + case LinphoneXmlRpcArgNone: + break; + case LinphoneXmlRpcArgInt: + memset(si, 0, sizeof(si)); + snprintf(si, sizeof(si), "%i", arg->data.i); + err = xmlTextWriterWriteElement(writer, (const xmlChar *)"int", (const xmlChar *)si); + break; + case LinphoneXmlRpcArgString: + err = xmlTextWriterWriteElement(writer, (const xmlChar *)"string", (const xmlChar *)arg->data.s); + break; + } + if (err >= 0) { + /* Close the "value" element. */ + err = xmlTextWriterEndElement(writer); + } + if (err >= 0) { + /* Close the "param" element. */ + err = xmlTextWriterEndElement(writer); + } + arg_ptr = arg_ptr->next; + } + if (err >= 0) { + /* Close the "params" element. */ + err = xmlTextWriterEndElement(writer); + } + if (err >= 0) { + /* Close the "methodCall" element. */ + err = xmlTextWriterEndElement(writer); + } + if (err >= 0) { + err = xmlTextWriterEndDocument(writer); + } + if (err > 0) { + /* xmlTextWriterEndDocument returns the size of the content. */ + request->content = belle_sip_strdup((const char *)buf->content); + } + xmlFreeTextWriter(writer); + xmlBufferFree(buf); +} + +static void free_arg(LinphoneXmlRpcArg *arg) { + if ((arg->type == LinphoneXmlRpcArgString) && (arg->data.s != NULL)) { + belle_sip_free(arg->data.s); + } + belle_sip_free(arg); +} + +static void process_io_error_from_post_xml_rpc_request(void *data, const belle_sip_io_error_event_t *event) { + LinphoneXmlRpcSession *session = (LinphoneXmlRpcSession *)data; + ms_error("I/O Error during XML-RPC request sending to %s", session->url); + session->request->status = LinphoneXmlRpcStatusFailed; + ms_cond_signal(&session->cond); +} + +static void process_auth_requested_from_post_xml_rpc_request(void *data, belle_sip_auth_event_t *event) { + LinphoneXmlRpcSession *session = (LinphoneXmlRpcSession *)data; + ms_error("Error during XML-RPC request sending to connect %s", session->url); + session->request->status = LinphoneXmlRpcStatusFailed; + ms_cond_signal(&session->cond); +} + +static void parse_valid_xml_rpc_response(LinphoneXmlRpcSession *session, const char *response_body) { + xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new(); + xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); + session->request->status = LinphoneXmlRpcStatusFailed; + xml_ctx->doc = xmlReadDoc((const unsigned char*)response_body, 0, NULL, 0); + 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; + } + linphone_free_xml_text_content(response_str); + } else { + ms_warning("Wrongly formatted XML-RPC response: %s", xml_ctx->errorBuffer); + } +end: + linphone_xmlparsing_context_destroy(xml_ctx); + ms_cond_signal(&session->cond); +} + +static void notify_xml_rpc_error(LinphoneXmlRpcSession *session) { + session->request->status = LinphoneXmlRpcStatusOk; + ms_cond_signal(&session->cond); +} + +/** + * Callback function called when we have a response from server during the upload of the log collection to the server (rcs5.1 recommandation) + * Note: The first post is empty and the server shall reply a 204 (No content) message, this will trigger a new post request to the server + * to upload the file. The server response to this second post is processed by this same function + * + * @param[in] data The user-defined pointer associated with the request, it contains the LinphoneCore object + * @param[in] event The response from server + */ +static void process_response_from_post_xml_rpc_request(void *data, const belle_http_response_event_t *event) { + LinphoneXmlRpcSession *session = (LinphoneXmlRpcSession *)data; + + /* Check the answer code */ + if (event->response) { + int code = belle_http_response_get_status_code(event->response); + if (code == 200) { /* Valid response from the server. */ + parse_valid_xml_rpc_response(session, belle_sip_message_get_body((belle_sip_message_t *)event->response)); + } else { + notify_xml_rpc_error(session); + } + } +} + + +static void linphone_xml_rpc_request_destroy(LinphoneXmlRpcRequest *request) { + belle_sip_list_free_with_data(request->arg_list, (void (*)(void*))free_arg); + if (request->content) belle_sip_free(request->content); + belle_sip_free(request->method); +} + +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); + ms_mutex_destroy(&session->mutex); +} + +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, + NULL, // clone + NULL, // marshal + TRUE +); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneXmlRpcSession, belle_sip_object_t, + (belle_sip_object_destroy_t)linphone_xml_rpc_session_destroy, + NULL, // clone + NULL, // marshal + TRUE +); + + +LinphoneXmlRpcRequest * linphone_xml_rpc_request_new(const char *method, ...) { + 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); + while (cont) { + arg_type = va_arg(args, LinphoneXmlRpcArgType); + switch (arg_type) { + case LinphoneXmlRpcArgNone: + 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); + 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); + break; + } + } + va_end(args); + format_request(request); + return request; +} + +LinphoneXmlRpcRequest * linphone_xml_rpc_request_ref(LinphoneXmlRpcRequest *request) { + belle_sip_object_ref(request); + return request; +} + +void linphone_xml_rpc_request_unref(LinphoneXmlRpcRequest *request) { + belle_sip_object_unref(request); +} + +void *linphone_xml_rpc_request_get_user_data(const LinphoneXmlRpcRequest *request) { + return request->user_data; +} + +void linphone_xml_rpc_request_set_user_data(LinphoneXmlRpcRequest *request, void *ud) { + request->user_data = ud; +} + +const char * linphone_xml_rpc_request_get_content(const LinphoneXmlRpcRequest *request) { + return request->content; +} + +LinphoneXmlRpcStatus linphone_xml_rpc_request_get_status(const LinphoneXmlRpcRequest *request) { + return request->status; +} + +int linphone_xml_rpc_request_get_response(const LinphoneXmlRpcRequest *request) { + return request->response; +} + + +LinphoneXmlRpcSession * linphone_xml_rpc_session_new(LinphoneCore *core, const char *url) { + LinphoneXmlRpcSession *session = belle_sip_object_new(LinphoneXmlRpcSession); + belle_sip_object_ref(session); + session->core = core; + session->url = belle_sip_strdup(url); + ms_cond_init(&session->cond, NULL); + ms_mutex_init(&session->cond_mutex, NULL); + ms_mutex_init(&session->mutex, NULL); + return session; +} + +LinphoneXmlRpcSession * linphone_xml_rpc_session_ref(LinphoneXmlRpcSession *session) { + belle_sip_object_ref(session); + return session; +} + +void linphone_xml_rpc_session_unref(LinphoneXmlRpcSession *session) { + belle_sip_object_unref(session); +} + +void *linphone_xml_rpc_session_get_user_data(const LinphoneXmlRpcSession *session) { + return session->user_data; +} + +void linphone_xml_rpc_session_set_user_data(LinphoneXmlRpcSession *session, void *ud) { + session->user_data = ud; +} + +LinphoneXmlRpcStatus linphone_xml_rpc_session_send_request(LinphoneXmlRpcSession *session, LinphoneXmlRpcRequest *request) { + belle_http_request_listener_callbacks_t cbs = { 0 }; + belle_http_request_listener_t *l; + belle_generic_uri_t *uri; + belle_http_request_t *req; + belle_sip_memory_body_handler_t *bh; + const char *data; + LinphoneXmlRpcStatus status; + + ms_mutex_lock(&session->mutex); + session->request = linphone_xml_rpc_request_ref(request); + session->content = linphone_content_new(); + linphone_content_set_type(session->content, "text"); + linphone_content_set_subtype(session->content,"xml"); + linphone_content_set_string_buffer(session->content, linphone_xml_rpc_request_get_content(request)); + uri = belle_generic_uri_parse(session->url); + req = belle_http_request_create("POST", uri, belle_sip_header_content_type_create("text", "xml"), NULL); + data = linphone_xml_rpc_request_get_content(request); + bh = belle_sip_memory_body_handler_new_copy_from_buffer(data, strlen(data), NULL, session); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(bh)); + cbs.process_response = process_response_from_post_xml_rpc_request; + cbs.process_io_error = process_io_error_from_post_xml_rpc_request; + cbs.process_auth_requested = process_auth_requested_from_post_xml_rpc_request; + l = belle_http_request_listener_create_from_callbacks(&cbs, session); + belle_http_provider_send_request(session->core->http_provider, req, l); + + ms_mutex_lock(&session->cond_mutex); + ms_cond_wait(&session->cond, &session->cond_mutex); + ms_mutex_unlock(&session->cond_mutex); + status = session->request->status; + linphone_xml_rpc_request_unref(session->request); + session->request = NULL; + linphone_content_unref(session->content); + session->content = NULL; + ms_mutex_unlock(&session->mutex); + return status; +} diff --git a/coreapi/xmlrpc.h b/coreapi/xmlrpc.h new file mode 100644 index 0000000000000000000000000000000000000000..34141be89eaf605dd360a12d1d7cfc7dd2fe777e --- /dev/null +++ b/coreapi/xmlrpc.h @@ -0,0 +1,164 @@ +/* +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_ */ diff --git a/gtk/setupwizard.c b/gtk/setupwizard.c index 96b12d50df6001ef2779bbe41806044b78f4a734..064ad783b4ca18c3d36bb8fe5d8a257ecca51071 100644 --- a/gtk/setupwizard.c +++ b/gtk/setupwizard.c @@ -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)