]> sjero.net Git - linphone/blob - coreapi/sipwizard.c
Aac-eld add missing header according to RFC3640 3.3.6
[linphone] / coreapi / sipwizard.c
1 /*
2 sipwizard.c
3 Copyright (C) 2011 Belledonne Communication, Grenoble, France
4
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.
9
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.
14
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.
18 */
19
20 #include "linphonecore.h"
21 #include "private.h"
22 #include <ctype.h>
23 #include <libsoup/soup.h>
24
25 typedef struct _BLReq{
26         int status;
27         int result;
28         SoupMessage *msg;
29         SoupSession *session;
30         ortp_thread_t th;
31 }BLReq;
32
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";
36
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);
41 }
42
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;
46         return domains;
47 }
48
49
50 static int xml_rpc_parse_response(BLReq *blreq, SoupMessage *sm){
51         SoupBuffer *sb;
52         GValue retval;
53         GError *error=NULL;
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){
57                 if (error!=NULL){
58                         ms_error("xmlrpc fault: %s",error->message);
59                         g_error_free(error);
60                 }else{
61                         ms_error("Could not parse xml-rpc response !");
62                 }
63                 blreq->status=XMLRPC_FAILED;
64         }else{
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;
69         }
70         soup_buffer_free(sb);
71         return blreq->status;
72 }
73
74 static void got_headers(BLReq *blreq, SoupMessage*msg){
75         ms_message("Got headers !");
76         blreq->status=XMLRPC_OK;
77 }
78
79 #if SERIALIZE_HTTPS
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...*/
84
85 static GStaticMutex big_mutex = G_STATIC_MUTEX_INIT;
86 #endif
87
88 static void * process_xml_rpc_request(void *up){
89         BLReq *blreq=(BLReq*)up;
90         SoupMessage *sm=blreq->msg;
91         int code;
92         g_signal_connect_swapped(G_OBJECT(sm),"got-headers",(GCallback)got_headers,blreq);
93         blreq->status=XMLRPC_OK;
94 #if SERIALIZE_HTTPS
95         g_static_mutex_lock(&big_mutex);
96 #endif
97         code=soup_session_send_message(blreq->session,sm);
98         if (code==200){
99                 xml_rpc_parse_response(blreq,sm);
100         }else{
101                 ms_error("request failed, error-code=%i (%s)",code,soup_status_get_phrase(code));
102                 blreq->status=XMLRPC_FAILED;
103         }
104 #if SERIALIZE_HTTPS
105         g_static_mutex_unlock(&big_mutex);
106 #endif
107         return NULL;
108 }
109
110
111 static int do_simple_xmlrpc_request(SoupMessage *msg) {
112         int ret=-1;
113         BLReq *req;
114
115         if (!msg){
116                 ms_error("Fail to create SoupMessage !");
117                 return -1;
118         }else{
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);
122         }
123
124         req=ms_new0(BLReq, 1);
125         req->session=soup_session_sync_new();
126         req->msg=msg;
127
128         process_xml_rpc_request(req);
129
130         if (req->status == XMLRPC_OK) {
131                 ret=req->result;
132         }
133
134         // Freeing allocated structures lead to a crash (why?)
135         //g_free(req->session);
136         //g_free(msg);
137         ms_free(req);
138
139         return ret;
140 }
141
142 /*
143  * Return 1 if account already exists
144  * 0 if account doesn't exists
145  * -1 if information isn't available
146  */
147 static int sip_wizard_account_exists(SipSetupContext *ctx, const char *identity) {
148         SoupMessage *msg=soup_xmlrpc_request_new(XMLRPC_URL,
149                                 "check_account",
150                                 G_TYPE_STRING, identity,
151                                 G_TYPE_INVALID);
152         return do_simple_xmlrpc_request(msg);
153 }
154
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,
159                                 G_TYPE_INVALID);
160         return do_simple_xmlrpc_request(msg);
161 }
162
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,
165                                 "create_account",
166                                 G_TYPE_STRING, identity,
167                                 G_TYPE_STRING, passwd,
168                                 G_TYPE_STRING, email,
169                                 G_TYPE_INT, suscribe,
170                                 G_TYPE_INVALID);
171         return do_simple_xmlrpc_request(msg);
172 }
173
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);
177         const char *it;
178         char *wptr=dn;
179         bool_t begin=TRUE;
180         bool_t surname=FALSE;
181         for(it=username;*it!='\0';++it){
182                 if (begin){
183                         *wptr=toupper(*it);
184                         begin=FALSE;
185                 }else if (*it=='.'){
186                         if (surname) break;
187                         *wptr=' ';
188                         begin=TRUE;
189                         surname=TRUE;
190                 }else {
191                         *wptr=*it;
192                 }
193                 wptr++;
194         }
195         *wptr='\0';
196         linphone_address_set_display_name(from,dn);
197         ms_free(dn);
198 }
199
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;
205         char *tmp;
206
207         parsed_uri=linphone_address_new(uri);
208         if (parsed_uri==NULL){
209                 return -1;
210         }
211         if (linphone_address_get_display_name(parsed_uri)!=NULL){
212                 guess_display_name(parsed_uri);
213         }
214         tmp=linphone_address_as_string(parsed_uri);
215         linphone_proxy_config_set_identity(cfg,tmp);
216         if (passwd) {
217                 auth=linphone_auth_info_new(linphone_address_get_username(parsed_uri),NULL,passwd,NULL,NULL);
218                 linphone_core_add_auth_info(lc,auth);
219         }
220         linphone_proxy_config_enable_register(cfg,TRUE);
221         linphone_proxy_config_done(cfg);
222         ms_free(tmp);
223         linphone_address_destroy(parsed_uri);
224         return 0;
225 }
226
227 /* a simple SipSetup built-in plugin to allow creating accounts at runtime*/
228
229 #ifndef _MSC_VER
230
231 SipSetup linphone_sip_wizard={
232         .name="SipWizard",
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
240 };
241
242 #else
243 SipSetup linphone_sip_wizard={
244         "SipWizard",
245         SIP_SETUP_CAP_ACCOUNT_MANAGER,
246         0,
247         NULL,
248         NULL,
249         sip_wizard_init_instance,
250         NULL,
251         sip_wizard_account_exists,
252         sip_wizard_create_account,
253         sip_wizard_do_login,
254         NULL,
255         NULL,
256         NULL,
257         NULL,
258         NULL,
259         NULL,
260         sip_wizard_get_domains,
261         NULL,
262         NULL,
263         sip_wizard_account_validated
264 };
265
266
267
268 #endif