3 Copyright (C) 2011 Simon MORLAT (simon.morlat@linphone.org)
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 const int XMLRPC_FAILED = -1;
34 const int XMLRPC_OK = 0;
35 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 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;
49 static SoupMessage * build_xmlrpc_check_account_request(const char *identity){
52 msg=soup_xmlrpc_request_new(XMLRPC_URL,
54 G_TYPE_STRING, identity,
57 ms_error("Fail to create SoupMessage !");
59 SoupBuffer *sb=soup_message_body_flatten(msg->request_body);
60 ms_message("This is the XML-RPC request we are going to send:\n%s\n",sb->data);
66 static SoupMessage * build_xmlrpc_check_account_validated(const char *identity){
69 msg=soup_xmlrpc_request_new(XMLRPC_URL,
70 "check_account_validated",
71 G_TYPE_STRING, identity,
74 ms_error("Fail to create SoupMessage !");
76 SoupBuffer *sb=soup_message_body_flatten(msg->request_body);
77 ms_message("This is the XML-RPC request we are going to send:\n%s\n",sb->data);
83 static SoupMessage * build_xmlrpc_create_account_request(const char *identity, const char *passwd, const char *email, int suscribe){
86 msg=soup_xmlrpc_request_new(XMLRPC_URL,
88 G_TYPE_STRING, identity,
89 G_TYPE_STRING, passwd,
94 ms_error("Fail to create SoupMessage !");
96 SoupBuffer *sb=soup_message_body_flatten(msg->request_body);
97 ms_message("This is the XML-RPC request we are going to send:\n%s\n",sb->data);
103 static int xml_rpc_parse_response(BLReq *blreq, SoupMessage *sm){
107 sb=soup_message_body_flatten(sm->response_body);
108 ms_message("This the xml-rpc response:\n%s\n",sb->data);
109 if (soup_xmlrpc_parse_method_response(sb->data,sb->length,&retval,&error)==FALSE){
111 ms_error("xmlrpc fault: %s",error->message);
114 ms_error("Could not parse xml-rpc response !");
116 blreq->status=XMLRPC_FAILED;
118 ms_message("Extracting values from return type...");
119 blreq->result = g_value_get_int(&retval);
120 g_value_unset(&retval);
121 blreq->status=XMLRPC_OK;
123 soup_buffer_free(sb);
124 return blreq->status;
127 static void got_headers(BLReq *blreq, SoupMessage*msg){
128 ms_message("Got headers !");
129 blreq->status=XMLRPC_OK;
133 /*on windows libsoup support for threads with gnutls is not yet functionnal (only in git)
134 This will come in next release of libsoup, probably.
135 In the meantime, we are forced to serialize all soup https processing with a big
136 ugly global mutex...*/
138 static GStaticMutex big_mutex = G_STATIC_MUTEX_INIT;
141 static void * process_xml_rpc_request(void *up){
142 BLReq *blreq=(BLReq*)up;
143 SoupMessage *sm=blreq->msg;
145 g_signal_connect_swapped(G_OBJECT(sm),"got-headers",(GCallback)got_headers,blreq);
146 blreq->status=XMLRPC_OK;
148 g_static_mutex_lock(&big_mutex);
150 code=soup_session_send_message(blreq->session,sm);
152 ms_message("Got a response from server, yeah !");
153 xml_rpc_parse_response(blreq,sm);
155 ms_error("request failed, error-code=%i (%s)",code,soup_status_get_phrase(code));
156 blreq->status=XMLRPC_FAILED;
159 g_static_mutex_unlock(&big_mutex);
164 int sip_wizard_account_exists(SipSetupContext *ctx, const char *uri) {
166 * Return 1 if account already exists
167 * 0 if account doesn't exists
168 * -1 if information isn't available
171 BLReq *req=ms_new0(BLReq, 1);
172 req->session=soup_session_sync_new();
173 sm=build_xmlrpc_check_account_request(uri);
175 process_xml_rpc_request(req);
177 if (req->status == XMLRPC_OK) {
184 int sip_wizard_account_validated(SipSetupContext *ctx, const char *uri) {
186 * Return 1 if account already exists
187 * 0 if account doesn't exists
188 * -1 if information isn't available
191 BLReq *req=ms_new0(BLReq, 1);
192 req->session=soup_session_sync_new();
193 sm=build_xmlrpc_check_account_validated(uri);
195 process_xml_rpc_request(req);
197 if (req->status == XMLRPC_OK) {
204 int sip_wizard_create_account(SipSetupContext *ctx, const char *uri, const char *passwd, const char *email, int suscribe) {
206 * Return 0 if account successfully created
210 BLReq *req=ms_new0(BLReq, 1);
211 req->session=soup_session_sync_new();
212 sm=build_xmlrpc_create_account_request(uri, passwd, email, suscribe);
214 process_xml_rpc_request(req);
216 if (req->status == XMLRPC_OK) {
223 static void guess_display_name(LinphoneAddress *from){
224 char *dn=(char*)ms_malloc(strlen(linphone_address_get_username(from))+3);
229 for(it=linphone_address_get_username(from);*it!='\0';++it){
241 linphone_address_set_display_name(from,dn);
245 static int sip_wizard_do_login(SipSetupContext * ctx, const char *uri, const char *passwd){
246 LinphoneProxyConfig *cfg=sip_setup_context_get_proxy_config(ctx);
247 LinphoneCore *lc=linphone_proxy_config_get_core(cfg);
248 LinphoneAuthInfo *auth;
249 LinphoneAddress *parsed_uri;
252 parsed_uri=linphone_address_new(uri);
253 if (parsed_uri==NULL){
256 if (linphone_address_get_display_name(parsed_uri)!=NULL){
257 guess_display_name(parsed_uri);
259 tmp=linphone_address_as_string(parsed_uri);
260 linphone_proxy_config_set_identity(cfg,tmp);
262 auth=linphone_auth_info_new(linphone_address_get_username(parsed_uri),NULL,passwd,NULL,NULL);
263 linphone_core_add_auth_info(lc,auth);
265 linphone_proxy_config_enable_register(cfg,TRUE);
266 linphone_proxy_config_done(cfg);
268 linphone_address_destroy(parsed_uri);
272 /* a simple SipSetup built-in plugin to allow creating accounts at runtime*/
276 SipSetup linphone_sip_wizard={
278 .capabilities=SIP_SETUP_CAP_ACCOUNT_MANAGER,
279 .init_instance=sip_wizard_init_instance,
280 .account_exists=sip_wizard_account_exists,
281 .create_account=sip_wizard_create_account,
282 .login_account=sip_wizard_do_login,
283 .get_domains=sip_wizard_get_domains,
284 .account_validated=sip_wizard_account_validated
288 SipSetup linphone_sip_wizard={
290 SIP_SETUP_CAP_ACCOUNT_MANAGER,
294 sip_wizard_init_instance,
296 sip_wizard_account_exists,
297 sip_wizard_create_account,
305 sip_wizard_get_domains,
308 sip_wizard_account_validated