~ubuntu-branches/ubuntu/vivid/linphone/vivid

« back to all changes in this revision

Viewing changes to osipua/src/uatransaction.c

  • Committer: Bazaar Package Importer
  • Author(s): Samuel Mimram
  • Date: 2006-11-15 10:34:50 UTC
  • mfrom: (1.2.1 upstream) (2.1.8 feisty)
  • Revision ID: james.westby@ubuntu.com-20061115103450-qgafwcks2lkhctlj
* New upstream release.
* Enable video support.
* Fix mismatched #endif in mscommon.h, closes: #398307.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
  The osipua library is a library based on oSIP that implements CallLeg and User Agent
3
 
  level.
4
 
  Copyright (C) 2001  Simon MORLAT simon.morlat@free.fr
5
 
                                                                                        Aymeric MOIZARD jack@atosc.org
6
 
  This library is free software; you can redistribute it and/or
7
 
  modify it under the terms of the GNU Lesser General Public
8
 
  License as published by the Free Software Foundation; either
9
 
  version 2.1 of the License, or (at your option) any later version.
10
 
 
11
 
  This library is distributed in the hope that it will be useful,
12
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
  Lesser General Public License for more details.
15
 
 
16
 
  You should have received a copy of the GNU Lesser General Public
17
 
  License along with this library; if not, write to the Free Software
18
 
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
*/
20
 
 
21
 
#include "osipua.h"
22
 
#include "utils.h"
23
 
#include "uatransaction.h"
24
 
#include "osipmanager.h"
25
 
#include <osip/smsg.h>
26
 
#include <osip/smsgtypes.h>
27
 
 
28
 
int ua_transaction_get_destination(transaction_t *trn, char **destination, int *port)
29
 
{
30
 
        if (trn->ctx_type==ICT){
31
 
                *destination=trn->ict_context->destination;
32
 
                *port=trn->ict_context->port;
33
 
        }
34
 
        else if (trn->ctx_type==NICT){
35
 
                *destination=trn->nict_context->destination;
36
 
                *port=trn->nict_context->port;
37
 
        }else {
38
 
                osip_trace(OSIP_ERROR,("Could not get destination for transaction: ctx_type=%i\n",trn->ctx_type));
39
 
                *destination=NULL;
40
 
                *port=0;
41
 
                return -1;
42
 
        }
43
 
        return 0;
44
 
}
45
 
 
46
 
void ua_transaction_set_destination(transaction_t *trn,char *destination, int port)
47
 
{
48
 
        if (trn->ctx_type==ICT){
49
 
                ict_set_destination(trn->ict_context,destination,port);
50
 
        }
51
 
        else if (trn->ctx_type==NICT){
52
 
                nict_set_destination(trn->nict_context,destination,port);
53
 
        }else {
54
 
                osip_trace(OSIP_ERROR,("Could not set destination for transaction: ctx_type=%i\n",trn->ctx_type));
55
 
        }
56
 
}
57
 
 
58
 
transaction_t * ua_transaction_new(OsipDialog *call,sip_t *sipmsg)
59
 
{
60
 
        transaction_t *transaction;
61
 
        OsipUA *ua;
62
 
        context_type_t type;
63
 
        int port=5060;
64
 
        
65
 
        if (call==NULL) return NULL;
66
 
        
67
 
        ua=(OsipUA*)call->ua;
68
 
        if (MSG_IS_INVITE(sipmsg))
69
 
        {
70
 
                type=ICT;
71
 
        }else type=NICT;
72
 
        transaction_init(&transaction,
73
 
                        type,
74
 
                        ua->config,
75
 
                        sipmsg);
76
 
        transaction->your_instance=(void*)call;
77
 
        if (transaction==NULL) return NULL;
78
 
        transaction_set_out_socket(transaction,ua->manager->send_sock);
79
 
        /* if an outbound proxy is set for this call-leg, then set it to the transaction */
80
 
        if ((ua->registrar!=NULL) && (ua->flags & OSIP_UA_USE_PROXY) )
81
 
        {
82
 
                
83
 
                if (ua->registrar->port!=NULL) port=atoi(ua->registrar->port);
84
 
                ua_transaction_set_destination(transaction,sgetcopy(ua->registrar->host),port);
85
 
                
86
 
        }else{
87
 
                route_t *route;
88
 
                /* else set the destination in the req uri */
89
 
                msg_getroute(sipmsg, 0, &route);
90
 
                if (route!=NULL)
91
 
                  {
92
 
                    port = 5060;
93
 
                    if (route->url->port!=NULL)
94
 
                      port = satoi(route->url->port);
95
 
                    if (MSG_IS_INVITE(sipmsg))
96
 
                      ict_set_destination(transaction->ict_context,
97
 
                                          sgetcopy(route->url->host),
98
 
                                          port);
99
 
                    else
100
 
                      nict_set_destination(transaction->nict_context,
101
 
                                          sgetcopy(route->url->host),
102
 
                                          port);
103
 
                  }
104
 
                else
105
 
                  {
106
 
                    int port = 5060;
107
 
                    if (sipmsg->strtline->rquri->port!=NULL)
108
 
                      port = satoi(sipmsg->strtline->rquri->port);
109
 
                    if (MSG_IS_INVITE(sipmsg))
110
 
                    ict_set_destination(transaction->ict_context,
111
 
                                        sgetcopy(sipmsg->strtline->rquri->host),
112
 
                                        port);
113
 
                    else
114
 
                    nict_set_destination(transaction->nict_context,
115
 
                                        sgetcopy(sipmsg->strtline->rquri->host),
116
 
                                        port);
117
 
                  }
118
 
        }
119
 
        
120
 
        if (MSG_IS_INVITE(sipmsg))
121
 
          ua_transaction_set_outgoing_invite_tr(transaction, call);
122
 
        else if (MSG_IS_REGISTER(sipmsg))
123
 
          ua_transaction_set_outgoing_register_tr(transaction, call);
124
 
        else if (MSG_IS_BYE(sipmsg))
125
 
          ua_transaction_set_outgoing_bye_tr(transaction, call);
126
 
        else if (MSG_IS_CANCEL(sipmsg))
127
 
          ua_transaction_set_outgoing_cancel_tr(transaction,call);
128
 
        
129
 
        return transaction;
130
 
}
131
 
 
132
 
void ua_transaction_set_incoming_invite_tr(transaction_t *trn,OsipDialog *call)
133
 
{
134
 
  OsipUA *ua = osip_dialog_get_ua (call);
135
 
  if (call->inc_invite_tr)
136
 
          call->inc_invite_tr->your_instance = NULL;
137
 
  call->inc_invite_tr = trn;
138
 
  trn->your_instance=call;
139
 
  transaction_set_out_socket(trn,ua->manager->send_sock);
140
 
}
141
 
 
142
 
void ua_transaction_set_outgoing_invite_tr(transaction_t *trn,OsipDialog *call)
143
 
{
144
 
  OsipUA *ua = osip_dialog_get_ua (call);
145
 
  if (call->out_invite_tr)
146
 
          call->out_invite_tr->your_instance = NULL;
147
 
  call->out_invite_tr = trn;
148
 
  trn->your_instance=call;
149
 
  transaction_set_out_socket(trn,ua->manager->send_sock);
150
 
}
151
 
 
152
 
void ua_transaction_set_incoming_bye_tr(transaction_t *trn,OsipDialog *call)
153
 
{
154
 
  OsipUA *ua = osip_dialog_get_ua (call);
155
 
  if (call->inc_bye_tr)
156
 
          call->inc_bye_tr->your_instance = NULL;
157
 
  call->inc_bye_tr = trn;
158
 
  trn->your_instance=call;
159
 
  transaction_set_out_socket(trn,ua->manager->send_sock);
160
 
}
161
 
 
162
 
void ua_transaction_set_outgoing_bye_tr(transaction_t *trn,OsipDialog *call)
163
 
{
164
 
  OsipUA *ua = osip_dialog_get_ua (call);
165
 
  if (call->out_bye_tr)
166
 
          call->out_bye_tr->your_instance = NULL;
167
 
  call->out_bye_tr = trn;
168
 
  trn->your_instance=call;
169
 
  transaction_set_out_socket(trn,ua->manager->send_sock);
170
 
}
171
 
 
172
 
void ua_transaction_set_outgoing_register_tr(transaction_t *trn,OsipDialog *call)
173
 
{
174
 
  OsipUA *ua = osip_dialog_get_ua (call);
175
 
  if (call->out_register_tr)
176
 
          call->out_register_tr->your_instance = NULL;
177
 
  call->out_register_tr = trn;
178
 
  trn->your_instance=call;
179
 
  transaction_set_out_socket(trn,ua->manager->send_sock);
180
 
}
181
 
 
182
 
void ua_transaction_set_outgoing_cancel_tr(transaction_t *trn,OsipDialog *call)
183
 
{
184
 
  OsipUA *ua = osip_dialog_get_ua (call);
185
 
  if (call->out_cancel_tr)
186
 
          call->out_cancel_tr->your_instance = NULL;
187
 
  call->out_cancel_tr = trn;
188
 
  trn->your_instance=call;
189
 
  transaction_set_out_socket(trn,ua->manager->send_sock);
190
 
}
191
 
 
192
 
void ua_transaction_set_incoming_cancel_tr(transaction_t *trn,OsipDialog *call)
193
 
{
194
 
  OsipUA *ua = osip_dialog_get_ua (call);
195
 
  if (call->inc_cancel_tr)
196
 
          call->inc_cancel_tr->your_instance = NULL;
197
 
  call->inc_cancel_tr = trn;
198
 
  trn->your_instance=call;
199
 
  transaction_set_out_socket(trn,ua->manager->send_sock);
200
 
}
201
 
 
202
 
 
203
 
/*
204
 
  void ua_transaction_incoming_set_dialog(transaction_t *trn,OsipDialog *call)
205
 
  {
206
 
  OsipUA *ua=osip_dialog_get_ua(call);
207
 
  list_add(&call->incoming_transactions,trn,-1);
208
 
  trn->your_instance=call;
209
 
  transaction_set_out_socket(trn,ua->manager->send_sock);
210
 
  }
211
 
*/
212
 
/*
213
 
  void ua_transaction_outgoing_set_dialog(transaction_t *trn,OsipDialog *call)
214
 
  {
215
 
  list_add(&call->outgoing_transactions,trn,-1);
216
 
  trn->your_instance=call;
217
 
  }
218
 
*/
219
 
 
220
 
int is_in_recv_thread_context(OsipManager *manager)
221
 
{
222
 
        return (manager->thread_pid==getpid());
223
 
}
224
 
 
225
 
void ua_transaction_free(transaction_t *transaction)
226
 
{
227
 
        OsipDialog *call;
228
 
        OsipUA *ua;
229
 
        int error;
230
 
        OsipManager *manager=def_manager;
231
 
        
232
 
        /* check if the call_leg that the transaction is part of should not be deleted too*/
233
 
        call=ua_transaction_get_dialog(transaction);
234
 
        if (call==NULL)
235
 
        {
236
 
                goto free_transaction;
237
 
                osip_trace(OSIP_WARNING,("error: dialog==NULL ! "));
238
 
                return;
239
 
        }
240
 
        ua=osip_dialog_get_ua(call);
241
 
        manager=ua->manager;
242
 
 
243
 
        if (transaction==call->inc_invite_tr)
244
 
          {
245
 
            call->inc_invite_tr = NULL;
246
 
          }
247
 
        else if (transaction==call->out_invite_tr)
248
 
          {
249
 
            call->out_invite_tr = NULL;
250
 
          }
251
 
        else if (transaction==call->inc_bye_tr)
252
 
          {
253
 
            call->inc_bye_tr = NULL;
254
 
          }
255
 
        else if (transaction==call->out_bye_tr)
256
 
          {
257
 
            call->out_bye_tr = NULL;
258
 
          }
259
 
        else if (transaction==call->out_register_tr)
260
 
          {
261
 
            call->out_register_tr = NULL;
262
 
          }
263
 
        else if (transaction==call->out_cancel_tr){
264
 
                call->out_cancel_tr = NULL;
265
 
        }else if (transaction==call->inc_cancel_tr){
266
 
                call->inc_cancel_tr = NULL;
267
 
        }
268
 
        transaction->your_instance=NULL;
269
 
 
270
 
        /* now if it was the last active transaction of the dialog, delete the dialog*/
271
 
        if (call->out_invite_tr==NULL && call->inc_invite_tr==NULL &&
272
 
            call->out_bye_tr==NULL && call->inc_bye_tr==NULL &&
273
 
            call->out_register_tr==NULL && 
274
 
                call->out_cancel_tr == NULL && call->inc_cancel_tr == NULL)
275
 
        {
276
 
                switch (call->status)
277
 
                {
278
 
                        
279
 
                        case DIALOG_INVITING:
280
 
                                /* if the transaction timed out, notify it */
281
 
                                if (transaction->last_response==NULL){
282
 
                                
283
 
                                        error=-ETIMEDOUT;
284
 
                                        /* the invite times out. The call-leg is lost. */
285
 
                                        if (ua->faillure!=NULL)
286
 
                                                ua->faillure(call,transaction,NULL,(void*)&error);
287
 
                                        /* then destroy the dialog*/
288
 
                                        osip_dialog_destroy(call);
289
 
                                }
290
 
                                
291
 
                        break;
292
 
                        case DIALOG_CANCELLING:
293
 
                        case DIALOG_FAKE:
294
 
                        case DIALOG_CANCELLED:
295
 
                        case DIALOG_TERMINATED:
296
 
                                osip_dialog_destroy(call);
297
 
                        break;
298
 
                }
299
 
        }
300
 
        
301
 
        free_transaction:
302
 
        if (is_in_recv_thread_context(manager) ){
303
 
                /* put the transaction in the free list */
304
 
                fifo_add(&manager->garbage_trn,(void*)transaction);
305
 
        }else{
306
 
                smutex_lock(manager->mutex);
307
 
                fifo_add(&manager->garbage_trn,(void*)transaction);
308
 
                smutex_unlock(manager->mutex);
309
 
        }
310
 
}
311
 
 
312
 
 
313
 
/* execute a transaction outside the receiving thread */
314
 
void ua_transaction_execute(transaction_t *trn, sipevent_t *ev)
315
 
{
316
 
        sipevent_t *se;
317
 
        OsipManager *manager;
318
 
        OsipDialog *dialog=ua_transaction_get_dialog(trn);
319
 
        OsipUA *ua;
320
 
        int cond;
321
 
        
322
 
        printf("Executing transaction...\n");
323
 
        fflush(NULL);
324
 
        
325
 
        if (dialog==NULL){
326
 
                osip_trace(OSIP_WARNING,("ua_transaction_execute: could not get dialog transaction.\n"));
327
 
                manager=def_manager;
328
 
        }else {
329
 
                ua=osip_dialog_get_ua(dialog);
330
 
                manager=ua->manager;
331
 
        }
332
 
        /* check if we are within the process of the receiving thread 
333
 
        If you we are in, (probably in one of the osip callbacks), then we can safely run
334
 
        fifo_add(trn->transactionff,ev);
335
 
        If not the we have to take a lock to prevent the receiving thread from executing
336
 
        the transaction while we process it */
337
 
        cond=is_in_recv_thread_context(manager);
338
 
        
339
 
        if (cond){
340
 
                fifo_add(trn->transactionff,ev);
341
 
                //transaction_execute(trn,ev);
342
 
        }
343
 
        else{
344
 
                smutex_lock(manager->mutex);
345
 
                fifo_add(trn->transactionff,ev);
346
 
                smutex_unlock(manager->mutex);
347
 
        }
348
 
        //osip_manager_wake_up(manager);
349
 
        
350
 
}