1 /*
2 belle-sip - SIP (RFC3261) library.
3 Copyright (C) 2010 Belledonne Communications SARL
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 2 of the License, or
8 (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, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "belle_sip_internal.h"
20 #include "listeningpoint_internal.h"
21 #include "md5.h"
22 #include "belle-sip/message.h"
23 static void belle_sip_provider_update_or_create_auth_context(belle_sip_provider_t *p,belle_sip_header_call_id_t* call_id,belle_sip_header_www_authenticate_t* authenticate,belle_sip_uri_t *from_uri,const char* realm) ;
24 struct authorization_context {
25 belle_sip_header_call_id_t* callid;
26 const char* scheme;
27 const char* realm;
28 const char* nonce;
29 const char* qop;
30 const char* opaque;
31 const char* user_id;
32 const char* algorithm;
33 int nonce_count;
34 int is_proxy;
35 };
36
GET_SET_STRING(authorization_context,realm)37 GET_SET_STRING(authorization_context,realm)
38 GET_SET_STRING(authorization_context,nonce)
39 GET_SET_STRING(authorization_context,qop)
40 GET_SET_STRING(authorization_context,scheme)
41 GET_SET_STRING(authorization_context,opaque)
42 GET_SET_STRING(authorization_context,user_id)
43 GET_SET_STRING(authorization_context,algorithm)
44 GET_SET_INT(authorization_context,nonce_count,int)
45 static authorization_context_t* belle_sip_authorization_create(belle_sip_header_call_id_t* call_id) {
46 authorization_context_t* result = malloc(sizeof(authorization_context_t));
47 memset(result,0,sizeof(authorization_context_t));
48 result->callid=call_id;
49 belle_sip_object_ref(result->callid);
50 return result;
51 }
belle_sip_authorization_destroy(authorization_context_t * object)52 void belle_sip_authorization_destroy(authorization_context_t* object) {
53 DESTROY_STRING(object,scheme);
54 DESTROY_STRING(object,realm);
55 DESTROY_STRING(object,nonce);
56 DESTROY_STRING(object,qop);
57 DESTROY_STRING(object,opaque);
58 DESTROY_STRING(object,user_id);
59 DESTROY_STRING(object,algorithm);
60 belle_sip_object_unref(object->callid);
61 belle_sip_free(object);
62 }
63
finalize_transaction(belle_sip_transaction_t * tr)64 static void finalize_transaction(belle_sip_transaction_t *tr){
65 belle_sip_transaction_state_t state=belle_sip_transaction_get_state(tr);
66 if (state!=BELLE_SIP_TRANSACTION_TERMINATED){
67 belle_sip_message("Transaction [%p] still in state [%s], will force termination.",tr,belle_sip_transaction_state_to_string(state));
68 belle_sip_transaction_terminate(tr);
69 }
70 }
71
finalize_transactions(const belle_sip_list_t * l)72 static void finalize_transactions(const belle_sip_list_t *l){
73 belle_sip_list_t *copy=belle_sip_list_copy(l);
74 belle_sip_list_free_with_data(copy,(void (*)(void*))finalize_transaction);
75 }
76
belle_sip_provider_uninit(belle_sip_provider_t * p)77 static void belle_sip_provider_uninit(belle_sip_provider_t *p){
78 finalize_transactions(p->client_transactions);
79 p->client_transactions=NULL;
80 finalize_transactions(p->server_transactions);
81 p->server_transactions=NULL;
82 p->listeners=belle_sip_list_free(p->listeners);
83 p->internal_listeners=belle_sip_list_free(p->internal_listeners);
84 p->auth_contexts=belle_sip_list_free_with_data(p->auth_contexts,(void(*)(void*))belle_sip_authorization_destroy);
85 p->dialogs=belle_sip_list_free_with_data(p->dialogs,belle_sip_object_unref);
86 p->lps=belle_sip_list_free_with_data(p->lps,belle_sip_object_unref);
87 }
88
channel_state_changed(belle_sip_channel_listener_t * obj,belle_sip_channel_t * chan,belle_sip_channel_state_t state)89 static void channel_state_changed(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_channel_state_t state){
90 belle_sip_io_error_event_t ev;
91 belle_sip_provider_t* prov=BELLE_SIP_PROVIDER(obj);
92 if (state == BELLE_SIP_CHANNEL_ERROR || state == BELLE_SIP_CHANNEL_DISCONNECTED) {
93 ev.transport=belle_sip_channel_get_transport_name(chan);
94 ev.port=chan->peer_port;
95 ev.host=chan->peer_name;
96 ev.source=BELLE_SIP_OBJECT(prov);
97 BELLE_SIP_PROVIDER_INVOKE_LISTENERS(prov->listeners,process_io_error,&ev);
98 /*IO error is also relevant for internal listener like refreshers*/
99 BELLE_SIP_PROVIDER_INVOKE_LISTENERS(prov->internal_listeners,process_io_error,&ev);
100 if (!chan->force_close) belle_sip_provider_release_channel(prov,chan);
101 }
102 }
103
notify_client_transaction_match(const void * transaction,const void * notify)104 static int notify_client_transaction_match(const void *transaction, const void *notify){
105 belle_sip_client_transaction_t *tr=(belle_sip_client_transaction_t*)transaction;
106 belle_sip_request_t *notify_req=(belle_sip_request_t*)notify;
107 return !belle_sip_client_transaction_is_notify_matching_pending_subscribe(tr,notify_req);
108 }
109
belle_sip_provider_find_matching_pending_subscribe_client_transaction_from_notify_req(belle_sip_provider_t * prov,belle_sip_request_t * req)110 belle_sip_client_transaction_t * belle_sip_provider_find_matching_pending_subscribe_client_transaction_from_notify_req(belle_sip_provider_t *prov, belle_sip_request_t *req) {
111 belle_sip_list_t* elem;
112 if (strcmp("NOTIFY",belle_sip_request_get_method(req)) != 0) {
113 belle_sip_error("belle_sip_provider_find_matching_pending_subscribe_client_transaction_from_notify_req requires a NOTIFY request, not a [%s], on prov [%p]"
114 ,belle_sip_request_get_method(req)
115 ,prov);
116 }
117 elem=belle_sip_list_find_custom(prov->client_transactions,notify_client_transaction_match,req);
118 return elem?BELLE_SIP_CLIENT_TRANSACTION(elem->data):NULL;
119 }
120
belle_sip_provider_dispatch_request(belle_sip_provider_t * prov,belle_sip_request_t * req)121 static void belle_sip_provider_dispatch_request(belle_sip_provider_t* prov, belle_sip_request_t *req){
122 belle_sip_server_transaction_t *t;
123 belle_sip_request_event_t ev;
124 t=belle_sip_provider_find_matching_server_transaction(prov,req);
125 if (t){
126 belle_sip_object_ref(t);
127 belle_sip_server_transaction_on_request(t,req);
128 belle_sip_object_unref(t);
129 }else{
130 const char *method=belle_sip_request_get_method(req);
131 ev.dialog=NULL;
132 /* Should we limit to ACK ? */
133 /*Search for a dialog if exist */
134
135 if (strcmp("CANCEL",method) == 0) {
136 /* Call leg does not exist */
137 belle_sip_server_transaction_t *tr = belle_sip_provider_create_server_transaction(prov, req);
138 belle_sip_server_transaction_send_response(tr, belle_sip_response_create_from_request(req, 481));
139 return;
140 }
141
142 ev.dialog=belle_sip_provider_find_dialog_from_message(prov,(belle_sip_message_t*)req,1/*request=uas*/);
143 if (ev.dialog){
144 if (strcmp("ACK",method)==0){
145 if (belle_sip_dialog_handle_ack(ev.dialog,req)==-1){
146 /*absorbed ACK retransmission, ignore */
147 return;
148 }
149 }else if ((strcmp("INVITE",method)==0)&&(ev.dialog->needs_ack)){
150 belle_sip_dialog_stop_200Ok_retrans(ev.dialog);
151 }else if (!belle_sip_dialog_is_authorized_transaction(ev.dialog,method)){
152 belle_sip_server_transaction_t *tr=belle_sip_provider_create_server_transaction(prov,req);
153 belle_sip_server_transaction_send_response(tr,
154 belle_sip_response_create_from_request(req,491));
155 return;
156 }
157 } else if (strcmp("NOTIFY",method) == 0) {
158 /*search for matching subscribe*/
159 belle_sip_client_transaction_t *sub = belle_sip_provider_find_matching_pending_subscribe_client_transaction_from_notify_req(prov,req);
160 if (sub) {
161 belle_sip_message("Found matching subscribe for NOTIFY [%p], creating dialog",req);
162 ev.dialog=belle_sip_provider_create_dialog_internal(prov,BELLE_SIP_TRANSACTION(sub),FALSE);
163 }
164 }
165
166 if (prov->unconditional_answer_enabled && strcmp("ACK",method)!=0) { /*always answer predefined value (I.E 480 by default)*/
167 belle_sip_server_transaction_t *tr=belle_sip_provider_create_server_transaction(prov,req);
168 belle_sip_server_transaction_send_response(tr,belle_sip_response_create_from_request(req,prov->unconditional_answer));
169 return;
170 } else {
171 ev.source=(belle_sip_object_t*)prov;
172 ev.server_transaction=NULL;
173 ev.request=req;
174 BELLE_SIP_PROVIDER_INVOKE_LISTENERS(prov->listeners,process_request_event,&ev);
175 }
176 }
177 }
178
179 static belle_sip_list_t* belle_sip_provider_get_auth_context_by_realm_or_call_id(belle_sip_provider_t *p,belle_sip_header_call_id_t* call_id,belle_sip_uri_t *from_uri,const char* realm);
180
belle_sip_auth_context_find_by_nonce(const void * elem,const void * nonce_value)181 static int belle_sip_auth_context_find_by_nonce(const void* elem, const void* nonce_value){
182 authorization_context_t * a = (authorization_context_t*)elem;
183
184 return strcmp(a->nonce, (const char*)nonce_value);
185 }
186
belle_sip_provider_dispatch_response(belle_sip_provider_t * p,belle_sip_response_t * msg)187 static void belle_sip_provider_dispatch_response(belle_sip_provider_t* p, belle_sip_response_t *msg){
188 belle_sip_client_transaction_t *t;
189 t=belle_sip_provider_find_matching_client_transaction(p,msg);
190
191 /*good opportunity to cleanup auth context if answer = 401|407|403*/
192
193 switch (belle_sip_response_get_status_code(msg)) {
194 case 401:
195 case 403:
196 case 407: {
197 if (t!=NULL){
198 const char* nonce = NULL;
199 belle_sip_message_t* req = BELLE_SIP_MESSAGE(belle_sip_transaction_get_request((belle_sip_transaction_t*)t));
200 belle_sip_header_authorization_t* authorization=BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(req, belle_sip_header_proxy_authorization_t));
201 if (authorization==NULL) authorization=belle_sip_message_get_header_by_type(req, belle_sip_header_authorization_t);
202 if (authorization!=NULL){
203 nonce = belle_sip_header_authorization_get_nonce(authorization);
204 if (nonce != NULL){
205 belle_sip_list_t * auth_context_with_nonce = NULL;
206 while ((auth_context_with_nonce = belle_sip_list_find_custom(p->auth_contexts, belle_sip_auth_context_find_by_nonce, nonce)) != NULL){
207 belle_sip_authorization_destroy(auth_context_with_nonce->data);
208 p->auth_contexts = belle_sip_list_delete_link(p->auth_contexts, auth_context_with_nonce);
209 }
210 }
211 }
212 }
213 break;
214 }
215 default:
216 if (t!=NULL){
217 belle_sip_message_t* req = BELLE_SIP_MESSAGE(belle_sip_transaction_get_request((belle_sip_transaction_t*)t));
218 belle_sip_header_authentication_info_t *authentication_info = belle_sip_message_get_header_by_type(msg,belle_sip_header_authentication_info_t);
219 belle_sip_list_t *authorization_lst = NULL;
220 belle_sip_header_call_id_t *call_id = belle_sip_message_get_header_by_type(msg,belle_sip_header_call_id_t);
221 belle_sip_header_from_t *from = belle_sip_message_get_header_by_type(req,belle_sip_header_from_t);
222 belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from);
223 /*searching for authentication headers*/
224 authorization_lst = belle_sip_list_copy(belle_sip_message_get_headers(BELLE_SIP_MESSAGE(req),BELLE_SIP_AUTHORIZATION));
225 /*search for proxy authenticate*/
226 authorization_lst=belle_sip_list_concat(authorization_lst,belle_sip_list_copy(belle_sip_message_get_headers(BELLE_SIP_MESSAGE(req),BELLE_SIP_PROXY_AUTHORIZATION)));
227 /*update auth contexts with authenticate headers from response*/
228 for (;authentication_info && authorization_lst!=NULL;authorization_lst=authorization_lst->next) {
229 belle_sip_header_authorization_t *authorization=BELLE_SIP_HEADER_AUTHORIZATION(authorization_lst->data);
230 belle_sip_header_www_authenticate_t *www_authenticate = belle_sip_auth_helper_create_www_authenticate(authorization);
231 belle_sip_header_www_authenticate_set_nonce(www_authenticate, belle_sip_header_authentication_info_get_next_nonce(authentication_info));
232 belle_sip_message( "Updating auth context for ream [%s] next nonce is going to be [%s]"
233 , belle_sip_header_www_authenticate_get_realm(www_authenticate)
234 , belle_sip_header_authentication_info_get_next_nonce(authentication_info));
235 belle_sip_provider_update_or_create_auth_context(p
236 , call_id
237 , www_authenticate
238 , from_uri
239 ,belle_sip_header_www_authenticate_get_realm(www_authenticate));
240 belle_sip_object_unref(www_authenticate);
241 }
242 if (authorization_lst)
243 belle_sip_list_free(authorization_lst);
244 }
245
246 }
247 if (t){ /*In some re-connection case, specially over udp, transaction may be found, but without associated channel*/
248 if (t->base.channel == NULL) {
249 belle_sip_channel_t *chan;
250 belle_sip_message("Transaction [%p] does not have any channel associated, searching for a new one",t);
251 chan=belle_sip_provider_get_channel(p,t->next_hop); /*might be faster to get channel directly from upper level*/
252 if (chan){
253 belle_sip_object_ref(chan);
254 belle_sip_channel_add_listener(chan,BELLE_SIP_CHANNEL_LISTENER(t));
255 t->base.channel=chan;
256 }
257 }
258 }
259
260 /*
261 * If a transaction is found and have a channel, pass it to the transaction and let it decide what to do.
262 * Else notifies directly.
263 */
264 if (t && t->base.channel){
265 /*since the add_response may indirectly terminate the transaction, we need to guarantee the transaction is not freed
266 * until full completion*/
267 belle_sip_object_ref(t);
268 belle_sip_client_transaction_add_response(t,msg);
269 belle_sip_object_unref(t);
270 }else{
271 belle_sip_response_event_t event;
272 event.source=(belle_sip_object_t*)p;
273 event.client_transaction=NULL;
274 event.dialog=NULL;
275 event.response=msg;
276 BELLE_SIP_PROVIDER_INVOKE_LISTENERS(p->listeners,process_response_event,&event);
277 }
278 }
279
belle_sip_provider_dispatch_message(belle_sip_provider_t * prov,belle_sip_message_t * msg)280 void belle_sip_provider_dispatch_message(belle_sip_provider_t *prov, belle_sip_message_t *msg){
281
282 if (TRUE
283 #ifndef BELLE_SIP_DONT_CHECK_HEADERS_IN_MESSAGE
284 && belle_sip_message_check_headers(msg)
285 #endif
286 ){
287 if (belle_sip_message_is_request(msg)){
288 belle_sip_provider_dispatch_request(prov,(belle_sip_request_t*)msg);
289 }else{
290 belle_sip_provider_dispatch_response(prov,(belle_sip_response_t*)msg);
291 }
292 }else{
293 /* incorrect message received, answer bad request if it was a request.*/
294 if (belle_sip_message_is_request(msg)){
295 belle_sip_response_t *resp=belle_sip_response_create_from_request(BELLE_SIP_REQUEST(msg),400);
296 if (resp){
297 belle_sip_provider_send_response(prov,resp);
298 }
299 }/*otherwise what can we do ?*/
300 }
301 belle_sip_object_unref(msg);
302 }
303
304 /*
305 * takes example on 16.11 of RFC3261
306 */
compute_hash_from_invariants(belle_sip_message_t * msg,char * branchid,size_t branchid_size,const char * initial)307 static void compute_hash_from_invariants(belle_sip_message_t *msg, char *branchid, size_t branchid_size, const char *initial){
308 md5_state_t ctx;
309 char tmp[256]={0};
310 uint8_t digest[16];
311
312 belle_sip_header_call_id_t* callid_hdr = belle_sip_message_get_header_by_type(msg,belle_sip_header_call_id_t);
313 belle_sip_header_cseq_t* cseq_hdr = belle_sip_message_get_header_by_type(msg,belle_sip_header_cseq_t);
314 belle_sip_header_from_t* from_hdr = belle_sip_message_get_header_by_type(msg,belle_sip_header_from_t);
315 belle_sip_header_to_t* to_hdr = belle_sip_message_get_header_by_type(msg,belle_sip_header_to_t);
316
317 unsigned int cseq = cseq_hdr ? belle_sip_header_cseq_get_seq_number(cseq_hdr) : 0;
318 const char *callid = callid_hdr ? belle_sip_header_call_id_get_call_id(callid_hdr) : "";
319 const char *from_tag = from_hdr ? belle_sip_header_from_get_tag(from_hdr) : "";
320 const char *to_tag = to_hdr ? belle_sip_header_to_get_tag(to_hdr) : "";
321
322 belle_sip_uri_t *requri=NULL;
323 belle_sip_header_via_t *via=NULL;
324 belle_sip_header_via_t *prev_via=NULL;
325 const belle_sip_list_t *vias=belle_sip_message_get_headers(msg,"via");
326 int is_request=belle_sip_message_is_request(msg);
327
328 if (vias){
329 via=(belle_sip_header_via_t*)vias->data;
330 if (vias->next){
331 prev_via=(belle_sip_header_via_t*)vias->next->data;
332 }
333 }
334
335 if (is_request){
336 requri=belle_sip_request_get_uri(BELLE_SIP_REQUEST(msg));
337 }
338
339 belle_sip_md5_init(&ctx);
340 if (initial)
341 belle_sip_md5_append(&ctx,(uint8_t*)initial,(int)strlen(initial));
342 if (requri){
343 size_t offset=0;
344 belle_sip_object_marshal((belle_sip_object_t*)requri,tmp,sizeof(tmp)-1,&offset);
345 belle_sip_md5_append(&ctx,(uint8_t*)tmp,(int)strlen(tmp));
346 }
347 if (from_tag)
348 belle_sip_md5_append(&ctx,(uint8_t*)from_tag,(int)strlen(from_tag));
349 if (to_tag)
350 belle_sip_md5_append(&ctx,(uint8_t*)to_tag,(int)strlen(to_tag));
351 belle_sip_md5_append(&ctx,(uint8_t*)callid,(int)strlen(callid));
352 belle_sip_md5_append(&ctx,(uint8_t*)&cseq,sizeof(cseq));
353 if (is_request){
354 if (prev_via){
355 size_t offset=0;
356 belle_sip_object_marshal((belle_sip_object_t*)prev_via,tmp,sizeof(tmp)-1,&offset);
357 belle_sip_md5_append(&ctx,(uint8_t*)tmp,(int)offset);
358 }
359 }else{
360 if (via){
361 size_t offset=0;
362 belle_sip_object_marshal((belle_sip_object_t*)via,tmp,sizeof(tmp)-1,&offset);
363 belle_sip_md5_append(&ctx,(uint8_t*)tmp,(int)offset);
364 }
365 }
366 belle_sip_md5_finish(&ctx,digest);
367 belle_sip_octets_to_text(digest,sizeof(digest),branchid,branchid_size);
368 }
369
370 /*
371 * RFC2543 10.1.2:
372 * "Responses are mapped to requests by the matching To, From, Call-ID,
373 * CSeq headers and the branch parameter of the first Via header."
374 *
375 * to-tag must not be used because an ACK will contain one while original INVITE will not.
376 * Cseq's method is changed for CANCEL so we must not use it as well.
377 **/
378
compute_rfc2543_branch(belle_sip_request_t * req,char * branchid,size_t branchid_size)379 static char *compute_rfc2543_branch(belle_sip_request_t *req, char *branchid, size_t branchid_size){
380 md5_state_t ctx;
381 unsigned int cseq=belle_sip_header_cseq_get_seq_number(belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t));
382 uint8_t digest[16];
383 const char* callid=belle_sip_header_call_id_get_call_id(belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t));
384 belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(req,belle_sip_header_via_t);
385 const char *v_branch=belle_sip_header_via_get_branch(via);
386 belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(req,belle_sip_header_from_t);
387 char *from_str=belle_sip_object_to_string(from);
388 belle_sip_header_to_t *to=belle_sip_message_get_header_by_type(req,belle_sip_header_to_t);
389 char *to_str=belle_sip_object_to_string(belle_sip_header_address_get_uri((belle_sip_header_address_t*)to));
390
391 belle_sip_md5_init(&ctx);
392
393 belle_sip_md5_append(&ctx,(uint8_t*)from_str,(int)strlen(from_str));
394 belle_sip_md5_append(&ctx,(uint8_t*)to_str,(int)strlen(to_str));
395 belle_sip_md5_append(&ctx,(uint8_t*)callid,(int)strlen(callid));
396 belle_sip_md5_append(&ctx,(uint8_t*)&cseq,sizeof(cseq));
397 belle_sip_free(from_str);
398 belle_sip_free(to_str);
399
400 if (v_branch)
401 belle_sip_md5_append(&ctx,(uint8_t*)v_branch,(int)strlen(v_branch));
402
403 belle_sip_md5_finish(&ctx,digest);
404 belle_sip_octets_to_text(digest,sizeof(digest),branchid,branchid_size);
405 return branchid;
406 }
407
fix_outgoing_via(belle_sip_provider_t * p,belle_sip_channel_t * chan,belle_sip_message_t * msg)408 static void fix_outgoing_via(belle_sip_provider_t *p, belle_sip_channel_t *chan, belle_sip_message_t *msg){
409 belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header(msg,"via"));
410 if (p->rport_enabled) belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"rport",NULL);
411
412 belle_sip_header_via_set_host(via,chan->local_ip);
413 belle_sip_header_via_set_port(via,chan->local_port);
414 belle_sip_header_via_set_protocol(via,"SIP/2.0");
415 belle_sip_header_via_set_transport(via,belle_sip_channel_get_transport_name(chan));
416
417 if (belle_sip_header_via_get_branch(via)==NULL){
418 /*branch id should not be set random here (stateless forwarding): but rather a hash of message invariants*/
419 char branchid[24];
420 char token[BELLE_SIP_BRANCH_ID_LENGTH];
421 compute_hash_from_invariants(msg,token,sizeof(token),NULL);
422 snprintf(branchid,sizeof(branchid)-1,BELLE_SIP_BRANCH_MAGIC_COOKIE ".%s",token);
423 belle_sip_header_via_set_branch(via,branchid);
424 belle_sip_message("Computing branch id %s for message sent statelessly", branchid);
425 }
426 }
427
channel_on_message_headers(belle_sip_channel_listener_t * obj,belle_sip_channel_t * chan,belle_sip_message_t * msg)428 static void channel_on_message_headers(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
429 /*not used*/
430 }
431
channel_on_message(belle_sip_channel_listener_t * obj,belle_sip_channel_t * chan,belle_sip_message_t * msg)432 static void channel_on_message(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
433 belle_sip_object_ref(msg);
434 belle_sip_provider_dispatch_message(BELLE_SIP_PROVIDER(obj),msg);
435 }
436
channel_on_auth_requested(belle_sip_channel_listener_t * obj,belle_sip_channel_t * chan,const char * distinguished_name)437 static int channel_on_auth_requested(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, const char* distinguished_name){
438 if (BELLE_SIP_IS_INSTANCE_OF(chan,belle_sip_tls_channel_t)) {
439 belle_sip_provider_t *prov=BELLE_SIP_PROVIDER(obj);
440 belle_sip_auth_event_t* auth_event = belle_sip_auth_event_create((belle_sip_object_t*)prov,NULL,NULL);
441 belle_sip_tls_channel_t *tls_chan=BELLE_SIP_TLS_CHANNEL(chan);
442 auth_event->mode=BELLE_SIP_AUTH_MODE_TLS;
443 belle_sip_auth_event_set_distinguished_name(auth_event,distinguished_name);
444 BELLE_SIP_PROVIDER_INVOKE_LISTENERS(prov->listeners,process_auth_requested,auth_event);
445 belle_sip_tls_channel_set_client_certificates_chain(tls_chan,auth_event->cert);
446 belle_sip_tls_channel_set_client_certificate_key(tls_chan,auth_event->key);
447 belle_sip_auth_event_destroy(auth_event);
448 }
449 return 0;
450 }
451
channel_on_sending(belle_sip_channel_listener_t * obj,belle_sip_channel_t * chan,belle_sip_message_t * msg)452 static void channel_on_sending(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
453 belle_sip_header_contact_t* contact;
454 belle_sip_header_content_length_t* content_length = (belle_sip_header_content_length_t*)belle_sip_message_get_header(msg,"Content-Length");
455 belle_sip_uri_t* contact_uri;
456 const belle_sip_list_t *contacts;
457 const char *ip=NULL;
458 int port=0;
459 belle_sip_provider_t *prov=BELLE_SIP_PROVIDER(obj);
460
461 if (belle_sip_message_is_request(msg)){
462 const belle_sip_list_t *rroutes;
463 /*probably better to be in channel*/
464 fix_outgoing_via(prov, chan, msg);
465
466 for (rroutes=belle_sip_message_get_headers(msg,"Record-Route");rroutes!=NULL;rroutes=rroutes->next){
467 belle_sip_header_record_route_t* rr=(belle_sip_header_record_route_t*)rroutes->data;
468 if (belle_sip_header_record_route_get_auto_outgoing(rr)) {
469 belle_sip_uri_t *rr_uri = belle_sip_channel_create_routable_uri(chan);
470 belle_sip_header_address_set_uri((belle_sip_header_address_t*) rr, rr_uri);
471 }
472 }
473 }
474
475 for (contacts=belle_sip_message_get_headers(msg,"Contact");contacts!=NULL;contacts=contacts->next){
476 const char *transport;
477 contact=(belle_sip_header_contact_t*)contacts->data;
478
479 if (belle_sip_header_contact_is_wildcard(contact)) continue;
480 /* fix the contact if in automatic mode or null uri (for backward compatibility)*/
481 if (!(contact_uri = belle_sip_header_address_get_uri((belle_sip_header_address_t*)contact))) {
482 contact_uri = belle_sip_uri_new();
483 belle_sip_header_address_set_uri((belle_sip_header_address_t*)contact,contact_uri);
484 belle_sip_header_contact_set_automatic(contact,TRUE);
485 }else if (belle_sip_uri_get_host(contact_uri)==NULL){
486 belle_sip_header_contact_set_automatic(contact,TRUE);
487 }
488 if (!belle_sip_header_contact_get_automatic(contact)) continue;
489
490 if (ip==NULL){
491 if (prov->nat_helper){
492 ip=chan->public_ip ? chan->public_ip : chan->local_ip;
493 port=chan->public_port ? chan->public_port : chan->local_port;
494 belle_sip_header_contact_set_unknown(contact,!chan->learnt_ip_port);
495 }else{
496 ip=chan->local_ip;
497 port=chan->local_port;
498 }
499 }
500
501 belle_sip_uri_set_host(contact_uri,ip);
502 transport=belle_sip_channel_get_transport_name_lower_case(chan);
503
504 /* Enforce a transport name in "sip" scheme.
505 * RFC3263 (locating SIP servers) says that UDP SHOULD be used in absence of transport parameter,
506 * when port or numeric IP are provided. It is a SHOULD, not a must.
507 * We need in this case that the automatic Contact exactly matches the socket that is going
508 * to be used for sending the messages.
509 * TODO: we may need to do the same for sips, but dtls is currently not supported.
510 **/
511
512 if (!belle_sip_uri_is_secure(contact_uri))
513 belle_sip_uri_set_transport_param(contact_uri,transport);
514
515 if (port!=belle_sip_listening_point_get_well_known_port(transport)) {
516 belle_sip_uri_set_port(contact_uri,port);
517 }else{
518 belle_sip_uri_set_port(contact_uri,0);
519 }
520 }
521
522 /*
523 * According to RFC3261, content-length is mandatory for stream based transport, but optional for datagram transport.
524 * However some servers (opensips) are confused when they receive a SIP/UDP packet without Content-Length (they shouldn't).
525 */
526 if (!content_length
527 && belle_sip_message_get_body_size(msg) == 0 /*if body present, content_length is automatically added at channel level*/
528 #ifndef BELLE_SIP_FORCE_CONTENT_LENGTH
529 && strcasecmp("udp",belle_sip_channel_get_transport_name(chan))!=0
530 #endif
531 ) {
532 content_length = belle_sip_header_content_length_create(0);
533 belle_sip_message_add_header(msg,(belle_sip_header_t*)content_length);
534 }
535 }
536
537 BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(belle_sip_provider_t,belle_sip_channel_listener_t)
538 channel_state_changed,
539 channel_on_message_headers,
540 channel_on_message,
541 channel_on_sending,
542 channel_on_auth_requested
543 BELLE_SIP_IMPLEMENT_INTERFACE_END
544
545 BELLE_SIP_DECLARE_IMPLEMENTED_INTERFACES_1(belle_sip_provider_t,belle_sip_channel_listener_t);
546
547 BELLE_SIP_INSTANCIATE_VPTR(belle_sip_provider_t,belle_sip_object_t,belle_sip_provider_uninit,NULL,NULL,FALSE);
548
belle_sip_provider_new(belle_sip_stack_t * s,belle_sip_listening_point_t * lp)549 belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_listening_point_t *lp){
550 belle_sip_provider_t *p=belle_sip_object_new(belle_sip_provider_t);
551 p->stack=s;
552 p->rport_enabled=1;
553 p->unconditional_answer = 480;
554 if (lp) belle_sip_provider_add_listening_point(p,lp);
555 return p;
556 }
557
558 /* This function is used by a proxy to set its call side record route.
559 * It must be called before adding any VIA header to the message. */
belle_sip_provider_create_inbound_record_route(belle_sip_provider_t * p,belle_sip_request_t * req)560 belle_sip_uri_t *belle_sip_provider_create_inbound_record_route(belle_sip_provider_t *p, belle_sip_request_t *req) {
561 belle_sip_uri_t* origin = belle_sip_request_extract_origin(req);
562 belle_sip_hop_t *hop = belle_sip_hop_new_from_uri(origin);
563 belle_sip_channel_t *inChan = belle_sip_provider_get_channel(p, hop);
564 return belle_sip_channel_create_routable_uri(inChan);
565 }
566
_belle_sip_provider_find_channel_using_routable(belle_sip_provider_t * p,const belle_sip_uri_t * routable_uri)567 static belle_sip_channel_t* _belle_sip_provider_find_channel_using_routable(belle_sip_provider_t *p, const belle_sip_uri_t* routable_uri) {
568 const char *transport;
569 belle_sip_listening_point_t *lp;
570 belle_sip_list_t *elem;
571 belle_sip_channel_t *chan;
572 belle_sip_uri_t* chan_uri;
573
574 if (!routable_uri) return NULL;
575
576 transport = belle_sip_uri_is_secure(routable_uri) ? "TLS" : belle_sip_uri_get_transport_param(routable_uri);
577 lp = belle_sip_provider_get_listening_point(p, transport);
578 if (!lp) return NULL;
579
580
581 for(elem=lp->channels; elem ;elem=elem->next){
582 chan=(belle_sip_channel_t*)elem->data;
583 chan_uri = belle_sip_channel_create_routable_uri(chan);
584 if (belle_sip_uri_get_port(routable_uri) == belle_sip_uri_get_port(chan_uri) &&
585 0 == strcmp(belle_sip_uri_get_host(routable_uri), belle_sip_uri_get_host(chan_uri))) {
586 return chan;
587 }
588 }
589 return NULL;
590 }
591
592 /*
593 * This function is not efficient at all, REVISIT.
594 * Its goal is to determine whether a routable (route or record route) matches the local provider instance.
595 * In order to do that, we go through all the channels and ask them their routable uri, and see if it matches the uri passed in argument.
596 * This creates a lot of temporary objects and iterates through a potentially long list of routables.
597 * Some more efficient solutions could be:
598 * 1- insert a magic cookie parameter in each routable created by the provider, so that recognition is immediate.
599 * Drawback: use of non-standard, possibly conflicting parameter.
600 * 2- check the listening point's uri first (but need to match the ip address to any local ip if it is INADDR_ANY), then use belle_sip_listening_point_get_channel()
601 * to see if a channel is matching.
602 * belle_sip_listening_point_get_channel() is not optimized currently but will have to be, so at least we leverage on something that will be optimized.
603 **/
belle_sip_provider_is_us(belle_sip_provider_t * p,belle_sip_uri_t * uri)604 int belle_sip_provider_is_us(belle_sip_provider_t *p, belle_sip_uri_t* uri) {
605 belle_sip_channel_t* chan = _belle_sip_provider_find_channel_using_routable(p, uri);
606 return !!chan;
607 }
608
609
belle_sip_provider_add_listening_point(belle_sip_provider_t * p,belle_sip_listening_point_t * lp)610 int belle_sip_provider_add_listening_point(belle_sip_provider_t *p, belle_sip_listening_point_t *lp){
611 if (lp == NULL) {
612 belle_sip_error("Cannot add NULL lp to provider [%p]",p);
613 return -1;
614 }
615 belle_sip_listening_point_set_channel_listener(lp,BELLE_SIP_CHANNEL_LISTENER(p));
616 p->lps=belle_sip_list_append(p->lps,belle_sip_object_ref(lp));
617 return 0;
618 }
619
belle_sip_provider_remove_listening_point(belle_sip_provider_t * p,belle_sip_listening_point_t * lp)620 void belle_sip_provider_remove_listening_point(belle_sip_provider_t *p, belle_sip_listening_point_t *lp) {
621 p->lps=belle_sip_list_remove(p->lps,lp);
622 belle_sip_object_unref(lp);
623 return;
624 }
625
belle_sip_provider_get_listening_point(belle_sip_provider_t * p,const char * transport)626 belle_sip_listening_point_t *belle_sip_provider_get_listening_point(belle_sip_provider_t *p, const char *transport){
627 belle_sip_list_t *l;
628 for(l=p->lps;l!=NULL;l=l->next){
629 belle_sip_listening_point_t *lp=(belle_sip_listening_point_t*)l->data;
630 if (strcasecmp(belle_sip_listening_point_get_transport(lp),transport)==0)
631 return lp;
632 }
633 return NULL;
634 }
635
belle_sip_provider_get_listening_points(belle_sip_provider_t * p)636 const belle_sip_list_t *belle_sip_provider_get_listening_points(belle_sip_provider_t *p){
637 return p->lps;
638 }
639
belle_sip_provider_add_internal_sip_listener(belle_sip_provider_t * p,belle_sip_listener_t * l,int prepend)640 void belle_sip_provider_add_internal_sip_listener(belle_sip_provider_t *p, belle_sip_listener_t *l, int prepend){
641 if (prepend)
642 p->internal_listeners=belle_sip_list_prepend(p->internal_listeners,l);
643 else
644 p->internal_listeners=belle_sip_list_append(p->internal_listeners,l);
645 }
646
belle_sip_provider_remove_internal_sip_listener(belle_sip_provider_t * p,belle_sip_listener_t * l)647 void belle_sip_provider_remove_internal_sip_listener(belle_sip_provider_t *p, belle_sip_listener_t *l){
648 p->internal_listeners=belle_sip_list_remove(p->internal_listeners,l);
649 }
650
belle_sip_provider_add_sip_listener(belle_sip_provider_t * p,belle_sip_listener_t * l)651 void belle_sip_provider_add_sip_listener(belle_sip_provider_t *p, belle_sip_listener_t *l){
652 p->listeners=belle_sip_list_append(p->listeners,l);
653 }
654
belle_sip_provider_remove_sip_listener(belle_sip_provider_t * p,belle_sip_listener_t * l)655 void belle_sip_provider_remove_sip_listener(belle_sip_provider_t *p, belle_sip_listener_t *l){
656 p->listeners=belle_sip_list_remove(p->listeners,l);
657 }
658
belle_sip_provider_create_call_id(const belle_sip_provider_t * prov)659 belle_sip_header_call_id_t * belle_sip_provider_create_call_id(const belle_sip_provider_t *prov){
660 belle_sip_header_call_id_t *cid=belle_sip_header_call_id_new();
661 char tmp[11];
662 belle_sip_header_call_id_set_call_id(cid,belle_sip_random_token(tmp,sizeof(tmp)));
663 return cid;
664 }
665
belle_sip_provider_create_dialog(belle_sip_provider_t * prov,belle_sip_transaction_t * t)666 belle_sip_dialog_t * belle_sip_provider_create_dialog(belle_sip_provider_t *prov, belle_sip_transaction_t *t) {
667 return belle_sip_provider_create_dialog_internal(prov,t,TRUE);
668 }
669
belle_sip_provider_create_dialog_internal(belle_sip_provider_t * prov,belle_sip_transaction_t * t,unsigned int check_last_resp)670 belle_sip_dialog_t * belle_sip_provider_create_dialog_internal(belle_sip_provider_t *prov, belle_sip_transaction_t *t,unsigned int check_last_resp){
671 belle_sip_dialog_t *dialog=NULL;
672
673 if (check_last_resp && t->last_response){
674 int code=belle_sip_response_get_status_code(t->last_response);
675 if (code>=200 && code<300){
676 belle_sip_fatal("You must not create dialog after sending the response that establish the dialog.");
677 return NULL;
678 }
679 }
680 dialog=belle_sip_dialog_new(t);
681 if (dialog) {
682 belle_sip_transaction_set_dialog(t,dialog);
683 belle_sip_provider_add_dialog(prov,dialog);
684 }
685 return dialog;
686 }
687
688 /*find a dialog given the call id, local-tag and to-tag*/
belle_sip_provider_find_dialog(const belle_sip_provider_t * prov,const char * call_id,const char * local_tag,const char * remote_tag)689 belle_sip_dialog_t* belle_sip_provider_find_dialog(const belle_sip_provider_t *prov, const char* call_id, const char* local_tag, const char* remote_tag) {
690 belle_sip_list_t* iterator;
691 belle_sip_dialog_t*returned_dialog=NULL;
692
693 if (call_id == NULL || local_tag == NULL || remote_tag == NULL) {
694 return NULL;
695 }
696
697 for(iterator=prov->dialogs;iterator!=NULL;iterator=iterator->next) {
698 belle_sip_dialog_t* dialog=(belle_sip_dialog_t*)iterator->data;
699 dialog=(belle_sip_dialog_t*)iterator->data;
700 /*ignore dialog in state BELLE_SIP_DIALOG_NULL, is it really the correct things to do*/
701 if (belle_sip_dialog_get_state(dialog) != BELLE_SIP_DIALOG_NULL && _belle_sip_dialog_match(dialog,call_id,local_tag,remote_tag)) {
702 if (!returned_dialog)
703 returned_dialog=dialog;
704 else
705 belle_sip_fatal("More than 1 dialog is matching, check your app");
706 }
707 }
708 return returned_dialog;
709 }
710
711 /*finds an existing dialog for an outgoing or incoming message */
belle_sip_provider_find_dialog_from_message(belle_sip_provider_t * prov,belle_sip_message_t * msg,int as_uas)712 belle_sip_dialog_t *belle_sip_provider_find_dialog_from_message(belle_sip_provider_t *prov, belle_sip_message_t *msg, int as_uas){
713 belle_sip_header_call_id_t *call_id;
714 belle_sip_header_from_t *from;
715 belle_sip_header_to_t *to;
716 const char *from_tag;
717 const char *to_tag;
718 const char *call_id_value;
719 const char *local_tag,*remote_tag;
720
721 if (belle_sip_message_is_request(msg)){
722 belle_sip_request_t *req=BELLE_SIP_REQUEST(msg);
723 if (req->dialog)
724 return req->dialog;
725 }
726
727 to=belle_sip_message_get_header_by_type(msg,belle_sip_header_to_t);
728
729 if (to==NULL || (to_tag=belle_sip_header_to_get_tag(to))==NULL){
730 /* a request without to tag cannot be part of a dialog */
731 return NULL;
732 }
733
734 call_id=belle_sip_message_get_header_by_type(msg,belle_sip_header_call_id_t);
735 from=belle_sip_message_get_header_by_type(msg,belle_sip_header_from_t);
736
737 if (call_id==NULL || from==NULL || (from_tag=belle_sip_header_from_get_tag(from))==NULL) return NULL;
738
739 call_id_value=belle_sip_header_call_id_get_call_id(call_id);
740 local_tag=as_uas ? to_tag : from_tag;
741 remote_tag=as_uas ? from_tag : to_tag;
742 return belle_sip_provider_find_dialog(prov,call_id_value,local_tag,remote_tag);
743 }
744
belle_sip_provider_add_dialog(belle_sip_provider_t * prov,belle_sip_dialog_t * dialog)745 void belle_sip_provider_add_dialog(belle_sip_provider_t *prov, belle_sip_dialog_t *dialog){
746 prov->dialogs=belle_sip_list_prepend(prov->dialogs,belle_sip_object_ref(dialog));
747 }
748
notify_dialog_terminated(belle_sip_dialog_terminated_event_t * ev)749 static void notify_dialog_terminated(belle_sip_dialog_terminated_event_t* ev) {
750 BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_DIALOG(ev->dialog,process_dialog_terminated,ev);
751 belle_sip_object_unref(ev->dialog);
752 belle_sip_free(ev);
753 }
754
belle_sip_provider_remove_dialog(belle_sip_provider_t * prov,belle_sip_dialog_t * dialog)755 void belle_sip_provider_remove_dialog(belle_sip_provider_t *prov, belle_sip_dialog_t *dialog){
756 belle_sip_dialog_terminated_event_t* ev=belle_sip_malloc(sizeof(belle_sip_dialog_terminated_event_t));
757 ev->source=prov;
758 ev->dialog=dialog;
759 ev->is_expired=dialog->is_expired;
760 prov->dialogs=belle_sip_list_remove(prov->dialogs,dialog);
761 belle_sip_main_loop_do_later(belle_sip_stack_get_main_loop(prov->stack)
762 ,(belle_sip_callback_t) notify_dialog_terminated
763 , ev);
764
765 }
766
belle_sip_provider_create_client_transaction(belle_sip_provider_t * prov,belle_sip_request_t * req)767 belle_sip_client_transaction_t *belle_sip_provider_create_client_transaction(belle_sip_provider_t *prov, belle_sip_request_t *req){
768 const char *method=belle_sip_request_get_method(req);
769 belle_sip_client_transaction_t *t;
770 belle_sip_client_transaction_t *inv_transaction;
771 if (strcmp(method,"INVITE")==0)
772 t=(belle_sip_client_transaction_t*)belle_sip_ict_new(prov,req);
773 else if (strcmp(method,"ACK")==0){
774 belle_sip_error("belle_sip_provider_create_client_transaction() cannot be used for ACK requests.");
775 return NULL;
776 } else {
777 t=(belle_sip_client_transaction_t*)belle_sip_nict_new(prov,req);
778 if (strcmp(method,"CANCEL")==0){
779 /*force next hop*/
780 inv_transaction=belle_sip_provider_find_matching_client_transaction_from_req(prov,req);
781 if (inv_transaction && inv_transaction->next_hop) {
782 /*found corresponding ict, taking next hop*/
783 /*9.1 Client Behavior
784 * The destination address,
785 port, and transport for the CANCEL MUST be identical to those used to
786 send the original request.*/
787 t->next_hop=(belle_sip_hop_t*)belle_sip_object_ref(inv_transaction->next_hop);
788 } else {
789 belle_sip_error ("No corresponding ict nor dest found for cancel request attached to transaction [%p]",t);
790 }
791 }
792 }
793 belle_sip_transaction_set_dialog((belle_sip_transaction_t*)t,belle_sip_provider_find_dialog_from_message(prov,(belle_sip_message_t*)req,FALSE));
794 belle_sip_request_set_dialog(req,NULL);/*get rid of the reference to the dialog, which is no longer needed in the message.
795 This is to avoid circular references.*/
796 return t;
797 }
798
belle_sip_provider_create_server_transaction(belle_sip_provider_t * prov,belle_sip_request_t * req)799 belle_sip_server_transaction_t *belle_sip_provider_create_server_transaction(belle_sip_provider_t *prov, belle_sip_request_t *req){
800 belle_sip_server_transaction_t* t;
801 belle_sip_response_t *resp = NULL;
802 if (strcmp(belle_sip_request_get_method(req),"INVITE")==0){
803 t=(belle_sip_server_transaction_t*)belle_sip_ist_new(prov,req);
804 /*create a 100 Trying response to immediately stop client retransmissions*/
805 resp=belle_sip_response_create_from_request(req,100);
806
807 }else if (strcmp(belle_sip_request_get_method(req),"ACK")==0){
808 belle_sip_error("Creating a server transaction for an ACK is not a good idea, probably");
809 return NULL;
810 }else
811 t=(belle_sip_server_transaction_t*)belle_sip_nist_new(prov,req);
812 belle_sip_transaction_set_dialog((belle_sip_transaction_t*)t,belle_sip_provider_find_dialog_from_message(prov,(belle_sip_message_t*)req,TRUE));
813 belle_sip_provider_add_server_transaction(prov,t);
814 if (resp){
815 /*the response must be sent after the server transaction is refd by belle_sip_provider_add_server_transaction , otherwise
816 * through callbacks we'll reach a point where it is unrefed before leaving from this function*/
817 belle_sip_server_transaction_send_response(t, resp);
818 }
819 return t;
820 }
821
belle_sip_provider_get_sip_stack(belle_sip_provider_t * p)822 belle_sip_stack_t *belle_sip_provider_get_sip_stack(belle_sip_provider_t *p){
823 return p->stack;
824 }
825
belle_sip_provider_get_channel(belle_sip_provider_t * p,const belle_sip_hop_t * hop)826 belle_sip_channel_t * belle_sip_provider_get_channel(belle_sip_provider_t *p, const belle_sip_hop_t *hop){
827 belle_sip_list_t *l;
828 belle_sip_listening_point_t *candidate=NULL,*lp;
829 belle_sip_channel_t *chan;
830
831 if (hop->transport!=NULL) {
832 for(l=p->lps;l!=NULL;l=l->next){
833 lp=(belle_sip_listening_point_t*)l->data;
834 if (strcasecmp(belle_sip_listening_point_get_transport(lp),hop->transport)==0){
835 chan=belle_sip_listening_point_get_channel(lp,hop);
836 if (chan) {
837 belle_sip_channel_check_dns_reusability(chan);
838 return chan;
839 }
840 candidate=lp;
841 }
842 }
843 if (candidate){
844 chan=belle_sip_listening_point_create_channel(candidate,hop);
845 if (!chan) belle_sip_error("Could not create channel to [%s://%s:%i]",hop->transport,hop->host,hop->port);
846 return chan;
847 }
848 }
849 belle_sip_error("No listening point matching for [%s://%s:%i]",hop->transport,hop->host,hop->port);
850 return NULL;
851 }
852
belle_sip_provider_release_channel(belle_sip_provider_t * p,belle_sip_channel_t * chan)853 void belle_sip_provider_release_channel(belle_sip_provider_t *p, belle_sip_channel_t *chan){
854 belle_sip_listening_point_remove_channel(chan->lp,chan);
855 }
856
belle_sip_provider_clean_channels(belle_sip_provider_t * p)857 void belle_sip_provider_clean_channels(belle_sip_provider_t *p){
858 belle_sip_list_t *l;
859 belle_sip_listening_point_t *lp;
860
861 for(l=p->lps;l!=NULL;l=l->next){
862 lp=(belle_sip_listening_point_t*)l->data;
863 belle_sip_listening_point_clean_channels(lp);
864 }
865 }
866
belle_sip_provider_send_request(belle_sip_provider_t * p,belle_sip_request_t * req)867 void belle_sip_provider_send_request(belle_sip_provider_t *p, belle_sip_request_t *req){
868 belle_sip_hop_t* hop;
869 belle_sip_channel_t *chan;
870 hop=belle_sip_stack_get_next_hop(p->stack,req);
871 chan=belle_sip_provider_get_channel(p,hop);
872 if (chan) {
873 belle_sip_channel_queue_message(chan,BELLE_SIP_MESSAGE(req));
874 }
875 }
876
belle_sip_provider_send_response(belle_sip_provider_t * p,belle_sip_response_t * resp)877 void belle_sip_provider_send_response(belle_sip_provider_t *p, belle_sip_response_t *resp){
878 belle_sip_hop_t* hop;
879 belle_sip_channel_t *chan;
880 belle_sip_header_to_t *to=(belle_sip_header_to_t*)belle_sip_message_get_header((belle_sip_message_t*)resp,"to");
881
882 if (belle_sip_response_get_status_code(resp)!=100 && to && belle_sip_header_to_get_tag(to)==NULL){
883 char token[BELLE_SIP_TAG_LENGTH];
884 compute_hash_from_invariants((belle_sip_message_t*)resp,token,sizeof(token),"tag");
885 belle_sip_header_to_set_tag(to,token);
886 }
887 hop=belle_sip_response_get_return_hop(resp);
888 if (hop){
889 chan=belle_sip_provider_get_channel(p,hop);
890 if (chan) belle_sip_channel_queue_message(chan,BELLE_SIP_MESSAGE(resp));
891 belle_sip_object_unref(hop);
892 }
893 }
894
895
896 /*private provider API*/
897
belle_sip_provider_set_transaction_terminated(belle_sip_provider_t * p,belle_sip_transaction_t * t)898 void belle_sip_provider_set_transaction_terminated(belle_sip_provider_t *p, belle_sip_transaction_t *t){
899 belle_sip_transaction_terminated_event_t ev;
900
901 BELLE_SIP_OBJECT_VPTR(t,belle_sip_transaction_t)->on_terminate(t);
902 ev.source=t->provider;
903 ev.transaction=t;
904 ev.is_server_transaction=BELLE_SIP_IS_INSTANCE_OF(t,belle_sip_server_transaction_t);
905 BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(t,process_transaction_terminated,&ev);
906 if (!ev.is_server_transaction){
907 belle_sip_provider_remove_client_transaction(p,(belle_sip_client_transaction_t*)t);
908 }else{
909 belle_sip_provider_remove_server_transaction(p,(belle_sip_server_transaction_t*)t);
910 }
911 }
912
belle_sip_provider_add_client_transaction(belle_sip_provider_t * prov,belle_sip_client_transaction_t * t)913 void belle_sip_provider_add_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t){
914 prov->client_transactions=belle_sip_list_prepend(prov->client_transactions,belle_sip_object_ref(t));
915 }
916
917 struct client_transaction_matcher{
918 const char *branchid;
919 const char *method;
920 };
921
client_transaction_match(const void * p_tr,const void * p_matcher)922 static int client_transaction_match(const void *p_tr, const void *p_matcher){
923 belle_sip_client_transaction_t *tr=(belle_sip_client_transaction_t*)p_tr;
924 struct client_transaction_matcher *matcher=(struct client_transaction_matcher*)p_matcher;
925 const char *req_method=belle_sip_request_get_method(tr->base.request);
926 if (strcmp(matcher->branchid,tr->base.branch_id)==0 && strcmp(matcher->method,req_method)==0) return 0;
927 return -1;
928 }
929
belle_sip_provider_find_matching_client_transaction(belle_sip_provider_t * prov,belle_sip_response_t * resp)930 belle_sip_client_transaction_t * belle_sip_provider_find_matching_client_transaction(belle_sip_provider_t *prov,
931 belle_sip_response_t *resp){
932 struct client_transaction_matcher matcher;
933 belle_sip_header_via_t *via=(belle_sip_header_via_t*)belle_sip_message_get_header((belle_sip_message_t*)resp,"via");
934 belle_sip_header_cseq_t *cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header((belle_sip_message_t*)resp,"cseq");
935 belle_sip_client_transaction_t *ret=NULL;
936 belle_sip_list_t *elem;
937 if (via==NULL){
938 belle_sip_warning("Response has no via.");
939 return NULL;
940 }
941 if (cseq==NULL){
942 belle_sip_warning("Response has no cseq.");
943 return NULL;
944 }
945 matcher.branchid=belle_sip_header_via_get_branch(via);
946 matcher.method=belle_sip_header_cseq_get_method(cseq);
947 elem=belle_sip_list_find_custom(prov->client_transactions,client_transaction_match,&matcher);
948 if (elem){
949 ret=(belle_sip_client_transaction_t*)elem->data;
950 belle_sip_message("Found transaction matching response.");
951 }
952 return ret;
953 }
954
belle_sip_provider_remove_client_transaction(belle_sip_provider_t * prov,belle_sip_client_transaction_t * t)955 void belle_sip_provider_remove_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t){
956 belle_sip_list_t* elem=belle_sip_list_find(prov->client_transactions,t);
957 if (elem) {
958 prov->client_transactions=belle_sip_list_delete_link(prov->client_transactions,elem);
959 belle_sip_object_unref(t);
960 } else {
961 belle_sip_error("trying to remove transaction [%p] not part of provider [%p]",t,prov);
962 }
963
964 }
965
belle_sip_provider_add_server_transaction(belle_sip_provider_t * prov,belle_sip_server_transaction_t * t)966 void belle_sip_provider_add_server_transaction(belle_sip_provider_t *prov, belle_sip_server_transaction_t *t){
967 prov->server_transactions=belle_sip_list_prepend(prov->server_transactions,belle_sip_object_ref(t));
968 }
969
970 struct transaction_matcher{
971 const char *branchid;
972 const char *method;
973 const char *sentby;
974 int is_ack_or_cancel;
975 };
976
transaction_match(const void * p_tr,const void * p_matcher)977 static int transaction_match(const void *p_tr, const void *p_matcher){
978 belle_sip_transaction_t *tr=(belle_sip_transaction_t*)p_tr;
979 struct transaction_matcher *matcher=(struct transaction_matcher*)p_matcher;
980 const char *req_method=belle_sip_request_get_method(tr->request);
981 if (strcmp(matcher->branchid,tr->branch_id)==0){
982 if (strcmp(matcher->method,req_method)==0) return 0;
983 if (matcher->is_ack_or_cancel && strcmp(req_method,"INVITE")==0) return 0;
984 }
985 return -1;
986 }
987
belle_sip_provider_find_matching_transaction(belle_sip_list_t * transactions,belle_sip_request_t * req)988 belle_sip_transaction_t * belle_sip_provider_find_matching_transaction(belle_sip_list_t *transactions, belle_sip_request_t *req){
989 struct transaction_matcher matcher;
990 belle_sip_header_via_t *via=(belle_sip_header_via_t*)belle_sip_message_get_header((belle_sip_message_t*)req,"via");
991 belle_sip_transaction_t *ret=NULL;
992 belle_sip_list_t *elem=NULL;
993 const char *branch;
994 char token[BELLE_SIP_BRANCH_ID_LENGTH];
995
996
997 matcher.method=belle_sip_request_get_method(req);
998 matcher.is_ack_or_cancel=(strcmp(matcher.method,"ACK")==0 || strcmp(matcher.method,"CANCEL")==0);
999
1000 if (via!=NULL && (branch=belle_sip_header_via_get_branch(via))!=NULL &&
1001 strncmp(branch,BELLE_SIP_BRANCH_MAGIC_COOKIE,strlen(BELLE_SIP_BRANCH_MAGIC_COOKIE))==0){
1002 matcher.branchid=branch;
1003 }else{
1004 /*this request comes from an old equipment, we need to compute our own branch for this request.*/
1005 matcher.branchid=compute_rfc2543_branch(req,token,sizeof(token));
1006 belle_sip_request_set_rfc2543_branch(req,token);
1007 belle_sip_message("Message from old RFC2543 stack, computed branch is %s", token);
1008 }
1009
1010 elem=belle_sip_list_find_custom(transactions,transaction_match,&matcher);
1011
1012 if (elem){
1013 ret=(belle_sip_transaction_t*)elem->data;
1014 belle_sip_message("Found transaction [%p] matching request.",ret);
1015 }
1016 return ret;
1017 }
belle_sip_provider_find_matching_server_transaction(belle_sip_provider_t * prov,belle_sip_request_t * req)1018 belle_sip_server_transaction_t * belle_sip_provider_find_matching_server_transaction(belle_sip_provider_t *prov, belle_sip_request_t *req) {
1019 belle_sip_transaction_t *ret=belle_sip_provider_find_matching_transaction(prov->server_transactions,req);
1020 return ret?BELLE_SIP_SERVER_TRANSACTION(ret):NULL;
1021 }
belle_sip_provider_find_matching_client_transaction_from_req(belle_sip_provider_t * prov,belle_sip_request_t * req)1022 belle_sip_client_transaction_t * belle_sip_provider_find_matching_client_transaction_from_req(belle_sip_provider_t *prov, belle_sip_request_t *req) {
1023 belle_sip_transaction_t *ret=belle_sip_provider_find_matching_transaction(prov->client_transactions,req);
1024 return ret?BELLE_SIP_CLIENT_TRANSACTION(ret):NULL;
1025 }
1026
belle_sip_provider_remove_server_transaction(belle_sip_provider_t * prov,belle_sip_server_transaction_t * t)1027 void belle_sip_provider_remove_server_transaction(belle_sip_provider_t *prov, belle_sip_server_transaction_t *t){
1028 prov->server_transactions=belle_sip_list_remove(prov->server_transactions,t);
1029 belle_sip_object_unref(t);
1030 }
1031
1032
authorization_context_fill_from_auth(authorization_context_t * auth_context,belle_sip_header_www_authenticate_t * authenticate,belle_sip_uri_t * from_uri)1033 static void authorization_context_fill_from_auth(authorization_context_t* auth_context,belle_sip_header_www_authenticate_t* authenticate,belle_sip_uri_t *from_uri) {
1034 authorization_context_set_realm(auth_context,belle_sip_header_www_authenticate_get_realm(authenticate));
1035 if (auth_context->nonce && strcmp(belle_sip_header_www_authenticate_get_nonce(authenticate),auth_context->nonce)!=0) {
1036 /*new nonce, resetting nounce_count*/
1037 auth_context->nonce_count=0;
1038 }
1039 authorization_context_set_nonce(auth_context,belle_sip_header_www_authenticate_get_nonce(authenticate));
1040 authorization_context_set_algorithm(auth_context,belle_sip_header_www_authenticate_get_algorithm(authenticate));
1041 authorization_context_set_qop(auth_context,belle_sip_header_www_authenticate_get_qop_first(authenticate));
1042 authorization_context_set_scheme(auth_context,belle_sip_header_www_authenticate_get_scheme(authenticate));
1043 authorization_context_set_opaque(auth_context,belle_sip_header_www_authenticate_get_opaque(authenticate));
1044 authorization_context_set_user_id(auth_context, from_uri?belle_sip_uri_get_user(from_uri):NULL);
1045
1046 if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(authenticate,belle_sip_header_proxy_authenticate_t)) {
1047 auth_context->is_proxy=1;
1048 }
1049 }
1050
1051
belle_sip_provider_get_auth_context_by_realm_or_call_id(belle_sip_provider_t * p,belle_sip_header_call_id_t * call_id,belle_sip_uri_t * from_uri,const char * realm)1052 static belle_sip_list_t* belle_sip_provider_get_auth_context_by_realm_or_call_id(belle_sip_provider_t *p,belle_sip_header_call_id_t* call_id,belle_sip_uri_t *from_uri,const char* realm) {
1053 belle_sip_list_t* auth_context_lst=NULL;
1054 belle_sip_list_t* result=NULL;
1055 authorization_context_t* auth_context;
1056
1057 for (auth_context_lst=p->auth_contexts;auth_context_lst!=NULL;auth_context_lst=auth_context_lst->next) {
1058 auth_context=(authorization_context_t*)auth_context_lst->data;
1059 if (belle_sip_header_call_id_equals(auth_context->callid,call_id) ) {
1060 result=belle_sip_list_append(result,auth_context_lst->data);
1061 }
1062 }
1063
1064 /* According to the RFC3261 22.3, if the outbound proxy realm is set, we could reuse its nonce value:
1065 * "If a UA receives a Proxy-Authenticate header field value in a 401/407
1066 * response to a request with a particular Call-ID, it should
1067 * incorporate credentials for that realm in all subsequent requests
1068 * that contain the same Call-ID. These credentials MUST NOT be cached
1069 * across dialogs; however, if a UA is configured with the realm of its
1070 * local outbound proxy, when one exists, then the UA MAY cache
1071 * credentials for that realm across dialogs."
1072 */
1073 if (result == NULL){
1074 const char * from_user=from_uri?belle_sip_uri_get_user(from_uri):NULL;
1075
1076 belle_sip_debug("belle_sip_provider_auth: no auth context registered with [call_id=%s], looking for realm..."
1077 , call_id?belle_sip_header_call_id_get_call_id(call_id):"(null)");
1078
1079 for (auth_context_lst=p->auth_contexts;auth_context_lst!=NULL;auth_context_lst=auth_context_lst->next) {
1080 auth_context=(authorization_context_t*)auth_context_lst->data;
1081
1082 belle_sip_debug("belle_sip_provider_auth: \t[realm=%s] [user_id=%s] [call_id=%s]",
1083 auth_context->realm?auth_context->realm:"(null)",
1084 auth_context->user_id?auth_context->user_id:"(null)",
1085 auth_context->callid?belle_sip_header_call_id_get_call_id(auth_context->callid):"(null)"
1086 );
1087 /* We also verify that user matches in case of multi-account to avoid use nonce from another account. For a
1088 * single user, from_uri user id and realm user id COULD be different but we assume here that this is not the case
1089 * in order to avoid adding another field in auth_context struct.
1090 **/
1091 if ((realm && strcmp(auth_context->realm,realm)==0)
1092 && (from_user && auth_context->user_id && strcmp(auth_context->user_id,from_user)==0)) {
1093
1094 result=belle_sip_list_append(result,auth_context_lst->data);
1095 belle_sip_debug("belle_sip_provider_auth: found a MATCHING realm auth context!");
1096 }
1097 }
1098 }
1099 return result;
1100 }
1101
belle_sip_provider_update_or_create_auth_context(belle_sip_provider_t * p,belle_sip_header_call_id_t * call_id,belle_sip_header_www_authenticate_t * authenticate,belle_sip_uri_t * from_uri,const char * realm)1102 static void belle_sip_provider_update_or_create_auth_context(belle_sip_provider_t *p,belle_sip_header_call_id_t* call_id,belle_sip_header_www_authenticate_t* authenticate,belle_sip_uri_t *from_uri,const char* realm) {
1103 belle_sip_list_t* auth_context_lst = NULL;
1104 authorization_context_t* auth_context;
1105
1106 for (auth_context_lst=belle_sip_provider_get_auth_context_by_realm_or_call_id(p,call_id,from_uri,realm);auth_context_lst!=NULL;auth_context_lst=auth_context_lst->next) {
1107 auth_context=(authorization_context_t*)auth_context_lst->data;
1108 if (strcmp(auth_context->realm,belle_sip_header_www_authenticate_get_realm(authenticate))==0) {
1109 authorization_context_fill_from_auth(auth_context,authenticate,from_uri);
1110 if (auth_context_lst) belle_sip_free(auth_context_lst);
1111 return; /*only one realm is supposed to be found for now*/
1112 }
1113 }
1114
1115 /*no auth context found, creating one*/
1116 auth_context=belle_sip_authorization_create(call_id);
1117 belle_sip_debug("belle_sip_provider_auth: no matching auth context, creating one for [realm=%s][user_id=%s][call_id=%s]"
1118 , belle_sip_header_www_authenticate_get_realm(authenticate)?belle_sip_header_www_authenticate_get_realm(authenticate):"(null)"
1119 , from_uri?belle_sip_uri_get_user(from_uri):"(null)"
1120 , call_id?belle_sip_header_call_id_get_call_id(call_id):"(null)");
1121 authorization_context_fill_from_auth(auth_context,authenticate,from_uri);
1122
1123 p->auth_contexts=belle_sip_list_append(p->auth_contexts,auth_context);
1124 if (auth_context_lst) belle_sip_free(auth_context_lst);
1125 return;
1126 }
1127
1128
belle_sip_provider_add_authorization(belle_sip_provider_t * p,belle_sip_request_t * request,belle_sip_response_t * resp,belle_sip_uri_t * from_uri,belle_sip_list_t ** auth_infos,const char * realm)1129 int belle_sip_provider_add_authorization(belle_sip_provider_t *p, belle_sip_request_t* request, belle_sip_response_t *resp,
1130 belle_sip_uri_t *from_uri, belle_sip_list_t** auth_infos, const char* realm) {
1131 belle_sip_header_call_id_t* call_id;
1132 belle_sip_list_t* auth_context_iterator;
1133 belle_sip_list_t* authenticate_lst;
1134 belle_sip_list_t* head;
1135 belle_sip_header_www_authenticate_t* authenticate;
1136 belle_sip_header_authorization_t* authorization;
1137 belle_sip_header_from_t* from;
1138 belle_sip_auth_event_t* auth_event;
1139 authorization_context_t* auth_context;
1140 const char* ha1;
1141 char computed_ha1[33];
1142 int result=0;
1143 const char* request_method;
1144 /*check params*/
1145 if (!p || !request) {
1146 belle_sip_error("belle_sip_provider_add_authorization bad parameters");
1147 return-1;
1148 }
1149 request_method=belle_sip_request_get_method(request);
1150
1151 /*22 Usage of HTTP Authentication
1152 22.1 Framework
1153 While a server can legitimately challenge most SIP requests, there
1154 are two requests defined by this document that require special
1155 handling for authentication: ACK and CANCEL.
1156 Under an authentication scheme that uses responses to carry values
1157 used to compute nonces (such as Digest), some problems come up for
1158 any requests that take no response, including ACK. For this reason,
1159 any credentials in the INVITE that were accepted by a server MUST be
1160 accepted by that server for the ACK. UACs creating an ACK message
1161 will duplicate all of the Authorization and Proxy-Authorization
1162 header field values that appeared in the INVITE to which the ACK
1163 corresponds. Servers MUST NOT attempt to challenge an ACK.
1164
1165 Although the CANCEL method does take a response (a 2xx), servers MUST
1166 NOT attempt to challenge CANCEL requests since these requests cannot
1167 be resubmitted. Generally, a CANCEL request SHOULD be accepted by a
1168 server if it comes from the same hop that sent the request being
1169 canceled (provided that some sort of transport or network layer
1170 security association, as described in Section 26.2.1, is in place).
1171 */
1172
1173 if (strcmp("CANCEL",request_method)==0 || strcmp("ACK",request_method)==0) {
1174 belle_sip_debug("no authorization header needed for method [%s]",request_method);
1175 return 0;
1176 }
1177
1178 if (from_uri==NULL){
1179 from = belle_sip_message_get_header_by_type(request,belle_sip_header_from_t);
1180 from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from);
1181 }
1182
1183 /*get authenticates value from response*/
1184 if (resp) {
1185 belle_sip_list_t *it;
1186 call_id = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(resp),belle_sip_header_call_id_t);
1187 /*searching for authentication headers*/
1188 authenticate_lst = belle_sip_list_copy(belle_sip_message_get_headers(BELLE_SIP_MESSAGE(resp),BELLE_SIP_WWW_AUTHENTICATE));
1189 /*search for proxy authenticate*/
1190 authenticate_lst=belle_sip_list_concat(authenticate_lst,belle_sip_list_copy(belle_sip_message_get_headers(BELLE_SIP_MESSAGE(resp),BELLE_SIP_PROXY_AUTHENTICATE)));
1191 /*update auth contexts with authenticate headers from response*/
1192 for (it=authenticate_lst;it!=NULL;it=it->next) {
1193 authenticate=BELLE_SIP_HEADER_WWW_AUTHENTICATE(it->data);
1194 belle_sip_provider_update_or_create_auth_context(p,call_id,authenticate,from_uri,realm);
1195 }
1196 belle_sip_list_free(authenticate_lst);
1197 }
1198
1199 /*put authorization header if passwd found*/
1200 call_id = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_call_id_t);
1201
1202 belle_sip_debug("belle_sip_provider_auth: looking an auth context for [method=%s][realm=%s][user_id=%s][call_id=%s]"
1203 , request_method
1204 , realm?realm:"(null)"
1205 , from_uri?belle_sip_uri_get_user(from_uri):"(null)"
1206 , call_id?belle_sip_header_call_id_get_call_id(call_id):"(null)"
1207 );
1208 head=belle_sip_provider_get_auth_context_by_realm_or_call_id(p,call_id,from_uri,realm);
1209 /*we assume there no existing auth headers*/
1210 for (auth_context_iterator=head;auth_context_iterator!=NULL;auth_context_iterator=auth_context_iterator->next) {
1211 /*clear auth info*/
1212 auth_context=(authorization_context_t*)auth_context_iterator->data;
1213 auth_event = belle_sip_auth_event_create((belle_sip_object_t*)p,auth_context->realm,from_uri);
1214 /*put data*/
1215 /*call listener*/
1216 BELLE_SIP_PROVIDER_INVOKE_LISTENERS(p->listeners,process_auth_requested,auth_event);
1217 if (auth_event->passwd || auth_event->ha1) {
1218 if (!auth_event->userid) {
1219 /*if no userid, username = userid*/
1220
1221 belle_sip_auth_event_set_userid(auth_event,auth_event->username);
1222 }
1223 belle_sip_message("Auth info found for [%s] realm [%s]",auth_event->userid,auth_event->realm);
1224 if (auth_context->is_proxy ||
1225 (!belle_sip_header_call_id_equals(call_id,auth_context->callid)
1226 &&realm
1227 &&strcmp(realm,auth_context->realm)==0
1228 &&from_uri
1229 &&strcmp(auth_event->username,belle_sip_uri_get_user(from_uri))==0
1230 &&strcmp("REGISTER",request_method)!=0)) /* Relying on method name for choosing between authorization and proxy-authorization
1231 is not very strong but I don't see any better solution as we don't know all the time what type of challange we will have*/{
1232 authorization=BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_header_proxy_authorization_new());
1233 } else {
1234 authorization=belle_sip_header_authorization_new();
1235 }
1236 belle_sip_header_authorization_set_scheme(authorization,auth_context->scheme);
1237 belle_sip_header_authorization_set_realm(authorization,auth_context->realm);
1238 belle_sip_header_authorization_set_username(authorization,auth_event->userid);
1239 belle_sip_header_authorization_set_nonce(authorization,auth_context->nonce);
1240 belle_sip_header_authorization_set_qop(authorization,auth_context->qop);
1241 belle_sip_header_authorization_set_opaque(authorization,auth_context->opaque);
1242 belle_sip_header_authorization_set_algorithm(authorization,auth_context->algorithm);
1243 belle_sip_header_authorization_set_uri(authorization,(belle_sip_uri_t*)belle_sip_request_get_uri(request));
1244 if (auth_context->qop){
1245 ++auth_context->nonce_count;
1246 belle_sip_header_authorization_set_nonce_count(authorization,auth_context->nonce_count);
1247 }
1248
1249 if (auth_event->ha1) {
1250 ha1=auth_event->ha1;
1251 } else {
1252 belle_sip_auth_helper_compute_ha1(auth_event->userid,auth_context->realm,auth_event->passwd, computed_ha1);
1253 ha1=computed_ha1;
1254 }
1255 if (belle_sip_auth_helper_fill_authorization(authorization
1256 ,belle_sip_request_get_method(request)
1257 ,ha1)) {
1258 belle_sip_object_unref(authorization);
1259 } else
1260 belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(authorization));
1261 result=1;
1262 } else {
1263 belle_sip_message("No auth info found for call id [%s]",belle_sip_header_call_id_get_call_id(call_id));
1264 }
1265 /*provides auth info in any cases, usefull even if found because auth info can contain wrong password*/
1266 if (auth_infos) {
1267 /*stored to give user information on realm/username which requires authentications*/
1268 *auth_infos=belle_sip_list_append(*auth_infos,auth_event);
1269 } else {
1270 belle_sip_auth_event_destroy(auth_event);
1271 }
1272 }
1273 belle_sip_list_free(head);
1274 return result;
1275 }
1276
belle_sip_provider_set_recv_error(belle_sip_provider_t * prov,int recv_error)1277 void belle_sip_provider_set_recv_error(belle_sip_provider_t *prov, int recv_error) {
1278 belle_sip_list_t *lps;
1279 belle_sip_list_t *channels;
1280 for(lps=prov->lps;lps!=NULL;lps=lps->next){
1281 for(channels=((belle_sip_listening_point_t*)lps->data)->channels;channels!=NULL;channels=channels->next){
1282 ((belle_sip_channel_t*)channels->data)->simulated_recv_return=recv_error;
1283 ((belle_sip_source_t*)channels->data)->notify_required=(recv_error<=0);
1284 }
1285 }
1286 }
belle_sip_provider_enable_rport(belle_sip_provider_t * prov,int enable)1287 void belle_sip_provider_enable_rport(belle_sip_provider_t *prov, int enable) {
1288 prov->rport_enabled=enable;
1289 }
1290
belle_sip_provider_is_rport_enabled(belle_sip_provider_t * prov)1291 int belle_sip_provider_is_rport_enabled(belle_sip_provider_t *prov) {
1292 return prov->rport_enabled;
1293 }
1294
belle_sip_provider_enable_nat_helper(belle_sip_provider_t * prov,int enabled)1295 void belle_sip_provider_enable_nat_helper(belle_sip_provider_t *prov, int enabled){
1296 prov->nat_helper=enabled;
1297 }
1298
belle_sip_provider_nat_helper_enabled(const belle_sip_provider_t * prov)1299 int belle_sip_provider_nat_helper_enabled(const belle_sip_provider_t *prov){
1300 return prov->nat_helper;
1301 }
belle_sip_provider_enable_unconditional_answer(belle_sip_provider_t * prov,int enable)1302 void belle_sip_provider_enable_unconditional_answer(belle_sip_provider_t *prov, int enable) {
1303 prov->unconditional_answer_enabled=enable;
1304 }
belle_sip_provider_set_unconditional_answer(belle_sip_provider_t * prov,unsigned short code)1305 void belle_sip_provider_set_unconditional_answer(belle_sip_provider_t *prov, unsigned short code) {
1306 prov->unconditional_answer=code;
1307 }
1308