sipvoiplink.cpp 52.6 KB
Newer Older
jpbl's avatar
jpbl committed
1
/*
yanmorin's avatar
   
yanmorin committed
2
 *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
jpbl's avatar
jpbl committed
3
4
5
6
7
 *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
 *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 3 of the License, or
jpbl's avatar
jpbl committed
9
10
11
12
13
14
15
16
17
18
19
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
20
21
22
/*
 * YM: 2006-11-15: changes unsigned int to std::string::size_type, thanks to Pierre Pomes (AMD64 compilation)
 */
jpbl's avatar
jpbl committed
23
24
#include "sipvoiplink.h"
#include "eventthread.h"
yanmorin's avatar
   
yanmorin committed
25
26
#include "sipcall.h"
#include <sstream> // for ostringstream
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
27
#include "sipaccount.h"
yanmorin's avatar
   
yanmorin committed
28
29
30

#include "manager.h"
#include "user_cfg.h" // SIGNALISATION / PULSE #define
jpbl's avatar
jpbl committed
31

yanmorin's avatar
   
yanmorin committed
32
33
34
35
// for listener
#define DEFAULT_SIP_PORT  5060
#define RANDOM_SIP_PORT   rand() % 64000 + 1024
#define RANDOM_LOCAL_PORT ((rand() % 27250) + 5250)*2
jpbl's avatar
jpbl committed
36
37
38
39
40

#define EXOSIP_ERROR_NO   0
#define EXOSIP_ERROR_STD -1
#define EXOSIP_ERROR_BUILDING -2

yanmorin's avatar
   
yanmorin committed
41
42
43
44
45
46
// for registration
#define EXPIRES_VALUE 180

// 1XX responses
#define DIALOG_ESTABLISHED 101
// see: osip_const.h
jpbl's avatar
jpbl committed
47

yanmorin's avatar
   
yanmorin committed
48
49
50
51
52
53
54
55
56
57
// FOR VOICE Message handling
#define VOICE_MSG     "Voice-Message"
#define LENGTH_VOICE_MSG  15

// need for hold/unhold
#define INVITE_METHOD "INVITE"


SIPVoIPLink::SIPVoIPLink(const AccountID& accountID)
 : VoIPLink(accountID), _localExternAddress("")
jpbl's avatar
jpbl committed
58
59
{
  _evThread = new EventThread(this);
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
60
  _initDone = false;
yanmorin's avatar
   
yanmorin committed
61

jpbl's avatar
jpbl committed
62
  _nMsgVoicemail = 0;
yanmorin's avatar
   
yanmorin committed
63
64
65
66
67
68
69
70
  _eXosipRegID = EXOSIP_ERROR_STD;

  _nbTryListenAddr = 2; // number of times to try to start SIP listener
  _localExternPort = 0;

  // to get random number for RANDOM_PORT
  srand (time(NULL));
}
jpbl's avatar
jpbl committed
71

yanmorin's avatar
   
yanmorin committed
72
73
74
SIPVoIPLink::~SIPVoIPLink()
{
  terminate();
75
  delete _evThread; _evThread = 0;
yanmorin's avatar
   
yanmorin committed
76
77
78
79
80
}

bool 
SIPVoIPLink::init()
{
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
81
  _debug("INIT DONE : %d\n" , _initDone);
82
  if (!_initDone) {
yanmorin's avatar
   
yanmorin committed
83
    if (0 != eXosip_init()) {
84
      _debug("! SIP Failure: Could not initialize eXosip\n");
yanmorin's avatar
   
yanmorin committed
85
86
      return false;
    }
87
88
89
90

    // Pour éviter qu'on refasse l'init sans avoir considéré l'erreur,
    // s'il y en a une ?
    _initDone = true;
yanmorin's avatar
   
yanmorin committed
91
92
93
  
    // check networking capabilities
    if ( !checkNetwork() ) {
94
      _debug("! SIP FAILURE: Unable to determine network capabilities\n");
yanmorin's avatar
   
yanmorin committed
95
96
97
98
99
100
101
102
103
104
105
      return false;
    }
  
    // if we useStun and we failed to receive something on port 5060, we try a random port
    // If use STUN server, firewall address setup
    int errExosip = 0;
    int port = DEFAULT_SIP_PORT;
  
    int iTry = 1;  // try number..
  
    do {
yanmorin's avatar
   
yanmorin committed
106
      if (_useStun && !Manager::instance().behindNat(_stunServer, port)) { 
yanmorin's avatar
   
yanmorin committed
107
        port = RANDOM_SIP_PORT; 
yanmorin's avatar
   
yanmorin committed
108
        if (!Manager::instance().behindNat(_stunServer, port)) {
109
         _debug("! SIP Failure: Unable to check NAT setting\n");
yanmorin's avatar
   
yanmorin committed
110
111
112
113
114
115
116
          return false; // hoho we can't use the random sip port too...
        }
      }
  
      // second parameter, NULL is "::" for ipv6 and "0.0.0.0" for ipv4, we can put INADDR_ANY
      errExosip = eXosip_listen_addr(IPPROTO_UDP, INADDR_ANY, port, AF_INET, 0);
      if (errExosip != 0) {
117
        _debug("* SIP Info: [%d/%d] could not initialize SIP listener on port %d\n", iTry, _nbTryListenAddr, port);
yanmorin's avatar
   
yanmorin committed
118
119
120
121
122
        port = RANDOM_SIP_PORT;
      }
    } while ( errExosip != 0 && iTry < _nbTryListenAddr );
  
    if ( errExosip != 0 ) { // we didn't succeeded
123
      _debug("! SIP Failure: SIP failed to listen on port %d\n", port);
yanmorin's avatar
   
yanmorin committed
124
125
126
      return false;
    }
    _localPort = port;
127
    _debug("  SIP Init: listening on port %d\n", port);
yanmorin's avatar
   
yanmorin committed
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
    
    if (_useStun) {
      // This method is used to replace contact address with the public address of your NAT
      // it should be call after eXosip_listen_addr
      // set by last behindNat() call (ish)...
      _localExternAddress  = Manager::instance().getFirewallAddress();
      _localExternPort     = Manager::instance().getFirewallPort();
      eXosip_masquerade_contact(_localExternAddress.data(), _localExternPort);
    } else {
      _localExternAddress = _localIPAddress;
      _localExternPort    = _localPort;
    }
    
    // Set user agent
    std::string tmp = std::string(PROGNAME_GLOBAL) + "/" + std::string(SFLPHONED_VERSION);
    eXosip_set_user_agent(tmp.data());
  
145
    _debug("  SIP Init: starting loop thread (SIP events)\n");
yanmorin's avatar
   
yanmorin committed
146
147
    _evThread->start();
  }
148
149
150
151
152

  _initDone = true;

  // Useless
  return true;
jpbl's avatar
jpbl committed
153
154
}

yanmorin's avatar
   
yanmorin committed
155
156
157
void 
SIPVoIPLink::terminate()
{
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
158
  _debug("Terminate before\n");
yanmorin's avatar
   
yanmorin committed
159
  terminateSIPCall(); 
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
160
  _debug("Terminate after\n");
161
  if (_initDone) {
162
163
164
165
    // TODO The next line makes the daemon crash on 
    // account delete if at least one account is registered.
    // It should called only when the last account 
    // is deleted/unregistered.
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
166
    // eXosip_quit();
167
    _initDone = false;
jpbl's avatar
jpbl committed
168
169
170
171
  }
}

void
yanmorin's avatar
   
yanmorin committed
172
SIPVoIPLink::terminateSIPCall()
jpbl's avatar
jpbl committed
173
{
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
174
  
yanmorin's avatar
   
yanmorin committed
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  ost::MutexLock m(_callMapMutex);
  CallMap::iterator iter = _callMap.begin();
  SIPCall *call;
  while( iter != _callMap.end() ) {
    call = dynamic_cast<SIPCall*>(iter->second);
    if (call) {
      // Release SIP stack.
      eXosip_lock();
      eXosip_call_terminate(call->getCid(), call->getDid() );
      eXosip_unlock();
      delete call; call = 0;
    }
    iter++;
  }
  _callMap.clear();
jpbl's avatar
jpbl committed
190
191
192
}

bool
yanmorin's avatar
   
yanmorin committed
193
SIPVoIPLink::checkNetwork()
jpbl's avatar
jpbl committed
194
195
{
  // Set IP address
yanmorin's avatar
   
yanmorin committed
196
  return loadSIPLocalIP();
jpbl's avatar
jpbl committed
197
198
199
}

bool
yanmorin's avatar
   
yanmorin committed
200
SIPVoIPLink::loadSIPLocalIP() 
jpbl's avatar
jpbl committed
201
{
yanmorin's avatar
   
yanmorin committed
202
203
204
205
206
207
208
  bool returnValue = true;
  if (_localIPAddress == "127.0.0.1") {
    char* myIPAddress = new char[65];
    if (eXosip_guess_localip(AF_INET, myIPAddress, 64) == EXOSIP_ERROR_STD) {
      returnValue = false;
    } else {
      _localIPAddress = std::string(myIPAddress);
209
      _debug("  SIP Info: Checking network, setting local IP address to: %s\n", myIPAddress);
yanmorin's avatar
   
yanmorin committed
210
    }
yanmorin's avatar
   
yanmorin committed
211
    delete [] myIPAddress; myIPAddress = NULL;
jpbl's avatar
jpbl committed
212
  }
yanmorin's avatar
   
yanmorin committed
213
  return returnValue;
jpbl's avatar
jpbl committed
214
215
216
}

void
yanmorin's avatar
   
yanmorin committed
217
SIPVoIPLink::getEvent()
jpbl's avatar
jpbl committed
218
{
219
	char* tmp2;
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
220
	const char* localport = ""+_localPort;
221
222
223
224
	eXosip_event_t* event = eXosip_event_wait(0, 50);
	eXosip_lock();
	eXosip_automatic_action();
	eXosip_unlock();
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
225
226

	if ( event == NULL ) {
227
228
		return;
	}
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
229
      
230
231
232
	switch (event->type) {
	/* REGISTER related events */
	case EXOSIP_REGISTRATION_NEW:         /** 00 < announce new registration.       */
233
		_debugMid(" !EXOSIP_REGISTRATION_NEW event is not implemented\n");
234
235
		break;
	case EXOSIP_REGISTRATION_SUCCESS:     /** 01 < user is successfully registred.  */
236
		_debugMid(" !EXOSIP_REGISTRATION_SUCCESS \n");
237
		if(_eXosipRegID == EXOSIP_ERROR_STD){
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
238
		  _debug("Successfully Unregister account ID = %s\n" , getAccountID().c_str());
239
		  setRegistrationState(Unregistered);
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
240
		  if( _evThread ) _evThread->stop();
241
242
		}
		else{
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
243
		  _debug("Successfully Register account ID = %s\n" , getAccountID().c_str());
244
		  setRegistrationState(Registered);
245
		}
246
247
248
		break;
	case EXOSIP_REGISTRATION_FAILURE:     /** 02 < user is not registred.           */
		setRegistrationState(Error, "SIP registration failure.");
249
		_debugMid(" !EXOSIP_REGISTRATION_FAILURE\n");
250
251
		break;
	case EXOSIP_REGISTRATION_REFRESHED:   /** 03 < registration has been refreshed. */
252
		_debugMid(" !EXOSIP_REGISTRATION_REFRESHED event is not implemented\n");
253
254
255
		break;
	case EXOSIP_REGISTRATION_TERMINATED:  /** 04 < UA is not registred any more.    */
		setRegistrationState(Unregistered, "Registration terminated by remote host");
256
		_debugMid(" !EXOSIP_REGISTRATION_TERMINATED event is not implemented\n");
257
258
259
260
		break;

	/* INVITE related events within calls */
	case EXOSIP_CALL_INVITE:          /** 05 < announce a new call                   */
261
		_debugMid(" !EXOSIP_CALL_INVITE\n");
262
		SIPCallInvite(event);
263
264
265
		break;
	case EXOSIP_CALL_REINVITE:        /** 06 < announce a new INVITE within call     */
		SIPCallReinvite(event);
266
		_debugMid(" !EXOSIP_REGISTRATION_TERMINATED event is not implemented\n");
267
268
269
270
		break;

	/* CALL related events */
	case EXOSIP_CALL_NOANSWER:        /** 07 < announce no answer within the timeout */
271
		_debugMid(" !EXOSIP_CALL_NOANSWER event is not implemented\n");
272
273
		break;
	case EXOSIP_CALL_PROCEEDING:      /** 08 < announce processing by a remote app   */
274
		_debugMid(" !EXOSIP_CALL_PROCEEDING event is not implemented\n");
275
276
		break;
	case EXOSIP_CALL_RINGING:         /** 09 < announce ringback                     */
277
		_debugMid(" !EXOSIP_CALL_RINGING\n");
278
279
280
		SIPCallRinging(event);
		break;
	case EXOSIP_CALL_ANSWERED:        /** 10 < announce start of call                */
281
		_debugMid(" !EXOSIP_CALL_ANSWERED\n");
282
283
284
		SIPCallAnswered(event);
		break;
	case EXOSIP_CALL_REDIRECTED:      /** 11 < announce a redirection                */
285
		_debugMid(" !EXOSIP_CALL_REDIRECTED event is not implemented\n");
286
287
		break;
	case EXOSIP_CALL_REQUESTFAILURE:  /** 12 < announce a request failure            */
288
		_debugMid(" !EXOSIP_CALL_REQUESTFAILURE");
289
290
291
		SIPCallRequestFailure(event);
		break;
	case EXOSIP_CALL_SERVERFAILURE:   /** 13 < announce a server failure             */
292
		_debugMid(" !EXOSIP_CALL_SERVERFAILURE");
293
294
295
		SIPCallServerFailure(event);
		break;
	case EXOSIP_CALL_GLOBALFAILURE:   /** 14 < announce a global failure             */
296
		_debugMid(" !EXOSIP_CALL_GLOBALFAILURE\n");
297
298
299
		SIPCallServerFailure(event);
		break;
	case EXOSIP_CALL_ACK:             /** 15 < ACK received for 200ok to INVITE      */
300
		_debugMid(" !EXOSIP_CALL_ACK\n");
301
302
303
		SIPCallAck(event);
		break;
	case EXOSIP_CALL_CANCELLED:       /** 16 < announce that call has been cancelled */
304
		_debugMid(" !EXOSIP_CALL_CANCELLED\n");
305
306
		break;
	case EXOSIP_CALL_TIMEOUT:         /** 17 < announce that call has failed         */
307
		_debugMid(" !EXOSIP_CALL_TIMEOUT\n");
308
309
310
311
312
		Manager::instance().displayError(" !EXOSIP Call Error not implemented yet");
		break;

	/* Request related events within calls (except INVITE) */
	case EXOSIP_CALL_MESSAGE_NEW:            /** 18 < announce new incoming MESSAGE. */
313
		_debugMid(" !EXOSIP_CALL_MESSAGE_NEW\n");
314
315
316
		SIPCallMessageNew(event);
		break;
	case EXOSIP_CALL_MESSAGE_PROCEEDING:     /** 19 < announce a 1xx for MESSAGE. */
317
		_debugMid(" !EXOSIP_CALL_MESSAGE_PROCEEDING\n");
318
319
320
		break;
	case EXOSIP_CALL_MESSAGE_ANSWERED:       /** 20 < announce a 200ok  */
		// 200 OK
321
		_debugMid(" !EXOSIP_CALL_MESSAGE_ANSWERED\n");
322
323
		break;
	case EXOSIP_CALL_MESSAGE_REDIRECTED:     /** 21 < announce a failure. */
324
		_debugMid(" !EXOSIP_CALL_MESSAGE_REDIRECTED\n");
325
326
		break;
	case EXOSIP_CALL_MESSAGE_REQUESTFAILURE: /** 22 < announce a failure. */
327
		_debugMid(" !EXOSIP_CALL_MESSAGE_REQUESTFAILURE\n");
328
329
		break;
	case EXOSIP_CALL_MESSAGE_SERVERFAILURE:  /** 23 < announce a failure. */
330
		_debugMid(" !EXOSIP_CALL_MESSAGE_SERVERFAILURE\n");
331
332
		break;
	case EXOSIP_CALL_MESSAGE_GLOBALFAILURE:  /** 24 < announce a failure. */
333
		_debugMid(" !EXOSIP_CALL_MESSAGE_GLOBALFAILURE\n");
334
335
336
337
		Manager::instance().displayError(" !EXOSIP Call Message not implemented yet");
		break;

	case EXOSIP_CALL_CLOSED:          /** 25 < a BYE was received for this call */
338
		_debugMid(" !EXOSIP_CALL_CLOSED\n");
339
340
341
342
343
		SIPCallClosed(event);
		break;

	/* For both UAS & UAC events */
	case EXOSIP_CALL_RELEASED:           /** 26 < call context is cleared. */
344
		_debugMid(" !EXOSIP_CALL_RELEASED\n");
345
346
347
348
349
		SIPCallReleased(event);
		break;

	/* Response received for request outside calls */
	case EXOSIP_MESSAGE_NEW:            /** 27 < announce new incoming MESSAGE. */
350
		_debugMid(" !EXOSIP_MESSAGE_NEW\n");
351
352
353
354
		if (event->request == NULL) { break; }
		SIPMessageNew(event);
		break;
	case EXOSIP_MESSAGE_PROCEEDING:     /** 28 < announce a 1xx for MESSAGE. */
355
		_debugMid(" !EXOSIP_MESSAGE_PROCEEDING\n");
356
357
		break;
	case EXOSIP_MESSAGE_ANSWERED:       /** 29 < announce a 200ok  */
358
		_debugMid(" !EXOSIP_MESSAGE_ANSWERED\n");
359
360
		break;
	case EXOSIP_MESSAGE_REDIRECTED:     /** 30 < announce a failure. */
361
		_debugMid(" !EXOSIP_MESSAGE_REDIRECTED\n");
362
363
364
365
		Manager::instance().displayError(" !EXOSIP Message not implemented yet");
		break;

	case EXOSIP_MESSAGE_REQUESTFAILURE: /** 31 < announce a failure. */
366
		_debugMid(" !EXOSIP_MESSAGE_REQUESTFAILURE\n");
367
368
369
370
371
372
373
		if (event->response !=0 && event->response->status_code == SIP_METHOD_NOT_ALLOWED) {
			Manager::instance().incomingMessage(getAccountID(), "Message are not allowed");
		} else {
			Manager::instance().displayError(" !EXOSIP_MESSAGE_REQUESTFAILURE not implemented yet");
		}
		break;
	case EXOSIP_MESSAGE_SERVERFAILURE:  /** 32 < announce a failure. */
374
		_debugMid(" !EXOSIP_MESSAGE_SERVERFAILURE\n");
375
376
		break;
	case EXOSIP_MESSAGE_GLOBALFAILURE:  /** 33 < announce a failure. */
377
		_debugMid(" !EXOSIP_MESSAGE_GLOBALFAILURE\n");
378
379
380
381
382
		Manager::instance().displayError(" !EXOSIP Message not implemented yet");
		break;

	/* Presence and Instant Messaging */
	case EXOSIP_SUBSCRIPTION_UPDATE:       /** 34 < announce incoming SUBSCRIBE.      */
383
		_debugMid(" !EXOSIP_SUBSCRIPTION_UPDATE\n");
384
385
		break;
	case EXOSIP_SUBSCRIPTION_CLOSED:       /** 35 < announce end of subscription.     */
386
		_debugMid(" !EXOSIP_SUBSCRIPTION_CLOSED\n");
387
388
389
390
		Manager::instance().displayError(" !EXOSIP Subscription not implemented yet");
		break;

	case EXOSIP_SUBSCRIPTION_NOANSWER:        /** 37 < announce no answer              */
391
		_debugMid(" !EXOSIP_SUBSCRIPTION_NOANSWER\n");
392
393
		break;
	case EXOSIP_SUBSCRIPTION_PROCEEDING:      /** 38 < announce a 1xx                  */
394
		_debugMid(" !EXOSIP_SUBSCRIPTION_PROCEEDING\n");
395
396
397
		Manager::instance().displayError(" !EXOSIP Subscription response not implemented yet");
		break;
	case EXOSIP_SUBSCRIPTION_ANSWERED:        /** 39 < announce a 200ok                */
398
		_debugMid(" !EXOSIP_SUBSCRIPTION_ANSWERED\n");
399
400
401
402
403
404
		eXosip_lock();
		eXosip_automatic_action();
		eXosip_unlock();
		break;

	case EXOSIP_SUBSCRIPTION_REDIRECTED:      /** 40 < announce a redirection          */
405
		_debugMid(" !EXOSIP_SUBSCRIPTION_REDIRECTED\n");
406
407
		break;
	case EXOSIP_SUBSCRIPTION_REQUESTFAILURE:  /** 41 < announce a request failure      */
408
		_debugMid(" !EXOSIP_SUBSCRIPTION_REQUESTFAILURE\n");
409
410
		break;
	case EXOSIP_SUBSCRIPTION_SERVERFAILURE:   /** 42 < announce a server failure       */
411
		_debugMid(" !EXOSIP_SUBSCRIPTION_REQUESTFAILURE\n");
412
413
		break;
	case EXOSIP_SUBSCRIPTION_GLOBALFAILURE:   /** 43 < announce a global failure       */
414
		_debugMid(" !EXOSIP_SUBSCRIPTION_GLOBALFAILURE\n");
415
416
		break;
	case EXOSIP_SUBSCRIPTION_NOTIFY:          /** 44 < announce new NOTIFY request     */
417
		_debugMid(" !EXOSIP_SUBSCRIPTION_NOTIFY\n");
418
419
420
421
		osip_body_t* body;
		osip_from_to_str(event->request->from, &tmp2);
		osip_message_get_body(event->request, 0, &body);
		if (body != NULL && body->body != NULL) {
422
423
424
//			printf("\n---------------------------------\n");
//			printf ("(%i) from: %s\n  %s\n", event->tid, tmp2, body->body);
//			printf("---------------------------------\n");
425
		}
426
		osip_free(tmp2);
427
428
		break;
	case EXOSIP_SUBSCRIPTION_RELEASED:        /** 45 < call context is cleared.        */
429
		_debugMid(" !EXOSIP_SUBSCRIPTION_RELEASED\n");
430
431
432
433
		Manager::instance().displayError(" !EXOSIP Subscription response not implemented yet.");
		break;

	case EXOSIP_IN_SUBSCRIPTION_NEW:          /** 46 < announce new incoming SUBSCRIBE.*/
434
		_debugMid(" !EXOSIP_IN_SUBSCRIPTION_NEW\n");
435
436
		break;
	case EXOSIP_IN_SUBSCRIPTION_RELEASED:     /** 47 < announce end of subscription.   */
437
		_debugMid(" !EXOSIP_IN_SUBSCRIPTION_RELEASED\n");
438
439
440
441
		Manager::instance().displayError(" !EXOSIP Subscription not implemented yet");
		break;

	case EXOSIP_EVENT_COUNT:               /** 48 < MAX number of events  */
442
		_debugMid(" !EXOSIP_EVENT_COUNT : SHOULD NEVER HAPPEN!!!!!\n");
443
444
445
446
		break;
	default:
		printf("received eXosip event (type, did, cid) = (%d, %d, %d)", event->type, event->did, event->cid);
		break;
447
	}
448
	eXosip_event_free(event);
jpbl's avatar
jpbl committed
449
450
}

yanmorin's avatar
   
yanmorin committed
451
bool
452
SIPVoIPLink::sendRegister()
jpbl's avatar
jpbl committed
453
{
454

yanmorin's avatar
   
yanmorin committed
455
  if (_eXosipRegID != EXOSIP_ERROR_STD) {
456
    Manager::instance().displayError("! SIP Error: Registration already sent. Try to unregister");
yanmorin's avatar
   
yanmorin committed
457
    return false;
jpbl's avatar
jpbl committed
458
459
  }

yanmorin's avatar
   
yanmorin committed
460
461
462
463
  std::string hostname = getHostName();
  if (hostname.empty()) {
    Manager::instance().displayConfigError("Fill host part field");
    return false;
jpbl's avatar
jpbl committed
464
  }
yanmorin's avatar
   
yanmorin committed
465
466
467
468

  if (_userpart.empty()) {
    Manager::instance().displayConfigError("Fill user part field");
    return false;
jpbl's avatar
jpbl committed
469
470
  }

yanmorin's avatar
   
yanmorin committed
471
472
473
474
475

  std::string proxy = "sip:" + _proxy;
  hostname = "sip:" + hostname;
  std::string from = SIPFromHeader(_userpart, getHostName());
  
jpbl's avatar
jpbl committed
476
477
  osip_message_t *reg = NULL;
  eXosip_lock();
yanmorin's avatar
   
yanmorin committed
478
  if (!_proxy.empty()) {
479
    _debug("* SIP Info: Register from: %s to %s\n", from.data(), proxy.data());
yanmorin's avatar
   
yanmorin committed
480
481
    _eXosipRegID = eXosip_register_build_initial_register(from.data(), 
                  proxy.data(), NULL, EXPIRES_VALUE, &reg);
jpbl's avatar
jpbl committed
482
  } else {
483
    _debug("* SIP Info: Register from: %s to %s\n", from.data(), hostname.data());
yanmorin's avatar
   
yanmorin committed
484
485
    _eXosipRegID = eXosip_register_build_initial_register(from.data(), 
                  hostname.data(), NULL, EXPIRES_VALUE, &reg);
jpbl's avatar
jpbl committed
486
487
  }
  eXosip_unlock();
yanmorin's avatar
   
yanmorin committed
488
489
  if (_eXosipRegID < EXOSIP_ERROR_NO ) {
    return false;
jpbl's avatar
jpbl committed
490
491
  }

yanmorin's avatar
   
yanmorin committed
492
  if (!sendSIPAuthentification()) {
493
    _debug("* SIP Info: register without authentication\n");
yanmorin's avatar
   
yanmorin committed
494
    return false;
jpbl's avatar
jpbl committed
495
496
497
498
499
500
  }

  osip_message_set_header (reg, "Event", "Registration");
  osip_message_set_header (reg, "Allow-Events", "presence");

  eXosip_lock();
yanmorin's avatar
   
yanmorin committed
501
502
  int eXosipErr = eXosip_register_send_register(_eXosipRegID, reg);
  if (eXosipErr == EXOSIP_ERROR_BUILDING) {
503
    _debug("! SIP Failure: Cannot build registration, check the setup\n"); 
jpbl's avatar
jpbl committed
504
    eXosip_unlock();
yanmorin's avatar
   
yanmorin committed
505
    return false;
jpbl's avatar
jpbl committed
506
  }
yanmorin's avatar
   
yanmorin committed
507
  if (eXosipErr == EXOSIP_ERROR_STD) {
508
    _debug("! SIP Failure: Registration sending failed\n");
jpbl's avatar
jpbl committed
509
    eXosip_unlock();
yanmorin's avatar
   
yanmorin committed
510
    return false;
jpbl's avatar
jpbl committed
511
512
  }

513
  setRegistrationState(Trying);
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
514
  eXosip_unlock();
515

yanmorin's avatar
   
yanmorin committed
516
  return true;
jpbl's avatar
jpbl committed
517
518
}

yanmorin's avatar
   
yanmorin committed
519
520
std::string
SIPVoIPLink::SIPFromHeader(const std::string& userpart, const std::string& hostpart) 
jpbl's avatar
jpbl committed
521
{
yanmorin's avatar
   
yanmorin committed
522
  return ("\"" + getFullName() + "\"" + " <sip:" + userpart + "@" + hostpart + ">");
jpbl's avatar
jpbl committed
523
524
}

Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
525
526
527
528
529
530
std::string
SIPVoIPLink::SIPFromHeaderAlternate(const std::string& userpart, const std::string& hostpart) 
{
  return ("<sip:" + userpart + "@" + hostpart + ">");
}

yanmorin's avatar
   
yanmorin committed
531
532
533
534
535
536
bool
SIPVoIPLink::sendSIPAuthentification() 
{
  std::string login = _authname;
  if (login.empty()) {
    login = _userpart;
jpbl's avatar
jpbl committed
537
  }
yanmorin's avatar
   
yanmorin committed
538
  if (login.empty()) {
539
    /** @todo Ajouter ici un call à setRegistrationState(Error, "Fill balh") ? */
yanmorin's avatar
   
yanmorin committed
540
541
542
543
    Manager::instance().displayConfigError("Fill authentification name");
    return false;
  }
  if (_password.empty()) {
544
    /** @todo Même chose ici  ? */
yanmorin's avatar
   
yanmorin committed
545
546
547
548
549
550
551
552
    Manager::instance().displayConfigError("Fill password field");
    return false;
  }
  eXosip_lock();
  int returnValue = eXosip_add_authentication_info(login.data(), login.data(), _password.data(), NULL, NULL);
  eXosip_unlock();

  return (returnValue != EXOSIP_ERROR_STD ? true : false);
jpbl's avatar
jpbl committed
553
554
}

yanmorin's avatar
   
yanmorin committed
555
bool
556
SIPVoIPLink::sendUnregister()
yanmorin's avatar
   
yanmorin committed
557
{
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
558
  _debug("SEND UNREGISTER for account %s\n" , getAccountID().c_str());
yanmorin's avatar
   
yanmorin committed
559
560
561
  if ( _eXosipRegID == EXOSIP_ERROR_STD) return false;
  int eXosipErr = EXOSIP_ERROR_NO;
  osip_message_t *reg = NULL;
jpbl's avatar
jpbl committed
562

yanmorin's avatar
   
yanmorin committed
563
564
565
566
567
  eXosip_lock();
  eXosipErr = eXosip_register_build_register (_eXosipRegID, 0, &reg);
  eXosip_unlock();

  if (eXosipErr != EXOSIP_ERROR_NO) {
568
    _debug("! SIP Failure: Unable to build registration for sendUnregister");
yanmorin's avatar
   
yanmorin committed
569
    return false;
jpbl's avatar
jpbl committed
570
571
  }

yanmorin's avatar
   
yanmorin committed
572
573
574
575
  eXosip_lock();
  _debug("< Sending REGISTER (expire=0)\n");
  eXosipErr = eXosip_register_send_register (_eXosipRegID, reg);
  if (eXosipErr == EXOSIP_ERROR_BUILDING) {
576
    _debug("! SIP Failure: Cannot build registration (unregister), check the setup\n"); 
yanmorin's avatar
   
yanmorin committed
577
578
    eXosip_unlock();
    return false;
jpbl's avatar
jpbl committed
579
  }
yanmorin's avatar
   
yanmorin committed
580
  if (eXosipErr == EXOSIP_ERROR_STD) {
581
    _debug("! SIP Failure: Unable to send registration (unregister)\n");
yanmorin's avatar
   
yanmorin committed
582
583
  }
  _eXosipRegID = EXOSIP_ERROR_STD;
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
584
  eXosip_unlock();
yanmorin's avatar
   
yanmorin committed
585
586

  return true;
jpbl's avatar
jpbl committed
587
588
}

yanmorin's avatar
   
yanmorin committed
589
590
Call* 
SIPVoIPLink::newOutgoingCall(const CallID& id, const std::string& toUrl)
jpbl's avatar
jpbl committed
591
{
yanmorin's avatar
   
yanmorin committed
592
593
594
595
596
597
598
599
600
601
602
  SIPCall* call = new SIPCall(id, Call::Outgoing);
  if (call) {
    call->setPeerNumber(toUrl);
    // we have to add the codec before using it in SIPOutgoingInvite...
    call->setCodecMap(Manager::instance().getCodecDescriptorMap());
    if ( SIPOutgoingInvite(call) ) {
      call->setConnectionState(Call::Progressing);
      call->setState(Call::Active);
      addCall(call);
    } else {
      delete call; call = 0;
jpbl's avatar
jpbl committed
603
604
    }
  }
yanmorin's avatar
   
yanmorin committed
605
  return call;
jpbl's avatar
jpbl committed
606
607
}

yanmorin's avatar
   
yanmorin committed
608
609
bool
SIPVoIPLink::answer(const CallID& id)
jpbl's avatar
jpbl committed
610
{
611
  _debug("- SIP Action: start answering\n");
jpbl's avatar
jpbl committed
612

yanmorin's avatar
   
yanmorin committed
613
614
  SIPCall* call = getSIPCall(id);
  if (call==0) {
615
    _debug("! SIP Failure: SIPCall doesn't exists\n");
yanmorin's avatar
   
yanmorin committed
616
617
    return false;
  }
jpbl's avatar
jpbl committed
618
619

  // Send 200 OK
yanmorin's avatar
   
yanmorin committed
620
  osip_message_t *answerMessage = NULL;
jpbl's avatar
jpbl committed
621
  eXosip_lock();
yanmorin's avatar
   
yanmorin committed
622
  int i = eXosip_call_build_answer(call->getTid(), SIP_OK, &answerMessage);
jpbl's avatar
jpbl committed
623
  if (i != 0) {
Alexandre Bourget's avatar
Alexandre Bourget committed
624
    _debug("< SIP Building Error: send 400 Bad Request\n");
yanmorin's avatar
   
yanmorin committed
625
    eXosip_call_send_answer (call->getTid(), SIP_BAD_REQUEST, NULL);
jpbl's avatar
jpbl committed
626
627
628
  } else {
    // use exosip, bug locked
    i = 0;
yanmorin's avatar
   
yanmorin committed
629
    sdp_message_t *remote_sdp = eXosip_get_remote_sdp(call->getDid());
jpbl's avatar
jpbl committed
630
    if (remote_sdp!=NULL) {
yanmorin's avatar
   
yanmorin committed
631
      i = call->sdp_complete_message(remote_sdp, answerMessage);
jpbl's avatar
jpbl committed
632
633
634
      if (i!=0) {
        osip_message_free(answerMessage);
      }
yanmorin's avatar
   
yanmorin committed
635
      sdp_message_free(remote_sdp);
jpbl's avatar
jpbl committed
636
637
    }
    if (i != 0) {
638
      _debug("< SIP Error: send 415 Unsupported Media Type\n");
yanmorin's avatar
   
yanmorin committed
639
      eXosip_call_send_answer (call->getTid(), SIP_UNSUPPORTED_MEDIA_TYPE, NULL);
jpbl's avatar
jpbl committed
640
    } else {
641
      _debug("< SIP send 200 OK\n");
yanmorin's avatar
   
yanmorin committed
642
      eXosip_call_send_answer (call->getTid(), SIP_OK, answerMessage);
jpbl's avatar
jpbl committed
643
644
645
646
    }
  }
  eXosip_unlock();

yanmorin's avatar
   
yanmorin committed
647
  if(i==0) {
648
    // Incoming call is answered, start the sound thread.
649
    _debug("* SIP Info: Starting AudioRTP when answering\n");
yanmorin's avatar
   
yanmorin committed
650
651
652
653
654
655
    if (_audiortp.createNewSession(call) >= 0) {
      call->setAudioStart(true);
      call->setConnectionState(Call::Connected);
      call->setState(Call::Active);
      return true;
    } else {
656
      _debug("! SIP Failure: Unable to start sound when answering %s/%d\n", __FILE__, __LINE__);
yanmorin's avatar
   
yanmorin committed
657
    }
jpbl's avatar
jpbl committed
658
  }
yanmorin's avatar
   
yanmorin committed
659
660
661
662
663
664
  removeCall(call->getCallId());
  return false;
}

bool
SIPVoIPLink::hangup(const CallID& id)
jpbl's avatar
jpbl committed
665
{
yanmorin's avatar
   
yanmorin committed
666
  SIPCall* call = getSIPCall(id);
667
  if (call==0) { _debug("! SIP Error: Call doesn't exist\n"); return false; }  
yanmorin's avatar
   
yanmorin committed
668

669
  _debug("- SIP Action: Hang up call %s [cd: %3d %3d]\n", id.data(), call->getCid(), call->getDid()); 
jpbl's avatar
jpbl committed
670
671
  // Release SIP stack.
  eXosip_lock();
yanmorin's avatar
   
yanmorin committed
672
  eXosip_call_terminate(call->getCid(), call->getDid());
jpbl's avatar
jpbl committed
673
674
  eXosip_unlock();

675
  // Release RTP thread
yanmorin's avatar
   
yanmorin committed
676
  if (Manager::instance().isCurrentCall(id)) {
677
    _debug("* SIP Info: Stopping AudioRTP for hangup\n");
jpbl's avatar
jpbl committed
678
679
    _audiortp.closeRtpSession();
  }
yanmorin's avatar
   
yanmorin committed
680
681
  removeCall(id);
  return true;
jpbl's avatar
jpbl committed
682
683
}

yanmorin's avatar
   
yanmorin committed
684
685
bool
SIPVoIPLink::cancel(const CallID& id)
jpbl's avatar
jpbl committed
686
{
yanmorin's avatar
   
yanmorin committed
687
  SIPCall* call = getSIPCall(id);
688
  if (call==0) { _debug("! SIP Error: Call doesn't exist\n"); return false; }  
yanmorin's avatar
   
yanmorin committed
689

690
  _debug("- SIP Action: Cancel call %s [cid: %3d]\n", id.data(), call->getCid()); 
jpbl's avatar
jpbl committed
691
692
  // Release SIP stack.
  eXosip_lock();
yanmorin's avatar
   
yanmorin committed
693
  eXosip_call_terminate(call->getCid(), -1);
jpbl's avatar
jpbl committed
694
695
  eXosip_unlock();

yanmorin's avatar
   
yanmorin committed
696
697
  removeCall(id);
  return true;
jpbl's avatar
jpbl committed
698
699
}

yanmorin's avatar
   
yanmorin committed
700
701
bool
SIPVoIPLink::onhold(const CallID& id)
jpbl's avatar
jpbl committed
702
{
yanmorin's avatar
   
yanmorin committed
703
  SIPCall* call = getSIPCall(id);
704
  if (call==0) { _debug("! SIP Error: call doesn't exist\n"); return false; }  
jpbl's avatar
jpbl committed
705

706
707
708
  // Stop sound
  call->setAudioStart(false);
  call->setState(Call::Hold);
709
  _debug("* SIP Info: Stopping AudioRTP for onhold action\n");
710
711
712
  _audiortp.closeRtpSession();


yanmorin's avatar
   
yanmorin committed
713
  int did = call->getDid();
jpbl's avatar
jpbl committed
714
715

  eXosip_lock ();
yanmorin's avatar
   
yanmorin committed
716
  sdp_message_t *local_sdp = eXosip_get_local_sdp(did);
jpbl's avatar
jpbl committed
717
718
719
  eXosip_unlock ();

  if (local_sdp == NULL) {
720
    _debug("! SIP Failure: unable to find local_sdp\n");
yanmorin's avatar
   
yanmorin committed
721
    return false;
jpbl's avatar
jpbl committed
722
723
724
  }

  // Build INVITE_METHOD for put call on-hold
yanmorin's avatar
   
yanmorin committed
725
  osip_message_t *invite = NULL;
jpbl's avatar
jpbl committed
726
  eXosip_lock ();
yanmorin's avatar
   
yanmorin committed
727
  int exosipErr = eXosip_call_build_request (did, INVITE_METHOD, &invite);
jpbl's avatar
jpbl committed
728
729
  eXosip_unlock ();

yanmorin's avatar
   
yanmorin committed
730
  if (exosipErr != 0) {
jpbl's avatar
jpbl committed
731
    sdp_message_free(local_sdp);
732
    _debug("! SIP Failure: unable to build invite method to hold call\n");
yanmorin's avatar
   
yanmorin committed
733
    return false;
jpbl's avatar
jpbl committed
734
735
736
737
738
739
  }

  /* add sdp body */
  {
    char *tmp = NULL;

yanmorin's avatar
   
yanmorin committed
740
    int i = sdp_hold_call(local_sdp);
jpbl's avatar
jpbl committed
741
742
743
    if (i != 0) {
      sdp_message_free (local_sdp);
      osip_message_free (invite);
744
      _debug("! SIP Failure: Unable to hold call in SDP\n");
yanmorin's avatar
   
yanmorin committed
745
      return false;
jpbl's avatar
jpbl committed
746
747
    }
    
yanmorin's avatar
   
yanmorin committed
748
749
    i = sdp_message_to_str(local_sdp, &tmp);
    sdp_message_free(local_sdp);
jpbl's avatar
jpbl committed
750
751
752
    if (i != 0) {
      osip_message_free (invite);
      osip_free (tmp);
753
      _debug("! SIP Failure: Unable to translate sdp message to string\n");
yanmorin's avatar
   
yanmorin committed
754
      return false;
jpbl's avatar
jpbl committed
755
756
757
758
759
760
    }
    osip_message_set_body (invite, tmp, strlen (tmp));
    osip_free (tmp);
    osip_message_set_content_type (invite, "application/sdp");
  }
  
yanmorin's avatar
   
yanmorin committed
761
  // send request
762
  _debug("< SIP: Send on hold request\n");
jpbl's avatar
jpbl committed
763
  eXosip_lock ();
yanmorin's avatar
   
yanmorin committed
764
  exosipErr = eXosip_call_send_request (did, invite);
jpbl's avatar
jpbl committed
765
766
  eXosip_unlock ();
  
yanmorin's avatar
   
yanmorin committed
767
  return true;
jpbl's avatar
jpbl committed
768
769
}

yanmorin's avatar
   
yanmorin committed
770
771
bool 
SIPVoIPLink::offhold(const CallID& id)
jpbl's avatar
jpbl committed
772
{
yanmorin's avatar
   
yanmorin committed
773
  SIPCall* call = getSIPCall(id);
774
  if (call==0) { _debug("! SIP Error: Call doesn't exist\n"); return false; }  
jpbl's avatar
jpbl committed
775

yanmorin's avatar
   
yanmorin committed
776
  int did = call->getDid();
jpbl's avatar
jpbl committed
777
778

  eXosip_lock ();
yanmorin's avatar
   
yanmorin committed
779
  sdp_message_t *local_sdp = eXosip_get_local_sdp(did);
jpbl's avatar
jpbl committed
780
  eXosip_unlock ();
yanmorin's avatar
   
yanmorin committed
781

jpbl's avatar
jpbl committed
782
  if (local_sdp == NULL) {
783
    _debug("! SIP Failure: unable to find local_sdp\n");
yanmorin's avatar
   
yanmorin committed
784
    return false;
jpbl's avatar
jpbl committed
785
786
787
  }

  // Build INVITE_METHOD for put call off-hold
yanmorin's avatar
   
yanmorin committed
788
  osip_message_t *invite;
jpbl's avatar
jpbl committed
789
  eXosip_lock ();
yanmorin's avatar
   
yanmorin committed
790
  int exosipErr = eXosip_call_build_request (did, INVITE_METHOD, &invite);
jpbl's avatar
jpbl committed
791
792
  eXosip_unlock ();

yanmorin's avatar
   
yanmorin committed
793
  if (exosipErr != 0) {
jpbl's avatar
jpbl committed
794
795
796
797
798
799
800
801
    sdp_message_free(local_sdp);
    return EXOSIP_ERROR_STD;
  }

  /* add sdp body */
  {
    char *tmp = NULL;
    
yanmorin's avatar
   
yanmorin committed
802
    int i = sdp_off_hold_call (local_sdp);
jpbl's avatar
jpbl committed
803
804
805
    if (i != 0) {
      sdp_message_free (local_sdp);
      osip_message_free (invite);
yanmorin's avatar
   
yanmorin committed
806
      return false;
jpbl's avatar
jpbl committed
807
808
809
810
811
812
813
    }
    
    i = sdp_message_to_str (local_sdp, &tmp);
    sdp_message_free (local_sdp);
    if (i != 0) {
      osip_message_free (invite);
      osip_free (tmp);
yanmorin's avatar
   
yanmorin committed
814
      return false;
jpbl's avatar
jpbl committed
815
816
817
818
819
820
821
822
823
    }
    osip_message_set_body (invite, tmp, strlen (tmp));
    osip_free (tmp);
    osip_message_set_content_type (invite, "application/sdp");
  }

  // Send request
  _debug("< Send off hold request\n");
  eXosip_lock ();
yanmorin's avatar
   
yanmorin committed
824
  exosipErr = eXosip_call_send_request (did, invite);
jpbl's avatar
jpbl committed
825
826
827
  eXosip_unlock ();

  // Enable audio
828
  _debug("* SIP Info: Starting AudioRTP when offhold\n");
829
  call->setState(Call::Active);
yanmorin's avatar
   
yanmorin committed
830
831
  // it's sure that this is the current call id...
  if (_audiortp.createNewSession(call) < 0) {
832
    _debug("! SIP Failure: Unable to start sound (%s:%d)\n", __FILE__, __LINE__);
yanmorin's avatar
   
yanmorin committed
833
    return false;
jpbl's avatar
jpbl committed
834
  }
yanmorin's avatar
   
yanmorin committed
835
  return true;
jpbl's avatar
jpbl committed
836
837
}

yanmorin's avatar
   
yanmorin committed
838
839
bool 
SIPVoIPLink::transfer(const CallID& id, const std::string& to)
jpbl's avatar
jpbl committed
840
{
yanmorin's avatar
   
yanmorin committed
841
  SIPCall* call = getSIPCall(id);
842
  if (call==0) { _debug("! SIP Failure: Call doesn't exist\n"); return false; }  
yanmorin's avatar
   
yanmorin committed
843
844

  std::string tmp_to = SIPToHeader(to);
jpbl's avatar
jpbl committed
845
  if (tmp_to.find("@") == std::string::npos) {
yanmorin's avatar
   
yanmorin committed
846
    tmp_to = tmp_to + "@" + getHostName();
jpbl's avatar
jpbl committed
847
848
  }

yanmorin's avatar
   
yanmorin committed
849
  osip_message_t *refer;
jpbl's avatar
jpbl committed
850
851
  eXosip_lock();
  // Build transfer request
yanmorin's avatar
   
yanmorin committed
852
853
  int exosipErr = eXosip_call_build_refer(call->getDid(), (char*)tmp_to.data(), &refer);
  if (exosipErr == 0) {
jpbl's avatar
jpbl committed
854
    // Send transfer request
855
    _debug("< SIP send transfer request to %s\n", tmp_to.data());
yanmorin's avatar
   
yanmorin committed
856
    exosipErr = eXosip_call_send_request(call->getDid(), refer);
jpbl's avatar
jpbl committed
857
858
  }
  eXosip_unlock();
yanmorin's avatar
   
yanmorin committed
859

Emmanuel Milou's avatar
Emmanuel Milou committed
860
  _audiortp.closeRtpSession();
yanmorin's avatar
   
yanmorin committed
861
  // shall we delete the call?
Emmanuel Milou's avatar
Emmanuel Milou committed
862
  //removeCall(id);
yanmorin's avatar
   
yanmorin committed
863
  return true;
jpbl's avatar
jpbl committed
864
865
}

yanmorin's avatar
   
yanmorin committed
866
867
bool
SIPVoIPLink::refuse (const CallID& id)
jpbl's avatar
jpbl committed
868
{
yanmorin's avatar
   
yanmorin committed
869
  SIPCall* call = getSIPCall(id);
yanmorin's avatar
   
yanmorin committed
870

yanmorin's avatar
   
yanmorin committed
871
872
  if (call==0) { _debug("Call doesn't exist\n"); return false; }  

yanmorin's avatar
   
yanmorin committed
873
874
875
876
877
878
879
  // can't refuse outgoing call or connected
  if (!call->isIncoming() || call->getConnectionState() == Call::Connected) { 
    _debug("It's not an incoming call, or it's already answered\n");
    return false; 
  }


jpbl's avatar
jpbl committed
880
881
882
  osip_message_t *answerMessage = NULL;
  eXosip_lock();
  // not BUSY.. where decline the invitation!
yanmorin's avatar
   
yanmorin committed
883
884
885
  int exosipErr = eXosip_call_build_answer(call->getTid(), SIP_DECLINE, &answerMessage);
  if (exosipErr == 0) {
    exosipErr = eXosip_call_send_answer(call->getTid(), SIP_DECLINE, answerMessage);
jpbl's avatar
jpbl committed
886
887
  }
  eXosip_unlock();
yanmorin's avatar
   
yanmorin committed
888
  return true;
jpbl's avatar
jpbl committed
889
890
}

yanmorin's avatar
   
yanmorin committed
891
892
bool 
SIPVoIPLink::carryingDTMFdigits(const CallID& id, char code)
jpbl's avatar
jpbl committed
893
{
yanmorin's avatar
   
yanmorin committed
894
895
  SIPCall* call = getSIPCall(id);
  if (call==0) { _debug("Call doesn't exist\n"); return false; }  
jpbl's avatar
jpbl committed
896
897
898
899
900
901
902
903
904
905

  int duration = Manager::instance().getConfigInt(SIGNALISATION, PULSE_LENGTH);
  osip_message_t *info;
  const int body_len = 1000;
  int i;

  char *dtmf_body = new char[body_len];

  eXosip_lock();
  // Build info request
yanmorin's avatar
   
yanmorin committed
906
  i = eXosip_call_build_info(call->getDid(), &info);
jpbl's avatar
jpbl committed
907
  if (i == 0) {
yanmorin's avatar
   
yanmorin committed
908
    snprintf(dtmf_body, body_len - 1, "Signal=%c\r\nDuration=%d\r\n", code, duration);
jpbl's avatar
jpbl committed
909
910
911
    osip_message_set_content_type (info, "application/dtmf-relay");
    osip_message_set_body (info, dtmf_body, strlen (dtmf_body));
    // Send info request
yanmorin's avatar
   
yanmorin committed
912
    i = eXosip_call_send_request(call->getDid(), info);
jpbl's avatar
jpbl committed
913
914
  }
  eXosip_unlock();
yanmorin's avatar
   
yanmorin committed
915
  
jpbl's avatar
jpbl committed
916
  delete[] dtmf_body; dtmf_body = NULL;
yanmorin's avatar
   
yanmorin committed
917
  return true;
jpbl's avatar
jpbl committed
918
919
}

yanmorin's avatar
   
yanmorin committed
920
921
bool
SIPVoIPLink::sendMessage(const std::string& to, const std::string& body)
jpbl's avatar
jpbl committed
922
{
yanmorin's avatar
   
yanmorin committed
923
  bool returnValue = false;
jpbl's avatar
jpbl committed
924

yanmorin's avatar
   
yanmorin committed
925
926
  // fast return
  if (body.empty()) {return returnValue; }
jpbl's avatar
jpbl committed
927

yanmorin's avatar
   
yanmorin committed
928
929
930
931
932
933
934
935
936
937
938
939
940
941
  osip_message_t* message = 0;
  const char* method = "MESSAGE";

  std::string sipFrom = getSipFrom();
  std::string sipTo   = getSipTo(to);
  std::string sipRoute = getSipRoute();

  if (!SIPCheckUrl(sipFrom)) {
    Manager::instance().displayConfigError("Error in source address");
    return returnValue;
  }
  if (!SIPCheckUrl(sipTo)) {
    Manager::instance().displayError("Error in destination address");
    return returnValue;
jpbl's avatar
jpbl committed
942
943
  }

yanmorin's avatar
   
yanmorin committed
944
945
946
947
948
949
950
  int eXosipError = EXOSIP_ERROR_STD;
  eXosip_lock();
  if ( sipRoute.empty() ) {
    eXosipError = eXosip_message_build_request(&message, method, sipTo.c_str(), sipFrom.c_str(), NULL);
  } else {
    eXosipError = eXosip_message_build_request(&message, method, sipTo.c_str(), sipFrom.c_str(), sipRoute.c_str());
  }
jpbl's avatar
jpbl committed
951

yanmorin's avatar
   
yanmorin committed
952
953
954
955
956