3 Copyright (C) 2011 Belledonne Communication, Grenoble, France
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "linphonecore.h"
23 #include <libsoup/soup.h>
25 typedef struct _BLReq{
33 static const int XMLRPC_FAILED = -1;
34 static const int XMLRPC_OK = 0;
35 static const char *XMLRPC_URL = "https://www.linphone.org/wizard.php";
37 static void sip_wizard_init_instance(SipSetupContext *ctx){
38 LinphoneProxyConfig *cfg=sip_setup_context_get_proxy_config(ctx);
39 /*disable registration until the user logs in*/
40 linphone_proxy_config_enable_register(cfg,FALSE);
43 static const char ** sip_wizard_get_domains(SipSetupContext *ctx) {
44 LinphoneProxyConfig *cfg=sip_setup_context_get_proxy_config(ctx);
45 const char **domains = (const char**) &cfg->reg_proxy;
50 static int xml_rpc_parse_response(BLReq *blreq, SoupMessage *sm){
54 sb=soup_message_body_flatten(sm->response_body);
55 ms_message("This the xml-rpc response:\n%s\n",sb->data);
56 if (soup_xmlrpc_parse_method_response(sb->data,sb->length,&retval,&error)==FALSE){
58 ms_error("xmlrpc fault: %s",error->message);
61 ms_error("Could not parse xml-rpc response !");
63 blreq->status=XMLRPC_FAILED;
65 ms_message("Extracting values from return type...");
66 blreq->result = g_value_get_int(&retval);
67 g_value_unset(&retval);
68 blreq->status=XMLRPC_OK;
74 static void got_headers(BLReq *blreq, SoupMessage*msg){
75 ms_message("Got headers !");
76 blreq->status=XMLRPC_OK;
80 /*on windows libsoup support for threads with gnutls is not yet functionnal (only in git)
81 This will come in next release of libsoup, probably.
82 In the meantime, we are forced to serialize all soup https processing with a big
83 ugly global mutex...*/
85 static GStaticMutex big_mutex = G_STATIC_MUTEX_INIT;
88 static void * process_xml_rpc_request(void *up){
89 BLReq *blreq=(BLReq*)up;
90 SoupMessage *sm=blreq->msg;
92 g_signal_connect_swapped(G_OBJECT(sm),"got-headers",(GCallback)got_headers,blreq);
93 blreq->status=XMLRPC_OK;
95 g_static_mutex_lock(&big_mutex);
97 code=soup_session_send_message(blreq->session,sm);
99 xml_rpc_parse_response(blreq,sm);
101 ms_error("request failed, error-code=%i (%s)",code,soup_status_get_phrase(code));
102 blreq->status=XMLRPC_FAILED;
105 g_static_mutex_unlock(&big_mutex);
111 static int do_simple_xmlrpc_request(SoupMessage *msg) {
116 ms_error("Fail to create SoupMessage !");
119 SoupBuffer *sb=soup_message_body_flatten(msg->request_body);
120 ms_message("This is the XML-RPC request we are going to send:\n%s\n",sb->data);
121 soup_buffer_free(sb);
124 req=ms_new0(BLReq, 1);
125 req->session=soup_session_sync_new();
128 process_xml_rpc_request(req);
130 if (req->status == XMLRPC_OK) {
134 // Freeing allocated structures lead to a crash (why?)
135 //g_free(req->session);
143 * Return 1 if account already exists
144 * 0 if account doesn't exists
145 * -1 if information isn't available
147 static int sip_wizard_account_exists(SipSetupContext *ctx, const char *identity) {
148 SoupMessage *msg=soup_xmlrpc_request_new(XMLRPC_URL,
150 G_TYPE_STRING, identity,
152 return do_simple_xmlrpc_request(msg);
155 static int sip_wizard_account_validated(SipSetupContext *ctx, const char *identity) {
156 SoupMessage *msg=soup_xmlrpc_request_new(XMLRPC_URL,
157 "check_account_validated",
158 G_TYPE_STRING, identity,
160 return do_simple_xmlrpc_request(msg);
163 static int sip_wizard_create_account(SipSetupContext *ctx, const char *identity, const char *passwd, const char *email, int suscribe) {
164 SoupMessage *msg=soup_xmlrpc_request_new(XMLRPC_URL,
166 G_TYPE_STRING, identity,
167 G_TYPE_STRING, passwd,
168 G_TYPE_STRING, email,
169 G_TYPE_INT, suscribe,
171 return do_simple_xmlrpc_request(msg);
174 static void guess_display_name(LinphoneAddress *from){
175 const char *username=linphone_address_get_username(from);
176 char *dn=(char*)ms_malloc(strlen(username)+1);
180 bool_t surname=FALSE;
181 for(it=username;*it!='\0';++it){
196 linphone_address_set_display_name(from,dn);
200 static int sip_wizard_do_login(SipSetupContext * ctx, const char *uri, const char *passwd){
201 LinphoneProxyConfig *cfg=sip_setup_context_get_proxy_config(ctx);
202 LinphoneCore *lc=linphone_proxy_config_get_core(cfg);
203 LinphoneAuthInfo *auth;
204 LinphoneAddress *parsed_uri;
207 parsed_uri=linphone_address_new(uri);
208 if (parsed_uri==NULL){
211 if (linphone_address_get_display_name(parsed_uri)!=NULL){
212 guess_display_name(parsed_uri);
214 tmp=linphone_address_as_string(parsed_uri);
215 linphone_proxy_config_set_identity(cfg,tmp);
217 auth=linphone_auth_info_new(linphone_address_get_username(parsed_uri),NULL,passwd,NULL,NULL);
218 linphone_core_add_auth_info(lc,auth);
220 linphone_proxy_config_enable_register(cfg,TRUE);
221 linphone_proxy_config_done(cfg);
223 linphone_address_destroy(parsed_uri);
227 /* a simple SipSetup built-in plugin to allow creating accounts at runtime*/
231 SipSetup linphone_sip_wizard={
233 .capabilities=SIP_SETUP_CAP_ACCOUNT_MANAGER,
234 .init_instance=sip_wizard_init_instance,
235 .account_exists=sip_wizard_account_exists,
236 .create_account=sip_wizard_create_account,
237 .login_account=sip_wizard_do_login,
238 .get_domains=sip_wizard_get_domains,
239 .account_validated=sip_wizard_account_validated
243 SipSetup linphone_sip_wizard={
245 SIP_SETUP_CAP_ACCOUNT_MANAGER,
249 sip_wizard_init_instance,
251 sip_wizard_account_exists,
252 sip_wizard_create_account,
260 sip_wizard_get_domains,
263 sip_wizard_account_validated