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
belle_sip_transaction_state_to_string(belle_sip_transaction_state_t state)21 const char *belle_sip_transaction_state_to_string(belle_sip_transaction_state_t state){
22 switch(state){
23 case BELLE_SIP_TRANSACTION_INIT:
24 return "INIT";
25 case BELLE_SIP_TRANSACTION_TRYING:
26 return "TRYING";
27 case BELLE_SIP_TRANSACTION_CALLING:
28 return "CALLING";
29 case BELLE_SIP_TRANSACTION_COMPLETED:
30 return "COMPLETED";
31 case BELLE_SIP_TRANSACTION_CONFIRMED:
32 return "CONFIRMED";
33 case BELLE_SIP_TRANSACTION_ACCEPTED:
34 return "ACCEPTED";
35 case BELLE_SIP_TRANSACTION_PROCEEDING:
36 return "PROCEEDING";
37 case BELLE_SIP_TRANSACTION_TERMINATED:
38 return "TERMINATED";
39 }
40 belle_sip_fatal("Invalid transaction state.");
41 return "INVALID";
42 }
43
belle_sip_transaction_set_state(belle_sip_transaction_t * t,belle_sip_transaction_state_t state)44 void belle_sip_transaction_set_state(belle_sip_transaction_t *t, belle_sip_transaction_state_t state) {
45 belle_sip_message("Changing [%s] [%s] transaction [%p], from state [%s] to [%s]",
46 BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_client_transaction_t) ? "client" : "server",
47 belle_sip_request_get_method(t->request),
48 t,
49 belle_sip_transaction_state_to_string(t->state),
50 belle_sip_transaction_state_to_string(state));
51 t->state=state;
52 }
53
belle_sip_transaction_get_method(const belle_sip_transaction_t * t)54 BELLESIP_EXPORT const char *belle_sip_transaction_get_method(const belle_sip_transaction_t *t){
55 return belle_sip_request_get_method(t->request);
56 }
57
transaction_end_background_task(belle_sip_transaction_t * obj)58 static void transaction_end_background_task(belle_sip_transaction_t *obj){
59 if (obj->bg_task_id){
60 belle_sip_message("transaction [%p]: ending transaction background task with id=[%lx].",obj,obj->bg_task_id);
61 belle_sip_end_background_task(obj->bg_task_id);
62 obj->bg_task_id=0;
63 }
64 }
65
transaction_background_task_ended(belle_sip_transaction_t * obj)66 static void transaction_background_task_ended(belle_sip_transaction_t *obj){
67 belle_sip_warning("transaction [%p]: transaction background task has to be ended now, but work isn't finished.",obj);
68 transaction_end_background_task(obj);
69 }
70
transaction_begin_background_task(belle_sip_transaction_t * obj)71 static void transaction_begin_background_task(belle_sip_transaction_t *obj){
72 if (obj->bg_task_id==0){
73 char *transaction = bctbx_strdup_printf("belle-sip transaction(%p)", obj);
74 obj->bg_task_id=belle_sip_begin_background_task(transaction,(void (*)(void*))transaction_background_task_ended, obj);
75 if (obj->bg_task_id) belle_sip_message("transaction [%p]: starting transaction background task with id=[%lx].",obj,obj->bg_task_id);
76 bctbx_free(transaction);
77 }
78 }
79
belle_sip_transaction_init(belle_sip_transaction_t * t,belle_sip_provider_t * prov,belle_sip_request_t * req)80 static void belle_sip_transaction_init(belle_sip_transaction_t *t, belle_sip_provider_t *prov, belle_sip_request_t *req){
81 transaction_begin_background_task(t);
82 t->request=(belle_sip_request_t*)belle_sip_object_ref(req);
83 t->provider=prov;
84 }
85
transaction_destroy(belle_sip_transaction_t * t)86 static void transaction_destroy(belle_sip_transaction_t *t){
87 if (t->call_repair_timer) {
88 belle_sip_transaction_stop_timer(t, t->call_repair_timer);
89 belle_sip_object_unref(t->call_repair_timer);
90 t->call_repair_timer = NULL;
91 }
92 if (t->request) belle_sip_object_unref(t->request);
93 if (t->last_response) belle_sip_object_unref(t->last_response);
94 if (t->channel) belle_sip_object_unref(t->channel);
95 if (t->branch_id) belle_sip_free(t->branch_id);
96 belle_sip_transaction_set_dialog(t,NULL);
97 belle_sip_message("Transaction [%p] deleted",t);
98
99 }
100
notify_timeout(belle_sip_transaction_t * t)101 static void notify_timeout(belle_sip_transaction_t *t){
102 belle_sip_timeout_event_t ev;
103 ev.source=(belle_sip_object_t*)t->provider;
104 ev.transaction=t;
105 ev.is_server_transaction=BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_server_transaction_t);
106 BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(t,process_timeout,&ev);
107 }
108
server_transaction_on_call_repair_timer(belle_sip_transaction_t * t)109 static int server_transaction_on_call_repair_timer(belle_sip_transaction_t *t) {
110 belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(t), belle_sip_response_create_from_request(t->request, 503));
111 return BELLE_SIP_STOP;
112 }
113
client_transaction_on_call_repair_timer(belle_sip_transaction_t * t)114 static int client_transaction_on_call_repair_timer(belle_sip_transaction_t *t) {
115 belle_sip_transaction_terminate(t);
116 return BELLE_SIP_STOP;
117 }
118
on_channel_state_changed(belle_sip_channel_listener_t * l,belle_sip_channel_t * chan,belle_sip_channel_state_t state)119 static void on_channel_state_changed(belle_sip_channel_listener_t *l, belle_sip_channel_t *chan, belle_sip_channel_state_t state){
120 belle_sip_transaction_t *t=(belle_sip_transaction_t*)l;
121 belle_sip_io_error_event_t ev;
122 const belle_sip_timer_config_t *timercfg = NULL;
123 belle_sip_transaction_state_t tr_state=belle_sip_transaction_get_state((belle_sip_transaction_t*)t);
124
125 belle_sip_message("transaction [%p] channel state changed to [%s]"
126 ,t
127 ,belle_sip_channel_state_to_string(state));
128 switch(state){
129 case BELLE_SIP_CHANNEL_READY:
130 if (tr_state==BELLE_SIP_TRANSACTION_INIT && BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_client_transaction_t) ){
131 belle_sip_client_transaction_t *ct = (belle_sip_client_transaction_t*) t;
132 BELLE_SIP_OBJECT_VPTR(ct,belle_sip_client_transaction_t)->send_request(ct);
133 }
134 break;
135 case BELLE_SIP_CHANNEL_DISCONNECTED:
136 case BELLE_SIP_CHANNEL_ERROR:
137 belle_sip_object_ref(t); /*take a ref in the case where the app calls belle_sip_transaction_terminate() within the listener*/
138 ev.transport=belle_sip_channel_get_transport_name(chan);
139 ev.source=BELLE_SIP_OBJECT(t);
140 ev.port=chan->peer_port;
141 ev.host=chan->peer_name;
142 if ( tr_state!=BELLE_SIP_TRANSACTION_COMPLETED
143 && tr_state!=BELLE_SIP_TRANSACTION_CONFIRMED
144 && tr_state!=BELLE_SIP_TRANSACTION_ACCEPTED
145 && tr_state!=BELLE_SIP_TRANSACTION_TERMINATED) {
146 BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(((belle_sip_transaction_t*)t),process_io_error,&ev);
147 }
148 if (t->timed_out) {
149 notify_timeout((belle_sip_transaction_t*)t);
150 } else {
151 if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(t, belle_sip_ist_t) || BELLE_SIP_OBJECT_IS_INSTANCE_OF(t, belle_sip_ict_t)) {
152 timercfg = belle_sip_transaction_get_timer_config(t);
153 if (t->call_repair_timer) {
154 belle_sip_transaction_stop_timer(t, t->call_repair_timer);
155 belle_sip_object_unref(t->call_repair_timer);
156 t->call_repair_timer = NULL;
157 }
158 }
159 }
160
161 if (!t->timed_out && belle_sip_transaction_state_is_transient(t->state) && BELLE_SIP_OBJECT_IS_INSTANCE_OF(t, belle_sip_ist_t)) {
162 t->call_repair_timer = belle_sip_timeout_source_new((belle_sip_source_func_t)server_transaction_on_call_repair_timer, t, 32 * timercfg->T1);
163 belle_sip_transaction_start_timer(t, t->call_repair_timer);
164 } else if (!t->timed_out && belle_sip_transaction_state_is_transient(t->state) && BELLE_SIP_OBJECT_IS_INSTANCE_OF(t, belle_sip_ict_t)) {
165 t->call_repair_timer = belle_sip_timeout_source_new((belle_sip_source_func_t)client_transaction_on_call_repair_timer, t, 32 * timercfg->T1);
166 belle_sip_transaction_start_timer(t, t->call_repair_timer);
167 } else {
168 belle_sip_transaction_terminate(t);
169 }
170 if (t->channel){
171 belle_sip_channel_remove_listener(t->channel, l);
172 belle_sip_object_unref(t->channel);
173 t->channel = NULL;
174 }
175 belle_sip_object_unref(t);
176
177 break;
178 default:
179 /*ignored*/
180 break;
181 }
182 }
183
184 BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(belle_sip_transaction_t,belle_sip_channel_listener_t)
185 on_channel_state_changed,
186 NULL, /* on_message_headers */
187 NULL, /* on_message */
188 NULL, /* on_sending */
189 NULL /* on_auth_requested */
190 BELLE_SIP_IMPLEMENT_INTERFACE_END
191
192 BELLE_SIP_DECLARE_IMPLEMENTED_INTERFACES_1(belle_sip_transaction_t, belle_sip_channel_listener_t);
193
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_transaction_t)194 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_transaction_t)
195 {
196 BELLE_SIP_VPTR_INIT(belle_sip_transaction_t,belle_sip_object_t,FALSE),
197 (belle_sip_object_destroy_t) transaction_destroy,
198 NULL,/*no clone*/
199 NULL,/*no marshal*/
200 BELLE_SIP_DEFAULT_BUFSIZE_HINT
201 },
202 NULL /*on_terminate*/
203 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
204
205 void *belle_sip_transaction_get_application_data_internal(const belle_sip_transaction_t *t){
206 return t->appdata;
207 }
208
belle_sip_transaction_get_application_data(const belle_sip_transaction_t * t)209 void *belle_sip_transaction_get_application_data(const belle_sip_transaction_t *t){
210 if (t->is_internal) {
211 belle_sip_error("belle_sip_transaction_get_application_data should not be used on internal transaction [%p]",t);
212 return NULL;
213 } else {
214 return belle_sip_transaction_get_application_data_internal(t);
215 };
216 }
217
belle_sip_transaction_set_application_data(belle_sip_transaction_t * t,void * data)218 void belle_sip_transaction_set_application_data(belle_sip_transaction_t *t, void *data){
219 t->appdata=data;
220 }
221
belle_sip_transaction_get_branch_id(const belle_sip_transaction_t * t)222 const char *belle_sip_transaction_get_branch_id(const belle_sip_transaction_t *t){
223 return t->branch_id;
224 }
225
belle_sip_transaction_get_state(const belle_sip_transaction_t * t)226 belle_sip_transaction_state_t belle_sip_transaction_get_state(const belle_sip_transaction_t *t){
227 return t->state;
228 }
229
belle_sip_transaction_state_is_transient(const belle_sip_transaction_state_t state)230 int belle_sip_transaction_state_is_transient(const belle_sip_transaction_state_t state) {
231 switch(state){
232 case BELLE_SIP_TRANSACTION_INIT:
233 case BELLE_SIP_TRANSACTION_TRYING:
234 case BELLE_SIP_TRANSACTION_CALLING:
235 case BELLE_SIP_TRANSACTION_PROCEEDING:
236 return 1;
237 default:
238 return 0;
239 }
240 }
241
belle_sip_transaction_terminate(belle_sip_transaction_t * t)242 void belle_sip_transaction_terminate(belle_sip_transaction_t *t){
243 belle_sip_object_ref(t);
244 if (t->call_repair_timer) {
245 belle_sip_transaction_stop_timer(t, t->call_repair_timer);
246 belle_sip_object_unref(t->call_repair_timer);
247 t->call_repair_timer = NULL;
248 }
249 if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t))!=BELLE_SIP_TRANSACTION_TERMINATED) {
250 int is_client=BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_client_transaction_t);
251 belle_sip_transaction_set_state(t,BELLE_SIP_TRANSACTION_TERMINATED);
252 if (t->dialog && (!t->last_response || belle_sip_response_get_status_code(t->last_response)<200)){
253 /*inform the dialog if a transaction terminates without final response.*/
254 belle_sip_dialog_update(t->dialog,t,!is_client);
255 }
256 belle_sip_message("%s%s %s transaction [%p] terminated" ,is_client ? "Client":"Server"
257 ,t->is_internal ? " internal":""
258 ,belle_sip_request_get_method(belle_sip_transaction_get_request(t))
259 ,t);
260 BELLE_SIP_OBJECT_VPTR(t,belle_sip_transaction_t)->on_terminate(t);
261 belle_sip_provider_set_transaction_terminated(t->provider,t);
262 }
263 transaction_end_background_task(t);
264 belle_sip_object_unref(t);
265 }
266
belle_sip_transaction_get_request(const belle_sip_transaction_t * t)267 belle_sip_request_t *belle_sip_transaction_get_request(const belle_sip_transaction_t *t){
268 return t->request;
269 }
belle_sip_transaction_get_response(const belle_sip_transaction_t * t)270 belle_sip_response_t *belle_sip_transaction_get_response(const belle_sip_transaction_t *t) {
271 return t->last_response;
272 }
273
belle_sip_transaction_notify_timeout(belle_sip_transaction_t * t)274 void belle_sip_transaction_notify_timeout(belle_sip_transaction_t *t){
275 /*report the channel as possibly dead. If an alternate IP can be tryied, the channel will notify us with the RETRY state.
276 * Otherwise it will report the error.
277 * We limit this dead channel reporting to REGISTER transactions, who are unlikely to be unresponded.
278 **/
279 belle_sip_object_ref(t); /*take a ref in the case where the app calls belle_sip_transaction_terminate() within the timeout listener*/
280 if (strcmp(belle_sip_request_get_method(t->request),"REGISTER")==0){
281 if ( belle_sip_channel_notify_timeout(t->channel)==TRUE){
282 belle_sip_warning("Transaction [%p] has timeout, reported to channel.",t);
283 t->timed_out=TRUE;
284 }
285 }else {
286 notify_timeout(t);
287 belle_sip_transaction_terminate(t);
288 }
289 belle_sip_object_unref(t);
290 }
291
belle_sip_transaction_get_dialog(const belle_sip_transaction_t * t)292 belle_sip_dialog_t* belle_sip_transaction_get_dialog(const belle_sip_transaction_t *t) {
293 return t->dialog;
294 }
295
belle_sip_transaction_reset_dialog(belle_sip_transaction_t * tr,belle_sip_dialog_t * dialog_disapeearing)296 static void belle_sip_transaction_reset_dialog(belle_sip_transaction_t *tr, belle_sip_dialog_t *dialog_disapeearing){
297 if (tr->dialog!=dialog_disapeearing) belle_sip_error("belle_sip_transaction_reset_dialog(): inconsistency.");
298 tr->dialog=NULL;
299 }
300
belle_sip_transaction_set_dialog(belle_sip_transaction_t * t,belle_sip_dialog_t * dialog)301 void belle_sip_transaction_set_dialog(belle_sip_transaction_t *t, belle_sip_dialog_t *dialog){
302 if (t->dialog==dialog) return;
303 if (dialog) belle_sip_object_weak_ref(dialog,(belle_sip_object_destroy_notify_t)belle_sip_transaction_reset_dialog,t);
304 if (t->dialog) belle_sip_object_weak_unref(t->dialog,(belle_sip_object_destroy_notify_t)belle_sip_transaction_reset_dialog,t);
305 t->dialog=dialog;
306 }
307
308 /*
309 * Server transaction
310 */
311
server_transaction_destroy(belle_sip_server_transaction_t * t)312 static void server_transaction_destroy(belle_sip_server_transaction_t *t){
313 }
314
315
316 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_server_transaction_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_server_transaction_t)317 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_server_transaction_t)
318 {
319 {
320 BELLE_SIP_VPTR_INIT(belle_sip_server_transaction_t,belle_sip_transaction_t,FALSE),
321 (belle_sip_object_destroy_t) server_transaction_destroy,
322 NULL,
323 NULL,
324 BELLE_SIP_DEFAULT_BUFSIZE_HINT
325 },
326 NULL
327 },
328 NULL, /* send_new_response */
329 NULL /* on_request_retransmission */
330 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
331
332 void belle_sip_server_transaction_init(belle_sip_server_transaction_t *t, belle_sip_provider_t *prov,belle_sip_request_t *req){
333 const char *branch;
334 belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)req,"via"));
335 branch=belle_sip_header_via_get_branch(via);
336 if (branch==NULL || strncmp(branch,BELLE_SIP_BRANCH_MAGIC_COOKIE,strlen(BELLE_SIP_BRANCH_MAGIC_COOKIE))!=0){
337 branch=req->rfc2543_branch;
338 if (branch==NULL) belle_sip_fatal("No computed branch for RFC2543 style of message, this should never happen.");
339 }
340 t->base.branch_id=belle_sip_strdup(branch);
341 belle_sip_transaction_init((belle_sip_transaction_t*)t,prov,req);
342 belle_sip_random_token(t->to_tag,sizeof(t->to_tag));
343 }
344
belle_sip_server_transaction_send_response(belle_sip_server_transaction_t * t,belle_sip_response_t * resp)345 void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *t, belle_sip_response_t *resp){
346 belle_sip_transaction_t *base=(belle_sip_transaction_t*)t;
347 belle_sip_header_to_t *to=(belle_sip_header_to_t*)belle_sip_message_get_header((belle_sip_message_t*)resp,"to");
348 belle_sip_dialog_t *dialog=base->dialog;
349 int status_code;
350
351 belle_sip_object_ref(resp);
352 if (!base->last_response || !base->channel){
353 belle_sip_hop_t* hop=belle_sip_response_get_return_hop(resp);
354 base->channel=belle_sip_provider_get_channel(base->provider,hop);
355 belle_sip_object_unref(hop);
356 if (!base->channel){
357 belle_sip_error("Transaction [%p]: No channel available for sending response.",t);
358 return;
359 }
360 belle_sip_object_ref(base->channel);
361 belle_sip_channel_add_listener(base->channel, BELLE_SIP_CHANNEL_LISTENER(t));
362 }
363 status_code=belle_sip_response_get_status_code(resp);
364 if (status_code!=100){
365 if (belle_sip_header_to_get_tag(to)==NULL){
366 //add a random to tag
367 belle_sip_header_to_set_tag(to,t->to_tag);
368 }
369 /*12.1 Creation of a Dialog
370 Dialogs are created through the generation of non-failure responses
371 to requests with specific methods. Within this specification, only
372 2xx and 101-199 responses with a To tag, where the request was
373 INVITE, will establish a dialog.*/
374 if (dialog && status_code>100 && status_code<300){
375 belle_sip_response_fill_for_dialog(resp,base->request);
376 }
377 }
378 if (BELLE_SIP_OBJECT_VPTR(t,belle_sip_server_transaction_t)->send_new_response(t,resp)==0){
379 if (base->last_response)
380 belle_sip_object_unref(base->last_response);
381 base->last_response=resp;
382 }
383 if (dialog)
384 belle_sip_dialog_update(dialog,BELLE_SIP_TRANSACTION(t),TRUE);
385 }
386
server_transaction_notify(belle_sip_server_transaction_t * t,belle_sip_request_t * req,belle_sip_dialog_t * dialog)387 static void server_transaction_notify(belle_sip_server_transaction_t *t, belle_sip_request_t *req, belle_sip_dialog_t *dialog){
388 belle_sip_request_event_t event;
389
390 event.source=(belle_sip_object_t*)t->base.provider;
391 event.server_transaction=t;
392 event.dialog=dialog;
393 event.request=req;
394 BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(((belle_sip_transaction_t*) t),process_request_event,&event);
395 }
396
belle_sip_server_transaction_on_request(belle_sip_server_transaction_t * t,belle_sip_request_t * req)397 void belle_sip_server_transaction_on_request(belle_sip_server_transaction_t *t, belle_sip_request_t *req){
398 const char *method=belle_sip_request_get_method(req);
399 if (strcmp(method,"ACK")==0){
400 /*this must be for an INVITE server transaction */
401 if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_ist_t)){
402 belle_sip_ist_t *ist=(belle_sip_ist_t*)t;
403 if (belle_sip_ist_process_ack(ist,(belle_sip_message_t*)req)==0){
404 belle_sip_dialog_t *dialog=t->base.dialog;
405 if (dialog && belle_sip_dialog_handle_ack(dialog,req)==0)
406 server_transaction_notify(t,req,dialog);
407 /*else nothing to do because retransmission of ACK*/
408
409 }
410 }else{
411 belle_sip_warning("ACK received for non-invite server transaction ?");
412 }
413 }else if (strcmp(method,"CANCEL")==0){
414 server_transaction_notify(t,req,t->base.dialog);
415 }else
416 BELLE_SIP_OBJECT_VPTR(t,belle_sip_server_transaction_t)->on_request_retransmission(t);
417 }
418
419 /*
420 * client transaction
421 */
422
423
424
belle_sip_client_transaction_create_cancel(belle_sip_client_transaction_t * t)425 belle_sip_request_t * belle_sip_client_transaction_create_cancel(belle_sip_client_transaction_t *t){
426 belle_sip_message_t *orig=(belle_sip_message_t*)t->base.request;
427 belle_sip_request_t *req;
428 const char *orig_method=belle_sip_request_get_method((belle_sip_request_t*)orig);
429 if (strcmp(orig_method,"ACK")==0 || strcmp(orig_method,"INVITE")!=0){
430 belle_sip_error("belle_sip_client_transaction_create_cancel() cannot be used for ACK or non-INVITE transactions.");
431 return NULL;
432 }
433 if ((t->base.state != BELLE_SIP_TRANSACTION_PROCEEDING) && (t->base.state != BELLE_SIP_TRANSACTION_CALLING)) {
434 belle_sip_error("belle_sip_client_transaction_create_cancel() can only be used in state PROCEEDING or CALLING"
435 " but current transaction state is %s",belle_sip_transaction_state_to_string(t->base.state));
436 return NULL;
437 }
438 req=belle_sip_request_new();
439 belle_sip_request_set_method(req,"CANCEL");
440 /* 9.1 Client Behavior
441 Since requests other than INVITE are responded to immediately,
442 sending a CANCEL for a non-INVITE request would always create a
443 race condition.
444 The following procedures are used to construct a CANCEL request. The
445 Request-URI, Call-ID, To, the numeric part of CSeq, and From header
446 fields in the CANCEL request MUST be identical to those in the
447 request being cancelled, including tags. A CANCEL constructed by a
448 client MUST have only a single Via header field value matching the
449 top Via value in the request being cancelled.*/
450 belle_sip_request_set_uri(req,(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri((belle_sip_request_t*)orig)));
451 belle_sip_util_copy_headers(orig,(belle_sip_message_t*)req,"via",FALSE);
452 belle_sip_util_copy_headers(orig,(belle_sip_message_t*)req,"call-id",FALSE);
453 belle_sip_util_copy_headers(orig,(belle_sip_message_t*)req,"from",FALSE);
454 belle_sip_util_copy_headers(orig,(belle_sip_message_t*)req,"to",FALSE);
455 belle_sip_util_copy_headers(orig,(belle_sip_message_t*)req,"route",TRUE);
456 belle_sip_util_copy_headers(orig,(belle_sip_message_t*)req,BELLE_SIP_MAX_FORWARDS,FALSE);
457 belle_sip_message_add_header((belle_sip_message_t*)req,
458 (belle_sip_header_t*)belle_sip_header_cseq_create(
459 belle_sip_header_cseq_get_seq_number((belle_sip_header_cseq_t*)belle_sip_message_get_header(orig,"cseq")),
460 "CANCEL"));
461 return req;
462 }
463
464
belle_sip_client_transaction_send_request(belle_sip_client_transaction_t * t)465 int belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t){
466 return belle_sip_client_transaction_send_request_to(t,NULL);
467
468 }
469
belle_sip_client_transaction_send_request_to(belle_sip_client_transaction_t * t,belle_sip_uri_t * outbound_proxy)470 int belle_sip_client_transaction_send_request_to(belle_sip_client_transaction_t *t,belle_sip_uri_t* outbound_proxy) {
471 belle_sip_channel_t *chan;
472 belle_sip_provider_t *prov=t->base.provider;
473 belle_sip_dialog_t *dialog=t->base.dialog;
474 belle_sip_request_t *req=t->base.request;
475 int result=-1;
476
477 if (t->base.state!=BELLE_SIP_TRANSACTION_INIT){
478 belle_sip_error("belle_sip_client_transaction_send_request: bad state.");
479 return -1;
480 }
481
482 /*check uris components compliance*/
483 if (!belle_sip_request_check_uris_components(t->base.request)) {
484 belle_sip_error("belle_sip_client_transaction_send_request: bad request for transaction [%p]",t);
485 return -1;
486 }
487 /*store preset route for future use by refresher*/
488 if (outbound_proxy){
489 t->preset_route=outbound_proxy;
490 belle_sip_object_ref(t->preset_route);
491 }
492
493 if (t->base.sent_by_dialog_queue){
494
495 /*it can be sent immediately, so update the request with latest cseq and route_set */
496 /*update route and contact just in case they changed*/
497 belle_sip_dialog_update_request(dialog,req);
498 } else if (t->base.request->dialog_queued){
499 /*this request was created by belle_sip_dialog_create_queued_request().*/
500
501 if (dialog == NULL){
502 belle_sip_error("belle_sip_client_transaction_send_request(): transaction [%p], cannot send"
503 " request because it was created in the context of a dialog that appears to be "
504 " no longer existing.", t);
505 belle_sip_transaction_terminate(BELLE_SIP_TRANSACTION(t));
506 return -1;
507 }
508
509 if (belle_sip_dialog_request_pending(dialog) || dialog->queued_ct!=NULL){
510 /*it cannot be sent immediately, queue the transaction into dialog*/
511 belle_sip_message("belle_sip_client_transaction_send_request(): transaction [%p], cannot send request now because dialog [%p] is busy"
512 " or other transactions are queued, so queuing into dialog.",t, dialog);
513 belle_sip_dialog_queue_client_transaction(dialog,t);
514 return 0;
515 }
516 belle_sip_dialog_update_request(dialog,req);
517 }
518
519 if (dialog){
520 belle_sip_dialog_update(dialog,(belle_sip_transaction_t*)t,BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_server_transaction_t));
521 }
522
523 if (!t->next_hop) {
524 if (t->preset_route) {
525 t->next_hop=belle_sip_hop_new_from_uri(t->preset_route);
526 } else {
527 t->next_hop = belle_sip_stack_get_next_hop(prov->stack,t->base.request);
528 }
529 belle_sip_object_ref(t->next_hop);
530 } else {
531 /*next hop already preset, probably in case of CANCEL*/
532 }
533 belle_sip_provider_add_client_transaction(t->base.provider,t); /*add it in any case*/
534 chan=belle_sip_provider_get_channel(prov,t->next_hop);
535 if (chan){
536 belle_sip_object_ref(chan);
537 belle_sip_channel_add_listener(chan,BELLE_SIP_CHANNEL_LISTENER(t));
538 t->base.channel=chan;
539 if (belle_sip_channel_get_state(chan)==BELLE_SIP_CHANNEL_INIT){
540 belle_sip_message("belle_sip_client_transaction_send_request(): waiting channel to be ready");
541 belle_sip_channel_prepare(chan);
542 /*the channel will notify us when it is ready*/
543 } else if (belle_sip_channel_get_state(chan)==BELLE_SIP_CHANNEL_READY){
544 /*otherwise we can send immediately*/
545 BELLE_SIP_OBJECT_VPTR(t,belle_sip_client_transaction_t)->send_request(t);
546 }
547 result=0;
548 }else {
549 belle_sip_error("belle_sip_client_transaction_send_request(): no channel available");
550 belle_sip_transaction_terminate(BELLE_SIP_TRANSACTION(t));
551 result=-1;
552 }
553 return result;
554 }
555
should_dialog_be_created(belle_sip_client_transaction_t * t,belle_sip_response_t * resp)556 static unsigned int should_dialog_be_created(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
557 belle_sip_request_t* req = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(t));
558 const char* method = belle_sip_request_get_method(req);
559 int status_code = belle_sip_response_get_status_code(resp);
560 return status_code>=101 && status_code<300 && (strcmp(method,"INVITE")==0 || strcmp(method,"SUBSCRIBE")==0);
561 }
562
belle_sip_client_transaction_notify_response(belle_sip_client_transaction_t * t,belle_sip_response_t * resp)563 void belle_sip_client_transaction_notify_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
564 belle_sip_transaction_t *base=(belle_sip_transaction_t*)t;
565 belle_sip_request_t* req = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(t));
566 const char* method = belle_sip_request_get_method(req);
567 belle_sip_response_event_t event;
568 belle_sip_dialog_t *dialog=base->dialog;
569 int status_code = belle_sip_response_get_status_code(resp);
570 if (base->last_response)
571 belle_sip_object_unref(base->last_response);
572 base->last_response=(belle_sip_response_t*)belle_sip_object_ref(resp);
573
574 if (dialog){
575 if (status_code>=101 && status_code<300
576 && strcmp(method,"INVITE")==0
577 && (dialog->state==BELLE_SIP_DIALOG_EARLY || dialog->state==BELLE_SIP_DIALOG_CONFIRMED)){
578 /*make sure this response matches the current dialog, or creates a new one*/
579 if (!belle_sip_dialog_match(dialog,(belle_sip_message_t*)resp,FALSE)){
580 dialog=belle_sip_provider_find_dialog_from_message(t->base.provider,(belle_sip_message_t*)resp,FALSE);
581 if (!dialog){
582 dialog=belle_sip_provider_create_dialog_internal(t->base.provider,BELLE_SIP_TRANSACTION(t),FALSE);/*belle_sip_dialog_new(base);*/
583 belle_sip_message("Handling response creating a new dialog !");
584 }
585 }
586 }
587 } else if (should_dialog_be_created(t,resp)) {
588 dialog=belle_sip_provider_create_dialog_internal(t->base.provider,BELLE_SIP_TRANSACTION(t),FALSE);
589 }
590
591 if (dialog && belle_sip_dialog_update(dialog,BELLE_SIP_TRANSACTION(t),FALSE)) {
592 /* retransmition, just return*/
593 belle_sip_message("Response [%p] absorbed by dialog [%p], skipped from transaction layer.",resp,dialog);
594 return;
595 }
596
597 event.source=(belle_sip_object_t*)base->provider;
598 event.client_transaction=t;
599 event.dialog=dialog;
600 event.response=(belle_sip_response_t*)resp;
601 BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(((belle_sip_transaction_t*)t),process_response_event,&event);
602 /*check that 200Ok for INVITEs have been acknowledged by listener*/
603 if (dialog && status_code>=200 && status_code<300 && strcmp(method,"INVITE")==0){
604 belle_sip_dialog_check_ack_sent(dialog);
605 }
606 /*report a server having internal errors for REGISTER to the channel, in order to go to a fallback IP*/
607 if (status_code == 500 && strcmp(method,"REGISTER") == 0){
608 belle_sip_channel_notify_server_error(base->channel);
609 }
610 }
611
612
belle_sip_client_transaction_add_response(belle_sip_client_transaction_t * t,belle_sip_response_t * resp)613 void belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
614 BELLE_SIP_OBJECT_VPTR(t,belle_sip_client_transaction_t)->on_response(t,resp);
615 }
616
belle_sip_client_transaction_get_route(belle_sip_client_transaction_t * t)617 belle_sip_uri_t *belle_sip_client_transaction_get_route(belle_sip_client_transaction_t *t){
618 return t->preset_route;
619 }
620
client_transaction_destroy(belle_sip_client_transaction_t * t)621 static void client_transaction_destroy(belle_sip_client_transaction_t *t ){
622 if (t->preset_route) belle_sip_object_unref(t->preset_route);
623 if (t->next_hop) belle_sip_object_unref(t->next_hop);
624 }
625
626
627
628 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_client_transaction_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_client_transaction_t)629 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_client_transaction_t)
630 {
631 {
632 BELLE_SIP_VPTR_INIT(belle_sip_client_transaction_t,belle_sip_transaction_t,FALSE),
633 (belle_sip_object_destroy_t)client_transaction_destroy,
634 NULL,
635 NULL,
636 BELLE_SIP_DEFAULT_BUFSIZE_HINT
637 },
638 NULL
639 },
640 NULL,
641 NULL
642 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
643
644 void belle_sip_client_transaction_init(belle_sip_client_transaction_t *obj, belle_sip_provider_t *prov, belle_sip_request_t *req){
645 belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)req,"via"));
646 char token[BELLE_SIP_BRANCH_ID_LENGTH];
647
648 if (!via){
649 belle_sip_fatal("belle_sip_client_transaction_init(): No via in request.");
650 }
651
652 if (strcmp(belle_sip_request_get_method(req),"CANCEL")!=0){
653 obj->base.branch_id=belle_sip_strdup_printf(BELLE_SIP_BRANCH_MAGIC_COOKIE ".%s",belle_sip_random_token(token,sizeof(token)));
654 belle_sip_header_via_set_branch(via,obj->base.branch_id);
655 }else{
656 obj->base.branch_id=belle_sip_strdup(belle_sip_header_via_get_branch(via));
657 }
658 belle_sip_transaction_init((belle_sip_transaction_t*)obj, prov,req);
659 }
660
belle_sip_client_transaction_create_refresher(belle_sip_client_transaction_t * t)661 belle_sip_refresher_t* belle_sip_client_transaction_create_refresher(belle_sip_client_transaction_t *t) {
662 return belle_sip_refresher_new(t);
663 }
664
belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t * t,belle_sip_list_t ** auth_infos,const char * realm)665 belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t,belle_sip_list_t** auth_infos,const char* realm) {
666 belle_sip_request_t* initial_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(t));
667 belle_sip_request_t* req=belle_sip_request_clone_with_body(initial_request);
668 belle_sip_header_cseq_t* cseq=belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t);
669 belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
670 if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)) != BELLE_SIP_TRANSACTION_COMPLETED
671 && belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)) != BELLE_SIP_TRANSACTION_TERMINATED) {
672 belle_sip_error("Invalid state [%s] for transaction [%p], should be BELLE_SIP_TRANSACTION_COMPLETED | BELLE_SIP_TRANSACTION_TERMINATED"
673 ,belle_sip_transaction_state_to_string(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)))
674 ,t);
675 belle_sip_object_unref(req);
676 return NULL;
677 }
678 /*remove auth headers*/
679 belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_AUTHORIZATION);
680 belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_PROXY_AUTHORIZATION);
681
682 /*put auth header*/
683 belle_sip_provider_add_authorization(t->base.provider,req,t->base.last_response,NULL,auth_infos,realm);
684 return req;
685 }
686
687 /*
688 rfc 3265
689 3.3.4. Dialog creation and termination
690 ...
691 NOTIFY requests are matched to such SUBSCRIBE requests if they
692 contain the same "Call-ID", a "To" header "tag" parameter which
693 matches the "From" header "tag" parameter of the SUBSCRIBE, and the
694 same "Event" header field. Rules for comparisons of the "Event"
695 headers are described in section 7.2.1. If a matching NOTIFY request
696 contains a "Subscription-State" of "active" or "pending", it creates
697 a new subscription and a new dialog (unless they have already been
698 created by a matching response, as described above).
699
700
701 */
702
belle_sip_client_transaction_is_notify_matching_pending_subscribe(belle_sip_client_transaction_t * trans,belle_sip_request_t * notify)703 int belle_sip_client_transaction_is_notify_matching_pending_subscribe(belle_sip_client_transaction_t *trans
704 , belle_sip_request_t *notify) {
705 belle_sip_request_t *subscription;
706 belle_sip_header_event_t *sub_event, *notif_event;
707 belle_sip_header_call_id_t *sub_call_id, *notif_call_id;
708 const char* sub_from_tag, *notif_to_tag;
709
710 if (!belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(trans)))
711 || strcmp("SUBSCRIBE", belle_sip_transaction_get_method(BELLE_SIP_TRANSACTION(trans)))!=0) return 0;
712
713
714 if (strcmp("NOTIFY",belle_sip_request_get_method(notify)) != 0) {
715 belle_sip_error("belle_sip_client_transaction_is_notify_matching_pending_subscribe for dialog [%p], requires a notify request",notify);
716 }
717
718 subscription = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(trans));
719 sub_event = belle_sip_message_get_header_by_type(subscription, belle_sip_header_event_t);
720 if (!sub_event || !belle_sip_header_event_get_package_name(sub_event))
721 return 0;
722
723 notif_event = belle_sip_message_get_header_by_type(notify, belle_sip_header_event_t);
724 if (!notif_event || !belle_sip_header_event_get_package_name(notif_event))
725 return 0;
726
727 sub_call_id = belle_sip_message_get_header_by_type(subscription, belle_sip_header_call_id_t);
728 notif_call_id = belle_sip_message_get_header_by_type(notify, belle_sip_header_call_id_t);
729 sub_from_tag = belle_sip_header_from_get_tag(belle_sip_message_get_header_by_type(subscription, belle_sip_header_from_t));
730 notif_to_tag = belle_sip_header_to_get_tag(belle_sip_message_get_header_by_type(notify, belle_sip_header_to_t));
731
732 return strcmp(belle_sip_header_call_id_get_call_id(sub_call_id),belle_sip_header_call_id_get_call_id(notif_call_id))==0
733 && sub_from_tag && notif_to_tag && strcmp(sub_from_tag,notif_to_tag)==0
734 && strcasecmp(belle_sip_header_event_get_package_name(sub_event),belle_sip_header_event_get_package_name(notif_event))==0;
735
736 }
737
738