diff --git a/src/Makefile.am b/src/Makefile.am
index 77070875f7a4720f0fa2aefd84cfa8714951ea02..014decc04471c121666f98edd6c1e36a028b80c2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,10 +13,10 @@ endif
 
 SUBDIRS = audio config gui $(ZEROCONFDIR)
 
-sflphoned_SOURCES = call.cpp 	eventthread.cpp 	main.cpp 	sipvoiplink.cpp 	voIPLink.cpp \
-		sipcall.cpp 	managerimpl.cpp	\
-		observer.cpp \
-		account.cpp sipaccount.cpp aixaccount.cpp accountcreator.cpp aixvoiplink.cpp
+sflphoned_SOURCES = eventthread.cpp 	main.cpp 	voIPLink.cpp \
+		managerimpl.cpp	observer.cpp \
+		account.cpp sipaccount.cpp iaxaccount.cpp accountcreator.cpp iaxvoiplink.cpp \
+                sipvoiplink.cpp call.cpp sipcall.cpp
 
 sflphoned_CXXFLAGS = -DPREFIX=\"$(prefix)\" -DPROGSHAREDIR=\"${datadir}/sflphone\" $(ZEROCONFFLAGS)
 
@@ -38,6 +38,8 @@ libsflphone_la_LIBADD = \
 libsflphone_la_SOURCES =
 
 noinst_LTLIBRARIES = libsflphone.la
-noinst_HEADERS = managerimpl.h manager.h global.h observer.h eventthread.h sipvoiplink.h user_cfg.h \
-                 call.h voIPLink.h sipcall.h \
-		 account.h sipaccount.h aixaccount.h accountcreator.h aixvoiplink.h
+noinst_HEADERS = managerimpl.h manager.h global.h observer.h eventthread.h user_cfg.h \
+                 voIPLink.h \
+		 account.h sipaccount.h iaxaccount.h accountcreator.h iaxvoiplink.h \
+                 sipvoiplink.h  call.h  sipcall.h
+
diff --git a/src/account.cpp b/src/account.cpp
index 20cb189460aa7348929e4deb2275e7750f949d36..a34da5011336d93a18f8daf92d65d0fdb5cefdbb 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -24,6 +24,7 @@ Account::Account(const AccountID& accountID) : _accountID(accountID)
   _link = 0;
 
   _shouldInitOnStart = false;
+  _shouldRegisterOnStart = false;
   _enabled = false;
   _registered = false;
 }
diff --git a/src/account.h b/src/account.h
index 3cbdc738877ccd2e4aca98ac199cf8f78e9886a8..a2ab5f6932659818b34e4eb29bd87d3aa43342e4 100644
--- a/src/account.h
+++ b/src/account.h
@@ -28,6 +28,8 @@ typedef std::string AccountID;
 #define AccountNULL ""
 #define CONFIG_ACCOUNT_TYPE   "Account.type"
 #define CONFIG_ACCOUNT_ENABLE "Account.enable"
+#define CONFIG_ACCOUNT_AUTO_REGISTER  "Account.autoregister"
+
 
 /**
 	@author Yan Morin 
@@ -39,13 +41,13 @@ class Account{
 public:
     Account(const AccountID& accountID);
 
-    ~Account();
+    virtual ~Account();
 
   /**
    * Load the default properties for the account
    */
   virtual void initConfig(Conf::ConfigTree& config) = 0;
-
+  virtual void loadConfig() = 0;
 
   /**
    * Get the voiplink pointer
@@ -77,6 +79,18 @@ public:
    */
   virtual bool terminate() = 0;
 
+  /**
+   * Tell if we should init the account on start
+   * @return true if we must init the link
+   */
+  bool shouldInitOnStart() {return _shouldInitOnStart; }
+
+  /**
+   * Tell if we should init the account on start
+   * @return true if we must init the link
+   */
+  bool shouldRegisterOnStart() {return _shouldRegisterOnStart; }
+
 private:
   /**
    * Create a unique voIPLink() depending on the protocol
@@ -102,6 +116,12 @@ protected:
    */
   bool _shouldInitOnStart;
 
+  /**
+   * Tells if we should register automatically on startup
+   * Modified by the configuration
+   */
+  bool _shouldRegisterOnStart;
+
   /**
    * Tells if the link is enabled or not
    * Modified by init/terminate
diff --git a/src/accountcreator.cpp b/src/accountcreator.cpp
index b013d09bfff229ebd3d793dbf8a3ad8d1d86399a..4bb4404c06320f1bab366a37e8df6e88889a55a2 100644
--- a/src/accountcreator.cpp
+++ b/src/accountcreator.cpp
@@ -18,7 +18,7 @@
  */
 #include "accountcreator.h"
 #include "sipaccount.h"
-#include "aixaccount.h"
+#include "iaxaccount.h"
 
 AccountCreator::AccountCreator()
 {
@@ -37,8 +37,8 @@ AccountCreator::createAccount(AccountType type, AccountID accountID)
       return new SIPAccount(accountID);
     break;
 
-    case AIX_ACCOUNT:
-      return new AIXAccount(accountID);
+    case IAX_ACCOUNT:
+      return new IAXAccount(accountID);
     break;
   }
   return 0;
diff --git a/src/accountcreator.h b/src/accountcreator.h
index b38d78b0263a3d397909f1e84b415c2ec61f72bc..cb156358b19e136a9ed540eccce5bf12299572e8 100644
--- a/src/accountcreator.h
+++ b/src/accountcreator.h
@@ -33,7 +33,7 @@ public:
    /**
     * Public account type
     */
-   enum AccountType {SIP_ACCOUNT, AIX_ACCOUNT };
+   enum AccountType {SIP_ACCOUNT, IAX_ACCOUNT };
 
   /**
    * Create a new account or null
diff --git a/src/aixaccount.cpp b/src/aixaccount.cpp
deleted file mode 100644
index f918a21fcc7aaa681ee678000cc9c453b48e9fa5..0000000000000000000000000000000000000000
--- a/src/aixaccount.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  Copyright (C) 2006 Savoir-Faire Linux inc.
- *  Author: Yan Morin <yan.morin@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
- *  the Free Software Foundation; either version 2 of the License, or
- *  (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.
- */
-#include "aixaccount.h"
-#include "aixvoiplink.h"
-
-AIXAccount::AIXAccount(const AccountID& accountID)
- : Account(accountID)
-{
-  createVoIPLink();
-}
-
-
-AIXAccount::~AIXAccount()
-{
-}
-
-/* virtual Account function implementation */
-bool
-AIXAccount::createVoIPLink()
-{
-  if (!_link) {
-    _link = new AIXVoIPLink();
-  }
-  return (_link != 0 ? true : false);
-}
-
-bool
-AIXAccount::registerAccount()
-{
-  if (_link && !_registered) {
-    _registered = (_link->setRegister() >= 0) ? true : false;
-  }
-  return _registered;
-}
-
-bool
-AIXAccount::unregisterAccount()
-{
-  if (_link && _registered) {
-    _registered = (_link->setUnregister() == 0) ? false : true;
-  }
-  return !_registered;
-}
-
-bool
-AIXAccount::init()
-{
-  if (_link && !_enabled) {
-    _link->init();
-    _enabled = true;
-    return true;
-  }
-  return false;
-}
-
-bool
-AIXAccount::terminate()
-{
-  if (_link && _enabled) {
-    _link->terminate();
-    _enabled = false;
-    return true;
-  }
-  return false;
-}
-
-void 
-AIXAccount::initConfig(Conf::ConfigTree& config)
-{
-  std::string section(_accountID);
-  std::string type_str("string");
-  std::string type_int("int");
-  
-  config.addConfigTreeItem(section, Conf::ConfigTreeItem(CONFIG_ACCOUNT_TYPE, "AIX", type_str));
-  config.addConfigTreeItem(section, Conf::ConfigTreeItem(CONFIG_ACCOUNT_ENABLE, "1", type_int));
-  config.addConfigTreeItem(section, Conf::ConfigTreeItem("AIX.Proxy", "", type_str));
-
-}
-
diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp
index d4af191490db6293444d865050ab1d0b36bb3e3a..98d0fbc59d4e91d0720e8644cef1b7ba7e39c5c0 100644
--- a/src/audio/audiortp.cpp
+++ b/src/audio/audiortp.cpp
@@ -49,7 +49,7 @@ AudioRtp::~AudioRtp (void) {
 }
 
 int 
-AudioRtp::createNewSession (SipCall *ca) {
+AudioRtp::createNewSession (SIPCall *ca) {
   ost::MutexLock m(_threadMutex);
 
   // something should stop the thread before...
@@ -90,7 +90,7 @@ AudioRtp::closeRtpSession () {
 ////////////////////////////////////////////////////////////////////////////////
 // AudioRtpRTX Class                                                          //
 ////////////////////////////////////////////////////////////////////////////////
-AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, AudioLayer* driver, bool sym) {
+AudioRtpRTX::AudioRtpRTX (SIPCall *sipcall, AudioLayer* driver, bool sym) {
   setCancel(cancelDeferred);
   time = new ost::Time();
   _ca = sipcall;
@@ -108,7 +108,7 @@ AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, AudioLayer* driver, bool sym) {
 
   // TODO: Change bind address according to user settings.
   // TODO: this should be the local ip not the external (router) IP
-  std::string localipConfig = "0.0.0.0"; // _ca->getLocalIp();
+  std::string localipConfig = _ca->getLocalIp(); // _ca->getLocalIp();
   ost::InetHostAddress local_ip(localipConfig.c_str());
 
   //_debug("AudioRtpRTX ctor : Local IP:port %s:%d\tsymmetric:%d\n", local_ip.getHostname(), _ca->getLocalAudioPort(), _sym);
@@ -159,9 +159,9 @@ AudioRtpRTX::initAudioRtpSession (void)
     if (_ca == 0) { return; }
 
     //_debug("Init audio RTP session\n");
-    ost::InetHostAddress remote_ip(_ca->getRemoteSdpAudioIp());
+    ost::InetHostAddress remote_ip(_ca->getRemoteIp().c_str());
     if (!remote_ip) {
-      _debug("AudioRTP Thread Error: Target IP address [%s] is not correct!\n", _ca->getRemoteSdpAudioIp());
+      _debug("AudioRTP Thread Error: Target IP address [%s] is not correct!\n", _ca->getRemoteIp().data());
       return;
     }
 
@@ -178,12 +178,12 @@ AudioRtpRTX::initAudioRtpSession (void)
     }
 
     if (!_sym) {
-      if ( !_sessionRecv->addDestination(remote_ip, (unsigned short) _ca->getRemoteSdpAudioPort()) ) {
-        _debug("AudioRTP Thread Error: could not connect to port %d\n",  _ca->getLocalAudioPort());
+      if ( !_sessionRecv->addDestination(remote_ip, (unsigned short) _ca->getRemoteAudioPort()) ) {
+        _debug("AudioRTP Thread Error: could not connect to port %d\n",  _ca->getRemoteAudioPort());
         return;
       }
-      if (!_sessionSend->addDestination (remote_ip, (unsigned short) _ca->getRemoteSdpAudioPort())) {
-        _debug("AudioRTP Thread Error: could not connect to port %d\n",  _ca->getRemoteSdpAudioPort());
+      if (!_sessionSend->addDestination (remote_ip, (unsigned short) _ca->getRemoteAudioPort())) {
+        _debug("AudioRTP Thread Error: could not connect to port %d\n",  _ca->getRemoteAudioPort());
         return;
       }
 
@@ -202,7 +202,7 @@ AudioRtpRTX::initAudioRtpSession (void)
 
       //_debug("AudioRTP Thread: Added session destination %s:%d\n", remote_ip.getHostname(), (unsigned short) _ca->getRemoteSdpAudioPort());
 
-      if (!_session->addDestination (remote_ip, (unsigned short) _ca->getRemoteSdpAudioPort())) {
+      if (!_session->addDestination (remote_ip, (unsigned short) _ca->getRemoteAudioPort())) {
         return;
       }
 
@@ -451,6 +451,7 @@ AudioRtpRTX::run () {
     audiolayer->flushMic();
     audiolayer->startStream();
     _start.post();
+    _debug("AudioRTP Start\n");
     while (!testCancel()) {
       ////////////////////////////
       // Send session
@@ -471,11 +472,11 @@ AudioRtpRTX::run () {
     audiolayer->stopStream();
   } catch(std::exception &e) {
     _start.post();
-    _debug("AudioRTP Thread, run: %s\n", e.what());
+    _debug("AudioRTP Stop: %s\n", e.what());
     throw;
   } catch(...) {
     _start.post();
-    _debugException("AudioRTP Thread, run()");
+    _debugException("AudioRTP Stop");
     throw;
   }
   delete [] data_for_speakers_stereo; data_for_speakers_stereo = 0;
diff --git a/src/audio/audiortp.h b/src/audio/audiortp.h
index aab5eaa425cd3b4247c085bca519ee82394eaf75..5a787ee802d905efe1819a3254cec1ae55682756 100644
--- a/src/audio/audiortp.h
+++ b/src/audio/audiortp.h
@@ -29,21 +29,21 @@
 #define RTP_FRAMES2SEND 160
 
 class AudioLayer;
-class SipCall;
+class SIPCall;
 
 ///////////////////////////////////////////////////////////////////////////////
 // Two pair of sockets
 ///////////////////////////////////////////////////////////////////////////////
 class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
 public:
-	AudioRtpRTX (SipCall *, AudioLayer*, bool);
+	AudioRtpRTX (SIPCall *, AudioLayer*, bool);
 	~AudioRtpRTX();
 
 	ost::Time *time; 	// For incoming call notification 
 	virtual void run ();
 
 private:
-	SipCall* _ca;
+	SIPCall* _ca;
 	AudioLayer* _audioDevice;
 	ost::RTPSession *_sessionSend;
 	ost::RTPSession *_sessionRecv;
@@ -72,7 +72,7 @@ public:
   AudioRtp();
   ~AudioRtp();
 
-  int 			createNewSession (SipCall *);
+  int 			createNewSession (SIPCall *);
   void			closeRtpSession	 ();
 
 private:
diff --git a/src/call.cpp b/src/call.cpp
index 38332db002c852c0c406aab9565f77a8f9a0400e..f483ed883a3b90104fc44a5bca4885ad6826c639 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -1,271 +1,61 @@
-/**
- *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
+/*
+ *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
- *  Author: Laurielle Lea <laurielle.lea@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
  *  the Free Software Foundation; either version 2 of the License, or
  *  (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.
  */
-
-#include <iostream>
-
 #include "call.h"
-#include "voIPLink.h"
-
-Call::Call (CALLID id, Call::CallType type, VoIPLink* voiplink)
-{
-	_state = NotExist;
-	_type = Null;
-	_id = id; 
-	_type = type;
-	_voIPLink = voiplink;
-  _flagNotAnswered = true;
-	
-	switch (_type) {
-	case Outgoing:
-		_voIPLink->newOutgoingCall(_id);
-		break;
-	case Incoming:
-		_voIPLink->newIncomingCall(_id);
-		break;
-	default:
-		break;
-	}
-}
 
-Call::~Call (void)
+Call::Call(const CallID& id, Call::CallType type) : _id(id), _type(type)
 {
+  _connectionState = Call::Disconnected;
+  _callState = Call::Inactive;
 }
 
-CALLID
-Call::getId (void)
-{
-	return _id;
-}
 
-void 
-Call::setId (CALLID id)
+Call::~Call()
 {
-	_id = id;
 }
 
 void 
-Call::setVoIPLink (VoIPLink* voIPLink)
-{
-	_voIPLink = voIPLink;
-}
-
-VoIPLink*
-Call::getVoIPLink (void)
-{
-	return _voIPLink;
-}
-
-std::string 
-Call::getCallerIdName (void)
+Call::setConnectionState(ConnectionState state) 
 {
-	return _callerIdName;
+  ost::MutexLock m(_callMutex);
+  _connectionState = state;
 }
 
-void 
-Call::setCallerIdName (const std::string& callerId_name)
+Call::ConnectionState
+Call::getConnectionState() 
 {
-	_callerIdName = callerId_name;
+  ost::MutexLock m(_callMutex);
+  return _connectionState;
 }
 
-std::string 
-Call::getCallerIdNumber (void)
-{
-	return _callerIdNumber;
-}
 
 void 
-Call::setCallerIdNumber (const std::string& callerId_number)
+Call::setState(CallState state) 
 {
-	_callerIdNumber = callerId_number;
+  ost::MutexLock m(_callMutex);
+  _callState = state;
 }
 
 Call::CallState
-Call::getState (void)
-{
-	return _state;  
-}
-
-void 
-Call::setState (Call::CallState state) 
-{
-	_state = state;
-}
-
-Call::CallType 
-Call::getType (void)
+Call::getState() 
 {
-	return _type;
+  ost::MutexLock m(_callMutex);
+  return _callState;
 }
 
-void 
-Call::setType (Call::CallType type)
-{
-	_type = type;
-}
-
-bool
-Call::isBusy (void)
-{
-	if (isAnswered() or isOffHold() or isOnMute() or isOffMute()) {
-		return true;
-	} else {
-		return false;
-	}
-}
-bool 
-Call::isOnHold (void)
-{
-	return (_state == OnHold) ? true : false;
-}
-
-bool 
-Call::isOffHold (void)
-{
-	return (_state == OffHold) ? true : false;
-}
-
-bool 
-Call::isOnMute (void)
-{
-	return (_state == MuteOn) ? true : false;
-}
-
-bool 
-Call::isOffMute (void)
-{
-	return (_state == MuteOff) ? true : false;
-}
-
-bool 
-Call::isTransfered (void)
-{
-	return (_state == Transfered) ? true : false;
-}
-
-bool 
-Call::isHungup (void)
-{
-	return (_state == Hungup) ? true : false;
-}
-
-bool 
-Call::isRinging (void)
-{
-	return (_state == Ringing) ? true : false;
-}
-
-bool 
-Call::isRefused (void)
-{
-	return (_state == Refused) ? true : false;
-}
-
-
-bool 
-Call::isAnswered (void)
-{
-	return (_state == Answered) ? true : false;
-}
-
-bool 
-Call::isNotAnswered (void)
-{
-	return (_state == Error || _state == NotExist || _state == Busy) ? true : false;
-}
-
-bool 
-Call::isProgressing (void)
-{
-	return (_state == Progressing) ? true : false;
-}
-
-bool
-Call::isOutgoingType (void)
-{
-	return (_type == Outgoing) ? true : false;
-}
-
-bool
-Call::isIncomingType (void)
-{
-	return (_type == Incoming) ? true : false;
-}
-
-int 
-Call::outgoingCall(const std::string& to)
-{
-	return _voIPLink->outgoingInvite(_id, to);
-}
-
-int 
-Call::hangup  (void)
-{
-	int i = _voIPLink->hangup(_id);
-  setState(Hungup);
-	return i;
-}
-
-int 
-Call::cancel  (void)
-{
-	int i = _voIPLink->cancel(_id);
-  setState(Hungup);
-	return i;
-}
-
-int 
-Call::answer  (void)
-{
-  _flagNotAnswered = false;
-	int i = _voIPLink->answer(_id);
-  setState(Answered);
-	return i;
-}
-
-int 
-Call::onHold  (void)
-{
-	int i = _voIPLink->onhold(_id);
-  setState(OnHold);
-	return i;
-}
-
-int 
-Call::offHold  (void)
-{
-	int i = _voIPLink->offhold(_id);
-  setState(OffHold);
-	return i;
-}
-
-int 
-Call::transfer  (const std::string& to)
-{
-	int i = _voIPLink->transfer(_id, to);
-  setState(Transfered);
-	return i;
-}
-
-int 
-Call::refuse  (void)
-{
-	int i = _voIPLink->refuse(_id);
-	return i;
-}
diff --git a/src/call.h b/src/call.h
index d6cf60513f750c296819cf0248313aabf48e5399..1f260825e7dbc7b3adc34568b393f9dfbac1c4f7 100644
--- a/src/call.h
+++ b/src/call.h
@@ -1,120 +1,109 @@
-/**
- *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
+/*
+ *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
- *  Author: Laurielle Lea <laurielle.lea@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
  *  the Free Software Foundation; either version 2 of the License, or
  *  (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.
  */
-
-#ifndef __CALL_H__
-#define __CALL_H__
+#ifndef CALL_H
+#define CALL_H
 
 #include <string>
+#include <cc++/thread.h> // for mutex
+
+//TODO: remove this, it's only for call ID
+typedef std::string CallID;
+
+/**
+	@author Yan Morin <yan.morin@gmail.com>
+  A call is the base classes for protocol-based calls
+*/
+class Call{
+public:
+    enum CallType {Incoming, Outgoing};
+    enum ConnectionState {Disconnected, Trying, Progressing, Ringing, Connected };
+    enum CallState {Inactive, Active, Hold, Busy, Refused, Error};
 
-typedef unsigned int CALLID;
+    /**
+     * Constructor of a call
+     * @param id Unique identifier of the call
+     * @param type set definitely this call as incoming/outgoing
+     */
+    Call(const CallID& id, Call::CallType type);
+    virtual ~Call();
 
+    /** 
+     * Return a reference on the call id
+     * @return call id
+     */
+    CallID& getCallId() {return _id; }
 
-class VoIPLink;
+    /** 
+     * Set the peer number (destination on outgoing)
+     * not protected by mutex (when created)
+     * @param number peer number
+     */
+    void setPeerNumber(const std::string& number) {  _peerNumber = number; }
+    const std::string& getPeerNumber() {  return _peerNumber; }
 
-class Call {
-public:
-  enum CallType {
-  	Null = 0,
-  	Incoming,
-	Outgoing
-  };
+    /** 
+     * Set the peer name (caller in ingoing)
+     * not protected by mutex (when created)
+     * @param number peer number
+     */
+    void setPeerName(const std::string& name) {  _peerName = name; }
+    const std::string& getPeerName() {  return _peerName; }
+
+    /** 
+     * Set the connection state of the call (protected by mutex)
+     */
+    void setConnectionState(ConnectionState state);
+    /** 
+     * get the connection state of the call (protected by mutex)
+     */
+    ConnectionState getConnectionState();
 
-  enum CallState {
-    NotExist = 0,
-    Busy,
-    OnHold,
-    OffHold,
-    MuteOn,
-    MuteOff,
-    Transfered,
-    Hungup,
-    Answered,
-    Ringing,
-    Progressing,
-    Refused,	// for refuse incoming ringing call	
-    Error     // when a error occur
-  };
+    /**
+     * Set the state of the call (protected by mutex)
+     */
+    void setState(CallState state);
+    /** 
+     * get the call state of the call (protected by mutex)
+     */
+    CallState getState();
 
-	// Constructor
-	Call(CALLID id, CallType type, VoIPLink* voiplink);
-	// Destructor
-	~Call(void);
-	
+protected:
+    /** Protect every attribute that can be changed by two threads */
+    ost::Mutex _callMutex;
 
-	// Handle call-id
-	CALLID getId (void);
-	void setId (CALLID id);
-	
-	// Accessor and modifior of VoIPLink
-	VoIPLink* getVoIPLink(void);
-	void setVoIPLink (VoIPLink* voIPLink);
-		
-	// Handle id name and id number
-	std::string getCallerIdName (void);
-	void setCallerIdName (const std::string& callerId_name);
-	std::string getCallerIdNumber (void);
-	void setCallerIdNumber (const std::string& callerId_number);
- 	
-	// Handle state
-	CallState getState (void);
-	void setState (CallState state);
-	
-	// Handle type of call (incoming or outoing)
-	enum CallType getType (void);
-	void setType (enum CallType type);
+private:  
+    /** Unique ID of the call */
+    CallID _id;
 
-  bool isNotAnswered(void);
-	bool isBusy			  (void);
-	bool isOnHold 		(void);
-	bool isOffHold 		(void);
-	bool isOnMute 		(void);
-	bool isOffMute 		(void);
-	bool isTransfered 	(void);
-	bool isHungup 		(void);
-	bool isRinging 		(void);
-	bool isRefused 		(void);
-	bool isAnswered 	(void);
-	bool isProgressing 	(void);
-	bool isOutgoingType (void);
-	bool isIncomingType (void);
-	
-	int outgoingCall  	(const std::string& to);
-	int hangup  		(void);
-	int cancel  		(void);
-	int answer  		(void);
-	int onHold  		(void);
-	int offHold  		(void);
-	int transfer  		(const std::string& to);
-	int refuse  		(void);
-  void setFlagNotAnswered(bool value) { _flagNotAnswered = value; }
-  bool getFlagNotAnswered() const { return _flagNotAnswered; }
+    /** Type of the call */
+    CallType _type;
+    /** Disconnected/Progressing/Trying/Ringing/Connected */
+    ConnectionState _connectionState;
+    /** Inactive/Active/Hold/Busy/Refused/Error */
+    CallState _callState;
 
-private:
-	VoIPLink		*_voIPLink;	
-	CALLID 		  	 _id;
-	enum CallState 	 _state;
-	enum CallType 	 _type;
-	std::string 			 _callerIdName;
-	std::string 			 _callerIdNumber;
+    /** Name of the peer */
+    std::string _peerName;
 
-  bool _flagNotAnswered;
+    /** Number of the peer */
+    std::string _peerNumber;
 };
 
-#endif // __CALL_H__
+#endif
diff --git a/src/eventthread.cpp b/src/eventthread.cpp
index 6e445ab232c3adda875de21ae6842ca0743dd7f9..7edc957062885343e4a99961ca21c25cafe1150e 100644
--- a/src/eventthread.cpp
+++ b/src/eventthread.cpp
@@ -19,11 +19,11 @@
  */
 
 #include "eventthread.h"
-#include "sipvoiplink.h"
+#include "voIPLink.h"
 
-EventThread::EventThread (SipVoIPLink* sip) : Thread () 
+EventThread::EventThread (VoIPLink* link) : Thread () 
 {
-	_sipthread = sip;
+	_linkthread = link;
 	setCancel(cancelDeferred);
 }
 
@@ -39,7 +39,7 @@ void
 EventThread::run (void) 
 {
   while(!testCancel()) {
-    _sipthread->getEvent();
+    _linkthread->getEvent();
   }
 }
 
diff --git a/src/eventthread.h b/src/eventthread.h
index 7508b1cfc33effb6911cb74ec83c028efaf7ff42..a9eba59aeaeecd8a2c22ccbf2bfc130b8797b606 100644
--- a/src/eventthread.h
+++ b/src/eventthread.h
@@ -1,4 +1,4 @@
-/**
+/*
  *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
@@ -23,16 +23,23 @@
 
 #include <cc++/thread.h>
 
-
-class SipVoIPLink;
+class VoIPLink;
+/**
+ * General thread to listen events continuously
+ */
 class EventThread : public ost::Thread {
 public:
-	EventThread (SipVoIPLink*);
+  /**
+   * Build a thread that call getEvents 
+   */
+	EventThread (VoIPLink*);
 	~EventThread (void);
 	
 	virtual void 	 run ();
+
 private:
-	SipVoIPLink*	_sipthread;
+  /** VoIPLink is the object being called by getEvents() method  */
+	VoIPLink*	_linkthread;
 };
 
 #endif // __EVENT_THREAD_H__
diff --git a/src/gui/guiframework.cpp b/src/gui/guiframework.cpp
index d0a84605d0c85e73cc18b7852f3fb1c3128f88a0..49150ab4950f07992ab258dad3d5d87a3b3dd9cf 100644
--- a/src/gui/guiframework.cpp
+++ b/src/gui/guiframework.cpp
@@ -1,5 +1,5 @@
-/** 
- *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
+/*
+ *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *                                                                              
@@ -30,10 +30,10 @@ GuiFramework::GuiFramework ()
 
 GuiFramework::~GuiFramework (void) {}
 
-int 
-GuiFramework::outgoingCall(const std::string&, const std::string& to)
+bool
+GuiFramework::outgoingCall(const std::string& account, const CallID& id, const std::string& to)
 {
-  return Manager::instance().outgoingCall(to);
+  return Manager::instance().outgoingCall(account, id, to);
 }
 
 bool
@@ -42,64 +42,40 @@ GuiFramework::sendTextMessage(const std::string& account, const std::string& to,
   return Manager::instance().sendTextMessage(account, to, message);
 }
 
-int 
-GuiFramework::hangupCall (CALLID id)
+bool
+GuiFramework::hangupCall (const CallID& id)
 {
-	if (Manager::instance().hangupCall(id) == 0) {
-		return 1;
-	} else {
-		return 0;
-	}
+  return Manager::instance().hangupCall(id);
 }
 
-int 
-GuiFramework::cancelCall (CALLID id)
+bool
+GuiFramework::cancelCall (const CallID& id)
 {
-	if (Manager::instance().cancelCall(id) == 0) {
-		return 1;
-	} else {
-		return 0;
-	}
+	return Manager::instance().cancelCall(id);
 }
 
-int 
-GuiFramework::answerCall (CALLID id)
+bool
+GuiFramework::answerCall(const CallID& id)
 {
-  if (Manager::instance().answerCall(id) == 0) {
-    return 1;
-  } else {
-    return 0;
-  }
+  return Manager::instance().answerCall(id);
 }
 
-int 
-GuiFramework::onHoldCall (CALLID id)
+bool
+GuiFramework::onHoldCall(const CallID& id)
 {
-  if (Manager::instance().onHoldCall(id) == 0) {
-    return 1;
-  } else {
-    return 0;
-  }
+  return Manager::instance().onHoldCall(id);
 }
 
-int 
-GuiFramework::offHoldCall (CALLID id)
+bool
+GuiFramework::offHoldCall(const CallID& id)
 {
-  if (Manager::instance().offHoldCall(id) == 0) {
-    return 1;
-  } else {
-    return 0;
-  }
+  return Manager::instance().offHoldCall(id);
 }
 
-int 
-GuiFramework::transferCall (CALLID id, const std::string& to)
+bool
+GuiFramework::transferCall(const CallID& id, const std::string& to)
 {
-	if (Manager::instance().transferCall(id, to) == 0) {
-		return 1;
-	} else {
-		return 0;
-	}
+	return Manager::instance().transferCall(id, to);
 }
 
 void
@@ -107,20 +83,17 @@ GuiFramework::mute()
 {
   Manager::instance().mute();
 }
+
 void
 GuiFramework::unmute() 
 {
   Manager::instance().unmute();
 }
 
-int 
-GuiFramework::refuseCall (CALLID id)
+bool
+GuiFramework::refuseCall (const CallID& id)
 {
-	if (Manager::instance().refuseCall(id) == 0) {
-		return 1;
-	} else {
-		return 0;
-	}
+	return Manager::instance().refuseCall(id);
 }
 
 bool
@@ -130,19 +103,19 @@ GuiFramework::saveConfig (void)
 }
 
 bool 
-GuiFramework::registerVoIPLink (void)
+GuiFramework::registerVoIPLink(const AccountID& accountId)
 {
-  return Manager::instance().registerVoIPLink();
+  return Manager::instance().registerVoIPLink(accountId);
 }
 
 bool 
-GuiFramework::unregisterVoIPLink (void)
+GuiFramework::unregisterVoIPLink (const AccountID& accountId)
 {
-  return Manager::instance().unregisterVoIPLink();
+  return Manager::instance().unregisterVoIPLink(accountId);
 }
 
 bool 
-GuiFramework::sendDtmf (CALLID id, char code)
+GuiFramework::sendDtmf (const CallID& id, char code)
 {
 	return Manager::instance().sendDtmf(id, code);
 }
@@ -202,7 +175,7 @@ GuiFramework::getCallStatus(const std::string& sequenceId)
   return Manager::instance().getCallStatus(sequenceId);
 }
 
-CALLID
+const CallID&
 GuiFramework::getCurrentId() 
 {
   return Manager::instance().getCurrentCallId();
diff --git a/src/gui/guiframework.h b/src/gui/guiframework.h
index 18242b499899f0ea4dae66cb805661143e0385dc..9a45ac5ca019e3b79cbf1bc070780bc6076c1cf0 100644
--- a/src/gui/guiframework.h
+++ b/src/gui/guiframework.h
@@ -1,5 +1,5 @@
-/**
- *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
+/*
+ *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *                                                                              
@@ -26,7 +26,8 @@
 #include <string>
 #include "server/argtokenizer.h"
 #include "../observer.h"
-#include "../call.h"
+#include "../call.h"   // for callid2
+#include "../account.h" // for account
 
 class GuiFramework {
 public:
@@ -34,43 +35,45 @@ public:
 	virtual ~GuiFramework (void);
 
 	/* Parent class to child class */
-	virtual int incomingCall (CALLID id, const std::string& accountId, const std::string& from) = 0;
-	virtual void peerAnsweredCall (CALLID id) = 0;
-	virtual void peerRingingCall (CALLID id) = 0;
-	virtual void peerHungupCall (CALLID id) = 0;
-  virtual void incomingMessage(const std::string& message) = 0;
+  virtual bool incomingCall (const AccountID& accountId, const CallID& id, const std::string& from) = 0;
+
+	virtual void peerAnsweredCall (const CallID& id) = 0;
+	virtual void peerRingingCall (const CallID& id) = 0;
+	virtual void peerHungupCall (const CallID& id) = 0;
+  virtual void incomingMessage(const AccountID& accountId, const std::string& message) = 0;
 	virtual void displayStatus (const std::string& status) = 0;
 	virtual void displayConfigError (const std::string& error) = 0;
-	virtual void displayTextMessage (CALLID id, const std::string& message) = 0;
-	virtual void displayErrorText (CALLID id, const std::string& message) = 0;
+	virtual void displayTextMessage (const CallID& id, const std::string& message) = 0;
+	virtual void displayErrorText (const CallID& id, const std::string& message) = 0;
 	virtual void displayError (const std::string& error) = 0;
 	virtual void startVoiceMessageNotification (void) {}
 	virtual void stopVoiceMessageNotification (void) {}
-  virtual void sendVoiceNbMessage(const std::string& nb_msg) = 0;
+  virtual void sendVoiceNbMessage(const AccountID& accountId, const std::string& nb_msg) = 0;
 	virtual void setup() = 0;
   virtual void sendMessage(const std::string& code, const std::string& seqId, TokenList& arg) = 0;
   virtual void sendCallMessage(const std::string& code, 
-  const std::string& sequenceId, CALLID id, TokenList arg) = 0;
-  virtual void sendRegistrationState(bool state) = 0;
-  virtual void callFailure(CALLID id) = 0;
+  const std::string& sequenceId, const CallID& id, TokenList arg) = 0;
+  virtual void sendRegistrationState(const AccountID& accountid, bool state) = 0;
+  virtual void callFailure(const CallID& id) = 0;
 
 	/* Child class to parent class */
-	int outgoingCall(const std::string& account, const std::string& to);
-  bool sendTextMessage(const std::string& account, const std::string& to, const std::string& message);
-	int hangupCall (CALLID id);
-	int cancelCall (CALLID id);
-	int answerCall (CALLID id);
-	int onHoldCall (CALLID id);
-	int offHoldCall (CALLID id);
-	int transferCall (CALLID id, const std::string& to);
+  bool outgoingCall(const AccountID& account, const CallID& id, const std::string& to);
+  bool answerCall(const CallID& id);
+
+  bool sendTextMessage(const AccountID& accountId, const std::string& to, const std::string& message);
+	bool hangupCall (const CallID& id);
+	bool cancelCall (const CallID& id);
+	bool onHoldCall (const CallID& id);
+	bool offHoldCall (const CallID& id);
+	bool transferCall (const CallID& id, const std::string& to);
 	void mute ();
 	void unmute ();
-	int refuseCall (CALLID id);
+	bool refuseCall (const CallID& id);
 
   bool saveConfig(void);
-  bool registerVoIPLink(void);
-  bool unregisterVoIPLink(void);
-  bool sendDtmf (CALLID id, char code);
+  bool registerVoIPLink(const AccountID& accountId);
+  bool unregisterVoIPLink(const AccountID& accountId);
+  bool sendDtmf (const CallID& id, char code);
   bool playDtmf (char code);
   bool playTone ();
   bool stopTone ();
@@ -92,7 +95,7 @@ public:
   bool setSwitch(const std::string& switchName);
 
   bool hasLoadedSetup();
-  CALLID getCurrentId();
+  const CallID& getCurrentId();
   bool getRegistrationState(std::string& stateCode, std::string& stateMessage);
 
 protected:
diff --git a/src/gui/qt/ConfigurationPanel.ui.h b/src/gui/qt/ConfigurationPanel.ui.h
index a6ee2f33799eaafaa6762cbc1403c3c9a83a6ee4..fe7c445f705fae42709610012e54c487184114fb 100644
--- a/src/gui/qt/ConfigurationPanel.ui.h
+++ b/src/gui/qt/ConfigurationPanel.ui.h
@@ -1,4 +1,4 @@
-/**
+/*
  *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author: Jean-Philippe Barrette-LaPierre
@@ -133,43 +133,41 @@ ConfigurationPanel::generate()
 			      .get(AUDIO_SECTION,
 				   AUDIO_RINGTONE));
   
+  QString account = ACCOUNT_DEFAULT_NAME;
+  QString type    = ConfigurationManager::instance().get(account, ACCOUNT_TYPE);
+  QString active  = ConfigurationManager::instance().get(account, ACCOUNT_ENABLE);
+
   // For signalisations tab
+  autoregister->setChecked(ConfigurationManager::instance()
+			   .get(account,ACCOUNT_AUTO_REGISTER).toUInt());
+
   fullName->setText(ConfigurationManager::instance()
-		    .get(SIGNALISATION_SECTION, 
-			 SIGNALISATION_FULL_NAME));
+		    .get(account,SIGNALISATION_FULL_NAME));
   userPart->setText(ConfigurationManager::instance()
-		    .get(SIGNALISATION_SECTION,
-			 SIGNALISATION_USER_PART));
+		    .get(account,SIGNALISATION_USER_PART));
   username->setText(ConfigurationManager::instance()
-		    .get(SIGNALISATION_SECTION,
-			 SIGNALISATION_AUTH_USER_NAME));
+		    .get(account,SIGNALISATION_AUTH_USER_NAME));
   password->setText(ConfigurationManager::instance()
-		    .get(SIGNALISATION_SECTION, 
-			 SIGNALISATION_PASSWORD));
+		    .get(account,SIGNALISATION_PASSWORD));
   hostPart->setText(ConfigurationManager::instance()
-		    .get(SIGNALISATION_SECTION,
-			 SIGNALISATION_HOST_PART));
+		    .get(account,SIGNALISATION_HOST_PART));
   sipproxy->setText(ConfigurationManager::instance()
-		    .get(SIGNALISATION_SECTION, 
-			 SIGNALISATION_PROXY));
-  autoregister->setChecked(ConfigurationManager::instance()
-			   .get(SIGNALISATION_SECTION,
-				SIGNALISATION_AUTO_REGISTER).toUInt());
+		    .get(account,SIGNALISATION_PROXY));
+  STUNserver->setText(ConfigurationManager::instance()
+		      .get(account,SIGNALISATION_STUN_SERVER));
+  ((QRadioButton*)stunButtonGroup->find(ConfigurationManager::instance()
+			.get(account,SIGNALISATION_USE_STUN).toUInt()))->setChecked(true); 
+
+  sendDTMFas->setCurrentItem(ConfigurationManager::instance()
+			     .get(SIGNALISATION_SECTION,
+				  SIGNALISATION_SEND_DTMF_AS).toUInt());
   playTones->setChecked(ConfigurationManager::instance()
 			.get(SIGNALISATION_SECTION, 
 			     SIGNALISATION_PLAY_TONES).toUInt());
   pulseLength->setValue(ConfigurationManager::instance()
 			.get(SIGNALISATION_SECTION, 
 			     SIGNALISATION_PULSE_LENGTH).toUInt());
-  sendDTMFas->setCurrentItem(ConfigurationManager::instance()
-			     .get(SIGNALISATION_SECTION,
-				  SIGNALISATION_SEND_DTMF_AS).toUInt());
-  STUNserver->setText(ConfigurationManager::instance()
-		      .get(SIGNALISATION_SECTION,
-			   SIGNALISATION_STUN_SERVER));
-  ((QRadioButton*)stunButtonGroup->find(ConfigurationManager::instance()
-					.get(SIGNALISATION_SECTION,
-					     SIGNALISATION_USE_STUN).toUInt()))->setChecked(true); 
+
   QRadioButton* device = 
     static_cast< QRadioButton * >(DriverChoice->find(ConfigurationManager::instance()
 						     .get(AUDIO_SECTION, 
@@ -185,27 +183,32 @@ ConfigurationPanel::generate()
 // For saving settings at application 'save'
 void ConfigurationPanel::saveSlot()
 {
-  ConfigurationManager::instance().set(SIGNALISATION_SECTION, 
+  QString account = ACCOUNT_DEFAULT_NAME;
+  ConfigurationManager::instance().set(account, 
 				       SIGNALISATION_FULL_NAME,
 				       fullName->text());
-  ConfigurationManager::instance().set(SIGNALISATION_SECTION, 
+  ConfigurationManager::instance().set(account, 
 				       SIGNALISATION_USER_PART,
 				       userPart->text());
-  ConfigurationManager::instance().set(SIGNALISATION_SECTION, 
+  ConfigurationManager::instance().set(account, 
 				       SIGNALISATION_AUTH_USER_NAME,
 				       username->text());
-  ConfigurationManager::instance().set(SIGNALISATION_SECTION, 
+  ConfigurationManager::instance().set(account, 
 				       SIGNALISATION_PASSWORD,
 				       password->text());
-  ConfigurationManager::instance().set(SIGNALISATION_SECTION, 
+  ConfigurationManager::instance().set(account, 
 				       SIGNALISATION_HOST_PART,
 				       hostPart->text());
-  ConfigurationManager::instance().set(SIGNALISATION_SECTION, 
+  ConfigurationManager::instance().set(account, 
 				       SIGNALISATION_PROXY,
 				       sipproxy->text());
-  ConfigurationManager::instance().set(SIGNALISATION_SECTION, 
-				       SIGNALISATION_AUTO_REGISTER,
+  ConfigurationManager::instance().set(account, 
+				       ACCOUNT_AUTO_REGISTER,
 				       QString::number(autoregister->isChecked()));
+  ConfigurationManager::instance().set(account, 
+				       SIGNALISATION_STUN_SERVER,
+				       STUNserver->text());
+
   ConfigurationManager::instance().set(SIGNALISATION_SECTION, 
 				       SIGNALISATION_PULSE_LENGTH,
 				       QString::number(pulseLength->value()));
@@ -215,9 +218,6 @@ void ConfigurationPanel::saveSlot()
   ConfigurationManager::instance().set(SIGNALISATION_SECTION, 
 				       SIGNALISATION_SEND_DTMF_AS,
 				       QString::number(sendDTMFas->currentItem()));
-  ConfigurationManager::instance().set(SIGNALISATION_SECTION, 
-				       SIGNALISATION_STUN_SERVER,
-				       STUNserver->text());
 
   if (codec1->currentText() != NULL) {
     ConfigurationManager::instance().set(AUDIO_SECTION, 
@@ -292,7 +292,8 @@ void ConfigurationPanel::changeTabSlot()
 
 void ConfigurationPanel::useStunSlot(int id)
 {
-  ConfigurationManager::instance().set(SIGNALISATION_SECTION,
+  QString account = ACCOUNT_DEFAULT_NAME;
+  ConfigurationManager::instance().set(account,
 				       SIGNALISATION_USE_STUN, 
 				       QString::number(id));
 }
diff --git a/src/gui/qt/Session.cpp b/src/gui/qt/Session.cpp
index 02d80a6e1eb0502874b2eeb6de3649fe29aaff81..9491565ac684411d26cf1f1d2aab5cb1e14cd492 100644
--- a/src/gui/qt/Session.cpp
+++ b/src/gui/qt/Session.cpp
@@ -176,6 +176,6 @@ Session::getAccount(const QString &name) const
 Account
 Session::getDefaultAccount() const
 {
-  return Account(mId, QString("mydefaultaccount"));
+  return Account(mId, QString("SIP0"));
 }
 
diff --git a/src/gui/qt/globals.h b/src/gui/qt/globals.h
index 6d446339806df99f15f6c0c004cf1cdcbe6656fc..80565bebd616ed9a650761af2180689955c38452 100644
--- a/src/gui/qt/globals.h
+++ b/src/gui/qt/globals.h
@@ -32,7 +32,6 @@
 #define AUDIO_CODEC3 "Codecs.codec3"
 #define AUDIO_RINGTONE "Rings.ringChoice"
 
-
 #define SIGNALISATION_SECTION "VoIPLink"
 #define SIGNALISATION_FULL_NAME "SIP.fullName"
 #define SIGNALISATION_USER_PART "SIP.userPart"
@@ -40,12 +39,16 @@
 #define SIGNALISATION_PASSWORD "SIP.password"
 #define SIGNALISATION_HOST_PART "SIP.hostPart"
 #define SIGNALISATION_PROXY "SIP.proxy"
-#define SIGNALISATION_AUTO_REGISTER "SIP.autoregister"
+#define SIGNALISATION_STUN_SERVER "STUN.STUNserver"
+#define SIGNALISATION_USE_STUN "STUN.useStun"
 #define SIGNALISATION_PLAY_TONES "DTMF.playTones"
 #define SIGNALISATION_PULSE_LENGTH "DTMF.pulseLength"
 #define SIGNALISATION_SEND_DTMF_AS "DTMF.sendDTMFas"
-#define SIGNALISATION_STUN_SERVER "STUN.STUNserver"
-#define SIGNALISATION_USE_STUN "STUN.useStun"
+
+#define ACCOUNT_DEFAULT_NAME "SIP0"
+#define ACCOUNT_TYPE "Account.type"
+#define ACCOUNT_ENABLE "Account.enable"
+#define ACCOUNT_AUTO_REGISTER "Account.autoregister"
 
 #define PREFERENCES_SECTION "Preferences"
 #define PREFERENCES_THEME "Themes.skinChoice"
diff --git a/src/gui/server/guiserverimpl.cpp b/src/gui/server/guiserverimpl.cpp
index 50f99f8796293bfa5bbf262223e47176eb38ac3d..a050875fb8410b848879c27294c3159534042481 100644
--- a/src/gui/server/guiserverimpl.cpp
+++ b/src/gui/server/guiserverimpl.cpp
@@ -48,12 +48,13 @@ GUIServerImpl::exec() {
  *  remove
  */
 void 
-GUIServerImpl::insertSubCall(CALLID id, SubCall& subCall) {
-  _callMap[id] = subCall;
+GUIServerImpl::insertSubCall(const CallID& id, const CallID& seq) {
+  
+  _callMap[id] = seq;
 }
 
 void
-GUIServerImpl::removeSubCall(CALLID id) {
+GUIServerImpl::removeSubCall(const CallID& id) {
   _callMap.erase(id);
 }
 
@@ -61,32 +62,21 @@ GUIServerImpl::removeSubCall(CALLID id) {
  * Retreive the sequenceId or send default sequenceId
  */
 std::string 
-GUIServerImpl::getSequenceIdFromId(CALLID id) {
+GUIServerImpl::getSequenceIdFromId(const CallID& id) {
   CallMap::iterator iter = _callMap.find(id);
   if (iter != _callMap.end()) {
-    return iter->second.sequenceId();
+    return iter->second;
   }
   return _getEventsSequenceId;
 }
-/**
- * Retreive the string callid from the id
- */
-std::string 
-GUIServerImpl::getCallIdFromId(CALLID id) {
-  CallMap::iterator iter = _callMap.find(id);
-  if (iter != _callMap.end()) {
-    return iter->second.callId();
-  }
-  throw std::runtime_error(_("No match for this id"));
-}
 
 bool
 GUIServerImpl::getCurrentCallId(std::string& callId) {
   bool returnValue = false;
   try {
-    CALLID id = GuiFramework::getCurrentId();
-    if (id!=0) {
-      callId = getCallIdFromId(id);
+    CallID id = GuiFramework::getCurrentId();
+    if (id != "") {
+      callId = id;
       returnValue = true;
     }
   } catch(...) {
@@ -95,19 +85,6 @@ GUIServerImpl::getCurrentCallId(std::string& callId) {
   return returnValue;
 }
 
-CALLID
-GUIServerImpl::getIdFromCallId(const std::string& callId) 
-{
-  CallMap::iterator iter = _callMap.begin();
-  while (iter != _callMap.end()) {
-    if (iter->second.callId()==callId) {
-      return iter->first;
-    }
-    iter++;
-  }
-  throw std::runtime_error(_("No match for this CallId"));
-}
-
 bool 
 GUIServerImpl::getEvents(const std::string& sequenceId)
 {
@@ -165,96 +142,45 @@ GUIServerImpl::outgoingCall(const std::string& seq,
  const std::string& callid, 
  const std::string& to) 
 {
-  CALLID serverCallId = GuiFramework::outgoingCall(account, to);
-  if ( serverCallId ) {
-    SubCall subcall(seq, callid);
-    insertSubCall(serverCallId, subcall);
-    return true;
-  } else {
-    return false;
-  }
+  insertSubCall(callid, seq);
+  return GuiFramework::outgoingCall(account, callid, to);
 }
 
 bool 
 GUIServerImpl::answerCall(const std::string& callId) 
 {
-  try {
-    CALLID id = getIdFromCallId(callId);
-    if (GuiFramework::answerCall(id)) {
-      return true;
-    }
-  } catch(...) {
-    return false;
-  }
-  return false;
+  return GuiFramework::answerCall(callId);
 }
 
 bool
 GUIServerImpl::refuseCall(const std::string& callId) 
 {
-  try {
-    CALLID id = getIdFromCallId(callId);
-    if (GuiFramework::refuseCall(id)) {
-      return true;
-    }
-  } catch(...) {
-    return false;
-  }
-  return false;
+  return GuiFramework::refuseCall(callId);
 }
 bool 
 GUIServerImpl::transferCall(const std::string& callId, const std::string& to)
 {
-  try {
-    CALLID id = getIdFromCallId(callId);
-    if (GuiFramework::transferCall(id, to)) {
-      return true;
-    }
-  } catch(...) {
-    return false;
-  }
-  return false;
+  return GuiFramework::transferCall(callId, to);
 }
 
 bool
 GUIServerImpl::holdCall(const std::string& callId) 
 {
-  try {
-    CALLID id = getIdFromCallId(callId);
-    if (GuiFramework::onHoldCall(id)) {
-      return true;
-    }
-  } catch(...) {
-    return false;
-  }
-  return false;
+  return GuiFramework::onHoldCall(callId);
 }
 
 bool
 GUIServerImpl::unholdCall(const std::string& callId) 
 {
-  try {
-    CALLID id = getIdFromCallId(callId);
-    if (GuiFramework::offHoldCall(id)) {
-      return true;
-    }
-  } catch(...) {
-    return false;
-  }
-  return false;
+  return GuiFramework::offHoldCall(callId);
 }
 
 bool
 GUIServerImpl::hangupCall(const std::string& callId) 
 {
-  try {
-    CALLID id = getIdFromCallId(callId);
-    if (GuiFramework::hangupCall(id)) {
-      _callMap.erase(id);
-      return true;
-    }
-  } catch(...) {
-    return false;
+  if ( GuiFramework::hangupCall(callId) ) {
+    removeSubCall(callId);
+    return true;
   }
   return false;
 }
@@ -267,12 +193,10 @@ bool
 GUIServerImpl::hangupAll()
 {
   bool result = true;
-  CALLID id;
   CallMap::iterator iter = _callMap.begin();
   // try to hangup every call, even if one fail
   while(iter!=_callMap.end()) {
-    id = iter->first;
-    if (!GuiFramework::hangupCall(id)) {
+    if (!GuiFramework::hangupCall(iter->first)) {
       result = false;
     }
     iter++;
@@ -284,14 +208,7 @@ GUIServerImpl::hangupAll()
 bool 
 GUIServerImpl::dtmfCall(const std::string& callId, const std::string& dtmfKey) 
 {
-  try {
-    CALLID id = getIdFromCallId(callId);
-    char code = dtmfKey[0];
-    return GuiFramework::sendDtmf(id, code);
-  } catch(...) {
-    return false;
-  }
-  return false;
+  return GuiFramework::sendDtmf(callId, dtmfKey[0]);
 }
 
 /**
@@ -307,62 +224,60 @@ GUIServerImpl::version()
 }
 
 
-int 
-GUIServerImpl::incomingCall (CALLID id, const std::string& accountId, const std::string& from) 
+bool
+GUIServerImpl::incomingCall(const AccountID& accountId, const CallID& id, const std::string& from) 
 {
   TokenList arg;
-  std::ostringstream callId;
-  callId << "s" << id;
-  arg.push_back(callId.str());
+  arg.push_back(id);
   arg.push_back(accountId);
   arg.push_back(from);
   arg.push_back("call");
 
-  SubCall subcall(_getEventsSequenceId, callId.str());
-
-  insertSubCall(id, subcall);
-
-  _requestManager.sendResponse(ResponseMessage("001", _getEventsSequenceId,arg));
+  insertSubCall(id, _getEventsSequenceId);
+  _requestManager.sendResponse(ResponseMessage("001", _getEventsSequenceId, arg));
 
   return 0;
 }
 
 void
-GUIServerImpl::incomingMessage(const std::string& message) {
-  _requestManager.sendResponse(ResponseMessage("030", _getEventsSequenceId, message));
+GUIServerImpl::incomingMessage(const std::string& account, const std::string& message) {
+  TokenList arg;
+  arg.push_back(account);
+  arg.push_back(message);
+  _requestManager.sendResponse(ResponseMessage("030", _getEventsSequenceId, arg));
 }
 
 void  
-GUIServerImpl::peerAnsweredCall (CALLID id) 
+GUIServerImpl::peerAnsweredCall (const CallID& id) 
 {
   CallMap::iterator iter = _callMap.find(id);
   if ( iter != _callMap.end() ) {
-    _requestManager.sendResponse(ResponseMessage("200", iter->second.sequenceId(), _("Established")));
+    _requestManager.sendResponse(ResponseMessage("200", iter->second, _("Established")));
   }
 }
 
 void
-GUIServerImpl::peerRingingCall (CALLID id) 
+GUIServerImpl::peerRingingCall (const CallID& id) 
 {
   CallMap::iterator iter = _callMap.find(id);
   if ( iter != _callMap.end() ) {
-    _requestManager.sendResponse(ResponseMessage("151", iter->second.sequenceId(), _("Ringing")));
+    _requestManager.sendResponse(ResponseMessage("151", iter->second, _("Ringing")));
   } 
 }
 
 void
-GUIServerImpl::peerHungupCall (CALLID id) 
+GUIServerImpl::peerHungupCall (const CallID& id) 
 {
   CallMap::iterator iter = _callMap.find(id);
   if ( iter != _callMap.end() ) {
     TokenList tk;
-    tk.push_back(iter->second.callId());
+    tk.push_back(id);
     tk.push_back("hangup");
 
     _requestManager.sendResponse(ResponseMessage("002", _getEventsSequenceId,tk));
     
     // remove this call...
-    _callMap.erase(id);
+    removeSubCall(id);
   }
 }
 
@@ -385,36 +300,23 @@ GUIServerImpl::displayConfigError (const std::string& error)
 }
 
 void  
-GUIServerImpl::displayTextMessage (CALLID id, const std::string& message) 
+GUIServerImpl::displayTextMessage (const CallID& id, const std::string& message) 
 {
-  try {
-    std::string callId = getCallIdFromId(id);
-    TokenList tk;
-    tk.push_back(callId);
-    tk.push_back(message);
-    tk.push_back("Text message");
-    _requestManager.sendResponse(ResponseMessage("102", _getEventsSequenceId, tk));
-  } catch(...) {
-    TokenList tk;
-    tk.push_back(message);
-    tk.push_back("Text message");
-    _requestManager.sendResponse(ResponseMessage("103", _getEventsSequenceId, tk));
-  }
+  TokenList tk;
+  tk.push_back(id);
+  tk.push_back(message);
+  tk.push_back("Text message");
+  _requestManager.sendResponse(ResponseMessage("102", _getEventsSequenceId, tk));
 }
 
 void  
-GUIServerImpl::displayErrorText (CALLID id, const std::string& message) 
+GUIServerImpl::displayErrorText (const CallID& id, const std::string& message) 
 {
-  try {
-    std::string callId = getCallIdFromId(id);
-    TokenList tk;
-    tk.push_back(callId);
-    tk.push_back(message);
-    tk.push_back("Error");
-    _requestManager.sendResponse(ResponseMessage("104", _getEventsSequenceId, tk));
-  } catch(...) {
-    displayError(message);
-  }
+  TokenList tk;
+  tk.push_back(id);
+  tk.push_back(message);
+  tk.push_back("Error");
+  _requestManager.sendResponse(ResponseMessage("104", _getEventsSequenceId, tk));
 }
 
 void  
@@ -427,18 +329,25 @@ GUIServerImpl::displayError (const std::string& error)
 }
 
 void
-GUIServerImpl::sendVoiceNbMessage(const std::string& nb_msg)
+GUIServerImpl::sendVoiceNbMessage(const AccountID& accountId, const std::string& nb_msg)
 {
-  _requestManager.sendResponse(ResponseMessage("020", _getEventsSequenceId, nb_msg));
+  TokenList tk;
+  tk.push_back(accountId);
+  tk.push_back(nb_msg);
+  _requestManager.sendResponse(ResponseMessage("020", _getEventsSequenceId, tk));
 }
 
 void
-GUIServerImpl::sendRegistrationState(bool state) 
+GUIServerImpl::sendRegistrationState(const AccountID& accountid, bool state) 
 {
+  TokenList tk;
+  tk.push_back(accountid);
   if (state == true) {
-  _requestManager.sendResponse(ResponseMessage("003", _getEventsSequenceId, _("Registration succeed")));
+    tk.push_back(_("Registration succeed"));
+  _requestManager.sendResponse(ResponseMessage("003", _getEventsSequenceId, tk));
   } else {
-  _requestManager.sendResponse(ResponseMessage("004", _getEventsSequenceId, _("Registration failed")));
+    tk.push_back(_("Registration failed"));
+  _requestManager.sendResponse(ResponseMessage("004", _getEventsSequenceId, tk));
   }
 }
 void
@@ -455,12 +364,11 @@ GUIServerImpl::sendMessage(const std::string& code, const std::string& seqId, To
 void 
 GUIServerImpl::sendCallMessage(const std::string& code, 
   const std::string& sequenceId, 
-  CALLID id, 
+  const CallID& id, 
   TokenList arg) 
 {
   try {
-    std::string callid = getCallIdFromId(id);
-    arg.push_front(callid);
+    arg.push_front(id);
     _requestManager.sendResponse(ResponseMessage(code, sequenceId, arg));
   } catch(...) {
     // no callid found
@@ -474,14 +382,15 @@ GUIServerImpl::update()
 }
 
 void
-GUIServerImpl::callFailure(CALLID id)
+GUIServerImpl::callFailure(const CallID& id)
 {
   CallMap::iterator iter = _callMap.find(id);
   if ( iter != _callMap.end() ) {
     TokenList tk;
-    tk.push_back(iter->second.callId());
+    tk.push_back(id);
     tk.push_back("Wrong number");
 
-    _requestManager.sendResponse(ResponseMessage("504", iter->second.sequenceId(), tk));
+    _requestManager.sendResponse(ResponseMessage("504", iter->second, tk));
+    removeSubCall(id);
   }
 }
diff --git a/src/gui/server/guiserverimpl.h b/src/gui/server/guiserverimpl.h
index f237a3f3d0b19ccb9728796f4497795acad7077b..8b2a8ab8dae8cefd2b64d6f643ec4fafa2963198 100644
--- a/src/gui/server/guiserverimpl.h
+++ b/src/gui/server/guiserverimpl.h
@@ -23,14 +23,13 @@
 #include <string>
 #include <map>
 
-#include "subcall.h"
 #include "requestmanager.h"
 
 
 /** Session port for the daemon, default is DEFAULT_SESSION_PORT */
 #define DEFAULT_SESSION_PORT 3999
 
-typedef std::map<CALLID, SubCall> CallMap;
+typedef std::map<CallID, std::string> CallMap;
 
 class GUIServerImpl : public GuiFramework {
 public:
@@ -42,26 +41,26 @@ public:
   // exec loop
   int exec(void);
 
-  int incomingCall(CALLID id, const std::string& accountId, const std::string& from);
-  void incomingMessage(const std::string& message);
+  bool incomingCall(const AccountID& accountId, const CallID& id, const std::string& from);
+  void incomingMessage(const AccountID& accountId, const std::string& message);
 
-	void peerAnsweredCall (CALLID id);
-	void peerRingingCall (CALLID id);
-	void peerHungupCall (CALLID id);
+	void peerAnsweredCall (const CallID& id);
+	void peerRingingCall (const CallID& id);
+	void peerHungupCall (const CallID& id);
 	void displayStatus (const std::string& status);
   void displayConfigError(const std::string& error);
-	void displayTextMessage (CALLID id, const std::string& message);
-	void displayErrorText (CALLID id, const std::string& message);
+	void displayTextMessage (const CallID& id, const std::string& message);
+	void displayErrorText (const CallID& id, const std::string& message);
 	void displayError (const std::string& error);
-  void sendVoiceNbMessage(const std::string& nb_msg);
-  void sendRegistrationState(bool state);
+  void sendVoiceNbMessage(const AccountID& accountid, const std::string& nb_msg);
+  void sendRegistrationState(const AccountID& accountid, bool state);
   void setup();
 
   void sendMessage(const std::string& code, const std::string& seqId, 
     TokenList& arg);
   void sendCallMessage(const std::string& code, const std::string& sequenceId, 
-    CALLID id, TokenList arg);
-  void callFailure(CALLID id);
+    const CallID& id, TokenList arg);
+  void callFailure(const CallID& id);
 
   bool getEvents(const std::string& sequenceId);
   bool sendGetEventsEnd();
@@ -90,17 +89,13 @@ public:
   };
 
 private:
-  void insertSubCall(CALLID id, SubCall& subCall);
-  void removeSubCall(CALLID id);
-  std::string getSequenceIdFromId(CALLID id);
-  std::string getCallIdFromId(CALLID id);
-  CALLID getIdFromCallId(const std::string& callId);
-
+  void insertSubCall(const CallID& id, const std::string& seq);
+  void removeSubCall(const CallID& id);
+  std::string getSequenceIdFromId(const CallID& id);
 
   /**
    * This callMap is necessary because
-   * ManagerImpl use callid-int
-   * and the client use a  callid-string
+   * because we want to retreive the seq associate to a call id
    * and also a sequence number
    */
   CallMap _callMap;
diff --git a/src/gui/server/request.cpp b/src/gui/server/request.cpp
index c4d84edfc6790a005edbeb14701c106275092475..124ec473a79a0f8e669e914b606dfa767ec58192 100644
--- a/src/gui/server/request.cpp
+++ b/src/gui/server/request.cpp
@@ -32,19 +32,19 @@ RequestCall::execute()
 }
 
 ResponseMessage
-RequestTextMessage::execute()
+RequestAnswer::execute()
 {
-  if ( GUIServer::instance().sendTextMessage(_account, _destination, _message) ) {
-    return message("200", "Sending message");
+  if ( GUIServer::instance().answerCall(_callId) ) {
+    return message("200", _("OK"));
   }
   return message("500","Server Error");
 }
 
 ResponseMessage
-RequestAnswer::execute()
+RequestTextMessage::execute()
 {
-  if ( GUIServer::instance().answerCall(_callId) ) {
-    return message("200", _("OK"));
+  if ( GUIServer::instance().sendTextMessage(_account, _destination, _message) ) {
+    return message("200", "Sending message");
   }
   return message("500","Server Error");
 }
diff --git a/src/gui/server/requestconfig.cpp b/src/gui/server/requestconfig.cpp
index 5ce1f5431a01ae13cef5a9254af925dcb63e8d5d..134a26ab7b89b1688eaf4344493e71072eb96655 100644
--- a/src/gui/server/requestconfig.cpp
+++ b/src/gui/server/requestconfig.cpp
@@ -242,20 +242,42 @@ RequestVolumeMic::execute()
   }
 }
 
+RequestRegister::RequestRegister(const std::string &sequenceId, const TokenList& argList) : RequestGlobal(sequenceId,argList)
+{
+  TokenList::iterator iter = _argList.begin();
+  if (iter != _argList.end()) {
+    _accountId = *iter;
+    _argList.pop_front();
+  } else {
+    throw RequestConstructorException();
+  }
+}
+
 ResponseMessage
 RequestRegister::execute()
 {
-  if (GUIServer::instance().registerVoIPLink()) {
+  if (GUIServer::instance().registerVoIPLink(_accountId)) {
     return message("200", _("OK"));
   } else {
     return message("500",_("Registration sending failed"));
   }
 }
 
+RequestUnregister::RequestUnregister(const std::string &sequenceId, const TokenList& argList) : RequestGlobal(sequenceId,argList)
+{
+  TokenList::iterator iter = _argList.begin();
+  if (iter != _argList.end()) {
+    _accountId = *iter;
+    _argList.pop_front();
+  } else {
+    throw RequestConstructorException();
+  }
+}
+
 ResponseMessage
 RequestUnregister::execute()
 {
-  if (GUIServer::instance().unregisterVoIPLink()) {
+  if (GUIServer::instance().unregisterVoIPLink(_accountId)) {
     return message("200", _("OK"));
   } else {
     return message("500",_("Unregistration sending failed"));
diff --git a/src/gui/server/requestconfig.h b/src/gui/server/requestconfig.h
index c34cbb8202ddd77a08526c6d2550134067bd5a69..2edd772625abd0f487f040079bce5929d5f496a3 100644
--- a/src/gui/server/requestconfig.h
+++ b/src/gui/server/requestconfig.h
@@ -112,14 +112,18 @@ private:
 
 class RequestRegister : public RequestGlobal {
 public:
-  RequestRegister(const std::string &sequenceId, const TokenList& argList) : RequestGlobal(sequenceId, argList) {}
+  RequestRegister(const std::string &sequenceId, const TokenList& argList);
   ResponseMessage execute();
+private:
+  std::string _accountId;
 };
 
 class RequestUnregister : public RequestGlobal {
 public:
-  RequestUnregister(const std::string &sequenceId, const TokenList& argList) : RequestGlobal(sequenceId, argList) {}
+  RequestUnregister(const std::string &sequenceId, const TokenList& argList);
   ResponseMessage execute();
+private:
+  std::string _accountId;
 };
 class RequestSwitch : public RequestGlobal {
 public:
diff --git a/src/aixaccount.h b/src/iaxvoiplink.cpp
similarity index 64%
rename from src/aixaccount.h
rename to src/iaxvoiplink.cpp
index d5d54e289b792129da6d64f4d96ae9c7fa2f86ec..7b0729d5acc1e8b3cd268db4b418ed63e4bb1a42 100644
--- a/src/aixaccount.h
+++ b/src/iaxvoiplink.cpp
@@ -16,32 +16,16 @@
  *  along with this program; if not, write to the Free Software
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#ifndef AIXACCOUNT_H
-#define AIXACCOUNT_H
+#include "iaxvoiplink.h"
 
-#include "account.h"
-
-/**
-	@author Yan Morin <yan.morin@gmail.com>
-  An AIX Account specify AIX specific functions and objects (AIXCall/AIXVoIPLink)
-*/
-class AIXAccount : public Account
+IAXVoIPLink::IAXVoIPLink(const AccountID& accountID)
+ : VoIPLink(accountID)
 {
-public:
-    AIXAccount(const AccountID& accountID);
+}
 
-    ~AIXAccount();
 
-  /* virtual Account function implementation */
-  void initConfig(Conf::ConfigTree& config);
-  bool registerAccount();
-  bool unregisterAccount();
-  bool init();
-  bool terminate();
+IAXVoIPLink::~IAXVoIPLink()
+{
+}
 
-private:
-  /* virtual Account function implementation */
-  bool createVoIPLink();
-};
 
-#endif
diff --git a/src/iaxvoiplink.h b/src/iaxvoiplink.h
new file mode 100644
index 0000000000000000000000000000000000000000..fddd03a88a0e20f64825972220263a55c406b073
--- /dev/null
+++ b/src/iaxvoiplink.h
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (C) 2006 Savoir-Faire Linux inc.
+ *  Author: Yan Morin <yan.morin@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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (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.
+ */
+#ifndef IAXVOIPLINK_H
+#define IAXVOIPLINK_H
+
+#include "voIPLink.h"
+
+class AudioCodec;
+
+/**
+	@author Yan Morin <yan.morin@gmail.com>
+  VoIPLink contains a thread that listen to external events and 
+  contains IAX Call related functions
+*/
+class IAXVoIPLink : public VoIPLink
+{
+public:
+    IAXVoIPLink(const AccountID& accountID);
+
+    ~IAXVoIPLink();
+
+  void getEvent (void) { }
+  bool init (void) { return false; }
+  bool checkNetwork (void) { return false; }
+  void terminate (void) { }
+
+  bool setRegister (void) { return false; }
+  bool setUnregister (void) { return false; }
+
+  Call* newOutgoingCall(const CallID& id, const std::string& toUrl) {return 0; }
+  bool answer(const CallID& id) {return false;}
+
+  bool hangup(const CallID& id) { return false; }
+  bool cancel(const CallID& id) { return false; }
+  bool onhold(const CallID& id) { return false; }
+  bool offhold(const CallID& id) { return false; }
+  bool transfer(const CallID& id, const std::string& to) { return false; }
+  bool refuse (const CallID& id) { return false; }
+  bool carryingDTMFdigits(const CallID& id, char code) { return false; }
+  bool sendMessage(const std::string& to, const std::string& body) { return false; }
+};
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
index fafad62cf8d4fc47ffadc77df73882c8e4abbe7c..bb74946f9c2904fc30614a687fb2f3fdfaf4340e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -22,7 +22,7 @@
 #include <cstring>
 #include <iostream>
 
-#include "config.h"
+//#include "config.h"
 #include "global.h"
 
 #include "user_cfg.h"
diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp
index 6cb14fb00a6aaace0429caa100c86b091246c62c..3085ce1c8de60a116c303da573c9b907b3a71091 100644
--- a/src/managerimpl.cpp
+++ b/src/managerimpl.cpp
@@ -39,7 +39,6 @@
 
 #include "accountcreator.h" // create new account
 #include "voIPLink.h"
-#include "call.h"
 
 #include "user_cfg.h"
 #include "gui/guiframework.h"
@@ -54,8 +53,6 @@
 #define fill_config_int(name, value) \
   (_config.addConfigTreeItem(section, Conf::ConfigTreeItem(std::string(name), std::string(value), type_int)))
 
-#define DFT_VOIP_LINK 0
-
 ManagerImpl::ManagerImpl (void)
 {
   // Init private variables 
@@ -73,19 +70,18 @@ ManagerImpl::ManagerImpl (void)
   _setupLoaded = false;
   _gui = NULL;
 
+  // sound
   _audiodriverPA = NULL;
   _dtmfKey = 0;
-
-  // Initialize after by init() -> initVolume()
-  _spkr_volume = 0;
-  _mic_volume  = 0; 
-  _mic_volume_before_mute = 0;
+  _spkr_volume = 0; // Initialize after by init() -> initVolume()
+  _mic_volume  = 0;  // Initialize after by init() -> initVolume()
+  _mic_volume_before_mute = 0; 
 
   // Call
-  _currentCallId = 0;
   _nbIncomingWaitingCall=0;
   _registerState = UNREGISTERED;
   _hasTriedToRegister = false;
+
   // initialize random generator for call id
   srand (time(NULL));
 
@@ -156,8 +152,6 @@ ManagerImpl::init()
     _dtmfKey = new DTMF(sampleRate, outChannel);
   }
 
-  _debugInit("Adding new VoIP Link");
-
   // initRegisterVoIP was here, but we doing it after the gui loaded... 
   // the stun detection is long, so it's a better idea to do it after getEvents
   initZeroconf();
@@ -169,16 +163,6 @@ void ManagerImpl::terminate()
 
   unloadAccountMap();
 
-  _debug("Removing calls\n");
-  _mutex.enterMutex();
-  for(CallVector::iterator pos = _callVector.begin();
-      pos != _callVector.end();
-      pos++) {
-    delete *pos;   *pos = NULL;
-  }
-  _callVector.clear();
-  _mutex.leaveMutex();
-
   _debug("Unload DTMF Key\n");
   delete _dtmfKey;
 
@@ -189,230 +173,165 @@ void ManagerImpl::terminate()
   delete _telephoneTone; _telephoneTone = 0;
 }
 
-void
-ManagerImpl::setGui(GuiFramework* gui)
-{
-	_gui = gui;
-}
-
-/**
- * Multi Thread with _mutex for callVector
- */
-Call *
-ManagerImpl::pushBackNewCall(CALLID id, Call::CallType type)
-{
-  ost::MutexLock m(_mutex);
-
-  Call* call = new Call(id, type, getAccountLink(ACCOUNT_SIP0));
-  // Set the wanted voip-link (first of the list)
-  _callVector.push_back(call);
-  return call;
-}
-
-/**
- * Multi Thread with _mutex for callVector
- */
-Call*
-ManagerImpl::getCall(CALLID id)
-{
-  //_debug("%10d: Getting call\n", id);
-  Call* call = NULL;
-  unsigned int size = _callVector.size();
-  for (unsigned int i = 0; i < size; i++) {
-    call = _callVector.at(i);
-    if (call && call->getId() == id) {
-      break;
-    } else {
-      call = NULL;
-    }
-  }
-  return call;
+bool
+ManagerImpl::isCurrentCall(const CallID& callId) {
+  ost::MutexLock m(_currentCallMutex);
+  return (_currentCallId2 == callId ? true : false);
 }
 
-/**
- * Multi Thread with _mutex for callVector
- */
-void
-ManagerImpl::deleteCall (CALLID id)
-{
-  //_debug("%10d: Deleting call\n", id);
-  CallVector::iterator iter = _callVector.begin();
-  while(iter!=_callVector.end()) {
-    Call *call = *iter;
-    if (call != NULL && call->getId() == id) {
-      if (call->getFlagNotAnswered() && call->isIncomingType() && call->getState() != Call::NotExist) {
-        decWaitingCall();
-      }
-      delete (*iter); *iter = NULL; 
-      call = NULL;
-      _callVector.erase(iter);
-      return;
-    }
-    iter++;
+bool
+ManagerImpl::hasCurrentCall() {
+  ost::MutexLock m(_currentCallMutex);
+  if ( _currentCallId2 != "") {
+    return true;
   }
+  return false;
 }
 
-void
-ManagerImpl::setCurrentCallId(CALLID id)
-{
-  //_debug("%10d: Setting current callid, old one was: %d\n", id, _currentCallId);
-  _currentCallId = id;
+const CallID& 
+ManagerImpl::getCurrentCallId() {
+  ost::MutexLock m(_currentCallMutex);
+  return _currentCallId2;
 }
 
 void
-ManagerImpl::removeCallFromCurrent(CALLID id)
-{
-  if ( _currentCallId == id ) {
-    //_debug("%10d: Setting current callid, old one was: %d\n", 0, _currentCallId);
-    _currentCallId = 0;
-  }
+ManagerImpl::switchCall(const CallID& id ) {
+  ost::MutexLock m(_currentCallMutex);
+  _currentCallId2 = id;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // Management of events' IP-phone user
 ///////////////////////////////////////////////////////////////////////////////
-/**
- * Main thread
- */
-int 
-ManagerImpl::outgoingCall (const std::string& to)
-{
-  CALLID id = generateNewCallId();
-  _debug("%10d: Outgoing Call\n", id);
-  Call *call = pushBackNewCall(id, Call::Outgoing);
-  ost::MutexLock m(_mutex);
-  call->setState(Call::Progressing);
-  call->setCallerIdNumber(to);
-  if (call->outgoingCall(to) == 0) {
-    return id;
+/* Main Thread */ 
+bool
+ManagerImpl::outgoingCall(const std::string& accountid, const CallID& id, const std::string& to)
+{
+  if (!accountExists(accountid)) {
+    _debug("Outgoing Call: account doesn't exist\n");
+    return false;
+  }
+  if (getAccountFromCall(id) != AccountNULL) {
+    _debug("Outgoing Call: call id already exists\n");
+    return false;
+  }
+  _debug("Adding Outgoing Call %s on account %s\n", id.data(), accountid.data());
+  if ( getAccountLink(accountid)->newOutgoingCall(id, to) ) {
+    associateCallToAccount( id, accountid );
+    switchCall(id);
+    return true;
   } else {
-    return 0;
+    _debug("An error occur, the call was not created\n");
   }
+  return false;
 }
 
-/**
- * Main thread
- */
-bool 
-ManagerImpl::sendTextMessage(const std::string&, const std::string& to, const std::string& message) 
+//THREAD=Main : for outgoing Call
+bool
+ManagerImpl::answerCall(const CallID& id)
 {
-  return getAccountLink(ACCOUNT_SIP0)->sendMessage(to, message);
-}
+  stopTone(); 
 
-/**
- * User action (main thread)
- * Every Call
- */
-int 
-ManagerImpl::hangupCall (CALLID id)
-{
-  _debug("%10d: Hangup Call\n", id);
-  stopTone();
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call == NULL) {
-    return -1;
-  }
-  int result = -1;
-  if (call->getState() != Call::Error) { 
-    result = call->hangup();
+  AccountID accountid = getAccountFromCall( id );
+  if (accountid == AccountNULL) {
+    _debug("Answering Call: Call doesn't exists\n");
+    return false;
   }
-  deleteCall(id);
-  // current call id or no line selected
-  if (id == _currentCallId || _currentCallId == 0) {
-    removeCallFromCurrent(id);
+
+  if (!getAccountLink(accountid)->answer(id)) {
+    // error when receiving...
+    removeCallAccount(id);
+    return false;
   }
-  return result;
+
+  // if it was waiting, it's waiting no more
+  removeWaitingCall(id);
+  switchCall(id);
+  return true;
 }
 
-/**
- * User action (main thread)
- * Every Call
- * -1 : call not found
- *  0 : already in this state...
- */
-int
-ManagerImpl::cancelCall (CALLID id)
+//THREAD=Main
+bool 
+ManagerImpl::sendTextMessage(const AccountID& accountId, const std::string& to, const std::string& message) 
 {
-  _debug("%10d: Cancel Call\n", id);
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call == NULL) { 
-    return -1; 
+  if (accountExists(accountId)) {
+    return getAccountLink(accountId)->sendMessage(to, message);
   }
-  int result = call->cancel();
-  deleteCall(id);
-  stopTone();
-  return result;
+  return false;
 }
 
-/**
- * User action (main thread)
- * Incoming Call
- */
-int 
-ManagerImpl::answerCall (CALLID id)
+//THREAD=Main
+bool
+ManagerImpl::hangupCall(const CallID& id)
 {
-  _debug("%10d: Answer Call\n", id);
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call == NULL) {
-    return -1;
-  }
-  if (call->getFlagNotAnswered()) {
-    decWaitingCall();
-    call->setFlagNotAnswered(false);
-  }
-  if (call->getState() != Call::OnHold) {
-    switchCall(id);
+  stopTone();
+
+  AccountID accountid = getAccountFromCall( id );
+  if (accountid == AccountNULL) {
+    _debug("Hangup Call: Call doesn't exists\n");
+    return false;
   }
-  stopTone(); // before answer, don't stop the audio stream after open it
-  return call->answer();
+
+  bool returnValue = getAccountLink(accountid)->hangup(id);
+  removeCallAccount(id);
+  switchCall("");
+
+  return returnValue;
 }
 
-/**
- * User action (main thread)
- * Every Call
- * @return 0 if it fails, -1 if not present
- */
-int 
-ManagerImpl::onHoldCall (CALLID id)
+//THREAD=Main
+bool
+ManagerImpl::cancelCall (const CallID& id)
 {
-  _debug("%10d: On Hold Call\n", id);
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call == NULL) {
-    return -1;
-  }
-  removeCallFromCurrent(id);
-  if ( call->getState() == Call::OnHold || call->isNotAnswered()) {
-    return 1;
+  stopTone();
+  AccountID accountid = getAccountFromCall( id );
+  if (accountid == AccountNULL) {
+    _debug("Cancel Call: Call doesn't exists\n");
+    return false;
   }
-  return call->onHold();
+
+  bool returnValue = getAccountLink(accountid)->cancel(id);
+  // it could be a waiting call?
+  removeWaitingCall(id);
+  removeCallAccount(id);
+  switchCall("");
+  
+  return returnValue;
 }
 
-/**
- * User action (main thread)
- * Every Call
- */
-int 
-ManagerImpl::offHoldCall (CALLID id)
+//THREAD=Main
+bool
+ManagerImpl::onHoldCall(const CallID& id)
 {
-  _debug("%10d: Off Hold Call\n", id);
-  ost::MutexLock m(_mutex);
   stopTone();
-  Call* call = getCall(id);
-  if (call == 0) {
-    return -1;
+  AccountID accountid = getAccountFromCall( id );
+  if (accountid == AccountNULL) {
+    _debug("On Hold Call: Call doesn't exists\n");
+    return false;
   }
-  if (call->getState() == Call::OffHold) {
-    return 1;
+
+  bool returnValue = getAccountLink(accountid)->onhold(id);
+  removeWaitingCall(id);
+  switchCall("");
+  
+  return returnValue;
+}
+
+//THREAD=Main
+bool
+ManagerImpl::offHoldCall(const CallID& id)
+{
+  stopTone();
+  AccountID accountid = getAccountFromCall( id );
+  if (accountid == AccountNULL) {
+    _debug("OffHold Call: Call doesn't exists\n");
+    return false;
   }
-  setCurrentCallId(id);
-  int returnValue = call->offHold();
-  // start audio if it's ok
-  if (returnValue != -1) {
+  bool returnValue = getAccountLink(accountid)->offhold(id);
+  switchCall(id);
+
+  if (returnValue) {
     try {
       getAudioDriver()->startStream();
     } catch(...) {
@@ -422,37 +341,32 @@ ManagerImpl::offHoldCall (CALLID id)
   return returnValue;
 }
 
-/**
- * User action (main thread)
- * Every Call
- */
-int 
-ManagerImpl::transferCall (CALLID id, const std::string& to)
+//THREAD=Main
+bool
+ManagerImpl::transferCall(const CallID& id, const std::string& to)
 {
-  _debug("%10d: Transfer Call to %s\n", id, to.c_str());
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call == 0) {
-    return -1;
+  stopTone();
+  AccountID accountid = getAccountFromCall( id );
+  if (accountid == AccountNULL) {
+    _debug("Transfer Call: Call doesn't exists\n");
+    return false;
   }
-  removeCallFromCurrent(id);
-  return call->transfer(to);
+  bool returnValue = getAccountLink(accountid)->transfer(id, to);
+  removeWaitingCall(id);
+  removeCallAccount(id);
+  switchCall("");
+
+  return returnValue;
 }
 
-/**
- * User action (main thread)
- * All Call
- */
+//THREAD=Main
 void
 ManagerImpl::mute() {
   _mic_volume_before_mute = _mic_volume;
   setMicVolume(0);
 }
 
-/**
- * User action (main thread)
- * All Call
- */
+//THREAD=Main
 void
 ManagerImpl::unmute() {
   if ( _mic_volume == 0 ) {
@@ -460,34 +374,24 @@ ManagerImpl::unmute() {
   }
 }
 
-/**
- * User action (main thread)
- * Call Incoming
- */
-int 
-ManagerImpl::refuseCall (CALLID id)
+//THREAD=Main : Call:Incoming
+bool
+ManagerImpl::refuseCall (const CallID& id)
 {
-  _debug("%10d: Refuse Call\n", id);
-  ost::MutexLock m(_mutex);
-  Call *call = getCall(id);
-  if (call == NULL) {
-    return -1;
-  }
-
-  if ( call->getState() != Call::Progressing ) {
-    return -1;
-  }
-
-  int refuse = call->refuse();
-  removeCallFromCurrent(id);
-  deleteCall(id);
   stopTone();
-  return refuse;
+  AccountID accountid = getAccountFromCall( id );
+  if (accountid == AccountNULL) {
+    _debug("OffHold Call: Call doesn't exists\n");
+    return false;
+  }
+  bool returnValue = getAccountLink(accountid)->refuse(id);
+  removeWaitingCall(id);
+  removeCallAccount(id);
+  switchCall("");
+  return returnValue;
 }
 
-/**
- * User action (main thread)
- */
+//THREAD=Main
 bool
 ManagerImpl::saveConfig (void)
 {
@@ -499,73 +403,67 @@ ManagerImpl::saveConfig (void)
   return _setupLoaded;
 }
 
-/**
- * Main Thread
- */
+//THREAD=Main
 bool
 ManagerImpl::initRegisterVoIPLink() 
 {
-  int returnValue = true;
-  _debugInit("Initiate VoIP Link Registration\n");
-  if (_hasTriedToRegister == false) {
-    if ( getAccount(ACCOUNT_SIP0)->init() ) { 
-      // we call here, because it's long...
-      // If network is available and exosip is start..
-      if (getConfigInt(SIGNALISATION, AUTO_REGISTER) && _exist == 1) {
-        registerVoIPLink();
-        _hasTriedToRegister = true;
+  _debugInit("Initiate VoIP Links Registration\n");
+  AccountMap::iterator iter = _accountMap.begin();
+  while( iter != _accountMap.end() ) {
+    if ( iter->second) {
+      iter->second->loadConfig();
+      if ( iter->second->shouldInitOnStart() ) {
+        iter->second->init();
+        if (iter->second->shouldRegisterOnStart()) {
+          iter->second->registerAccount();
+        }
       }
-    } else {
-      returnValue = false;
     }
+    iter++;
   }
-  return returnValue;
+  return true;
 }
 
-
-/**
- * Initialize action (main thread)
- * Note that Registration is only send if STUN is not activated
- * @return true if setRegister is call without failure, else return false
- */
+//THREAD=Main
 bool
-ManagerImpl::registerVoIPLink (void)
+ManagerImpl::registerVoIPLink(const AccountID& accountId)
 {
   _debug("Register VoIP Link\n");
   int returnValue = false;
-  returnValue = getAccount(ACCOUNT_SIP0)->registerAccount();
-  if (returnValue) {
-    _registerState = REGISTERED;
-  } else {
-    _registerState = FAILED;
+  if (accountExists( accountId ) ) {
+    returnValue = getAccount(accountId)->registerAccount();
   }
   return returnValue;
 }
 
-/**
- * Terminate action (main thread)
- * @return true if the unregister method is send correctly
- */
+//THREAD=Main
 bool 
-ManagerImpl::unregisterVoIPLink (void)
+ManagerImpl::unregisterVoIPLink(const AccountID& accountId)
 {
   _debug("Unregister VoIP Link\n");
-	return getAccount(ACCOUNT_SIP0)->unregisterAccount();
+  int returnValue = false;
+  if (accountExists( accountId ) ) {
+    returnValue = getAccount(accountId)->registerAccount();
+  }
+  return returnValue;
 }
 
-/**
- * User action (main thread)
- */
+//THREAD=Main
 bool 
-ManagerImpl::sendDtmf (CALLID id, char code)
+ManagerImpl::sendDtmf(const CallID& id, char code)
 {
+  AccountID accountid = getAccountFromCall( id );
+  if (accountid == AccountNULL) {
+    _debug("Send DTMF: call doesn't exists\n");
+    return false;
+  }
+
   int sendType = getConfigInt(SIGNALISATION, SEND_DTMF_AS);
-  int returnValue = false;
+  bool returnValue = false;
   switch (sendType) {
   case 0: // SIP INFO
     playDtmf(code);
-    getAccountLink(ACCOUNT_SIP0)->carryingDTMFdigits(id, code);
-    returnValue = true;
+    returnValue = getAccountLink(accountid)->carryingDTMFdigits(id, code);
     break;
 
   case 1: // Audio way
@@ -578,10 +476,7 @@ ManagerImpl::sendDtmf (CALLID id, char code)
   return returnValue;
 }
 
-/**
- * User action (main thread)
- * Or sip event (dtmf body submit)
- */
+//THREAD=Main | VoIPLink
 bool
 ManagerImpl::playDtmf(char code)
 {
@@ -595,7 +490,6 @@ ManagerImpl::playDtmf(char code)
 
   // numbers of int = length in milliseconds / 1000 (number of seconds)
   //                = number of seconds * SAMPLING_RATE by SECONDS
-
   AudioLayer* audiolayer = getAudioDriver();
 
   // fast return, no sound, so no dtmf
@@ -634,264 +528,158 @@ ManagerImpl::playDtmf(char code)
   return returnValue;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Management of event peer IP-phone 
-////////////////////////////////////////////////////////////////////////////////
-/**
- * Multi-thread
- */
+
+
+// Multi-thread 
 bool
 ManagerImpl::incomingCallWaiting() {
-  ost::MutexLock m(_incomingCallMutex);
+  ost::MutexLock m(_waitingCallMutex);
   return (_nbIncomingWaitingCall > 0) ? true : false;
 }
 
 void
-ManagerImpl::incWaitingCall() {
-  ost::MutexLock m(_incomingCallMutex);
+ManagerImpl::addWaitingCall(const CallID& id) {
+  ost::MutexLock m(_waitingCallMutex);
+  _waitingCall.insert(id);
   _nbIncomingWaitingCall++;
-  //_debug("incWaitingCall: %d\n", _nbIncomingWaitingCall);
-}
-
-void
-ManagerImpl::decWaitingCall() {
-  ost::MutexLock m(_incomingCallMutex);
-  _nbIncomingWaitingCall--;
-  //_debug("decWaitingCall: %d\n", _nbIncomingWaitingCall);
 }
 
-
-/**
- * SipEvent Thread
- * Set the call info for incoming call
- */
 void
-ManagerImpl::callSetInfo(CALLID id, const std::string& name, const std::string& number)
-{
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call != 0) {
-    call->setCallerIdName(name);
-    call->setCallerIdNumber(number);
+ManagerImpl::removeWaitingCall(const CallID& id) {
+  ost::MutexLock m(_waitingCallMutex);
+  // should return more than 1 if it erase a call
+  if (_waitingCall.erase(id)) {
+    _nbIncomingWaitingCall--;
   }
 }
 
-/**
- * SipEvent Thread
- * ask if it can close the call
- */
 bool
-ManagerImpl::callCanBeClosed(CALLID id) {
-  bool returnValue = false;
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call != NULL && call->getState() != Call::Progressing) {
-    returnValue = true;
+ManagerImpl::isWaitingCall(const CallID& id) {
+  ost::MutexLock m(_waitingCallMutex);
+  CallIDSet::iterator iter = _waitingCall.find(id);
+  if (iter != _waitingCall.end()) {
+    return false;
   }
-  return returnValue;
+  return true;
 }
 
-/**
- * SipEvent Thread
- * ask if it can answer the call
- */
-bool
-ManagerImpl::callCanBeAnswered(CALLID id) {
-  bool returnValue = false;
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call != NULL && ( call->getFlagNotAnswered() || 
-       (call->getState()!=Call::OnHold && call->getState()!=Call::OffHold) )) {
-    returnValue = true;
-  }
-  return returnValue;
-}
 
-/**
- * SipEvent Thread
- * ask if it can start the sound thread
- */
-bool
-ManagerImpl::callIsOnHold(CALLID id) {
-  bool returnValue = false;
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call != NULL && (call->getState()==Call::OnHold)) {
-    returnValue = true;
-  }
-  return returnValue;
-}
 
-/**
- * SipEvent Thread
- */
-int 
-ManagerImpl::incomingCall (CALLID id, const std::string& name, const std::string& number)
+///////////////////////////////////////////////////////////////////////////////
+// Management of event peer IP-phone 
+////////////////////////////////////////////////////////////////////////////////
+// SipEvent Thread 
+bool 
+ManagerImpl::incomingCall(Call* call, const AccountID& accountId) 
 {
-  _debug("%10d: Incoming call\n", id);
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call == NULL) {
-    return -1;
-  }
-  call->setType(Call::Incoming);
-  call->setState(Call::Progressing);
-
-  if ( _currentCallId == 0 ) {
-    call->setFlagNotAnswered(false);
+  _debug("Incoming call\n");
+  associateCallToAccount(call->getCallId(), accountId);
+  if ( !hasCurrentCall() ) {
+    call->setConnectionState(Call::Ringing);
     ringtone();
-    switchCall(id);
+    switchCall(call->getCallId());
   } else {
-    incWaitingCall();
+     addWaitingCall(call->getCallId());
   }
 
-  // TODO: Account not yet implemented
-  std::string accountId = "acc1";
-  std::string from = name;     call->setCallerIdName(name);
-  call->setCallerIdNumber(number);
+  std::string from = call->getPeerName();
+  std::string number = call->getPeerNumber();
+
   if ( !number.empty() ) {
     from.append(" <");
     from.append(number);
     from.append(">");
   }
-  return _gui->incomingCall(id, accountId, from);
+  _gui->incomingCall(accountId, call->getCallId(), from);
+
+  return true;
 }
 
-/**
- * SipEvent Thread
- * for outgoing message, send by SipEvent
- */
-void 
-ManagerImpl::incomingMessage(const std::string& message) {
+//THREAD=VoIP
+void
+ManagerImpl::incomingMessage(const AccountID& accountId, const std::string& message) {
   if (_gui) {
-    _gui->incomingMessage(message);
+    _gui->incomingMessage(accountId, message);
   }
 }
 
-/**
- * SipEvent Thread
- * for outgoing call, send by SipEvent
- */
-void 
-ManagerImpl::peerAnsweredCall (CALLID id)
+//THREAD=VoIP CALL=Outgoing
+void
+ManagerImpl::peerAnsweredCall(const CallID& id)
 {
-  _debug("%10d: Peer Answered Call\n", id);
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call != 0) {
-    call->setFlagNotAnswered(false);
-    call->setState(Call::Answered);
-
+  if (isCurrentCall(id)) {
     stopTone();
-    // switch current call
-    switchCall(id);
-    if (_gui) _gui->peerAnsweredCall(id);
   }
+  if (_gui) _gui->peerAnsweredCall(id);
 }
 
-/**
- * SipEvent Thread
- * for outgoing call, send by SipEvent
- */
-int
-ManagerImpl::peerRingingCall (CALLID id)
+//THREAD=VoIP Call=Outgoing
+void
+ManagerImpl::peerRingingCall(const CallID& id)
 {
-  _debug("%10d: Peer Ringing Call\n", id);
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call != 0) {
-    call->setState(Call::Ringing);
-
-    // ring
+  if (isCurrentCall(id)) {
     ringback();
-    if (_gui) _gui->peerRingingCall(id);
   }
-  return 1;
+  if (_gui) _gui->peerRingingCall(id);
 }
 
-/**
- * SipEvent Thread
- * for outgoing call, send by SipEvent
- */
-int 
-ManagerImpl::peerHungupCall (CALLID id)
+//THREAD=VoIP Call=Outgoing/Ingoing
+void
+ManagerImpl::peerHungupCall(const CallID& id)
 {
-  _debug("%10d: Peer Hungup Call\n", id);
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if ( call == NULL ) {
-    return -1;
+  AccountID accountid = getAccountFromCall( id );
+  if (accountid == AccountNULL) {
+    _debug("peerHungupCall: Call doesn't exists\n");
+    return;
   }
-  if ( _currentCallId == id ) {
+  if (isCurrentCall(id)) {
     stopTone();
+    switchCall("");
   }
-
-  if (_gui) _gui->peerHungupCall(id);
-  deleteCall(id);
-  call->setState(Call::Hungup);
-
-  removeCallFromCurrent(id);
-  return 1;
+  removeWaitingCall(id);
+  removeCallAccount(id);
 }
 
-/**
- * Multi Thread
- */
+//THREAD=VoIP
 void
-ManagerImpl::callBusy(CALLID id) {
-  _debug("%10d: Call is busy\n", id);
-  playATone(Tone::TONE_BUSY);
-  ost::MutexLock m(_mutex);
-  Call* call = getCall(id);
-  if (call != 0) {
-    call->setState(Call::Busy);
+ManagerImpl::callBusy(const CallID& id) {
+  _debug("Call busy\n");
+  if (isCurrentCall(id) ) {
+    playATone(Tone::TONE_BUSY);
+    switchCall("");
   }
-  deleteCall(id);
-  call->setState(Call::Hungup);
-
-  removeCallFromCurrent(id);
+  removeCallAccount(id);
+  removeWaitingCall(id);
 }
 
-/**
- * Multi Thread
- */
+//THREAD=VoIP
 void
-ManagerImpl::callFailure(CALLID id) {
-  _debug("%10d: Call failed\n", id);
-  playATone(Tone::TONE_BUSY);
-  _mutex.enterMutex();
-  Call* call = getCall(id);
-  if (call != 0) {
-    call->setState(Call::Error);
-  }
-  _mutex.leaveMutex();
+ManagerImpl::callFailure(const CallID& id) 
+{
+  _debug("Call failed\n");
+  if (isCurrentCall(id) ) {
+    playATone(Tone::TONE_BUSY);
+    switchCall("");
+  }
   if (_gui) {
     _gui->callFailure(id);
   }
-  deleteCall(id);
-  call->setState(Call::Hungup);
-
-  removeCallFromCurrent(id);
+  removeCallAccount(id);
+  removeWaitingCall(id);
 }
 
-/**
- * SipEvent Thread
- * for outgoing call, send by SipEvent
- */
+//THREAD=VoIP
 void 
-ManagerImpl::displayTextMessage (CALLID id, const std::string& message)
+ManagerImpl::displayTextMessage(const CallID& id, const std::string& message)
 {
   if(_gui) {
-    _gui->displayTextMessage(id, message);
+   _gui->displayTextMessage(id, message);
   }
 }
 
-/**
- * SipEvent Thread
- * for outgoing call, send by SipEvent
- */
+//THREAD=VoIP
 void 
-ManagerImpl::displayErrorText (CALLID id, const std::string& message)
+ManagerImpl::displayErrorText(const CallID& id, const std::string& message)
 {
   if(_gui) {
     _gui->displayErrorText(id, message);
@@ -900,10 +688,7 @@ ManagerImpl::displayErrorText (CALLID id, const std::string& message)
   }
 }
 
-/**
- * SipEvent Thread
- * for outgoing call, send by SipEvent
- */
+//THREAD=VoIP
 void 
 ManagerImpl::displayError (const std::string& error)
 {
@@ -912,22 +697,16 @@ ManagerImpl::displayError (const std::string& error)
   }
 }
 
-/**
- * SipEvent Thread
- * for outgoing call, send by SipEvent
- */
+//THREAD=VoIP
 void 
-ManagerImpl::displayStatus (const std::string& status)
+ManagerImpl::displayStatus(const std::string& status)
 {
   if(_gui) {
     _gui->displayStatus(status);
   }
 }
 
-/**
- * SipEvent Thread
- * for outgoing call, send by SipEvent
- */
+//THREAD=VoIP
 void 
 ManagerImpl::displayConfigError (const std::string& message)
 {
@@ -936,42 +715,32 @@ ManagerImpl::displayConfigError (const std::string& message)
   }
 }
 
-/**
- * SipEvent Thread
- * for outgoing call, send by SipEvent
- */
+//THREAD=VoIP
 void
-ManagerImpl::startVoiceMessageNotification (const std::string& nb_msg)
+ManagerImpl::startVoiceMessageNotification(const AccountID& accountId, const std::string& nb_msg)
 {
-  if (_gui) _gui->sendVoiceNbMessage(nb_msg);
+  if (_gui) _gui->sendVoiceNbMessage(accountId, nb_msg);
 }
 
-/**
- * SipEvent Thread
- * for outgoing call, send by SipEvent
- */
+//THREAD=VoIP
 void
-ManagerImpl::stopVoiceMessageNotification (void)
+ManagerImpl::stopVoiceMessageNotification(const AccountID& accountId)
 {
-  if (_gui) _gui->sendVoiceNbMessage(std::string("0"));
+  if (_gui) _gui->sendVoiceNbMessage(accountId, std::string("0"));
 }
 
-/**
- * SipEvent Thread
- */
+//THREAD=VoIP
 void 
-ManagerImpl::registrationSucceed()
+ManagerImpl::registrationSucceed(const AccountID& accountid)
 {
-  if (_gui) _gui->sendRegistrationState(true);
+  if (_gui) _gui->sendRegistrationState(accountid, true);
 }
 
-/**
- * SipEvent Thread
- */
+//THREAD=VoIP
 void 
-ManagerImpl::registrationFailed()
+ManagerImpl::registrationFailed(const AccountID& accountid)
 {
-  if (_gui) _gui->sendRegistrationState(false);
+  if (_gui) _gui->sendRegistrationState(accountid, false);
 }
 
 /**
@@ -1109,7 +878,7 @@ ManagerImpl::getTelephoneFile()
  * By AudioRTP thread
  */
 void
-ManagerImpl::notificationIncomingCall (void) {
+ManagerImpl::notificationIncomingCall(void) {
 
   AudioLayer* audiolayer = getAudioDriver();
   if (audiolayer != 0) {
@@ -1123,7 +892,6 @@ ManagerImpl::notificationIncomingCall (void) {
     tone.getNext(buf, tone.getSize());
     audiolayer->putUrgent(buf, sizeof(int16)*nbInt16);
   }
-
 }
 
 /**
@@ -1158,37 +926,30 @@ ManagerImpl::getStunInfo (StunAddress4& stunSvrAddr, int port)
 }
 
 bool
-ManagerImpl::useStun (void) 
-{
-  if (getConfigInt(SIGNALISATION, USE_STUN)) {
-      return true;
-  } else {
-      return false;
+ManagerImpl::behindNat(int port)
+{
+  StunAddress4 stunSvrAddr;
+  stunSvrAddr.addr = 0;
+  
+  // Stun server
+  std::string svr = getConfigString(SIGNALISATION, STUN_SERVER);
+  
+  // Convert char* to StunAddress4 structure
+  bool ret = stunParseServerName ((char*)svr.data(), stunSvrAddr);
+  if (!ret) {
+    _debug("SIP: Stun server address (%s) is not valid\n", svr.data());
+    return 0;
   }
+  
+  // Firewall address
+  //_debug("STUN server: %s\n", svr.data());
+  return getStunInfo(stunSvrAddr, port);
 }
 
+
 ///////////////////////////////////////////////////////////////////////////////
 // Private functions
 ///////////////////////////////////////////////////////////////////////////////
-
-/**
- * Multi Thread
- */
-CALLID 
-ManagerImpl::generateNewCallId (void)
-{
-  CALLID random_id = (unsigned)rand();
-
-  // Check if already a call with this id exists 
-  _mutex.enterMutex();
-  while (getCall(random_id) != NULL && random_id != 0) {
-    random_id = rand();
-  }
-  _mutex.leaveMutex();
-  // If random_id is not attributed, returns it.
-  return random_id;
-}
-
 /**
  * Initialization: Main Thread
  * @return 1: ok
@@ -1357,7 +1118,7 @@ ManagerImpl::initZeroconf(void)
 void
 ManagerImpl::initVolume()
 {
-  _debugInit("Initiate Volume\n");
+  _debugInit("Initiate Volume");
   setSpkrVolume(getConfigInt(AUDIO, VOLUME_SPKR));
   setMicVolume(getConfigInt(AUDIO, VOLUME_MICRO));
 }
@@ -1453,58 +1214,68 @@ ManagerImpl::getEvents() {
   return true;
 }
 
+// TODO: rewrite this
 /**
  * Main Thread
  */
 bool 
 ManagerImpl::getCallStatus(const std::string& sequenceId)
 {
-  // TODO: implement account
-  std::string accountId = "acc1"; 
+  if (!_gui) { return false; }
+  ost::MutexLock m(_callAccountMapMutex);
+  CallAccountMap::iterator iter = _callAccountMap.begin();
+  TokenList tk;
   std::string code;
   std::string status;
-  TokenList tk;
-  Call* call;
-
-  if (_gui!=NULL) {
-    ost::MutexLock m(_mutex);
-    CallVector::iterator iter = _callVector.begin();
-    while(iter!=_callVector.end()){
-      call = (*iter);
-      switch( call->getState() ) {
-       case Call::Progressing: code="110"; status="Trying";        break;
-       case Call::Ringing:     code="111"; status = "Ringing";     break;
-       case Call::Answered:    code="112"; status = "Established"; break;
-       case Call::Busy:        code="113"; status = "Busy";        break;
-       case Call::OnHold:      code="114"; status = "Held";        break;
-       case Call::OffHold:     code="115"; status = "Unheld";      break;
-       default:                code="125"; status="Other";    
+  std::string destination;  
+  std::string number;
+
+  while (iter != _callAccountMap.begin())
+  {
+    Call* call = getAccountLink(iter->second)->getCall(iter->first);
+    Call::ConnectionState state = call->getConnectionState();
+    if (state != Call::Connected) {
+      switch(state) {
+        case Call::Trying:       code="110"; status = "Trying";       break;
+        case Call::Ringing:      code="111"; status = "Ringing";      break;
+        case Call::Progressing:  code="125"; status = "Progressing";  break;
+        case Call::Disconnected: code="125"; status = "Disconnected"; break;
+        default: code=""; status= "";
       }
-
-      // No Congestion
-      // No Wrong Number
-      // 116 <CSeq> <call-id> <acc> <destination> Busy
-      std::string destination = call->getCallerIdName();
-      std::string number = call->getCallerIdNumber();
-      if (number!="") {
-        destination.append(" <");
-        destination.append(number);
-        destination.append(">");
+    } else {
+      switch (call->getState()) {
+        case Call::Active:       code="112"; status = "Established";  break;
+        case Call::Hold:         code="114"; status = "Held";         break;
+        case Call::Busy:         code="113"; status = "Busy";         break;
+        case Call::Refused:      code="125"; status = "Refused";      break;
+        case Call::Error:        code="125"; status = "Error";        break;
+        case Call::Inactive:     code="125"; status = "Inactive";     break;
       }
-      tk.push_back(accountId);
-      tk.push_back(destination);
-      tk.push_back(status);
-      _gui->sendCallMessage(code, sequenceId, (*iter)->getId(), tk);
-      iter++;
-      tk.clear();
     }
+
+    // No Congestion
+    // No Wrong Number
+    // 116 <CSeq> <call-id> <acc> <destination> Busy
+    destination = call->getPeerName();
+    number = call->getPeerNumber();
+    if (number!="") {
+      destination.append(" <");
+      destination.append(number);
+      destination.append(">");
+    }
+    tk.push_back(iter->second);
+    tk.push_back(destination);
+    tk.push_back(status);
+    _gui->sendCallMessage(code, sequenceId, iter->first, tk);
+    tk.clear();
+
+    iter++;
   }
+  
   return true;
 }
 
-/**
- * Main Thread
- */
+//THREAD=Main
 bool 
 ManagerImpl::getConfigAll(const std::string& sequenceId)
 {
@@ -1521,18 +1292,14 @@ ManagerImpl::getConfigAll(const std::string& sequenceId)
   return returnValue;
 }
 
-/**
- * Main Thread
- */
+//THREAD=Main
 bool 
 ManagerImpl::getConfig(const std::string& section, const std::string& name, TokenList& arg)
 {
   return _config.getConfigTreeItemToken(section, name, arg);
 }
 
-/**
- * Main Thread
- */
+//THREAD=Main
 // throw an Conf::ConfigTreeItemException if not found
 int 
 ManagerImpl::getConfigInt(const std::string& section, const std::string& name)
@@ -1545,9 +1312,7 @@ ManagerImpl::getConfigInt(const std::string& section, const std::string& name)
   return 0;
 }
 
-/**
- * Main Thread
- */
+//THREAD=Main
 std::string 
 ManagerImpl::getConfigString(const std::string& section, const std::string&
 name)
@@ -1560,18 +1325,14 @@ name)
   return "";
 }
 
-/**
- * Main Thread
- */
+//THREAD=Main
 bool 
 ManagerImpl::setConfig(const std::string& section, const std::string& name, const std::string& value)
 {
   return _config.setConfigTreeItem(section, name, value);
 }
 
-/**
- * Main Thread
- */
+//THREAD=Main
 bool 
 ManagerImpl::setConfig(const std::string& section, const std::string& name, int value)
 {
@@ -1580,9 +1341,7 @@ ManagerImpl::setConfig(const std::string& section, const std::string& name, int
   return _config.setConfigTreeItem(section, name, valueStream.str());
 }
 
-/**
- * Main Thread
- */
+//THREAD=Main
 bool 
 ManagerImpl::getConfigList(const std::string& sequenceId, const std::string& name)
 {
@@ -1634,9 +1393,7 @@ ManagerImpl::getConfigList(const std::string& sequenceId, const std::string& nam
   return returnValue;
 }
 
-/**
- * User request Main Thread (list)
- */
+//THREAD=Main
 bool 
 ManagerImpl::getAudioDeviceList(const std::string& sequenceId, int ioDeviceMask) 
 {
@@ -1672,6 +1429,7 @@ ManagerImpl::getAudioDeviceList(const std::string& sequenceId, int ioDeviceMask)
   return returnValue;
 }
 
+//THREAD=Main
 bool
 ManagerImpl::getCountryTones(const std::string& sequenceId)
 {
@@ -1687,6 +1445,7 @@ ManagerImpl::getCountryTones(const std::string& sequenceId)
   return true;
 }
 
+//THREAD=Main
 void 
 ManagerImpl::sendCountryTone(const std::string& sequenceId, int index, const std::string& name) {
   TokenList tk;
@@ -1695,9 +1454,7 @@ ManagerImpl::sendCountryTone(const std::string& sequenceId, int index, const std
   _gui->sendMessage("100", sequenceId, tk);
 }
 
-/**
- * User action : main thread
- */
+//THREAD=Main
 bool
 ManagerImpl::getDirListing(const std::string& sequenceId, const std::string& path, int *nbFile) {
   TokenList tk;
@@ -1726,21 +1483,8 @@ ManagerImpl::getDirListing(const std::string& sequenceId, const std::string& pat
   }
 }
 
-/**
- * Multi Thread
- */
-void 
-ManagerImpl::switchCall(CALLID id)
-{
-  // we can only switch the current call id if we 
-  // it's not selected yet..
-  if (_currentCallId == 0 ) {
-    setCurrentCallId(id);
-  }
-}
-
-/**
- * Main Thread - Gui
+//THREAD=Main
+/*
  * Experimental...
  */
 bool
@@ -1781,7 +1525,7 @@ ManagerImpl::setSwitch(const std::string& switchName) {
 
 // ACCOUNT handling
 bool
-ManagerImpl::associateCallToAccount(CALLID callID, const AccountID& accountID)
+ManagerImpl::associateCallToAccount(const CallID& callID, const AccountID& accountID)
 {
   if (getAccountFromCall(callID) == AccountNULL) { // nothing with the same ID
     if (  accountExists(accountID)  ) { // account id exist in AccountMap
@@ -1797,7 +1541,7 @@ ManagerImpl::associateCallToAccount(CALLID callID, const AccountID& accountID)
 }
 
 AccountID
-ManagerImpl::getAccountFromCall(const CALLID callID)
+ManagerImpl::getAccountFromCall(const CallID& callID)
 {
   ost::MutexLock m(_callAccountMapMutex);
   CallAccountMap::iterator iter = _callAccountMap.find(callID);
@@ -1809,7 +1553,7 @@ ManagerImpl::getAccountFromCall(const CALLID callID)
 }
 
 bool
-ManagerImpl::removeCallAccount(CALLID callID)
+ManagerImpl::removeCallAccount(const CallID& callID)
 {
   ost::MutexLock m(_callAccountMapMutex);
   if ( _callAccountMap.erase(callID) ) {
@@ -1818,15 +1562,19 @@ ManagerImpl::removeCallAccount(CALLID callID)
   return false;
 }
 
-CALLID
+CallID 
 ManagerImpl::getNewCallID() 
 {
-  CALLID random_id = (unsigned)rand();
+  std::ostringstream random_id("s");
+  random_id << (unsigned)rand();
+  
   // when it's not found, it return ""
-  while (getAccountFromCall(random_id) != AccountNULL) {
-    random_id = rand();
+  while (getAccountFromCall(random_id.str()) != AccountNULL) {
+    random_id.clear();
+    random_id << "s";
+    random_id << (unsigned)rand();
   }
-  return random_id;
+  return random_id.str();
 }
 
 short
@@ -1837,7 +1585,7 @@ ManagerImpl::loadAccountMap()
   _accountMap[ACCOUNT_SIP0] = AccountCreator::createAccount(AccountCreator::SIP_ACCOUNT, ACCOUNT_SIP0);
   nbAccount++;
 
-  _accountMap[ACCOUNT_AIX0] = AccountCreator::createAccount(AccountCreator::AIX_ACCOUNT, ACCOUNT_AIX0);
+  _accountMap[ACCOUNT_IAX0] = AccountCreator::createAccount(AccountCreator::IAX_ACCOUNT, ACCOUNT_IAX0);
   nbAccount++;
 
   return nbAccount;
@@ -1907,7 +1655,7 @@ bool ManagerImpl::testCallAccountMap()
   if ( removeCallAccount(1) != false ) {
     _debug("TEST: removeCallAccount with empty list failed\n");
   }
-  CALLID newid = getNewCallID();
+  CallID newid = getNewCallID();
   if ( associateCallToAccount(newid, "acc0") == false ) {
     _debug("TEST: associateCallToAccount with new CallID empty list failed\n");
   }
@@ -1917,7 +1665,7 @@ bool ManagerImpl::testCallAccountMap()
   if ( getAccountFromCall( newid ) != "acc0" ) {
     _debug("TEST: getAccountFromCall don't return the good account id\n");
   }
-  CALLID secondnewid = getNewCallID();
+  CallID secondnewid = getNewCallID();
   if ( associateCallToAccount(secondnewid, "xxxx") == true ) {
     _debug("TEST: associateCallToAccount with unknown account id failed\n");
   }
diff --git a/src/managerimpl.h b/src/managerimpl.h
index 7e37bc9f56285865a4e6872d3a8c859ce17cee51..e47b2a4cca91c13f6996eb071a5faee744d84bc6 100644
--- a/src/managerimpl.h
+++ b/src/managerimpl.h
@@ -25,16 +25,17 @@
 
 #include <string>
 #include <vector>
+#include <set>
 #include <map>
 #include <cc++/thread.h>
 
 #include "stund/stun.h"
-#include "call.h"
 #include "observer.h"
 #include "config/config.h"
+
 #include "account.h"
+#include "call.h"
 
-//#include "audio/audiodevice.h"
 #include "audio/tonelist.h" // for Tone::TONEID declaration
 #include "audio/audiofile.h"
 #include "audio/dtmf.h"
@@ -42,44 +43,40 @@
 
 class AudioLayer;
 class CodecDescriptor;
-
 class GuiFramework;
-
 class TelephoneTone;
-
 class VoIPLink;
 
 #ifdef USE_ZEROCONF
 class DNSService;
 #endif
 
-#define	NOTIFICATION_LEN	250
 // Status
-#define CONNECTED_STATUS	"Connected"
-#define LOGGED_IN_STATUS	"Logged in"
-#define RINGING_STATUS		"Ringing"
-#define TRYING_STATUS		"Trying ..."
-#define HANGUP_STATUS       "Hang up"
-#define ONHOLD_STATUS       "On hold ..."
-#define TRANSFER_STATUS     "Transfer to:"
-#define MUTE_ON_STATUS		"Mute on"
-#define ENTER_NUMBER_STATUS "Enter Phone Number:"
+//#define CONNECTED_STATUS	"Connected"
+//#define LOGGED_IN_STATUS	"Logged in"
+//#define RINGING_STATUS		"Ringing"
+//#define TRYING_STATUS		"Trying ..."
+//#define HANGUP_STATUS       "Hang up"
+//#define ONHOLD_STATUS       "On hold ..."
+//#define TRANSFER_STATUS     "Transfer to:"
+//#define MUTE_ON_STATUS		"Mute on"
+//#define ENTER_NUMBER_STATUS "Enter Phone Number:"
 
-/*
- * Define a type for a list of call
+/**
+ * Define a type for a AccountMap container
  */
-typedef std::vector< Call* > CallVector;
-
+typedef std::map<AccountID, Account*> AccountMap;
+ 
 /**
  * Define a type for a CallID to AccountID Map inside ManagerImpl
  */
-typedef std::map<CALLID, AccountID> CallAccountMap;
+typedef std::map<CallID, AccountID> CallAccountMap;
 
 /**
- * Define a type for a AccountMap container
+ * Define a type for CallID vector (waiting list, incoming not answered)
  */
-typedef std::map<AccountID, Account*> AccountMap;
- 
+typedef std::set<CallID> CallIDSet;
+
 /**
  * To send multiple string
  */
@@ -91,87 +88,107 @@ public:
   ~ManagerImpl (void);
 
 	// Init a new VoIPLink, audio codec and audio driver
+  /**
+   * Initialisation of thread (sound) and map
+   */
   void init (void);
+
+  /**
+   * Terminate all thread (sound, link) and clear map
+   */
   void terminate (void);
 
-	// Set the graphic user interface
-  void setGui (GuiFramework* gui);
+  /**
+   * Set the graphic user interface : only GuiServer right now
+   * @param gui A GuiFramework gui implmentation
+   */
+  void setGui (GuiFramework* gui) { _gui = gui; }
 
 	// Accessor to audiodriver
-        // it's multi-thread and use mutex internally
+  // it's multi-thread and use mutex internally
   AudioLayer* getAudioDriver(void) const { return _audiodriverPA ;}
 
-  // Codec Descriptor
+  /**
+   * Get a descriptor map of codec available
+   */
   CodecDescriptorMap& getCodecDescriptorMap(void) {return _codecDescriptorMap;}
 
-  /* 
-   * Attribute a new random id for a new call 
-   * and check if it's already attributed to existing calls. 
-   * If not exists, returns 'id' otherwise return 0 
-   */ 
-  CALLID generateNewCallId (void);
-
-  /*
-   * Add a new call at the end of the CallVector with identifiant 'id'
-   */
-  Call* pushBackNewCall (CALLID id, Call::CallType type);
-  void callSetInfo(CALLID id, const std::string& name, const std::string& number);
-  bool callCanBeAnswered(CALLID id);
-  bool callCanBeClosed(CALLID id);
-  bool callIsOnHold(CALLID id);
-	
-  /*
+  /**
    * Functions which occur with a user's action
    */
-  int outgoingCall (const std::string& to);
-  int hangupCall (CALLID id);
-  int cancelCall (CALLID id);
-  int answerCall (CALLID id);
-  int onHoldCall (CALLID id);
-  int offHoldCall (CALLID id);
-  int transferCall (CALLID id, const std::string& to);
+  bool outgoingCall(const AccountID& accountId, const CallID& id, const std::string& to);
+  bool answerCall(const CallID& id);
+  bool hangupCall(const CallID& id);
+  bool cancelCall(const CallID& id);
+  bool onHoldCall(const CallID& id);
+  bool offHoldCall(const CallID& id);
+  bool transferCall(const CallID& id, const std::string& to);
   void mute();
   void unmute();
-  int refuseCall (CALLID id);
+  bool refuseCall(const CallID& id);
 
+  /** Save config on file */
   bool saveConfig (void);
-  bool registerVoIPLink (void);
-  bool unregisterVoIPLink (void);
+  /**
+  * Initialize action (main thread)
+  * @param accountId Account to register
+  * @return true if setRegister is call without failure, else return false
+  */
+  bool registerVoIPLink(const AccountID& accountId);
+  /**
+  * Unregister an account
+  * @param accountId Account to unregister
+  * @return true if the unregister method is send correctly
+  */
+  bool unregisterVoIPLink(const AccountID& accountId);
 
-  bool sendTextMessage(const std::string& account, const std::string& to, const std::string& message);
+  bool sendTextMessage(const AccountID& accountId, const std::string& to, const std::string& message);
 	
-  /**
+  /*
    * Handle choice of the DTMF-send-way
    *
    * @param   id: callid of the line.
    * @param   code: pressed key.
    */
-  bool sendDtmf (CALLID id, char code);
-  bool playDtmf (char code);
+  bool sendDtmf(const CallID& id, char code);
+  bool playDtmf(char code);
   bool playTone ();
   void stopTone();
-  CALLID getCurrentCallId() { ost::MutexLock m(_mutex); return _currentCallId; }
-
-  int incomingCall (CALLID id, const std::string& name, const std::string& number);
-  void peerAnsweredCall (CALLID id);
-  int peerRingingCall (CALLID id);
-  int peerHungupCall (CALLID id);
-  void incomingMessage(const std::string& message);
-
-  void displayTextMessage (CALLID id, const std::string& message);
-  void displayErrorText (CALLID id, const std::string& message);
-  void displayError (const std::string& error);
-  void displayStatus (const std::string& status);
+
+  // From links
+  /**
+   * When receiving a new incoming call, add it to the callaccount map
+   * and notify user
+   * @param call A call pointer
+   * @param accountid an account id
+   * @return true if the call was added correctly
+   */
+  bool incomingCall(Call* call, const AccountID& accountId);
+  void peerAnsweredCall(const CallID& id);
+  void peerRingingCall(const CallID& id);
+  void peerHungupCall(const CallID& id);
+  void incomingMessage(const AccountID& accountId, const std::string& message);
+
+  void displayTextMessage (const CallID& id, const std::string& message);
+  void displayErrorText (const CallID& id, const std::string& message);
+  void displayError(const std::string& error);
+  void displayStatus(const std::string& status);
   void displayConfigError(const std::string& message);
 
-  void startVoiceMessageNotification (const std::string& nb_msg);
-  void stopVoiceMessageNotification (void);
+  void startVoiceMessageNotification(const AccountID& accountId, const std::string& nb_msg);
+  void stopVoiceMessageNotification(const AccountID& accountId);
 
-  void registrationSucceed();
-  void registrationFailed();
+  /** Notify the user that registration succeeded  */
+  void registrationSucceed(const AccountID& accountId);
+  /** Notify the user that registration succeeded  */
+  void registrationFailed(const AccountID& accountId);
 
   // configuration function requests
+  /** Start events thread*/
+  // TODO: receive account name
   bool getEvents();
+
+  //
   bool getZeroconf(const std::string& sequenceId);
   bool attachZeroconfEvents(const std::string& sequenceId, Pattern::Observer& observer);
   bool detachZeroconfEvents(Pattern::Observer& observer);
@@ -182,30 +199,33 @@ public:
   bool setConfig(const std::string& section, const std::string& name, int value);
   bool getConfigList(const std::string& sequenceId, const std::string& name);
   void selectAudioDriver(void);
+  /** Set Audio Driver with switchName == audiodriver */
   bool setSwitch(const std::string& switchName);
 
   // configuration function for extern
   // throw an Conf::ConfigTreeItemException if not found
+  /** Get a int from the config tree */
   int getConfigInt(const std::string& section, const std::string& name);
+  /** Get a string from the config tree */
   std::string getConfigString(const std::string& section, const std::string& name);
 
-	/*
+	/**
 	 * Handle audio sounds heard by a caller while they wait for their 
 	 * connection to a called party to be completed.
 	 */
   void ringback ();
 
-	/*
+	/**
 	 * Handle played music when an incoming call occurs
 	 */
   void ringtone ();
   void congestion ();
-  void callBusy(CALLID id);
-  void callFailure(CALLID id);
+  void callBusy(const CallID& id);
+  void callFailure(const CallID& id);
 
-  // return 0 if no tone (init before calling this function)
+  /** @return 0 if no tone (init before calling this function) */
   AudioLoop* getTelephoneTone();
-  // return 0 if the wav is stopped
+  /** @return 0 if the wav is stopped */
   AudioLoop* getTelephoneFile();
 
   /**
@@ -213,20 +233,12 @@ public:
    * new call, not anwsered or refused
    */
   bool incomingCallWaiting(void);
-	/*
+	/**
 	 * Notification of incoming call when you are already busy
 	 */
-  void notificationIncomingCall (void);
+  void notificationIncomingCall(void);
+
 
-  /*
-   * Get information about firewall 
-   * @param  stunSvrAddr: stun server
-   * @param  port         port number to open to test the connection
-   * @return true if the connection is successful
-   */
-  bool getStunInfo(StunAddress4& stunSvrAddr, int port);
-  bool useStun (void);
-	
   /*
    * Inline functions to manage volume control
    * Read by main thread and AudioLayer thread
@@ -237,20 +249,40 @@ public:
   unsigned short getMicVolume(void) {  return _mic_volume;  }
   void setMicVolume(unsigned short mic_vol) {    _mic_volume = mic_vol;   }
 
+  // Manage information about firewall
   /*
-   * Manage information about firewall
+   * Get information about firewall 
+   * @param  stunSvrAddr: stun server
+   * @param  port         port number to open to test the connection
+   * @return true if the connection is successful
    */
+  bool getStunInfo(StunAddress4& stunSvrAddr, int port);
+
   inline int getFirewallPort 		(void) 		{ return _firewallPort; }
   inline void setFirewallPort 	(int port) 	{ _firewallPort = port; }
   inline std::string getFirewallAddress (void) 	{ return _firewallAddr; }
 
-	/*
+  /**
+   * If you are behind a NAT, you have to use STUN server, specified in 
+   * STUN configuration(you can change this one by default) to give you an 
+   * public IP address and assign a port number.
+   * Note: Set firewall port/address retreive
+         * @param port : on which port we want to listen to
+   * 
+   * Return true if we are behind a NAT (without error)
+   */
+  bool behindNat(int port);
+
+	/**
 	 * Init default values for the different fields
 	 */
   void initConfigFile (void);
+
+  /**
+   * Tell if the setup was already loaded
+   */
   bool hasLoadedSetup() { return _setupLoaded; }
 	
-
   enum REGISTRATION_STATE {
     UNREGISTERED,
     REGISTERED,
@@ -259,6 +291,24 @@ public:
 
   REGISTRATION_STATE getRegistrationState() { return _registerState; }
 
+  /** Return a new random callid that is not present in the list
+   * @return a brand new callid
+   */
+  CallID getNewCallID();
+
+  /**
+   * Get the current call id
+   * @return the call id or ""
+   */
+  const CallID& getCurrentCallId();
+
+  /**
+   * Check if a call is the current one
+   * @param id the new callid
+   * @return if the id is the current call
+   */
+  bool isCurrentCall(const CallID& callId);
+
 private:
  /**
   * Create .PROGNAME directory in home user and create 
@@ -304,14 +354,24 @@ private:
   bool getCountryTones(const std::string& sequenceId);
   void sendCountryTone(const std::string& sequenceId, int index, const std::string& name);
 
-  /*
-   * Erase the Call(id) from the CallVector
-   * Protected by other function by _mutex lock
+  /**
+   * Tell if there is a current call processed
+   * @return true if there is a current call
+   */
+  bool hasCurrentCall();
+
+  /**
+   * Switch of current call id
+   * @param id the new callid
    */
-  void deleteCall	(CALLID id);
-  Call* getCall (CALLID id);
-  void setCurrentCallId(CALLID id);
-  void removeCallFromCurrent(CALLID id);
+  void switchCall(const CallID& id);
+
+  /** Current Call ID */
+  CallID _currentCallId2;
+
+  /** Protected current call access */
+  ost::Mutex _currentCallMutex;
+
 
   /*
    * Play one tone
@@ -347,45 +407,41 @@ private:
   short _spkr_volume;
   short _mic_volume;
   short _mic_volume_before_mute;
-
-  //
   // End of sound variable
-  //
+
 
   // Multithread variable (protected by _mutex)
   // 
   /** Mutex to protect access to code section */
   ost::Mutex _mutex;
-  /* Vector of calls  */
-  CallVector _callVector;
-  // Current callid : protected implicitely by function using _mutex 
-  CALLID _currentCallId; 
-  // functions that set mutex:
-  //  terminate, pushBackNewCall, generateNewCallId, outgoingCall (after gen/push)
-  //  hangupCall, cancelCall, answerCall, onHoldCall, offHoldCall, transferCall, refuseCall, 
-  //  callSetInfo, callCanBeClosed, callCanBeAnswered, callIsOnHold, incomingCall,
-  //  peerAnsweredCall, peerRingingCall, peerHunguCall, callBusy, callFailure
-  //  getCallStatus, getCurrentCallId
-  // functions that are called by those functions
-  //  getCall, deleteCall, stopTone, switchCall, decWaitingCall, setCurrentCallId, getAudioDriver, ringtone, incWaitingCall
-
-  // warning, incomingCallWaiting | incWaitingCall | decWaitingCall are prtected by _incomingCallMutex
-  
 
   //
   // Multithread variable (non protected)
   //
   GuiFramework* _gui;
 
+  /** Waiting Call Vectors */
+  CallIDSet _waitingCall;
+  /** Protect waiting call list, access by many voip/audio threads */
+  ost::Mutex _waitingCallMutex;
+  /** Number of waiting call, synchronize with waitingcall callidvector */
+  unsigned int _nbIncomingWaitingCall;
   /**
-   * Multithreaded
-   * Incomings Call:
+   * Add incoming callid to the waiting list
+   * @param id CallID to add
    */
-  ost::Mutex _incomingCallMutex;
-  unsigned int _nbIncomingWaitingCall;
-  void incWaitingCall(void);
-  void decWaitingCall(void);
-	
+  void addWaitingCall(const CallID& id);
+  /**
+   * Remove incoming callid to the waiting list
+   * @param id CallID to remove
+   */
+  void removeWaitingCall(const CallID& id);
+  /**
+   * Tell if a call is waiting and should be remove
+   * @param id CallID to test
+   * @return true if the call is waiting
+   */
+  bool isWaitingCall(const CallID& id);
 
 	/**
    * Path of the ConfigFile 
@@ -401,13 +457,10 @@ private:
   // return false if exosip or the network checking failed
   bool initRegisterVoIPLink();
   // true if we tried to register Once
-  bool    _hasTriedToRegister;
+  bool _hasTriedToRegister;
   // Register state
   REGISTRATION_STATE _registerState;
 
-
-  void switchCall(CALLID id);
-
   // tell if we have zeroconf is enabled
   int _hasZeroconf;
 
@@ -417,8 +470,6 @@ private:
   DNSService *_DNSService;
 #endif
 
-// CALLID
-
   /** Map to associate a CallID to the good account */
   CallAccountMap _callAccountMap;
   /** Mutex to lock the call account map (main thread + voiplink thread) */
@@ -430,26 +481,21 @@ private:
    * @param accountID the known accountID present in accountMap
    * @return true if the new association is create
    */
-  bool associateCallToAccount(CALLID callID, const AccountID& accountID);
+  bool associateCallToAccount(const CallID& callID, const AccountID& accountID);
 
   /** Return the AccountID from a CallID
    * Protected by mutex
    * @param callID the CallID in the list
    * @return the accountID associated or "" if the callID is not found
    */
-  AccountID getAccountFromCall(const CALLID callID);
+  AccountID getAccountFromCall(const CallID& callID);
 
   /** Remove a CallID/AccountID association
    * Protected by mutex
    * @param callID the CallID to remove
    * @return true if association is removed
    */
-  bool removeCallAccount(CALLID callID);
-
-  /** Return a new random callid that is not present in the list
-   * @return a brand new callid
-   */
-  CALLID getNewCallID();
+  bool removeCallAccount(const CallID& callID);
 
   /** Contains a list of account (sip, aix, etc) and their respective voiplink/calls */
   AccountMap _accountMap;
diff --git a/src/sipaccount.cpp b/src/sipaccount.cpp
index 153d2d172fc9556edff9e1ac16d0666eefb05618..54d9d5cfad2a38e32703ad8e88526500a8f44126 100644
--- a/src/sipaccount.cpp
+++ b/src/sipaccount.cpp
@@ -18,14 +18,14 @@
  */
 #include "sipaccount.h"
 #include "sipvoiplink.h"
+#include "manager.h"
 
 #define SIP_FULL_NAME      "SIP.fullName"
 #define SIP_USER_PART      "SIP.userPart"
-#define SIP_AUTH_USER_NAME "SIP.username"
+#define SIP_AUTH_NAME      "SIP.username"
 #define SIP_PASSWORD       "SIP.password"
 #define SIP_HOST_PART      "SIP.hostPart"
 #define SIP_PROXY          "SIP.proxy"
-#define SIP_AUTO_REGISTER  "SIP.autoregister"
 #define SIP_STUN_SERVER    "STUN.STUNserver"
 #define SIP_USE_STUN       "STUN.useStun"
 
@@ -46,7 +46,8 @@ bool
 SIPAccount::createVoIPLink()
 {
   if (!_link) {
-    _link = new SipVoIPLink();
+  //_link = new SipVoIPLink();
+    _link = new SIPVoIPLink(_accountID);
   }
   return (_link != 0 ? true : false);
 }
@@ -55,7 +56,14 @@ bool
 SIPAccount::registerAccount()
 {
   if (_link && !_registered) {
-    _registered = (_link->setRegister() >= 0) ? true : false;
+    SIPVoIPLink* tmplink = dynamic_cast<SIPVoIPLink*> (_link);
+    if (tmplink) {
+      tmplink->setProxy(Manager::instance().getConfigString(_accountID,SIP_PROXY));
+      tmplink->setUserPart(Manager::instance().getConfigString(_accountID,SIP_USER_PART));
+      tmplink->setAuthName(Manager::instance().getConfigString(_accountID,SIP_AUTH_NAME));
+      tmplink->setPassword(Manager::instance().getConfigString(_accountID,SIP_PASSWORD));
+    }
+    _registered = _link->setRegister();
   }
   return _registered;
 }
@@ -64,7 +72,7 @@ bool
 SIPAccount::unregisterAccount()
 {
   if (_link && _registered) {
-    _registered = (_link->setUnregister() == 0) ? false : true;
+    _registered = _link->setUnregister();
   }
   return !_registered;
 }
@@ -73,6 +81,13 @@ bool
 SIPAccount::init()
 {
   if (_link && !_enabled) {
+    _link->setFullName(Manager::instance().getConfigString(_accountID,SIP_FULL_NAME));
+    _link->setHostName(Manager::instance().getConfigString(_accountID,SIP_HOST_PART));
+    int useStun = Manager::instance().getConfigInt(_accountID,SIP_USE_STUN);
+    SIPVoIPLink* tmplink = dynamic_cast<SIPVoIPLink*> (_link);
+    if (tmplink) {
+      tmplink->setUseStun( useStun!=0 ? true : false);
+    }
     _link->init();
     _enabled = true;
     return true;
@@ -102,10 +117,18 @@ SIPAccount::initConfig(Conf::ConfigTree& config)
   config.addConfigTreeItem(section, Conf::ConfigTreeItem(CONFIG_ACCOUNT_ENABLE,"1", type_int));
   config.addConfigTreeItem(section, Conf::ConfigTreeItem(SIP_FULL_NAME, "", type_str));
   config.addConfigTreeItem(section, Conf::ConfigTreeItem(SIP_USER_PART, "", type_str));
-  config.addConfigTreeItem(section, Conf::ConfigTreeItem(SIP_AUTH_USER_NAME, "", type_str));
+  config.addConfigTreeItem(section, Conf::ConfigTreeItem(SIP_HOST_PART, "", type_str));
+  config.addConfigTreeItem(section, Conf::ConfigTreeItem(SIP_AUTH_NAME, "", type_str));
+  config.addConfigTreeItem(section, Conf::ConfigTreeItem(SIP_PASSWORD, "", type_str));
   config.addConfigTreeItem(section, Conf::ConfigTreeItem(SIP_PROXY, "", type_str));
-  config.addConfigTreeItem(section, Conf::ConfigTreeItem(SIP_AUTO_REGISTER, "1", type_int));
+  config.addConfigTreeItem(section, Conf::ConfigTreeItem(CONFIG_ACCOUNT_AUTO_REGISTER, "1", type_int));
   config.addConfigTreeItem(section, Conf::ConfigTreeItem(SIP_STUN_SERVER, "stun.fwdnet.net:3478", type_str));
   config.addConfigTreeItem(section, Conf::ConfigTreeItem(SIP_USE_STUN, "0", type_int));
 }
 
+void
+SIPAccount::loadConfig() 
+{
+  _shouldInitOnStart = Manager::instance().getConfigInt(_accountID, CONFIG_ACCOUNT_ENABLE) ? true : false;
+  _shouldRegisterOnStart = Manager::instance().getConfigInt(_accountID, CONFIG_ACCOUNT_AUTO_REGISTER) ? true : false;
+}
diff --git a/src/sipaccount.h b/src/sipaccount.h
index 157c0ad51863f5defe0bcca5aad72baba527b493..c5da7b18fe833a28525af96b300d5dfcac390e8c 100644
--- a/src/sipaccount.h
+++ b/src/sipaccount.h
@@ -30,10 +30,11 @@ class SIPAccount : public Account
 public:
   SIPAccount(const AccountID& accountID);
 
-  ~SIPAccount();
+  virtual ~SIPAccount();
 
   /* virtual Account function implementation */
   void initConfig(Conf::ConfigTree& config);
+  void loadConfig();
   bool registerAccount();
   bool unregisterAccount();
   bool init();
diff --git a/src/sipcall.cpp b/src/sipcall.cpp
index 36997919e07add582bba505b6ffb5b81f4be1bbe..f9e56662987407c7579b88668bbf3d9d361da449 100644
--- a/src/sipcall.cpp
+++ b/src/sipcall.cpp
@@ -1,270 +1,107 @@
-/**
- *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
+/*
+ *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
- *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> 
- *
- * Portions Copyright (C) 2002,2003   Aymeric Moizard <jack@atosc.org>
+ *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2,
- * or (at your option) any later version.
+ *  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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
- * This 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.
+ *  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 dpkg; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  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.
  */
 
-#include <osipparser2/sdp_message.h>
-#include <string.h> // strcpy
- 
-// For AF_INET
-#include <sys/socket.h>
-#include <sstream>
-
-#include "global.h"
-#include "audio/audiocodec.h"
-#include "audio/codecDescriptor.h"
 #include "sipcall.h"
+#include "global.h" // for _debug
+#include <sstream> // for media buffer
 
-SipCall::SipCall (CALLID id, CodecDescriptorMap& codecMap) : _localIp("127.0.0.1"), _codecMap(codecMap)
-{
-  _id = id;	  // Same id of Call object
-  _cid = 0; // call id, from the sipvoiplink
-  _did = 0; // dialog id
-  _tid = 0; // transaction id
-
-  _standby = false;
-  _status_code = 0;
-
-  alloc(); // char* allocation
-  _audiocodec = 0;
-
-  _local_audio_port = 0;
-  _remote_sdp_audio_port = 0;
-  _local_sendrecv  = 0;           /* _SENDRECV, _SENDONLY, _RECVONLY */
-  _remote_sendrecv = 0;
-
-  _reinvite = false;
-}
-
-
-SipCall::~SipCall (void) 
-{
-	dealloc();
-  //delete _audiocodec;  don't delete it, the Manager will do it...
-  _audiocodec = 0;
-}
-
-void
-SipCall::setLocalAudioPort (int newport) 
-{
-	_local_audio_port = newport;
-}
-
-int
-SipCall::getLocalAudioPort (void) 
-{
-	return _local_audio_port;
-}
-
-void
-SipCall::setId (CALLID id)
-{
-	_id = id;
-}
-
-CALLID
-SipCall::getId (void)
-{
-	return _id;
-}
-
-void
-SipCall::setDid (int did)
-{
-	_did = did;
-}
-
-int
-SipCall::getDid (void)
-{
-	return _did;
-}
-
-void
-SipCall::setCid (int cid)
-{
-	_cid = cid;
-}
-
-int
-SipCall::getCid (void)
-{
-	return _cid;
-}
+#define _SENDRECV 0
+#define _SENDONLY 1
+#define _RECVONLY 2
 
-void
-SipCall::setTid (int tid)
+SIPCall::SIPCall(const CallID& id, Call::CallType type) : Call(id, type), 
+ _localIPAddress(""), _remoteIPAddress("")  
 {
-	_tid = tid;
+  _cid = 0;
+  _did = 0;
+  _tid = 0;
+  _audioCodec = 0;
+  _localAudioPort = 0;
+  _localExternalAudioPort = 0;
+  _remoteAudioPort = 0;
 }
 
-int
-SipCall::getTid (void)
+SIPCall::~SIPCall() 
 {
-	return _tid;
 }
 
-int
-SipCall::getRemoteSdpAudioPort (void)
+CodecDescriptorMap& 
+SIPCall::getCodecMap()
 {
-	return _remote_sdp_audio_port;
+  return _codecMap;
 }
 
-char*
-SipCall::getRemoteSdpAudioIp (void)
+/**
+ * Answer incoming call correclty before telling the user
+ * @param event eXosip Event
+ */
+bool 
+SIPCall::SIPCallInvite(eXosip_event_t *event)
 {
-	return _remote_sdp_audio_ip;
-}
-
-// newIncomingCall is called when the IP-Phone user receives a new call.
-int 
-SipCall::newIncomingCall (eXosip_event_t *event) {	
-
-  _cid = event->cid;
-  _did = event->did;
-  _tid = event->tid;
-
   if (_did < 1 && _cid < 1) {
-    return -1; /* not enough information for this event?? */
+    _debug("SIP Failure: Invalid cid and did\n");
+    return false;
   }
-  osip_strncpy (_textinfo, event->textinfo, 255);
 
-  if (event->response != NULL) {
-    _status_code = event->response->status_code;
-    snprintf (_reason_phrase, 49, "%s", event->response->reason_phrase);
-    _debug("            Status: code:%1$d reason:%2$s\n", _status_code, _reason_phrase);
+  if (event->request == NULL) {
+    _debug("SIP Failure: No request into the event\n");
+    return false;
   }
 
-  strcpy(_remote_uri, "");
-  _name = "";
-  _number = "";
-  if (event->request != NULL) {
-    char *tmp = NULL;
-
-    osip_from_to_str(event->request->from, &tmp);
-    if (tmp != NULL) {
-      snprintf (_remote_uri, 255, "%s", tmp);
-      osip_free (tmp);
-
-      // Get the name/number
-      osip_from_t *from;
-      osip_from_init(&from);
-      osip_from_parse(from, _remote_uri);
-      char *name = osip_from_get_displayname(from);
-      if ( name != NULL ) {
-        _name = name;
-      }
-      osip_uri_t* url = osip_from_get_url(from); 
-      if ( url != NULL && url->username != NULL) {
-        _number = url->username;
-      }
-      osip_from_free(from);
-    }
-  }
-  _debug("            Name: %s\n", _name.c_str());
-  _debug("            Number: %s\n", _number.c_str());
-  _debug("            Remote URI: %s\n", _remote_uri);
+  setCid(event->cid);
+  setDid(event->did);
+  setTid(event->tid);
 
-  /* negotiate payloads */
-  sdp_message_t *remote_sdp = NULL;
-  if (event->request != NULL) {
-    eXosip_lock();
-    remote_sdp = eXosip_get_sdp_info (event->request);
-    eXosip_unlock();
+  setPeerInfoFromRequest(event);
+  
+  sdp_message_t* remote_sdp = getRemoteSDPFromRequest(event);
+  if (remote_sdp == 0) {
+    return false;
   }
-  if (remote_sdp == NULL) {
-    _debug("< Sending 400 Bad Request (no SDP)\n");
-    eXosip_lock();
-    eXosip_call_send_answer (_tid, 400, NULL);
-    eXosip_unlock();
-    return -1;
-  }
-  /* TODO: else build an offer */
 
-  // Remote Media IP
-  eXosip_lock();
-  sdp_connection_t *conn = eXosip_get_audio_connection (remote_sdp);
-  eXosip_unlock();
-  if (conn != NULL && conn->c_addr != NULL) {
-      snprintf (_remote_sdp_audio_ip, 49, "%s", conn->c_addr);
-      _debug("            Remote Audio IP: %s\n", _remote_sdp_audio_ip);
+  sdp_media_t* remote_med = getRemoteMedia(event->tid, remote_sdp);
+  if (remote_med == 0) {
+    sdp_message_free (remote_sdp);
+    return false;
   }
 
-  // Remote Media Port
-  eXosip_lock();
-  sdp_media_t *remote_med = eXosip_get_audio_media (remote_sdp);
-  eXosip_unlock();
-
-  if (remote_med == NULL || remote_med->m_port == NULL) {
-    // no audio media proposed
-    _debug("< Sending 415 Unsupported media type\n");
-    eXosip_lock();
-    eXosip_call_send_answer (_tid, 415, NULL);
-    eXosip_unlock();
+  if (!setRemoteAudioFromSDP(remote_med, remote_sdp)) {
+    _debug("SIP Failure: unable to set IP address and port from SDP\n");
     sdp_message_free (remote_sdp);
-    return -1;
+    return false;
   }
-  _remote_sdp_audio_port = atoi(remote_med->m_port);
-  _debug("            Remote Audio Port: %d\n", _remote_sdp_audio_port);
 
-  // Remote Payload
-  char *tmp = NULL;
-  if (_remote_sdp_audio_port > 0 && _remote_sdp_audio_ip[0] != '\0') {
-    int pos = 0;
-    while (!osip_list_eol (remote_med->m_payloads, pos)) {
-      tmp = (char *) osip_list_get (remote_med->m_payloads, pos);
-      if (tmp != NULL ) {
-        int payload = atoi(tmp);
-        // stop if we find a correct codec
-        if (0 != _codecMap.getCodec((CodecType)payload)){
-           break;
-        }
-      }
-      tmp = NULL;
-      pos++;
-    }
-  }
-  setAudioCodec(0);
-  if (tmp != NULL) {
-    int payload = atoi (tmp);
-    _debug("            Payload: %d\n", payload);
-    setAudioCodec(_codecMap.getCodec((CodecType)payload)); // codec builder for the mic
-  }
-  if (getAudioCodec() == 0) {
-    _debug("< Sending 415 Unsupported media type\n");
-    eXosip_lock();
-    eXosip_call_send_answer (_tid, 415, NULL);
-    eXosip_unlock();
+  if (!setAudioCodecFromSDP(remote_med, event->tid)) {
     sdp_message_free (remote_sdp);
-    return -1;
+    return false;
   }
 
   osip_message_t *answer = 0;
   eXosip_lock();
   _debug("< Building Answer 183\n");
-  if (0 == eXosip_call_build_answer (_tid, 183, &answer)) {
+  if (0 == eXosip_call_build_answer (event->tid, 183, &answer)) {
     if ( 0 != sdp_complete_message(remote_sdp, answer)) {
       osip_message_free(answer);
       // Send 415 Unsupported media type
-      _debug("< Sending Answer 415\n");
-      eXosip_call_send_answer (_tid, 415, NULL);
+      _debug("< Sending Answer 415 : unsupported media type\n");
+      eXosip_call_send_answer (event->tid, 415, NULL);
     } else {
 
       sdp_message_t *local_sdp = eXosip_get_sdp_info(answer);
@@ -274,8 +111,8 @@ SipCall::newIncomingCall (eXosip_event_t *event) {
       }
       if (local_sdp != NULL && local_med != NULL) {
         /* search if stream is sendonly or recvonly */
-        _remote_sendrecv = sdp_analyse_attribute (remote_sdp, remote_med);
-        _local_sendrecv =  sdp_analyse_attribute (local_sdp, local_med);
+        int _remote_sendrecv = sdp_analyse_attribute (remote_sdp, remote_med);
+        int _local_sendrecv =  sdp_analyse_attribute (local_sdp, local_med);
         _debug("            Remote SendRecv: %d\n", _remote_sendrecv);
         _debug("            Local  SendRecv: %d\n", _local_sendrecv);
         if (_local_sendrecv == _SENDRECV) {
@@ -286,149 +123,73 @@ SipCall::newIncomingCall (eXosip_event_t *event) {
         sdp_message_free (local_sdp);
       }
       _debug("< Sending answer 183\n");
-      if (0 != eXosip_call_send_answer (_tid, 183, answer)) {
+      if (0 != eXosip_call_send_answer (event->tid, 183, answer)) {
         _debug("SipCall::newIncomingCall: cannot send 183 progress?\n");
       }
     }
   }
   eXosip_unlock ();
-  sdp_message_free (remote_sdp);
 
-  return 0;
+  sdp_message_free (remote_sdp);
+  return true;
 }
 
-// newReinviteCall is called when the IP-Phone user receives a change in the call
-// it's almost an newIncomingCall but we send a 200 OK
-// See: 3.7.  Session with re-INVITE (IP Address Change)
-int 
-SipCall::newReinviteCall (eXosip_event_t *event) {
-
-  _cid = event->cid;
-  _did = event->did;
-  _tid = event->tid;
-
+/**
+  * newReinviteCall is called when the IP-Phone user receives a change in the call
+  * it's almost an newIncomingCall but we send a 200 OK
+  * See: 3.7.  Session with re-INVITE (IP Address Change)
+  * @param event eXosip Event
+  * @return true if ok
+  */
+bool 
+SIPCall::SIPCallReinvite(eXosip_event_t *event)
+{
   if (_did < 1 && _cid < 1) {
-    return -1; /* not enough information for this event?? */
+    _debug("SIP Failure: Invalid cid and did\n");
+    return false;
   }
-  osip_strncpy (_textinfo, event->textinfo, 255);
 
-  if (event->response != NULL) {
-    _status_code = event->response->status_code;
-    snprintf (_reason_phrase, 49, "%s", event->response->reason_phrase);
-    _debug("            Status: %d %s\n", _status_code, _reason_phrase);
+  if (event->request == NULL) {
+    _debug("SIP Failure: No request into the event\n");
+    return false;
   }
 
-  strcpy(_remote_uri, "");
-  _name = "";
-  _number = "";
-  if (event->request != NULL) {
-    char *tmp = NULL;
-
-    osip_from_to_str(event->request->from, &tmp);
-    if (tmp != NULL) {
-      snprintf (_remote_uri, 255, "%s", tmp);
-      osip_free (tmp);
-
-      // Get the name/number
-      osip_from_t *from;
-      osip_from_init(&from);
-      osip_from_parse(from, _remote_uri);
-      char *name = osip_from_get_displayname(from);
-      if ( name != NULL ) {
-        _name = name;
-      }
-      osip_uri_t* url = osip_from_get_url(from); 
-      if ( url != NULL && url->username != NULL ) {
-        _number = url->username;
-      }
-      osip_from_free(from);
-    }
-  }
-  _debug("            Name: %s\n", _name.c_str());
-  _debug("            Number: %s\n", _number.c_str());
-  _debug("            Remote URI: %s\n", _remote_uri);
+  setCid(event->cid);
+  setDid(event->did);
+  setTid(event->tid);
 
-  /* negotiate payloads */
-  sdp_message_t *remote_sdp = NULL;
-  if (event->request != NULL) {
-    eXosip_lock();
-    remote_sdp = eXosip_get_sdp_info (event->request);
-    eXosip_unlock();
-  }
-  if (remote_sdp == NULL) {
-    _debug("< Sending 400 Bad Request (no sdp)\n");
-    // Send 400 BAD REQUEST
-    eXosip_lock();
-    eXosip_call_send_answer (_tid, 400, NULL);
-    eXosip_unlock();
-    return 0;
-  }
-  /* TODO: else build an offer */
+  setPeerInfoFromRequest(event);
 
-  // Remote Media IP
-  eXosip_lock();
-  sdp_connection_t *conn = eXosip_get_audio_connection (remote_sdp);
-  eXosip_unlock();
-  if (conn != NULL && conn->c_addr != NULL) {
-      snprintf (_remote_sdp_audio_ip, 49, "%s", conn->c_addr);
-      _debug("            Remote Audio IP: %s\n", _remote_sdp_audio_ip);
+  sdp_message_t* remote_sdp = getRemoteSDPFromRequest(event);
+  if (remote_sdp == 0) {
+    return false;
   }
 
-  // Remote Media Port
-  eXosip_lock();
-  sdp_media_t *remote_med = eXosip_get_audio_media (remote_sdp);
-  eXosip_unlock();
-
-  if (remote_med == NULL || remote_med->m_port == NULL) {
-    // no audio media proposed
-    _debug("< Sending 415 Unsupported media type\n");
-    eXosip_lock();
-    eXosip_call_send_answer (_tid, 415, NULL);
-    eXosip_unlock();
+  sdp_media_t* remote_med = getRemoteMedia(event->tid, remote_sdp);
+  if (remote_med == 0) {
     sdp_message_free (remote_sdp);
-    return 0;
+    return false;
   }
-  _remote_sdp_audio_port = atoi(remote_med->m_port);
-  _debug("            Remote Audio Port: %d\n", _remote_sdp_audio_port);
 
-  // Remote Payload
-  char *tmp = NULL;
-  if (_remote_sdp_audio_port > 0 && _remote_sdp_audio_ip[0] != '\0') {
-    int pos = 0;
-    while (!osip_list_eol (remote_med->m_payloads, pos)) {
-      tmp = (char *) osip_list_get (remote_med->m_payloads, pos);
-      if (tmp != NULL) {
-        // we could check if the payload is active here...
-        break;
-      }
-      tmp = NULL;
-      pos++;
-    }
+  if (!setRemoteAudioFromSDP(remote_med, remote_sdp)) {
+    _debug("SIP Failure: unable to set IP address and port from SDP\n");
+    sdp_message_free (remote_sdp);
+    return false;
   }
 
-  setAudioCodec(0);
-  if (tmp != NULL) {
-    int payload = atoi (tmp);
-    _debug("            Payload: %d\n", payload);
-    setAudioCodec(_codecMap.getCodec((CodecType)payload)); // codec builder for the mic
-  }
-  if (getAudioCodec() == 0) {
-    _debug("< Sending 415 Unsupported media type\n");
-    eXosip_lock();
-    eXosip_call_send_answer (_tid, 415, NULL);
-    eXosip_unlock();
+  if (!setAudioCodecFromSDP(remote_med, event->tid)) {
     sdp_message_free (remote_sdp);
-    return 0;
+    return false;
   }
 
   osip_message_t *answer = 0;
   eXosip_lock();
   _debug("< Building Answer 200\n");
-  if (0 == eXosip_call_build_answer (_tid, 200, &answer)) {
+  if (0 == eXosip_call_build_answer (event->tid, 200, &answer)) {
     if ( 0 != sdp_complete_message(remote_sdp, answer)) {
       osip_message_free(answer);
       // Send 415 Unsupported media type
-      eXosip_call_send_answer (_tid, 415, NULL);
+      eXosip_call_send_answer (event->tid, 415, NULL);
       _debug("< Sending Answer 415\n");
     } else {
 
@@ -439,8 +200,8 @@ SipCall::newReinviteCall (eXosip_event_t *event) {
       }
       if (local_sdp != NULL && local_med != NULL) {
         /* search if stream is sendonly or recvonly */
-        _remote_sendrecv = sdp_analyse_attribute (remote_sdp, remote_med);
-        _local_sendrecv =  sdp_analyse_attribute (local_sdp, local_med);
+        int _remote_sendrecv = sdp_analyse_attribute (remote_sdp, remote_med);
+        int _local_sendrecv =  sdp_analyse_attribute (local_sdp, local_med);
         _debug("            Remote SendRecv: %d\n", _remote_sendrecv);
         _debug("            Local  SendRecv: %d\n", _local_sendrecv);
         if (_local_sendrecv == _SENDRECV) {
@@ -451,88 +212,44 @@ SipCall::newReinviteCall (eXosip_event_t *event) {
         sdp_message_free (local_sdp);
       }
       _debug("< Sending answer 200\n");
-      if (0 != eXosip_call_send_answer (_tid, 200, answer)) {
+      if (0 != eXosip_call_send_answer (event->tid, 200, answer)) {
         _debug("SipCall::newIncomingCall: cannot send 200 OK?\n");
       }
     }
   }
   eXosip_unlock ();
   sdp_message_free (remote_sdp);
-  _reinvite = true;
-  return 0;
+  return true;
 }
 
-int 
-SipCall::ringingCall (eXosip_event_t *event) {     
-
-  this->_cid = event->cid;
-  this->_did = event->did;
-  this->_tid = event->tid;
-
-  if (this->_did < 1 && this->_cid < 1) {
-    return -1; 
-  }
-
-  osip_strncpy (_textinfo, event->textinfo, 255);
-
-  if (event->response != NULL) {
-    _status_code = event->response->status_code;
-    snprintf (_reason_phrase, 49, "%s", event->response->reason_phrase);
-  }
-
-  if (event->request != NULL) {
-    char *tmp = NULL;
-
-    osip_from_to_str (event->request->from, &tmp);
-    if (tmp != NULL) {
-      snprintf (_remote_uri, 255, "%s", tmp);
-      osip_free (tmp);
-    }
-  }
-  	return 0;
-}
-
-int
-SipCall::receivedAck (eXosip_event_t *event)
+  /**
+   * Peer answered to a call (on hold or not)
+   * @param event eXosip Event
+   * @return true if ok
+   */
+bool 
+SIPCall::SIPCallAnswered(eXosip_event_t *event)
 {
-  _cid = event->cid;
-  _did = event->did;
-  return 0;
-}
-
-
-
-int 
-SipCall::answeredCall(eXosip_event_t *event) {
-  _cid = event->cid;
-  _did = event->did;
-
-  if (_did < 1 && _cid < 1)	{
-    return -1; /* not enough information for this event?? */
+  if (_did < 1 && _cid < 1) {
+    _debug("SIP Failure: Invalid cid and did\n");
+    return false;
   }
-  osip_strncpy(this->_textinfo,   event->textinfo, 255);
 
-  if (event->response != NULL) {
-    _status_code = event->response->status_code;
-    snprintf (_reason_phrase, 49, "%s", event->response->reason_phrase);
+  if (event->request == NULL) {
+    _debug("SIP Failure: No request into the event\n");
+    return false;
+  }
 
-    char *tmp = NULL;
+  setCid(event->cid);
+  setDid(event->did);
 
-    osip_from_to_str (event->response->from, &tmp);
-    if (tmp != NULL) {
-        snprintf (_remote_uri, 255, "%s", tmp);
-        osip_free (tmp);
-    }
-  }
-  _debug("            Status: %d %s\n", _status_code, _reason_phrase);
-  _debug("            From URI: %s\n", _remote_uri);
+  //setPeerInfoFromResponse()
 
   eXosip_lock ();
   {
     osip_message_t *ack = NULL;
     int i;
-
-    i = eXosip_call_build_ack (_did, &ack);
+    i = eXosip_call_build_ack (event->did, &ack);
     if (i != 0) {
       _debug("SipCall::answeredCall: Cannot build ACK for call!\n");
     } else {
@@ -554,114 +271,120 @@ SipCall::answeredCall(eXosip_event_t *event) {
       sdp_message_free (remote_sdp);
 
       _debug("< Send ACK\n");
-      eXosip_call_send_ack (_did, ack);
+      eXosip_call_send_ack (event->did, ack);
     }
   }
   eXosip_unlock ();
-
-  return 0;
+  return true;  
 }
-
-void
-SipCall::answeredCall_without_hold (eXosip_event_t *event) 
+  /**
+   * We retreive final SDP info if they changed
+   * @param event eXosip Event
+   * @return true if ok (change / no change) or false on error
+   */
+bool 
+SIPCall::SIPCallAnsweredWithoutHold(eXosip_event_t *event)
 {
-  if (event->response == NULL ) { return; }
-
-  // TODO: understand this code..
-  if (_cid!=0) {
-    eXosip_lock();
-    sdp_message_t *sdp = eXosip_get_sdp_info (event->response);
-    eXosip_unlock();
-    if (sdp != NULL) {
-       /* audio is started and session has just been modified */
-      sdp_message_free (sdp);
-    }
+  if (event->response == NULL || event->request  == NULL) { return false; }
+  
+  eXosip_lock();
+  sdp_message_t *remote_sdp = eXosip_get_sdp_info (event->response);
+  eXosip_unlock();
+  if (remote_sdp == NULL) {
+    _debug("SIP Failure: no remote sdp\n");
+    sdp_message_free(remote_sdp);
+    return false;
   }
 
-  if (event->request != NULL) {   /* audio is started */ 
-
-    eXosip_lock();
-    sdp_message_t *local_sdp = eXosip_get_sdp_info (event->request);
-    sdp_message_t *remote_sdp = eXosip_get_sdp_info (event->response);
-    eXosip_unlock();
+  sdp_media_t *remote_med = getRemoteMedia(event->tid, remote_sdp);
+  if (remote_med==NULL) {
+    sdp_message_free(remote_sdp);
+    return false;
+  }
+  if ( ! setRemoteAudioFromSDP(remote_med, remote_sdp) ) {
+    sdp_message_free(remote_sdp);
+    return false;
+  }
 
-    sdp_media_t *remote_med = NULL;
-    char *tmp = NULL;
-    if (remote_sdp == NULL) {
-      _debug("SipCall::answeredCall_without_hold: No remote SDP body found for call\n");
-      /* TODO: remote_sdp = retreive from ack above */
-    } else {
-      eXosip_lock();
-      sdp_connection_t *conn = eXosip_get_audio_connection (remote_sdp);
-      if (conn != NULL && conn->c_addr != NULL) {
-          snprintf (_remote_sdp_audio_ip, 49, "%s", conn->c_addr);
-      }
+  char *tmp = (char *) osip_list_get (remote_med->m_payloads, 0);
 
-      remote_med = eXosip_get_audio_media (remote_sdp);
-      if (remote_med != NULL && remote_med->m_port != NULL) {
-        _remote_sdp_audio_port = atoi (remote_med->m_port);
-      }
-      eXosip_unlock();
-      _debug("            Remote Audio: %s:%d\n", _remote_sdp_audio_ip, _remote_sdp_audio_port);
-
-      if (_remote_sdp_audio_port > 0 && _remote_sdp_audio_ip[0] != '\0' && 
-        remote_med != NULL) {
-        tmp = (char *) osip_list_get (remote_med->m_payloads, 0);
-      }
+  setAudioCodec(0);
+  if (tmp != NULL) {
+    int payload = atoi (tmp);
+    _debug("            Remote Payload: %d\n", payload);
+    setAudioCodec(_codecMap.getCodec((CodecType)payload)); // codec builder for the mic
+  }
 
-      setAudioCodec(0);
-      if (tmp != NULL) {
-        int payload = atoi (tmp);
-        _debug("            Remote Payload: %d\n", payload);
-        setAudioCodec(_codecMap.getCodec((CodecType)payload)); // codec builder for the mic
-      }
+/*
+    // search if stream is sendonly or recvonly
+    _remote_sendrecv = sdp_analyse_attribute (remote_sdp, remote_med);
+    _local_sendrecv = sdp_analyse_attribute (local_sdp, local_med);
+    if (_local_sendrecv == _SENDRECV) {
+      if (_remote_sendrecv == _SENDONLY)
+          _local_sendrecv = _RECVONLY;
+      else if (_remote_sendrecv == _RECVONLY)
+          _local_sendrecv = _SENDONLY;
     }
+  _debug("            Remote Sendrecv: %d\n", _remote_sendrecv);
+  _debug("            Local Sendrecv: %d\n", _local_sendrecv);
+*/
+  sdp_message_free (remote_sdp);
+  return true;
+}
 
-    if (local_sdp == NULL) {
-      _debug("SipCall::answeredCall_without_hold: SDP body was probably in the ACK (TODO)\n");
-    }
+const std::string& 
+SIPCall::getLocalIp()
+{
+  ost::MutexLock m(_callMutex);  
+  return _localIPAddress;
+}
 
-    if (remote_sdp != NULL && local_sdp != NULL) {
-      int audio_port = 0;
-      eXosip_lock();
-      sdp_media_t *local_med = eXosip_get_audio_media (local_sdp);
-      eXosip_unlock();
-      if (local_med != NULL && local_med->m_port != NULL) {
-        audio_port = atoi (local_med->m_port);
-      }
-      _debug("            Local Audio port: %d\n", audio_port);
+unsigned int 
+SIPCall::getLocalAudioPort()
+{
+  ost::MutexLock m(_callMutex);  
+  return _localAudioPort;
+}
 
-      if (tmp != NULL && audio_port > 0
-          && _remote_sdp_audio_port > 0
-          && _remote_sdp_audio_ip[0] != '\0') {
+unsigned int 
+SIPCall::getRemoteAudioPort()
+{
+  ost::MutexLock m(_callMutex);  
+  return _remoteAudioPort;
+}
 
-        /* search if stream is sendonly or recvonly */
-        _remote_sendrecv = sdp_analyse_attribute (remote_sdp, remote_med);
-        _local_sendrecv = sdp_analyse_attribute (local_sdp, local_med);
-        if (_local_sendrecv == _SENDRECV) {
-          if (_remote_sendrecv == _SENDONLY)
-              _local_sendrecv = _RECVONLY;
-          else if (_remote_sendrecv == _RECVONLY)
-              _local_sendrecv = _SENDONLY;
-        }
-      }
-      _debug("            Remote Sendrecv: %d\n", _remote_sendrecv);
-      _debug("            Local Sendrecv: %d\n", _local_sendrecv);
-    }
-    sdp_message_free (local_sdp);
-    sdp_message_free (remote_sdp);
-  }
+const std::string& 
+SIPCall::getRemoteIp()
+{
+  ost::MutexLock m(_callMutex);  
+  return _remoteIPAddress;
 }
 
-int
-SipCall::sdp_complete_message(sdp_message_t * remote_sdp, 
-		osip_message_t * msg)
+AudioCodec* 
+SIPCall::getAudioCodec()
 {
-  char *tmp = NULL;
-  char buf[4096];
+  ost::MutexLock m(_callMutex);  
+  return _audioCodec;  
+}
 
-  char localip[128];
+void 
+SIPCall::setAudioStart(bool start)
+{
+  ost::MutexLock m(_callMutex);  
+  _audioStarted = start;  
+}
 
+bool 
+SIPCall::isAudioStarted()
+{
+  ost::MutexLock m(_callMutex);  
+  return _audioStarted;
+}
+
+  //TODO: humm?
+int 
+SIPCall::sdp_complete_message(sdp_message_t * remote_sdp, osip_message_t * msg)
+{
   // Format port to a char*
   if (remote_sdp == NULL) {
     _debug("SipCall::sdp_complete_message: No remote SDP body found for call\n");
@@ -672,13 +395,11 @@ SipCall::sdp_complete_message(sdp_message_t * remote_sdp,
     return -1;
   }
 
-  // this exosip is locked and is protected by other function
-  eXosip_guess_localip(AF_INET, localip, 128);
-
   std::ostringstream media;
 
   // for each medias
   int iMedia = 0;
+  char *tmp = NULL;
   while (!osip_list_eol(remote_sdp->m_medias, iMedia)) {
     sdp_media_t *remote_med = (sdp_media_t *)osip_list_get(remote_sdp->m_medias, iMedia);
     if (remote_med == 0) { continue; }
@@ -712,19 +433,20 @@ SipCall::sdp_complete_message(sdp_message_t * remote_sdp,
         media << "m=" << remote_med->m_media << " 0 << " << remote_med->m_proto << " \r\n";
       } else {
         // we add the media line + a=rtpmap list
-        media << "m=" << remote_med->m_media << " " << _local_audio_port << " RTP/AVP " << listCodec.str() << "\r\n";
+        media << "m=" << remote_med->m_media << " " << getLocalExternAudioPort() << " RTP/AVP " << listCodec.str() << "\r\n";
         media << listRtpMap.str();
       }
     }
     iMedia++;
   }
+  char buf[4096];
   snprintf (buf, 4096,
     "v=0\r\n"
     "o=user 0 0 IN IP4 %s\r\n"
     "s=session\r\n"
     "c=IN IP4 %s\r\n"
     "t=0 0\r\n"
-    "%s\n", localip, localip, media.str().c_str());
+    "%s\n", getLocalIp().c_str(), getLocalIp().c_str(), media.str().c_str());
 
   osip_message_set_body (msg, buf, strlen (buf));
   osip_message_set_content_type (msg, "application/sdp");
@@ -732,78 +454,200 @@ SipCall::sdp_complete_message(sdp_message_t * remote_sdp,
   return 0;
 }
 
-int
-SipCall::sdp_analyse_attribute (sdp_message_t * sdp, sdp_media_t * med)
+
+  // TODO: hum???
+int 
+SIPCall::sdp_analyse_attribute (sdp_message_t * sdp, sdp_media_t * med)
 {
-  	int pos;
-  	int pos_media;
-
-  	/* test media attributes */
-  	pos = 0;
-  	while (!osip_list_eol (med->a_attributes, pos)) {
-      	sdp_attribute_t *at;
-
-      	at = (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
-      	if (at->a_att_field != NULL && 
-				0 == strcmp (at->a_att_field, "sendonly")) {
-		  	return _SENDONLY;
-      	} else if (at->a_att_field != NULL &&
-                 0 == strcmp (at->a_att_field, "recvonly")) {
-          	return _RECVONLY;
-      	} else if (at->a_att_field != NULL &&
-                 0 == strcmp (at->a_att_field, "sendrecv")) {
-          	return _SENDRECV;
-        }
-      	pos++;
-    }
+  int pos;
+  int pos_media;
+
+  /* test media attributes */
+  pos = 0;
+  while (!osip_list_eol (med->a_attributes, pos)) {
+      sdp_attribute_t *at;
+
+      at = (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
+      if (at->a_att_field != NULL && 
+      0 == strcmp (at->a_att_field, "sendonly")) {
+      return _SENDONLY;
+      } else if (at->a_att_field != NULL &&
+                0 == strcmp (at->a_att_field, "recvonly")) {
+          return _RECVONLY;
+      } else if (at->a_att_field != NULL &&
+                0 == strcmp (at->a_att_field, "sendrecv")) {
+          return _SENDRECV;
+      }
+      pos++;
+  }
 
-  	/* test global attributes */
-  	pos_media = -1;
-  	pos = 0;
-  	while (!osip_list_eol (sdp->a_attributes, pos)) {
-      	sdp_attribute_t *at;
-
-      	at = (sdp_attribute_t *) osip_list_get (sdp->a_attributes, pos);
-      	if (at->a_att_field != NULL && 
-				0 == strcmp (at->a_att_field, "sendonly")) {
-          	return _SENDONLY;
-      	} else if (at->a_att_field != NULL &&
-                 0 == strcmp (at->a_att_field, "recvonly")) {
-          	return _RECVONLY;
-      	} else if (at->a_att_field != NULL &&
-                 0 == strcmp (at->a_att_field, "sendrecv")) {
-          	return _SENDRECV;
-        }
-      	pos++;
+  /* test global attributes */
+  pos_media = -1;
+  pos = 0;
+  while (!osip_list_eol (sdp->a_attributes, pos)) {
+      sdp_attribute_t *at;
+
+      at = (sdp_attribute_t *) osip_list_get (sdp->a_attributes, pos);
+      if (at->a_att_field != NULL && 
+      0 == strcmp (at->a_att_field, "sendonly")) {
+          return _SENDONLY;
+      } else if (at->a_att_field != NULL &&
+                0 == strcmp (at->a_att_field, "recvonly")) {
+          return _RECVONLY;
+      } else if (at->a_att_field != NULL &&
+                0 == strcmp (at->a_att_field, "sendrecv")) {
+          return _SENDRECV;
+      }
+      pos++;
+  }
+
+  return _SENDRECV;
+}
+
+bool 
+SIPCall::setPeerInfoFromRequest(eXosip_event_t *event)
+{
+  // event->request should not be NULL!
+  char remote_uri[256] = "";
+  std::string name("");
+  std::string number("");
+
+  char *tmp = NULL;
+  osip_from_to_str(event->request->from, &tmp);
+  if (tmp != NULL) {
+    snprintf (remote_uri, 255, "%s", tmp);
+    remote_uri[255] = '\0';
+    osip_free (tmp);
+
+    // Get the name/number
+    osip_from_t *from;
+    osip_from_init(&from);
+    osip_from_parse(from, remote_uri);
+    char *tmpname = osip_from_get_displayname(from);
+    if ( tmpname != NULL ) {
+      name = tmpname;
     }
+    osip_uri_t* url = osip_from_get_url(from); 
+    if ( url != NULL && url->username != NULL) {
+      number = url->username;
+    }
+    osip_from_free(from);
+  }
 
-  	return _SENDRECV;
+  _debug("            Name: %s\n", name.c_str());
+  _debug("            Number: %s\n", number.c_str());
+  _debug("            Remote URI: %s\n", remote_uri);
+
+  setPeerName(name);
+  setPeerNumber(number);  
+  return true;
 }
 
-void
-SipCall::alloc(void) {
-  this->_reason_phrase = new char[50];
-  this->_textinfo = new char[256];
-  this->_remote_uri = new char[256];
-  this->_remote_sdp_audio_ip = new char[50];
-
-  // initialize the strings...
-  this->_reason_phrase[0] = '\0';
-  this->_textinfo[0] = '\0';
-  this->_remote_uri[0] = '\0';
-  strcpy(this->_remote_sdp_audio_ip, "127.0.0.1");
+sdp_message_t* 
+SIPCall::getRemoteSDPFromRequest(eXosip_event_t *event)
+{
+  // event->request should not be null!
+  /* negotiate payloads */
+  sdp_message_t *remote_sdp = NULL;
+  if (event->request != NULL) {
+    eXosip_lock();
+    remote_sdp = eXosip_get_sdp_info (event->request);
+    eXosip_unlock();
+  }
+  if (remote_sdp == NULL) {
+    _debug("SIP Failure: No SDP into the request\n");
+    _debug("< Sending 400 Bad Request (no SDP)\n");
+    eXosip_lock();
+    eXosip_call_send_answer (event->tid, 400, NULL);
+    eXosip_unlock();
+    return 0;
+  }
+  return remote_sdp;
 }
 
-void
-SipCall::dealloc(void) {
-  delete [] _reason_phrase;       _reason_phrase = NULL;
-  delete [] _textinfo;            _textinfo      = NULL;
-  delete [] _remote_uri;          _remote_uri    = NULL;
-  delete [] _remote_sdp_audio_ip; _remote_sdp_audio_ip = NULL;
+sdp_media_t* 
+SIPCall::getRemoteMedia(int tid, sdp_message_t* remote_sdp)
+{
+  // Remote Media Port
+  eXosip_lock();
+  sdp_media_t *remote_med = eXosip_get_audio_media(remote_sdp);
+  eXosip_unlock();
+
+  if (remote_med == NULL || remote_med->m_port == NULL) {
+    // no audio media proposed
+    _debug("SIP Failure: unsupported media\n");
+    _debug("< Sending 415 Unsupported media type\n");
+    eXosip_lock();
+    eXosip_call_send_answer (tid, 415, NULL);
+    eXosip_unlock();
+    sdp_message_free (remote_sdp);
+    return 0;
+  }
+  return remote_med;
 }
 
-void
-SipCall::noSupportedCodec (void) {
-	_debug("SipCall::noSupportedCodec: Codec no supported\n");
+bool 
+SIPCall::setRemoteAudioFromSDP(sdp_media_t* remote_med, sdp_message_t* remote_sdp)
+{
+  // Remote Media IP
+  eXosip_lock();
+  sdp_connection_t *conn = eXosip_get_audio_connection(remote_sdp);
+  eXosip_unlock();
+  if (conn != NULL && conn->c_addr != NULL) {
+    char _remote_sdp_audio_ip[50] = "";
+    snprintf (_remote_sdp_audio_ip, 49, "%s", conn->c_addr);
+    _remote_sdp_audio_ip[49] = '\0';
+    _debug("            Remote Audio IP: %s\n", _remote_sdp_audio_ip);
+    setRemoteIP(_remote_sdp_audio_ip);
+    if (_remote_sdp_audio_ip[0] == '\0') {
+      setRemoteAudioPort(0);
+      return false;
+    }
+  }
+
+  // Remote port
+  int _remote_sdp_audio_port = atoi(remote_med->m_port);
+  _debug("            Remote Audio Port: %d\n", _remote_sdp_audio_port);
+  setRemoteAudioPort(_remote_sdp_audio_port);
+
+  if (_remote_sdp_audio_port == 0) {
+    return false;
+  }
+  return true;
 }
 
+bool 
+SIPCall::setAudioCodecFromSDP(sdp_media_t* remote_med, int tid)
+{
+  // Remote Payload
+  char *tmp = NULL;
+  int pos = 0;
+  while (!osip_list_eol (remote_med->m_payloads, pos)) {
+    tmp = (char *) osip_list_get (remote_med->m_payloads, pos);
+    if (tmp != NULL ) {
+      int payload = atoi(tmp);
+      // stop if we find a correct codec
+      if (0 != _codecMap.getCodec((CodecType)payload)){
+          break;
+      }
+    }
+    tmp = NULL;
+    pos++;
+  }
+
+  setAudioCodec(0);
+  if (tmp != NULL) {
+    int payload = atoi (tmp);
+    _debug("            Payload: %d\n", payload);
+    setAudioCodec(_codecMap.getCodec((CodecType)payload)); // codec builder for the mic
+  }
+  if (getAudioCodec() == 0) {
+    _debug("SIPCall Failure: Unable to set codec\n");
+    _debug("< Sending 415 Unsupported media type\n");
+    eXosip_lock();
+    eXosip_call_send_answer(tid, 415, NULL);
+    eXosip_unlock();
+    return false;
+  }
+  return true;
+}
diff --git a/src/sipcall.h b/src/sipcall.h
index bf9c3ab195abc063853bad1d5e8d9d2dee4ce2a4..cbe640a055f25aea066e14bedd060e2df4adb50b 100644
--- a/src/sipcall.h
+++ b/src/sipcall.h
@@ -1,155 +1,181 @@
-/**
- * Copyright (C) 2004-2005 Savoir-Faire Linux inc.
- * Author: Yan Morin <yan.morin@savoirfairelinux.com>
- * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> 
- *
- * Portions Copyright (C) 2002,2003   Aymeric Moizard <jack@atosc.org>
+/*
+ *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
+ *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
+ *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2,
- * or (at your option) any later version.
+ *  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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
- * This 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.
+ *  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 dpkg; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  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.
  */
+#ifndef SIPCALL_H
+#define SIPCALL_H
 
-#ifndef __SIP_CALL_H__
-#define __SIP_CALL_H__
-
-#include <eXosip2/eXosip.h>
-#include <vector>
-#include <string>
 #include "call.h"
+#include "audio/codecDescriptor.h"
+#include <eXosip2/eXosip.h>
 
-class CodecDescriptor;
 class AudioCodec;
 
-#define _SENDRECV 0
-#define _SENDONLY 1
-#define _RECVONLY 2
-
-// Vector of CodecDescriptor
-class SipCall {
+/**
+	@author Yan Morin <yan.morin@gmail.com>
+  SIPCall are SIP implementation of a normal Call 
+*/
+class SIPCall : public Call
+{
 public:
-  SipCall(CALLID id, CodecDescriptorMap& codecMap);
-  ~SipCall (void);
+    SIPCall(const CallID& id, Call::CallType type);
+
+    ~SIPCall();
+
+  /** @return SIP call id : protected by eXosip lock */
+  int  getCid() { return _cid; }
+  /** @param cid SIP call id : protected by eXosip lock */
+  void setCid(int cid) { _cid = cid ; } 
+  /** @return SIP domain id : protected by eXosip lock  */
+  int  getDid() { return _did; }
+  /** @param did SIP domain id : protected by eXosip lock */
+  void setDid(int did) { _did = did; } 
+  /** @return SIP transaction id : protected by eXosip lock  */
+  int  getTid() { return _tid; }
+  /** @param did SIP transaction id : protected by eXosip lock */
+  void setTid(int tid) { _tid = tid; } 
+
+  // AUDIO
+  /** Set internal codec Map: initialization only, not protected */
+  void setCodecMap(const CodecDescriptorMap& map) { _codecMap = map; } 
+  CodecDescriptorMap& getCodecMap();
+
+  /** set internal, not protected */
+  void setLocalIp(const std::string& ip)     { _localIPAddress = ip; }
+  void setLocalAudioPort(unsigned int port)  { _localAudioPort = port;}
+  void setLocalExternAudioPort(unsigned int port) { _localExternalAudioPort = port; }
+  unsigned int getLocalExternAudioPort() { return _localExternalAudioPort; }
 
   /**
-   * Store information about incoming call and negociate payload
+   * Answer incoming call correclty before telling the user
+   * @param event eXosip Event
    */
-  int newIncomingCall(eXosip_event_t *);
-  int newReinviteCall(eXosip_event_t *);
-	
-	/*
-	 * Use to answer to a ONHOLD/OFFHOLD event 
-	 */
-	int answeredCall 		(eXosip_event_t *);
-	
-	/* 
-	 * Use to answer to an incoming call 
-	 */
-	void  	answeredCall_without_hold (eXosip_event_t *);
-
-	int  	ringingCall			(eXosip_event_t *);
-	int  	receivedAck			(eXosip_event_t *);
-
-	/*
-	 * Manage local audio port for each sipcall
-	 */
-	void	setLocalAudioPort 	(int);
-	int 	getLocalAudioPort 	(void);	
-
-  std::string getLocalIp() { return _localIp; }
-  void setLocalIp(const std::string& ip) { _localIp = ip; }
-
-  bool isReinvite() { return _reinvite; }
-  void endReinvite() { _reinvite = false; }; 
-
-	/*
-	 * Manage id, did (dialog-id), cid (call-id) and tid (transaction-id) 
-	 * for each sipcall
-	*/ 
-	void 	setId				(CALLID id);
-	CALLID	getId				(void);
-	void 	setDid				(int did);
-	int 	getDid				(void);
-	void 	setCid				(int cid);
-	int 	getCid				(void);
-	void 	setTid				(int tid);
-	int 	getTid				(void);
-
-	/*
-	 * Manage remote sdp audio port
-	 */
-	int 	getRemoteSdpAudioPort (void);
-	char* 	getRemoteSdpAudioIp (void);
-
-  /*
-   * Manage audio codec
+  bool SIPCallInvite(eXosip_event_t *event);
+
+  /**
+   * newReinviteCall is called when the IP-Phone user receives a change in the call
+   * it's almost an newIncomingCall but we send a 200 OK
+   * See: 3.7.  Session with re-INVITE (IP Address Change)
+   * @param event eXosip Event
+   * @return true if ok
    */
-  AudioCodec* getAudioCodec(void) { return _audiocodec; }
-  void setAudioCodec(AudioCodec* ac) { _audiocodec = ac; }
-  CodecDescriptorMap& getCodecMap() { return _codecMap; }
+  bool SIPCallReinvite(eXosip_event_t *event);
 
-  /*
-   * Accessor to remote-uri
+  /**
+   * Peer answered to a call (on hold or not)
+   * @param event eXosip Event
+   * @return true if ok
+   */
+  bool SIPCallAnswered(eXosip_event_t *event);
+  /**
+   * We retreive final SDP info if they changed
+   * @param event eXosip Event
+   * @return true if ok (change / no change) or false on error
    */
-  inline char* getRemoteUri (void) { return _remote_uri; }
+  bool SIPCallAnsweredWithoutHold(eXosip_event_t *event);
 
-  /*
-   * To avoid confusion when an incoming call occured in the same time 
-   * that you make an outgoing call
+  /** protected */
+  const std::string& getLocalIp();
+  unsigned int getLocalAudioPort();
+  unsigned int getRemoteAudioPort();
+  const std::string& getRemoteIp();
+  AudioCodec* getAudioCodec();
+
+  /**
+   * Set the audio start boolean (protected by mutex)
+   * @param start true if we start the audio
+   */
+  void setAudioStart(bool start);
+  /**
+   * Tell if the audio is started (protected by mutex)
+   * @return true if it's already started
    */
-  inline void setStandBy (bool standby) { _standby = standby; }
-  inline bool getStandBy (void) { return _standby; }
+  bool isAudioStarted();
 
-  std::string getName() const { return _name; }
-  std::string getNumber() const { return _number; }
+  //TODO: humm?
   int sdp_complete_message(sdp_message_t * remote_sdp, osip_message_t * msg);
 
+
 private:
-  void	alloc			(void);
-  void	dealloc			(void);
-  void 	noSupportedCodec(void);	
+  /** set internal, not protected */
+  void setRemoteIP(const std::string& ip)    { _remoteIPAddress = ip; }
+  void setRemoteAudioPort(unsigned int port) { _remoteAudioPort = port; }
+  void setAudioCodec(AudioCodec* audioCodec) { _audioCodec = audioCodec; }
 
+  // TODO: hum???
   int sdp_analyse_attribute (sdp_message_t * sdp, sdp_media_t * med);
-	
-  ///////////////////////////
-  // Private member variables
-  ///////////////////////////
-  CodecDescriptorMap& _codecMap;
-  AudioCodec* _audiocodec;
-	
-  CALLID 	_id;
-  int 	_cid;		// call id
-  int 	_did;		// dialog id
-  int 	_tid;		// transaction id
-  bool	_standby; 	// wait for a cid and did when outgoing call is made
-  
-  int  	_status_code;
-  
-  char*	_reason_phrase;
-  char*	_textinfo;
-  char*	_remote_uri;
-  
-  char*	_remote_sdp_audio_ip;
-  int		_local_audio_port;
-  int  	_remote_sdp_audio_port;
-  int 	_local_sendrecv;           /* _SENDRECV, _SENDONLY, _RECVONLY */
-  int 	_remote_sendrecv;          /* _SENDRECV, _SENDONLY, _RECVONLY */
-
-  std::string _localIp;
-  std::string _name;   // set by incoming call
-  std::string _number; // set by incoming call
-
-  bool _reinvite;
+  /**
+   * Set peer name and number with event->request->from
+   * @param event eXosip event
+   * @return false the event is invalid
+   */
+  bool setPeerInfoFromRequest(eXosip_event_t *event);
+  /**
+   * Get a valid remote SDP or return a 400 bad request response if invalid
+   * @param event eXosip event
+   * @return valid remote_sdp or 0
+   */
+  sdp_message_t* getRemoteSDPFromRequest(eXosip_event_t *event);
+
+  /**
+   * Get a valid remote media or return a 415 unsupported media type
+   * @param tid transaction id
+   * @param remote_sdp Remote SDP pointer
+   * @return valid sdp_media_t or 0
+   */
+  sdp_media_t* getRemoteMedia(int tid, sdp_message_t* remote_sdp);
+
+  /**
+   * Set Audio Port and Audio IP from Remote SDP Info
+   * @param remote_med Remote Media info
+   * @param remote_sdp Remote SDP pointer
+   * @return true if everything is set correctly
+   */
+  bool setRemoteAudioFromSDP(sdp_media_t* remote_med, sdp_message_t* remote_sdp);
+
+  /**
+   * Set Audio Codec with the remote choice
+   * @param remote_med Remote Media info
+   * @return true if everything is set correctly
+   */
+  bool setAudioCodecFromSDP(sdp_media_t* remote_med, int tid);
+
+ 
+  /** SIP call id */
+  int _cid;
+  /** SIP domain id */
+  int _did;
+  /** SIP transaction id */
+  int _tid;
+
+  /** Codec Map */
+  CodecDescriptorMap _codecMap;
+  /** codec pointer */
+  AudioCodec* _audioCodec;
+  bool _audioStarted;
+
+  // Informations about call socket / audio
+  std::string _localIPAddress;
+  unsigned int _localAudioPort;
+  unsigned int _localExternalAudioPort; // what peer (NAT) should connect to
+
+  std::string _remoteIPAddress;
+  unsigned int _remoteAudioPort;
 };
 
-#endif // __SIP_CALL_H__
+#endif
diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp
index 314f462852e1e8d1f12e9413d643e83a40f623de..9214b097222dac6b357745f4fa36f3e583fcb7f5 100644
--- a/src/sipvoiplink.cpp
+++ b/src/sipvoiplink.cpp
@@ -1,10 +1,8 @@
 /*
- *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
+ *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *
- *  Portions Copyright (C) 2002,2003   Aymeric Moizard <jack@atosc.org>
- *
  *  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
  *  the Free Software Foundation; either version 2 of the License, or
@@ -19,564 +17,686 @@
  *  along with this program; if not, write to the Free Software
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include <eXosip2/eXosip.h>
-#include <osip2/osip.h>
-#include <osipparser2/osip_const.h>
-
 #include "sipvoiplink.h"
-#include "global.h"
-#include "audio/codecDescriptor.h"
-#include "manager.h"
-#include "sipcall.h"
-#include "user_cfg.h"
 #include "eventthread.h"
+#include "sipcall.h"
+#include <sstream> // for ostringstream
+
+#include "manager.h"
+#include "user_cfg.h" // SIGNALISATION / PULSE #define
 
-#define DEFAULT_SIP_PORT	5060
-#define RANDOM_SIP_PORT		rand() % 64000 + 1024
-#define	DEFAULT_LOCAL_PORT	10500
-#define	RANDOM_LOCAL_PORT	((rand() % 27250) + 5250)*2
+// for listener
+#define DEFAULT_SIP_PORT  5060
+#define RANDOM_SIP_PORT   rand() % 64000 + 1024
+#define RANDOM_LOCAL_PORT ((rand() % 27250) + 5250)*2
 
 #define EXOSIP_ERROR_NO   0
 #define EXOSIP_ERROR_STD -1
 #define EXOSIP_ERROR_BUILDING -2
 
-#define VOICE_MSG			"Voice-Message"
-#define LENGTH_VOICE_MSG	15
+// for registration
+#define EXPIRES_VALUE 180
+
+// 1XX responses
+#define DIALOG_ESTABLISHED 101
+// see: osip_const.h
 
-SipVoIPLink::SipVoIPLink() : VoIPLink()
+// 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("")
 {
-  // default _audioRTP object initialization
   _evThread = new EventThread(this);
-  _localPort = 0;
+
   _nMsgVoicemail = 0;
-  _reg_id = EXOSIP_ERROR_STD;
+  _eXosipRegID = EXOSIP_ERROR_STD;
+  _eXosipStarted = false;
+
+  _nbTryListenAddr = 2; // number of times to try to start SIP listener
+  _localExternPort = 0;
+
+  // to get random number for RANDOM_PORT
+  srand (time(NULL));
+}
 
-  _registrationSend = false;
-  _started = false;
-  _localIpAddress = "127.0.0.1"; // sipvoip require this value to check network
+SIPVoIPLink::~SIPVoIPLink()
+{
+  delete _evThread; _evThread = 0;
+  terminate();
+}
+
+bool 
+SIPVoIPLink::init()
+{
+  if (!_eXosipStarted) {
+    if (0 != eXosip_init()) {
+      _debug("Could not initialize eXosip\n");
+      return false;
+    }
+    _eXosipStarted = true;
+  
+    // check networking capabilities
+    if ( !checkNetwork() ) {
+      _debug("SIP FAILURE: Unable to determine network capabilities\n");
+      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 {
+      if (_useStun && !Manager::instance().behindNat(port)) { 
+        port = RANDOM_SIP_PORT; 
+        if (!Manager::instance().behindNat(port)) {
+         _debug("SIP FAILURE: Unable to check NAT setting\n");
+          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) {
+        _debug("SIP ERROR: [%d/%d] could not initialize SIP listener on port %d\n", iTry, _nbTryListenAddr, port);
+        port = RANDOM_SIP_PORT;
+      }
+    } while ( errExosip != 0 && iTry < _nbTryListenAddr );
+  
+    if ( errExosip != 0 ) { // we didn't succeeded
+      _debug("SIP FAILURE: SIP failed to listen on port %d\n", port);
+      return false;
+    }
+    _localPort = port;
+    _debug("SIP Init: listening on port %d\n", port);
+    
+    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());
+  
+    _debug("SIP Init: starting loop thread (SIP events)\n");
+    _evThread->start();
+  }
+  return _eXosipStarted;
 }
 
-SipVoIPLink::~SipVoIPLink(void) {
-  endSipCalls();
-  delete _evThread; _evThread = NULL;
-  if (_started) {
+
+
+void 
+SIPVoIPLink::terminate()
+{
+  terminateSIPCall(); 
+  if (_eXosipStarted) {
     eXosip_quit();
+    _eXosipStarted = false;
   }
 }
 
-// for voIPLink interface
 void
-SipVoIPLink::terminate(void) 
+SIPVoIPLink::terminateSIPCall()
 {
+  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();
 }
 
 bool
-SipVoIPLink::checkNetwork (void)
+SIPVoIPLink::checkNetwork()
 {
   // Set IP address
-  return getSipLocalIp();
+  return loadSIPLocalIP();
 }
 
-
-/**
- * Steps:
- * 1. Init eXosip
- * 2. Try to listen two times on a port
- *    if we use stun, we check if we can use 5060, before connecting to eXosip...
- *    if we can't we check on a random port
- */
 bool
-SipVoIPLink::init(void)
+SIPVoIPLink::loadSIPLocalIP() 
 {
-  // TODO: should be inside the account
-  _fullname = Manager::instance().getConfigString(SIGNALISATION,FULL_NAME) ;
-  _hostname = Manager::instance().getConfigString(SIGNALISATION,HOST_PART);
-
-  if (0 != eXosip_init()) {
-    _debug("Could not initialize eXosip\n");
-    return false;
-  }
-  _started = true;
-
-  srand (time(NULL));
-  int i;
-
-  // check networking capabilities
-  if ( !checkNetwork() ) {
-    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
-  bool useStun = Manager::instance().useStun();
-  int port = DEFAULT_SIP_PORT;
-
-  int nbTry = 2; // number of times to try to start SIP listener
-  int iTry = 1;  // try number..
-
-  do {
-    if (useStun && !behindNat(port)) { 
-      port = RANDOM_SIP_PORT; 
-      if (!behindNat(port)) {
-        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
-    i = eXosip_listen_addr(IPPROTO_UDP, INADDR_ANY, port, AF_INET, 0);
-    if (i != 0) {
-      _debug("SIP ERROR: [%d/%d] could not initialize SIP listener on port %d\n", iTry, nbTry, port);
-      port = RANDOM_SIP_PORT;
+  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);
+      _debug("Checking network, setting local IP address to: %s\n", myIPAddress);
     }
-  } while ( i != 0 && iTry < nbTry );
-
-  if ( i != 0 ) { // we didn't succeeded
-    _debug("SIP FAILURE: SIP failed to listen on port %d\n", port);
-    return false;
-  }
-  _debug("SIP Init: listening on port %d\n", port);
-  
-  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
-    eXosip_masquerade_contact((Manager::instance().getFirewallAddress()).data(), Manager::instance().getFirewallPort());
+    delete [] myIPAddress; myIPAddress = NULL;
   }
-
-  // Set user agent
-  std::string tmp = std::string(PROGNAME_GLOBAL) + "/" + std::string(SFLPHONED_VERSION);
-  eXosip_set_user_agent(tmp.data());
-
-  _debug("SIP Init: starting loop thread (SIP events)\n");
-  _evThread->start();
-  return true;
+  return returnValue;
 }
 
-/**
- * Subscibe to message-summary notify
- * It allows eXosip to not send ' 481 Subcription Does Not Exist ' response
- */
 void
-SipVoIPLink::subscribeMessageSummary()
+SIPVoIPLink::getEvent()
 {
-  osip_message_t *subscribe;
-  const char *route= NULL;
-
-  // from/to
-  ManagerImpl& manager = Manager::instance();
-  std::string from = fromHeader(manager.getConfigString(SIGNALISATION, USER_PART), manager.getConfigString(SIGNALISATION, HOST_PART));
-
-  // to
-  std::string to;
-  to = manager.getConfigString(SIGNALISATION, PROXY);
-  if (!to.empty()) {
-    to = toHeader(manager.getConfigString(SIGNALISATION, USER_PART)) + "@" + to;
-  } else {
-    to = from;
-  }
-  
-
-  // like in http://www.faqs.org/rfcs/rfc3842.html
-  const char *event="message-summary";
-  int expires = 86400;
-
-  // return 0 if no error
-  // the first from is the to... but we send the same
+  eXosip_event_t* event = eXosip_event_wait(0, 50);
   eXosip_lock();
-  int error = eXosip_subscribe_build_initial_request(&subscribe, to.c_str(), from.c_str(), route, event, expires);
+  eXosip_automatic_action();
   eXosip_unlock();
 
-  if (error == 0) {
-    // Accept: application/simple-message-summary
-    osip_message_set_header (subscribe, "Accept", "application/simple-message-summary");
-
-    _debug("Sending Message-summary subscription");
-    // return 0 if ok
-    eXosip_lock();
-    error = eXosip_subscribe_send_initial_request (subscribe);
-    eXosip_unlock();
-    _debug(" and return %d\n", error);
+  if (event == NULL) {
+    return;
   }
+
+  _debug("SIP Event: [cdt=%4d:%4d:%4d] type=#%03d %s \n", event->cid, event->did, event->tid, event->type, event->textinfo);
+  switch (event->type) {
+     /* REGISTER related events */
+     case EXOSIP_REGISTRATION_NEW:         /** 00 < announce new registration.       */
+       _debug("EXOSIP_REGISTRATION_NEW event is not implemented\n");
+       break;
+     case EXOSIP_REGISTRATION_SUCCESS:     /** 01 < user is successfully registred.  */
+       Manager::instance().registrationSucceed(getAccountID());
+       break;
+     case EXOSIP_REGISTRATION_FAILURE:     /** 02 < user is not registred.           */
+       Manager::instance().registrationFailed(getAccountID());
+       break;
+     case EXOSIP_REGISTRATION_REFRESHED:   /** 03 < registration has been refreshed. */
+       _debug("EXOSIP_REGISTRATION_REFRESHED event is not implemented\n");
+       break;
+     case EXOSIP_REGISTRATION_TERMINATED:  /** 04 < UA is not registred any more.    */
+       _debug("EXOSIP_REGISTRATION_TERMINATED event is not implmeneted\n");
+       break;
+      
+      /* INVITE related events within calls */
+     case EXOSIP_CALL_INVITE:          /** 05 < announce a new call                   */
+       SIPCallInvite(event);
+       break;
+     case EXOSIP_CALL_REINVITE:        /** 06 < announce a new INVITE within call     */
+       SIPCallReinvite(event);
+       break;
+
+     case EXOSIP_CALL_NOANSWER:        /** 07 < announce no answer within the timeout */
+       _debug("EXOSIP_CALL_NOANSWER event is not implemented\n");
+       break;
+     case EXOSIP_CALL_PROCEEDING:      /** 08 < announce processing by a remote app   */
+       _debug("EXOSIP_CALL_NOANSWER event is not implemented\n");
+       break;
+     case EXOSIP_CALL_RINGING:         /** 09 < announce ringback                     */
+       SIPCallRinging(event);
+       break;
+     case EXOSIP_CALL_ANSWERED:        /** 10 < announce start of call                */
+       SIPCallAnswered(event);
+       break;
+     case EXOSIP_CALL_REDIRECTED:      /** 11 < announce a redirection                */
+       _debug("EXOSIP_CALL_REDIRECTED event is not implemented\n");
+       break;
+     case EXOSIP_CALL_REQUESTFAILURE:  /** 12 < announce a request failure            */
+       SIPCallRequestFailure(event);
+       break;
+     case EXOSIP_CALL_SERVERFAILURE:   /** 13 < announce a server failure             */
+       SIPCallServerFailure(event);
+       break;
+     case EXOSIP_CALL_GLOBALFAILURE:   /** 14 < announce a global failure             */
+       SIPCallServerFailure(event);
+       break;
+     case EXOSIP_CALL_ACK:             /** 15 < ACK received for 200ok to INVITE      */
+       SIPCallAck(event);
+       break;
+      
+     case EXOSIP_CALL_CANCELLED:       /** 16 < announce that call has been cancelled */
+     case EXOSIP_CALL_TIMEOUT:         /** 17 < announce that call has failed         */
+       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. */
+      SIPCallMessageNew(event);
+      break;
+     case EXOSIP_CALL_MESSAGE_PROCEEDING:     /** 19 < announce a 1xx for MESSAGE. */
+     case EXOSIP_CALL_MESSAGE_ANSWERED:       /** 20 < announce a 200ok  */
+       // 200 OK
+     case EXOSIP_CALL_MESSAGE_REDIRECTED:     /** 21 < announce a failure. */
+     case EXOSIP_CALL_MESSAGE_REQUESTFAILURE: /** 22 < announce a failure. */
+     case EXOSIP_CALL_MESSAGE_SERVERFAILURE:  /** 23 < announce a failure. */
+     case EXOSIP_CALL_MESSAGE_GLOBALFAILURE:  /** 24 < announce a failure. */
+       Manager::instance().displayError("EXOSIP Call Message not implemented yet");
+       break;
+
+     case EXOSIP_CALL_CLOSED:          /** 25 < a BYE was received for this call      */
+       SIPCallClosed(event);
+       break;
+
+      /* for both UAS & UAC events */
+     case EXOSIP_CALL_RELEASED:           /** 26 < call context is cleared.            */
+       SIPCallReleased(event);
+       break;
+     
+      /* response received for request outside calls */
+     case EXOSIP_MESSAGE_NEW:            /** 27 < announce new incoming MESSAGE. */
+       if (event->request == NULL) { break; }
+       SIPMessageNew(event);
+       break;
+     case EXOSIP_MESSAGE_PROCEEDING:     /** 28 < announce a 1xx for MESSAGE. */
+     case EXOSIP_MESSAGE_ANSWERED:       /** 29 < announce a 200ok  */
+     case EXOSIP_MESSAGE_REDIRECTED:     /** 30 < announce a failure. */
+       Manager::instance().displayError("EXOSIP Message not implemented yet");
+     break;
+
+     case EXOSIP_MESSAGE_REQUESTFAILURE: /** 31 < announce a failure. */
+       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. */
+     case EXOSIP_MESSAGE_GLOBALFAILURE:  /** 33 < announce a failure. */
+       Manager::instance().displayError("EXOSIP Message not implemented yet");
+       break;
+      
+      /* Presence and Instant Messaging */
+     case EXOSIP_SUBSCRIPTION_UPDATE:       /** 34 < announce incoming SUBSCRIBE.      */
+     case EXOSIP_SUBSCRIPTION_CLOSED:       /** 35 < announce end of subscription.     */
+       Manager::instance().displayError("EXOSIP Subscription not implemented yet");
+       break;
+      
+     case EXOSIP_SUBSCRIPTION_NOANSWER:        /** 37 < announce no answer              */
+     case EXOSIP_SUBSCRIPTION_PROCEEDING:      /** 38 < announce a 1xx                  */
+       Manager::instance().displayError("EXOSIP Subscription resposne not implemented yet");
+       break;
+     case EXOSIP_SUBSCRIPTION_ANSWERED:        /** 39 < announce a 200ok                */
+       eXosip_lock();
+       eXosip_automatic_action();
+       eXosip_unlock();
+     break;
+
+     case EXOSIP_SUBSCRIPTION_REDIRECTED:      /** 40 < announce a redirection          */
+     case EXOSIP_SUBSCRIPTION_REQUESTFAILURE:  /** 41 < announce a request failure      */
+     case EXOSIP_SUBSCRIPTION_SERVERFAILURE:   /** 42 < announce a server failure       */
+     case EXOSIP_SUBSCRIPTION_GLOBALFAILURE:   /** 43 < announce a global failure       */
+     case EXOSIP_SUBSCRIPTION_NOTIFY:          /** 44 < announce new NOTIFY request     */
+     case EXOSIP_SUBSCRIPTION_RELEASED:        /** 45 < call context is cleared.        */
+       Manager::instance().displayError("EXOSIP Subscription resposne not implemented yet");
+       break;
+      
+     case EXOSIP_IN_SUBSCRIPTION_NEW:          /** 46 < announce new incoming SUBSCRIBE.*/
+     case EXOSIP_IN_SUBSCRIPTION_RELEASED:     /** 47 < announce end of subscription.   */
+       Manager::instance().displayError("EXOSIP Subscription not implemented yet");
+       break;
+      
+     case EXOSIP_EVENT_COUNT:               /** 48 < MAX number of events  */
+      break;
+  }  
+  eXosip_event_free(event);
 }
 
-int
-SipVoIPLink::setRegister (void) 
+bool
+SIPVoIPLink::setRegister()
 {
-  ManagerImpl& manager = Manager::instance();
-
-  if (_reg_id != EXOSIP_ERROR_STD) {
-    manager.displayError("Registration already sent. Try to unregister");
-    return EXOSIP_ERROR_STD;
+  if (_eXosipRegID != EXOSIP_ERROR_STD) {
+    Manager::instance().displayError("SIP Error: Registration already sent. Try to unregister");
+    return false;
   }
 
-  // all this will be inside the profil associate with the voip link
-  std::string proxy = "sip:" + manager.getConfigString(SIGNALISATION, PROXY);
-  std::string hostname = "sip:" + manager.getConfigString(SIGNALISATION, HOST_PART);
-  std::string from = fromHeader(manager.getConfigString(SIGNALISATION, USER_PART), manager.getConfigString(SIGNALISATION, HOST_PART));
-
-  if (manager.getConfigString(SIGNALISATION, HOST_PART).empty()) {
-    manager.displayConfigError("Fill host part field");
-    return EXOSIP_ERROR_STD;
+  std::string hostname = getHostName();
+  if (hostname.empty()) {
+    Manager::instance().displayConfigError("Fill host part field");
+    return false;
   }
-  if (manager.getConfigString(SIGNALISATION, USER_PART).empty()) {
-    manager.displayConfigError("Fill user part field");
-    return EXOSIP_ERROR_STD;
+
+  if (_userpart.empty()) {
+    Manager::instance().displayConfigError("Fill user part field");
+    return false;
   }
 
+
+  std::string proxy = "sip:" + _proxy;
+  hostname = "sip:" + hostname;
+  std::string from = SIPFromHeader(_userpart, getHostName());
+  
   osip_message_t *reg = NULL;
   eXosip_lock();
-  if (!manager.getConfigString(SIGNALISATION, PROXY).empty()) {
-    _debug("REGISTER From: %s to %s\n", from.data(), proxy.data());
-    _reg_id = eXosip_register_build_initial_register ((char*)from.data(), 
-						      (char*)proxy.data(), NULL, EXPIRES_VALUE, &reg);
+  if (!_proxy.empty()) {
+    _debug("SIP Register: From: %s to %s\n", from.data(), proxy.data());
+    _eXosipRegID = eXosip_register_build_initial_register(from.data(), 
+                  proxy.data(), NULL, EXPIRES_VALUE, &reg);
   } else {
-    _debug("REGISTER From: %s to %s\n", from.data(), hostname.data());
-    _reg_id = eXosip_register_build_initial_register ((char*)from.data(), 
-						      (char*)hostname.data(), NULL, EXPIRES_VALUE, &reg);
+    _debug("SIP Register: From: %s to %s\n", from.data(), hostname.data());
+    _eXosipRegID = eXosip_register_build_initial_register(from.data(), 
+                  hostname.data(), NULL, EXPIRES_VALUE, &reg);
   }
   eXosip_unlock();
-  if (_reg_id < EXOSIP_ERROR_NO ) {
-    return EXOSIP_ERROR_STD;
+  if (_eXosipRegID < EXOSIP_ERROR_NO ) {
+    return false;
   }
 
-  if (setAuthentication() != EXOSIP_ERROR_NO) {
-    _debug("No authentication\n");
-    return EXOSIP_ERROR_STD;
+  if (!sendSIPAuthentification()) {
+    _debug("SIP Register: No authentication\n");
+    return false;
   }
 
   osip_message_set_header (reg, "Event", "Registration");
   osip_message_set_header (reg, "Allow-Events", "presence");
 
   eXosip_lock();
-  int i = eXosip_register_send_register (_reg_id, reg);
-  if (i == -2) {
-    _debug("Cannot build registration, check the setup\n"); 
+  int eXosipErr = eXosip_register_send_register(_eXosipRegID, reg);
+  if (eXosipErr == EXOSIP_ERROR_BUILDING) {
+    _debug("SIP Failure: Cannot build registration, check the setup\n"); 
     eXosip_unlock();
-    return EXOSIP_ERROR_STD;
+    return false;
   }
-  if (i == -1) {
-    _debug("Registration sending failed\n");
+  if (eXosipErr == EXOSIP_ERROR_STD) {
+    _debug("SIP Failure: Registration sending failed\n");
     eXosip_unlock();
-    return EXOSIP_ERROR_STD;
+    return false;
   }
   eXosip_unlock();
 
-  // subscribe to message one time?
-  // subscribeMessageSummary();
-  _registrationSend = true;
-  return i;
+  return true;
 }
 
-/**
- * setUnregister 
- * unregister if we already send the first registration
- * @return -1 if there is an error
- */
-int 
-SipVoIPLink::setUnregister (void)
+std::string
+SIPVoIPLink::SIPFromHeader(const std::string& userpart, const std::string& hostpart) 
 {
-  if ( _registrationSend ) {
-    int i = 0;
-    osip_message_t *reg = NULL;
-
-    eXosip_lock();
-
-    if (_reg_id > 0) {
-      i = eXosip_register_build_register (_reg_id, 0, &reg);
-    }
-    eXosip_unlock();
-    if (i < 0) {
-      return EXOSIP_ERROR_STD;
-    }
-
-    eXosip_lock();
-    _debug("< Sending REGISTER (expire=0)\n");
-    i = eXosip_register_send_register (_reg_id, reg);
-    if (i == EXOSIP_ERROR_BUILDING) {
-      _debug("  Cannot build registration (unregister), check the setup\n"); 
-      eXosip_unlock();
-      return EXOSIP_ERROR_STD;
-    }
-    if (i == EXOSIP_ERROR_STD) {
-      _debug("  Registration (unregister) Failed\n");
-    }
-    eXosip_unlock();
-    _reg_id = EXOSIP_ERROR_STD;
-    return i;
-  } else {
-    // no registration send before
-    return EXOSIP_ERROR_STD;
-  }
+  return ("\"" + getFullName() + "\"" + " <sip:" + userpart + "@" + hostpart + ">");
 }
 
-/**
- * Get the Sip FROM url (add sip:, add @host, etc...)
- */ 
-std::string
-SipVoIPLink::getSipFrom() {
-
-  // Form the From header field basis on configuration panel
-  std::string user = Manager::instance().getConfigString(SIGNALISATION, USER_PART);
-  std::string host = Manager::instance().getConfigString(SIGNALISATION, HOST_PART);
-  if ( host.empty() ) {
-    host = getLocalIpAddress();
+bool
+SIPVoIPLink::sendSIPAuthentification() 
+{
+  std::string login = _authname;
+  if (login.empty()) {
+    login = _userpart;
   }
-  return fromHeader(user, host);
+  if (login.empty()) {
+    Manager::instance().displayConfigError("Fill authentification name");
+    return false;
+  }
+  if (_password.empty()) {
+    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);
 }
 
-/**
- * Get the Sip TO url (add sip:, add @host, etc...)
- */
-std::string
-SipVoIPLink::getSipTo(const std::string& to_url) {
-  // Form the From header field basis on configuration panel
-  bool isRegistered = (_reg_id < EXOSIP_ERROR_NO) ? false : true;
+bool
+SIPVoIPLink::setUnregister()
+{
+  if ( _eXosipRegID == EXOSIP_ERROR_STD) return false;
+  int eXosipErr = EXOSIP_ERROR_NO;
+  osip_message_t *reg = NULL;
 
-  // add a @host if we are registered and there is no one inside the url
-  if (to_url.find("@") == std::string::npos && isRegistered) {
-    std::string host = Manager::instance().getConfigString(SIGNALISATION, HOST_PART);
-    if(!host.empty()) {
-      return toHeader(to_url + "@" + host);
-    }
+  eXosip_lock();
+  eXosipErr = eXosip_register_build_register (_eXosipRegID, 0, &reg);
+  eXosip_unlock();
+
+  if (eXosipErr != EXOSIP_ERROR_NO) {
+    _debug("SIP Failure: Unable to build registration for setUnregister");
+    return false;
   }
-  return toHeader(to_url);
-}
 
-/**
- * Get the sip proxy (add sip: if there is one) 
- * @return empty string or <sip:proxy;lr> url
- */
-std::string
-SipVoIPLink::getSipRoute() {
-  std::string proxy = Manager::instance().getConfigString(SIGNALISATION, PROXY);
-  if ( !proxy.empty() ) {
-    proxy = "<sip:" + proxy + ";lr>";
+  eXosip_lock();
+  _debug("< Sending REGISTER (expire=0)\n");
+  eXosipErr = eXosip_register_send_register (_eXosipRegID, reg);
+  if (eXosipErr == EXOSIP_ERROR_BUILDING) {
+    _debug("SIP Failure: Cannot build registration (unregister), check the setup\n"); 
+    eXosip_unlock();
+    return false;
   }
-  return proxy; // return empty
+  if (eXosipErr == EXOSIP_ERROR_STD) {
+    _debug("SIP Failure: Unable to send registration (unregister)\n");
+  }
+  eXosip_unlock();
+  _eXosipRegID = EXOSIP_ERROR_STD;
+
+  return true;
 }
 
-int
-SipVoIPLink::outgoingInvite (CALLID id, const std::string& to_url) 
+Call* 
+SIPVoIPLink::newOutgoingCall(const CallID& id, const std::string& toUrl)
 {
-  bool has_ip = checkNetwork();
-  std::string from  = getSipFrom();
-  std::string to    = getSipTo(to_url);
-  std::string route = getSipRoute();
-
-  _debug("            From: %s\n", from.data());
-  _debug("            To: %s\n", to.data());
-  _debug("            Route: %s\n", route.data());
-
-  // If no SIP proxy setting for direct call with only IP address
-  if (has_ip) {
-    if (startCall(id, from, to, "", route) <= 0) {
-      _debug("Warning SipVoIPLink: call not started\n");
-      return EXOSIP_ERROR_STD;
+  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;
     }
-  } else {
-    Manager::instance().displayErrorText(id, "No network found\n");
-    return EXOSIP_ERROR_STD;
   }
-  return 0;
+  return call;
 }
 
-/**
- * @return 0 is good, -1 is bad
- */
-int
-SipVoIPLink::answer(CALLID id) 
+bool
+SIPVoIPLink::answer(const CallID& id)
 {
-  int i;
-  int port;
-  char tmpbuf[64];
-  bzero (tmpbuf, 64);
-  // Get  port   
-  snprintf (tmpbuf, 63, "%d", getSipCall(id)->getLocalAudioPort());
-
-  _debug("%10d: Answer call [cid = %d, did = %d]\n", id, getSipCall(id)->getCid(), getSipCall(id)->getDid());
-  port = getSipCall(id)->getLocalAudioPort();
-  _debug("            Local audio port: %d\n", port);
+  _debug("SIP Action: start answering\n");
 
-  osip_message_t *answerMessage = NULL;
-  SipCall* ca = getSipCall(id);
+  SIPCall* call = getSIPCall(id);
+  if (call==0) {
+    _debug("SIP Failure: SIPCall doesn't exists\n");
+    return false;
+  }
 
   // Send 180 RINGING
   _debug("< Send 180 Ringing\n");
   eXosip_lock ();
-  eXosip_call_send_answer(ca->getTid(), RINGING, NULL);
+  eXosip_call_send_answer(call->getTid(), SIP_RINGING, NULL);
   eXosip_unlock ();
+  call->setConnectionState(Call::Ringing);
 
   // Send 200 OK
+  osip_message_t *answerMessage = NULL;
   eXosip_lock();
-  i = eXosip_call_build_answer(ca->getTid(), OK, &answerMessage);
+  _debug("< Building 200 OK\n");
+  int i = eXosip_call_build_answer(call->getTid(), SIP_OK, &answerMessage);
   if (i != 0) {
    _debug("< Send 400 Bad Request\n");
-    eXosip_call_send_answer (ca->getTid(), BAD_REQ, NULL);
+    eXosip_call_send_answer (call->getTid(), SIP_BAD_REQUEST, NULL);
   } else {
     // use exosip, bug locked
     i = 0;
-    sdp_message_t *remote_sdp = eXosip_get_remote_sdp(ca->getDid());
+    sdp_message_t *remote_sdp = eXosip_get_remote_sdp(call->getDid());
     if (remote_sdp!=NULL) {
-      i = ca->sdp_complete_message(remote_sdp, answerMessage);
+      i = call->sdp_complete_message(remote_sdp, answerMessage);
       if (i!=0) {
         osip_message_free(answerMessage);
       }
-      sdp_message_free (remote_sdp);
+      sdp_message_free(remote_sdp);
     }
     if (i != 0) {
       _debug("< Send 415 Unsupported Media Type\n");
-      eXosip_call_send_answer (ca->getTid(), UNSUP_MEDIA_TYPE, NULL);
+      eXosip_call_send_answer (call->getTid(), SIP_UNSUPPORTED_MEDIA_TYPE, NULL);
     } else {
       _debug("< Send 200 OK\n");
-      eXosip_call_send_answer (ca->getTid(), OK, answerMessage);
+      eXosip_call_send_answer (call->getTid(), SIP_OK, answerMessage);
     }
   }
   eXosip_unlock();
 
-  // Incoming call is answered, start the sound channel.
-  _debug("          Starting AudioRTP\n");
-  if (_audiortp.createNewSession (getSipCall(id)) < 0) {
-    _debug("FATAL: Unable to start sound (%s:%d)\n", __FILE__, __LINE__);
-    i = EXOSIP_ERROR_STD;
+  if(i==0) {
+    // Incoming call is answered, start the sound channel.
+    _debug("          Starting AudioRTP\n");
+    if (_audiortp.createNewSession(call) >= 0) {
+      call->setAudioStart(true);
+      call->setConnectionState(Call::Connected);
+      call->setState(Call::Active);
+      return true;
+    } else {
+      _debug("FATAL: Unable to start sound when answering %s/%d\n", __FILE__, __LINE__);
+    }
   }
-  return i;
-}
+  removeCall(call->getCallId());
+  return false;
 
+/*  int i;
+  int port;
+  char tmpbuf[64];
+  bzero (tmpbuf, 64);
+  // Get  port   
+  snprintf (tmpbuf, 63, "%d", getSipCall(id)->getLocalAudioPort());
 
-/**
- * @return > 0 is good, -1 is bad
- */
-int
-SipVoIPLink::hangup (CALLID id) 
+  _debug("%10d: Answer call [cid = %d, did = %d]\n", id, getSipCall(id)->getCid(), getSipCall(id)->getDid());
+  port = getSipCall(id)->getLocalAudioPort();
+  _debug("            Local audio port: %d\n", port);
+*/
+}
+
+bool
+SIPVoIPLink::hangup(const CallID& id)
 {
-  int i = 0;
-  SipCall* sipcall = getSipCall(id);
-  if (sipcall == NULL) { return EXOSIP_ERROR_STD; }
-  _debug("%10d: Hang up call [cid = %d, did = %d]\n", 
-    id, sipcall->getCid(), sipcall->getDid());	
+  SIPCall* call = getSIPCall(id);
+  if (call==0) { _debug("Call doesn't exist\n"); return false; }  
+
+  _debug("Hang up call %s [cd: %3d %3d]\n", id.data(), call->getCid(), call->getDid()); 
   // Release SIP stack.
   eXosip_lock();
-  i = eXosip_call_terminate (sipcall->getCid(), sipcall->getDid());
+  eXosip_call_terminate(call->getCid(), call->getDid());
   eXosip_unlock();
 
   // Release RTP channels
-  if (id == Manager::instance().getCurrentCallId()) {
+  if (Manager::instance().isCurrentCall(id)) {
     _audiortp.closeRtpSession();
   }
-
-  deleteSipCall(id);
-  return i;
+  removeCall(id);
+  return true;
 }
 
-int
-SipVoIPLink::cancel (CALLID id) 
+bool
+SIPVoIPLink::cancel(const CallID& id)
 {
-  int i = 0;
-  SipCall* sipcall = getSipCall(id);
-  _debug("%10d: Cancel call [cid = %d]\n", id, sipcall->getCid());
+  SIPCall* call = getSIPCall(id);
+  if (call==0) { _debug("Call doesn't exist\n"); return false; }  
+
+  _debug("Cancel call %s [cid: %3d]\n", id.data(), call->getCid()); 
   // Release SIP stack.
   eXosip_lock();
-  i = eXosip_call_terminate (sipcall->getCid(), -1);
+  eXosip_call_terminate(call->getCid(), -1);
   eXosip_unlock();
 
-  deleteSipCall(id);
-  return i;
+  removeCall(id);
+  return true;
 }
 
-/*
- * @return -1 = sipcall not present
- */
-int
-SipVoIPLink::onhold (CALLID id) 
+bool
+SIPVoIPLink::onhold(const CallID& id)
 {
-  osip_message_t *invite;
-  int i;
-  int did;
-
-  sdp_message_t *local_sdp = NULL;
-
-  SipCall *sipcall = getSipCall(id);
-  if ( sipcall == NULL ) { return EXOSIP_ERROR_STD; }
+  SIPCall* call = getSIPCall(id);
+  if (call==0) { _debug("Call doesn't exist\n"); return false; }  
 
-  did = sipcall->getDid();
+  int did = call->getDid();
 
   eXosip_lock ();
-  local_sdp = eXosip_get_local_sdp (did);
+  sdp_message_t *local_sdp = eXosip_get_local_sdp(did);
   eXosip_unlock ();
 
   if (local_sdp == NULL) {
-    return EXOSIP_ERROR_STD;
+    _debug("SIP Failure: unable to find local_sdp\n");
+    return false;
   }
 
   // Build INVITE_METHOD for put call on-hold
+  osip_message_t *invite = NULL;
   eXosip_lock ();
-  i = eXosip_call_build_request (did, INVITE_METHOD, &invite);
+  int exosipErr = eXosip_call_build_request (did, INVITE_METHOD, &invite);
   eXosip_unlock ();
 
-  if (i != 0) {
+  if (exosipErr != 0) {
     sdp_message_free(local_sdp);
-    return EXOSIP_ERROR_STD;
+    _debug("SIP Failure: unable to build invite method to hold call\n");
+    return false;
   }
 
   /* add sdp body */
   {
     char *tmp = NULL;
 
-    i = sdp_hold_call (local_sdp);
+    int i = sdp_hold_call(local_sdp);
     if (i != 0) {
       sdp_message_free (local_sdp);
       osip_message_free (invite);
-      return EXOSIP_ERROR_STD;
+      _debug("SIP Failure: Unable to hold call in SDP\n");
+      return false;
     }
     
-    i = sdp_message_to_str (local_sdp, &tmp);
-    sdp_message_free (local_sdp);
+    i = sdp_message_to_str(local_sdp, &tmp);
+    sdp_message_free(local_sdp);
     if (i != 0) {
       osip_message_free (invite);
       osip_free (tmp);
-      return EXOSIP_ERROR_STD;
+      _debug("SIP Failure: Unable to translate sdp message to string\n");
+      return false;
     }
     osip_message_set_body (invite, tmp, strlen (tmp));
     osip_free (tmp);
     osip_message_set_content_type (invite, "application/sdp");
   }
   
-  // Send request
+  // Stop sound
+  call->setAudioStart(false);
   _audiortp.closeRtpSession();
 
+  // send request
+  _debug("< Send on hold request\n");
   eXosip_lock ();
-  i = eXosip_call_send_request (did, invite);
+  exosipErr = eXosip_call_send_request (did, invite);
   eXosip_unlock ();
   
-  // Disable audio
-  return i;
+  return true;
 }
 
-/**
- * @return 0 is good, -1 is bad
- */
-int
-SipVoIPLink::offhold (CALLID id) 
+bool 
+SIPVoIPLink::offhold(const CallID& id)
 {
-  osip_message_t *invite;
-  int i;
-  int did;
+  SIPCall* call = getSIPCall(id);
+  if (call==0) { _debug("Call doesn't exist\n"); return false; }  
 
-  sdp_message_t *local_sdp = NULL;
+  int did = call->getDid();
 
-  did = getSipCall(id)->getDid();
   eXosip_lock ();
-  local_sdp = eXosip_get_local_sdp (did);
+  sdp_message_t *local_sdp = eXosip_get_local_sdp(did);
   eXosip_unlock ();
+
   if (local_sdp == NULL) {
-    return EXOSIP_ERROR_STD;
+    _debug("SIP Failure: unable to find local_sdp\n");
+    return false;
   }
 
   // Build INVITE_METHOD for put call off-hold
+  osip_message_t *invite;
   eXosip_lock ();
-  i = eXosip_call_build_request (did, INVITE_METHOD, &invite);
+  int exosipErr = eXosip_call_build_request (did, INVITE_METHOD, &invite);
   eXosip_unlock ();
 
-  if (i != 0) {
+  if (exosipErr != 0) {
     sdp_message_free(local_sdp);
     return EXOSIP_ERROR_STD;
   }
@@ -585,11 +705,11 @@ SipVoIPLink::offhold (CALLID id)
   {
     char *tmp = NULL;
     
-    i = sdp_off_hold_call (local_sdp);
+    int i = sdp_off_hold_call (local_sdp);
     if (i != 0) {
       sdp_message_free (local_sdp);
       osip_message_free (invite);
-      return EXOSIP_ERROR_STD;
+      return false;
     }
     
     i = sdp_message_to_str (local_sdp, &tmp);
@@ -597,7 +717,7 @@ SipVoIPLink::offhold (CALLID id)
     if (i != 0) {
       osip_message_free (invite);
       osip_free (tmp);
-      return EXOSIP_ERROR_STD;
+      return false;
     }
     osip_message_set_body (invite, tmp, strlen (tmp));
     osip_free (tmp);
@@ -607,516 +727,67 @@ SipVoIPLink::offhold (CALLID id)
   // Send request
   _debug("< Send off hold request\n");
   eXosip_lock ();
-  i = eXosip_call_send_request (did, invite);
+  exosipErr = eXosip_call_send_request (did, invite);
   eXosip_unlock ();
 
   // Enable audio
   _debug("          Starting AudioRTP\n");
-  if (_audiortp.createNewSession (getSipCall(id)) < 0) {
-    _debug("FATAL: Unable to start sound (%s:%d)\n", __FILE__, __LINE__);
-    i = EXOSIP_ERROR_STD;
+  // it's sure that this is the current call id...
+  if (_audiortp.createNewSession(call) < 0) {
+    _debug("SIP Failure: Unable to start sound (%s:%d)\n", __FILE__, __LINE__);
+    return false;
   }
-  return i;
+  return true;
 }
 
-int
-SipVoIPLink::transfer (CALLID id, const std::string& to)
+bool 
+SIPVoIPLink::transfer(const CallID& id, const std::string& to)
 {
-  osip_message_t *refer;
-  int i;
-  std::string tmp_to;
-  tmp_to = toHeader(to);
+  SIPCall* call = getSIPCall(id);
+  if (call==0) { _debug("Call doesn't exist\n"); return false; }  
+
+  std::string tmp_to = SIPToHeader(to);
   if (tmp_to.find("@") == std::string::npos) {
-    tmp_to = tmp_to + "@" + Manager::instance().getConfigString(SIGNALISATION,
-HOST_PART);
+    tmp_to = tmp_to + "@" + getHostName();
   }
 
+  osip_message_t *refer;
   eXosip_lock();
   // Build transfer request
-  i = eXosip_call_build_refer (getSipCall(id)->getDid(), (char*)tmp_to.data(),
-			       &refer);
-  if (i == 0) {
+  int exosipErr = eXosip_call_build_refer(call->getDid(), (char*)tmp_to.data(), &refer);
+  if (exosipErr == 0) {
     // Send transfer request
-    i = eXosip_call_send_request (getSipCall(id)->getDid(), refer);
+    exosipErr = eXosip_call_send_request(call->getDid(), refer);
   }
   eXosip_unlock();
-  return i;
+
+  // shall we delete the call?
+  removeCall(id);
+  return true;
 }
 
-int
-SipVoIPLink::refuse (CALLID id)
+bool
+SIPVoIPLink::refuse (const CallID& id)
 {
-  int i;
-  char tmpbuf[64];
-  bzero (tmpbuf, 64);
-  // Get local port   
-  snprintf (tmpbuf, 63, "%d", getSipCall(id)->getLocalAudioPort());
-	
+  SIPCall* call = getSIPCall(id);
+  if (call==0) { _debug("Call doesn't exist\n"); return false; }  
+
   osip_message_t *answerMessage = NULL;
   eXosip_lock();
   // not BUSY.. where decline the invitation!
-  i = eXosip_call_build_answer (getSipCall(id)->getTid(), SIP_DECLINE, &answerMessage);
-  if (i == 0) {
-    i = eXosip_call_send_answer (getSipCall(id)->getTid(), SIP_DECLINE, answerMessage);
+  int exosipErr = eXosip_call_build_answer(call->getTid(), SIP_DECLINE, &answerMessage);
+  if (exosipErr == 0) {
+    exosipErr = eXosip_call_send_answer(call->getTid(), SIP_DECLINE, answerMessage);
   }
   eXosip_unlock();
-  return i;
-}
-
-int
-SipVoIPLink::getEvent (void)
-{
-  // wait for 0 s, 50 ms
-  eXosip_event_t* event = eXosip_event_wait (0, 50);
-  eXosip_lock();
-  eXosip_automatic_action();
-  eXosip_unlock();
-
-  if (event == NULL) {
-    return EXOSIP_ERROR_STD;
-  }
-
-  SipCall* sipcall = NULL;
-  CALLID id = 0;
-  int returnValue = EXOSIP_ERROR_NO;
-
-  _debug("SIP Event: #%03d %s\n", event->type, event->textinfo);
-
-  switch (event->type) {
-    // IP-Phone user receives a new call
-  case EXOSIP_CALL_INVITE: //
-    _debug("> INVITE (receive)\n");
-    checkNetwork();
-
-    // Set local random port for incoming call
-    if (!Manager::instance().useStun()) {
-      setLocalPort(RANDOM_LOCAL_PORT);
-    } else {
-      // If there is a firewall
-      if (behindNat(DEFAULT_LOCAL_PORT) != 0) {
-        setLocalPort(Manager::instance().getFirewallPort());
-      } else {
-        returnValue = EXOSIP_ERROR_STD;
-        break;
-      }
-    }
-
-    // Generate id
-    id = Manager::instance().generateNewCallId();
-    Manager::instance().pushBackNewCall(id, Call::Incoming);
-    _debug("%10d: [cid = %d, did = %d]\n", id, event->cid, event->did);
-
-    // Associate an audio port with a call
-    sipcall = getSipCall(id);
-    sipcall->setLocalAudioPort(_localPort);
-    sipcall->setLocalIp(getLocalIpAddress());
-    _debug("            Local listening port: %d\n", _localPort);
-    _debug("            Local listening IP: %s\n", getLocalIpAddress().c_str());
-
-    if (sipcall->newIncomingCall(event) == 0 ) {
-      if (Manager::instance().incomingCall(id, sipcall->getName(), sipcall->getNumber()) == EXOSIP_ERROR_STD) {
-        Manager::instance().displayError("Incoming Call Failed");
-        deleteSipCall(id);
-      }
-    } else {
-      Manager::instance().peerHungupCall(id);
-      deleteSipCall(id);
-      Manager::instance().displayError("Incoming Call Failed");
-    }
-    break;
-
-  case EXOSIP_CALL_REINVITE:
-    _debug("> INVITE (reinvite)\n");
-    //eXosip_call_send_answer(event->tid, 403, NULL);
-    //488 as http://www.atosc.org/pipermail/public/osip/2005-June/005385.html
-
-    id = findCallId(event);
-    if (id != 0) {
-      sipcall = getSipCall(id);
-      if (sipcall != 0) {
-        _debug("%10d: Receive Reinvite [cid = %d, did = %d], localport=%d\n", id, event->cid, event->did,sipcall->getLocalAudioPort());
-
-        if ( id == Manager::instance().getCurrentCallId() ) {
-          Manager::instance().stopTone();
-          _audiortp.closeRtpSession();
-        }
-        sipcall->newReinviteCall(event);
-        // we should receive an ack after that...
-      }
-    } else {
-      _debug("< Send 488 Not Acceptable Here");
-      eXosip_lock();
-      eXosip_call_send_answer(event->tid, 488, NULL);
-      eXosip_unlock();
-    }
-    break;
-
-  case EXOSIP_CALL_PROCEEDING: // 8
-    // proceeding call...
-    break;
-
-  case EXOSIP_CALL_RINGING: // 9 peer call is ringing
-    id = findCallIdInitial(event);
-    _debug("%10d: Receive Call Ringing [cid = %d, did = %d]\n", id, event->cid, event->did);
-    if (id != 0) {
-      getSipCall(id)->ringingCall(event);
-      Manager::instance().peerRingingCall(id);
-    } else {
-      returnValue = -1;
-    }
-    break;
-
-  // The peer-user answers
-  case EXOSIP_CALL_ANSWERED: // 10
-  {
-    id = findCallIdInitial(event);
-    if ( id != 0) {
-      sipcall = getSipCall(id);
-      if ( sipcall != 0 ) {
-        _debug("%10d: Receive Call Answer [cid = %d, did = %d], localport=%d\n", id, event->cid, event->did, sipcall->getLocalAudioPort());
-
-        // Answer
-        if (Manager::instance().callCanBeAnswered(id)) {
-          sipcall->setStandBy(false);
-          if (sipcall->answeredCall(event) != -1) {
-            sipcall->answeredCall_without_hold(event);
-            Manager::instance().peerAnsweredCall(id);
-  
-            if(!Manager::instance().callIsOnHold(id) && Manager::instance().getCurrentCallId()==id) {
-              // Outgoing call is answered, start the sound channel.
-              _debug("            Starting AudioRTP\n");
-              if (_audiortp.createNewSession(sipcall) < 0) {
-                _debug("            FATAL: Unable to start sound (%s:%d)\n", 
-                __FILE__, __LINE__);
-                returnValue = -1;
-              }
-            }
-          }
-        } else {
-          // Answer to on/off hold to send ACK
-          _debug("            Answering call\n");
-          sipcall->answeredCall(event);
-        }
-      }
-    } else {
-      returnValue = -1;
-    }
-  }
-   break;
-  case EXOSIP_CALL_REDIRECTED: // 11
-    break;
-
-  case EXOSIP_CALL_ACK: // 15
-    id = findCallId(event); 
-    _debug("%10d: Receive ACK [cid = %d, did = %d]\n", id, event->cid, event->did);
-    if (id != 0 ) {
-      sipcall = getSipCall(id);
-      if(sipcall != 0 ) { 
-        sipcall->receivedAck(event);
-        if (sipcall->isReinvite()) {
-          sipcall->endReinvite();
-          if(!Manager::instance().callIsOnHold(id) && Manager::instance().getCurrentCallId()==id) {
-            _debug("            Starting AudioRTP\n");
-            _audiortp.createNewSession(sipcall);
-          } else {
-            _debug("            Didn't start RTP because it's on hold or it's not the current call id\n");
-          }
-        }
-      }
-    } else {
-      returnValue = -1;
-    }
-    break;
-
-    // The peer-user closed the phone call(we received BYE).
-  case EXOSIP_CALL_CLOSED: // 25
-    id = findCallId(event);
-    if (id==0) { id = findCallIdInitial(event); }
-    _debug("%10d: Receive BYE [cid = %d, did = %d]\n", id, event->cid, event->did);	
-    if (id != 0) {
-      if (Manager::instance().callCanBeClosed(id)) {
-         sipcall = getSipCall(id);
-         _audiortp.closeRtpSession();
-      }
-      Manager::instance().peerHungupCall(id);
-      deleteSipCall(id);
-    } else {
-      returnValue = -1;
-    }	
-    break;
-  case EXOSIP_CALL_RELEASED:
-    if (event) {
-      _debug("SIP call released: [cid = %d, did = %d]\n", event->cid, event->did);
-      id = findCallId(event);
-      if (id!=0) {
-        // not supposed to be execute on a current call...
-        Manager::instance().callFailure(id);
-        deleteSipCall(id);
-      }
-
-    }
-    break;
-  case EXOSIP_CALL_REQUESTFAILURE: //12
-
-    _debug("Request Failure, receive code %d\n", event->response->status_code);
-    // Handle 4XX errors
-    switch (event->response->status_code) {
-    case AUTH_REQUIRED: 
-      _debug("SIP Server ask required authentification: logging...\n");
-      setAuthentication();
-      eXosip_lock();
-      eXosip_automatic_action();
-      eXosip_unlock();
-      break;
-    case UNAUTHORIZED:
-      _debug("Request is unauthorized. SIP Server ask authentification: logging...\n");
-      setAuthentication();
-      break;
-
-    case BAD_REQ:
-    case FORBIDDEN:
-    case NOT_FOUND:
-    case NOT_ALLOWED:
-    case NOT_ACCEPTABLE:
-    case REQ_TIMEOUT:
-    case TEMP_UNAVAILABLE:
-    case ADDR_INCOMPLETE:
-    case NOT_ACCEPTABLE_HERE: // 488
-      // Display error on the screen phone
-      //Manager::instance().displayError(event->response->reason_phrase);
-      id = findCallId(event);
-      Manager::instance().displayErrorText(id, event->response->reason_phrase);
-      Manager::instance().callFailure(id);
-      deleteSipCall(id);
-    break;
-    case BUSY_HERE:
-      id = findCallId(event);
-      Manager::instance().displayErrorText(id, event->response->reason_phrase);
-      Manager::instance().callBusy(id);
-      deleteSipCall(id);
-      break;
-    case REQ_TERMINATED:
-      break;
-    default:
-      // sipphone.com send 478 Unresolveable destination (478/TM)
-      id = findCallId(event);
-      Manager::instance().displayErrorText(id, event->response->reason_phrase);
-      Manager::instance().callFailure(id);
-      deleteSipCall(id);
-      break;
-    }
-
-    break; 
-
-  case EXOSIP_CALL_SERVERFAILURE:
-    // Handle 5XX errors
-    switch (event->response->status_code) {
-    case SERVICE_UNAVAILABLE:
-      id = findCallId(event);
-      Manager::instance().callFailure(id);
-      break;
-    default:
-      break;
-    }
-    break;
-
-  case EXOSIP_CALL_GLOBALFAILURE:
-    // Handle 6XX errors
-    switch (event->response->status_code) {
-    case BUSY_EVERYWHERE:
-    case DECLINE:
-      id = findCallId(event);
-      Manager::instance().callFailure(id);
-      break;
-    default:
-      break;
-    }
-    break;
-
-  case EXOSIP_CALL_MESSAGE_NEW: // 18
-    if (0 == event->request) break;
-    if (MSG_IS_INFO(event->request)) {
-      _debug("Receive a call message request info\n");
-      osip_content_type_t* c_t = event->request->content_type;
-      if (c_t != 0 && c_t->type != 0 && c_t->subtype != 0 ) {
-        _debug("  Content Type of the message: %s/%s\n", c_t->type, c_t->subtype);
-        // application/dtmf-relay
-        if (strcmp(c_t->type, "application") == 0 && strcmp(c_t->subtype, "dtmf-relay") == 0) {
-          handleDtmfRelay(event);
-        }
-      }
-    }
-
-    osip_message_t *answerOKNewMessage;
-    eXosip_lock();
-    if ( 0 == eXosip_call_build_answer(event->tid, OK, &answerOKNewMessage)) {
-      _debug("< Sending 200 OK\n");
-      eXosip_call_send_answer(event->tid, OK, answerOKNewMessage);
-    } else {
-      _debug("Could not sent an OK message\n");
-    }
-    eXosip_unlock();
-    break;
- 
-  case EXOSIP_REGISTRATION_SUCCESS: // 1
-    // Manager::instance().displayStatus(LOGGED_IN_STATUS);
-    Manager::instance().registrationSucceed();
-    break;
-
-  case EXOSIP_REGISTRATION_FAILURE: // 2
-    //Manager::instance().displayError("getEvent : Registration Failure");
-    Manager::instance().registrationFailed();
-    break;
-
-  case EXOSIP_MESSAGE_NEW: //27
-
-    if ( event->request == NULL) {
-      break; // do nothing
-    }
-    unsigned int k;
-				
-    if (MSG_IS_OPTIONS(event->request)) {
-      for (k = 0; k < _sipcallVector.size(); k++) {
-        if (_sipcallVector.at(k)->getCid() == event->cid) { 
-          break;
-        }
-      }
-
-      // TODO: Que faire si rien trouve??
-      eXosip_lock();
-      if (k == _sipcallVector.size()) {
-        /* answer 200 ok */
-        eXosip_options_send_answer (event->tid, OK, NULL);
-
-      } else if (_sipcallVector.at(k)->getCid() == event->cid) {
-        /* already answered! */
-      } else {
-        /* answer 486 ok */
-      	eXosip_options_send_answer (event->tid, BUSY_HERE, NULL);
-      }
-      eXosip_unlock();
-    } 
-
-    // Voice message 
-    else if (MSG_IS_NOTIFY(event->request)){
-      _debug("> NOTIFY Voice message\n");
-      int ii;
-      unsigned int pos;
-      unsigned int pos_slash;
-
-      osip_body_t *body = NULL;
-      // Get the message body
-      ii = osip_message_get_body(event->request, 0, &body);
-      if (ii != 0) {
-        _debug("  Cannot get body in a new EXOSIP_MESSAGE_NEW event\n");
-        returnValue = EXOSIP_ERROR_STD;
-        break;
-      }
-
-      // Analyse message body
-      if (!body || !body->body) {
-        returnValue = EXOSIP_ERROR_STD;
-        break;
-      }
-      std::string str(body->body);
-      pos = str.find(VOICE_MSG);
-
-      if (pos == std::string::npos) {
-	     // If the string is not found
-        returnValue = EXOSIP_ERROR_STD;
-        break;
-      } 
-
-      pos_slash = str.find ("/");
-      std::string nb_msg = str.substr(pos + LENGTH_VOICE_MSG, 
-      pos_slash - (pos + LENGTH_VOICE_MSG));
-
-      // Set the number of voice-message
-      setMsgVoicemail(atoi(nb_msg.data()));
-
-      if (getMsgVoicemail() != 0) {
-        // If there is at least one voice-message, start notification
-        Manager::instance().startVoiceMessageNotification(nb_msg);
-      } else {
-        // Stop notification when there is 0 voice message
-        Manager::instance().stopVoiceMessageNotification();
-      }
-    // http://www.jdrosen.net/papers/draft-ietf-simple-im-session-00.txt
-    } else if (MSG_IS_MESSAGE(event->request)) {
-      _debug("> MESSAGE received\n");
-      // osip_content_type_t* osip_message::content_type
-      osip_content_type_t* c_t = event->request->content_type;
-      if (c_t != 0 &&  c_t->type != 0 && c_t->subtype != 0 ) {
-        _debug("  Content Type of the message: %s/%s\n", c_t->type, c_t->subtype);
-
-        osip_body_t *body = NULL;
-        // Get the message body
-        if (0 == osip_message_get_body(event->request, 0, &body)) {
-          _debug("  Body length: %d\n", body->length);
-          if (body->body!=0 && 
-              strcmp(c_t->type,"text") == 0 && 
-              strcmp(c_t->subtype,"plain") == 0
-            ) {
-            _debug("  Text body: %s\n", body->body);
-            Manager::instance().incomingMessage(body->body);
-          }
-        }
-      }
-      osip_message_t *answerOK;
-      eXosip_lock();
-      if ( 0 == eXosip_message_build_answer(event->tid, OK, &answerOK)) {
-          _debug("< Sending 200 OK\n");
-          eXosip_message_send_answer(event->tid, OK, answerOK);
-      }
-      eXosip_unlock();
-    }
-    break;
-
-  case EXOSIP_MESSAGE_REQUESTFAILURE: // 31
-    // 405 Method Not Allowed
-    if (event->response != 0 && event->response->status_code == SIP_METHOD_NOT_ALLOWED) {
-//      setAllows(event);
-//      AllowList::iterator iter = _allowList.find(std::string("MESSAGE"));
-//      if (iter==_allowList.end()) {
-        Manager::instance().incomingMessage("Message are not allowed");
-//      }
-    }
-    break;
-
-  case EXOSIP_SUBSCRIPTION_ANSWERED: // 38
-    eXosip_lock();
-    eXosip_automatic_action();
-    eXosip_unlock();
-    break;
-
-  case EXOSIP_SUBSCRIPTION_REQUESTFAILURE: //40
-    break;
-
-  default:
-    returnValue = EXOSIP_ERROR_STD;
-    break;
-  }
-  eXosip_event_free(event);
-
-  return returnValue;
-}
-
-int
-SipVoIPLink::getLocalPort (void) 
-{
-  return _localPort;
+  return true;
 }
 
-void
-SipVoIPLink::setLocalPort (int port) 
+bool 
+SIPVoIPLink::carryingDTMFdigits(const CallID& id, char code)
 {
-  _localPort = port;
-}
-
-void
-SipVoIPLink::carryingDTMFdigits (CALLID id, char code) {
-  SipCall* sipcall = getSipCall(id);
-  if (sipcall == 0) { return; }
+  SIPCall* call = getSIPCall(id);
+  if (call==0) { _debug("Call doesn't exist\n"); return false; }  
 
   int duration = Manager::instance().getConfigInt(SIGNALISATION, PULSE_LENGTH);
   osip_message_t *info;
@@ -1127,438 +798,666 @@ SipVoIPLink::carryingDTMFdigits (CALLID id, char code) {
 
   eXosip_lock();
   // Build info request
-  i = eXosip_call_build_info (getSipCall(id)->getDid(), &info);
+  i = eXosip_call_build_info(call->getDid(), &info);
   if (i == 0) {
-    snprintf(dtmf_body, body_len - 1, "Signal=%c\r\nDuration=%d\r\n",
-	     code, duration);
+    snprintf(dtmf_body, body_len - 1, "Signal=%c\r\nDuration=%d\r\n", code, duration);
     osip_message_set_content_type (info, "application/dtmf-relay");
     osip_message_set_body (info, dtmf_body, strlen (dtmf_body));
     // Send info request
-    i = eXosip_call_send_request(sipcall->getDid(), info);
+    i = eXosip_call_send_request(call->getDid(), info);
   }
   eXosip_unlock();
-	
+  
   delete[] dtmf_body; dtmf_body = NULL;
-}
- 
-void
-SipVoIPLink::newOutgoingCall (CALLID id)
-{
-  SipCall* sipcall = new SipCall(id, Manager::instance().getCodecDescriptorMap());
-  if (sipcall != NULL) {
-    _sipcallVector.push_back(sipcall);
-    sipcall->setStandBy(true);
-  }
+  return true;
 }
 
-void
-SipVoIPLink::newIncomingCall (CALLID id)
+bool
+SIPVoIPLink::sendMessage(const std::string& to, const std::string& body)
 {
-  SipCall* sipcall = new SipCall(id, Manager::instance().getCodecDescriptorMap());
-  if (sipcall != NULL) {
-    _sipcallVector.push_back(sipcall);
-  }
-}
+  bool returnValue = false;
 
-void
-SipVoIPLink::deleteSipCall (CALLID id)
-{
-  std::vector< SipCall* >::iterator iter = _sipcallVector.begin();
+  // fast return
+  if (body.empty()) {return returnValue; }
 
-  while(iter != _sipcallVector.end()) {
-    if (*iter && (*iter)->getId() == id) {
-      delete *iter; *iter = NULL;
-      _sipcallVector.erase(iter);
-      return;
-    }
-    iter++;
+  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;
   }
-}
 
-void
-SipVoIPLink::endSipCalls()
-{
-  std::vector< SipCall* >::iterator iter = _sipcallVector.begin();
-  while(iter != _sipcallVector.end()) {
-    if ( *iter ) {
+  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());
+  }
 
-      // Release SIP stack.
-      eXosip_lock();
-      eXosip_call_terminate ((*iter)->getCid(), (*iter)->getDid());
-      eXosip_unlock();
+  if (eXosipError == EXOSIP_ERROR_NO) {
+    // add body
+    // add message
+    // src: http://www.atosc.org/pipermail/public/osip/2005-October/006007.html
+    osip_message_set_expires(message, "120");
+    osip_message_set_body(message, body.c_str(), body.length());
+    osip_message_set_content_type(message, "text/plain");
 
-      // Release RTP channels
-      _audiortp.closeRtpSession();
-      delete *iter; *iter = NULL;
+    eXosipError = eXosip_message_send_request(message);
+    if (eXosipError == EXOSIP_ERROR_NO) {
+      // correctly send the message
+      returnValue = true;
     }
-    iter++;
   }
-  _sipcallVector.clear();
+  eXosip_unlock();
+  return returnValue;
 }
 
-SipCall*
-SipVoIPLink::getSipCall (CALLID id)
+bool
+SIPVoIPLink::SIPOutgoingInvite(SIPCall* call) 
 {
-  SipCall* sipcall = NULL;
-  for (unsigned int i = 0; i < _sipcallVector.size(); i++) {
-    sipcall = _sipcallVector.at(i);
-    if (sipcall && sipcall->getId() == id) {
-      return sipcall;
-    } 
+  // If no SIP proxy setting for direct call with only IP address
+  if (!SIPStartCall(call, "")) {
+    _debug("SIP Failure: call not started\n");
+    return false;
   }
-  return NULL;
+  return true;
 }
 
-AudioCodec*
-SipVoIPLink::getAudioCodec (CALLID id)
+bool
+SIPVoIPLink::SIPStartCall(SIPCall* call, const std::string& subject) 
 {
-  SipCall* sipcall = getSipCall(id);
-  if (sipcall != NULL) {
-    return sipcall->getAudioCodec();
-  } else {
-    return NULL;
+  if (!call) return false;
+
+  std::string to    = getSipTo(call->getPeerNumber());
+  std::string from  = getSipFrom();
+  std::string route = getSipRoute();
+  _debug("            From: %s\n", from.data());
+  _debug("            Route: %s\n", route.data());
+
+  if (!SIPCheckUrl(from)) {
+    _debug("SIP Error: Source address is invalid %s\n", from.data());
+    Manager::instance().displayConfigError("Error in source address");
+    return false;
+  }
+  if (!SIPCheckUrl(to)) {
+    Manager::instance().displayErrorText(call->getCallId(), "Error in destination address");
+    return false;
   }
-}
-///////////////////////////////////////////////////////////////////////////////
-// Private functions
-///////////////////////////////////////////////////////////////////////////////
-int
-SipVoIPLink::sdp_hold_call (sdp_message_t * sdp)
-{
-  int pos;
-  int pos_media = -1;
-  char *rcvsnd;
-  int recv_send = -1;
 
-  pos = 0;
-  rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
-  while (rcvsnd != NULL) {
-    if (rcvsnd != NULL && 0 == strcmp (rcvsnd, "sendonly")) {
-      recv_send = 0;
-    } else if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "recvonly")
-				  || 0 == strcmp (rcvsnd, "sendrecv"))) {
-      recv_send = 0;
-      sprintf (rcvsnd, "sendonly");
-    }
-    pos++;
-    rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
+  osip_message_t *invite;
+  eXosip_lock();
+  int eXosipError = eXosip_call_build_initial_invite (&invite, (char*)to.data(),
+                                        (char*)from.data(),
+                                        (char*)route.data(),
+                                        (char*)subject.data());
+  
+  if (eXosipError != 0) {
+    eXosip_unlock();
+    return false; // error when building the invite
   }
 
-  pos_media = 0;
-  while (!sdp_message_endof_media (sdp, pos_media)) {
-    pos = 0;
-    rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
-    while (rcvsnd != NULL) {
-      if (rcvsnd != NULL && 0 == strcmp (rcvsnd, "sendonly")) {
-	recv_send = 0;
-      } else if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "recvonly")
-				    || 0 == strcmp (rcvsnd, "sendrecv"))) {
-	recv_send = 0;
-	sprintf (rcvsnd, "sendonly");
+  setCallAudioLocal(call);
+
+  std::ostringstream media_audio;
+  std::ostringstream rtpmap_attr;
+  int payload;
+  int nbChannel;
+
+  // Set rtpmap according to the supported codec order
+  CodecMap map = call->getCodecMap().getMap();
+  CodecMap::iterator iter = map.begin();
+
+  while(iter != map.end()) {
+    if (iter->second!=0 && iter->second->isActive()) {
+      payload = iter->first;
+      // add each payload in the list of payload
+      media_audio << payload << " ";
+
+      rtpmap_attr << "a=rtpmap: " << payload << " " << 
+      iter->second->getCodecName().data() << "/" << iter->second->getClockRate();
+
+      nbChannel = iter->second->getChannel();
+      if (nbChannel!=1) {
+        rtpmap_attr << "/" << nbChannel;
       }
-      pos++;
-      rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
+      rtpmap_attr << "\r\n";
     }
-    pos_media++;
+    // go to next codec
+    iter++;
   }
 
-  if (recv_send == -1) {
-    /* we need to add a global attribute with a field set to "sendonly" */
-    sdp_message_a_attribute_add (sdp, -1, osip_strdup ("sendonly"), NULL);
+  // http://www.antisip.com/documentation/eXosip2/group__howto1__initialize.html
+  // tell sip if we support SIP extension like 100rel
+  // osip_message_set_supported (invite, "100rel");
+
+  /* add sdp body */
+  {
+    char tmp[4096];
+    snprintf (tmp, 4096,
+              "v=0\r\n"
+              "o=SFLphone 0 0 IN IP4 %s\r\n"
+              "s=call\r\n"
+              "c=IN IP4 %s\r\n"
+              "t=0 0\r\n"
+              "m=audio %d RTP/AVP %s\r\n"
+              "%s",
+              _localExternAddress.c_str(), _localExternAddress.c_str(), call->getLocalExternAudioPort(), media_audio.str().c_str(), rtpmap_attr.str().c_str());
+    // media_audio should be one, two or three numbers?
+    osip_message_set_body (invite, tmp, strlen (tmp));
+    osip_message_set_content_type (invite, "application/sdp");
+    _debug("SDP send: %s", tmp);
   }
+  
+  _debug("> INVITE To <%s>\n", to.data());
+  int cid = eXosip_call_send_initial_invite(invite);
 
-  return 0;
+  // Keep the cid in case of cancelling
+  call->setCid(cid);
+
+  if (cid <= 0) {
+    eXosip_unlock();
+    return false ;
+  } else {
+    _debug("SIP Info: Outgoing callID is %s, cid=%d\n", call->getCallId().data(), cid);
+    eXosip_call_set_reference (cid, NULL);
+  }
+  eXosip_unlock();
+
+  return true;
 }
 
-int
-SipVoIPLink::sdp_off_hold_call (sdp_message_t * sdp)
-{
-  int pos;
-  int pos_media = -1;
-  char *rcvsnd;
+/**
+ * Get the Sip FROM url (add sip:, add @host, etc...)
+ */ 
+std::string
+SIPVoIPLink::getSipFrom() {
 
-  pos = 0;
-  rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
-  while (rcvsnd != NULL) {
-    if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "sendonly")
-			   || 0 == strcmp (rcvsnd, "recvonly"))) {
-      sprintf (rcvsnd, "sendrecv");
-    }
-    pos++;
-    rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
+  // Form the From header field basis on configuration panel
+  std::string host = getHostName();
+  if ( host.empty() ) {
+    host = _localIPAddress;
   }
+  return SIPFromHeader(_userpart, host);
+}
 
-  pos_media = 0;
-  while (!sdp_message_endof_media (sdp, pos_media)) {
-    pos = 0;
-    rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
-    while (rcvsnd != NULL) {
-      if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "sendonly")
-			     || 0 == strcmp (rcvsnd, "recvonly"))) {
-	sprintf (rcvsnd, "sendrecv");
-      }
-      pos++;
-      rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
+/**
+ * Get the Sip TO url (add sip:, add @host, etc...)
+ */
+std::string
+SIPVoIPLink::getSipTo(const std::string& to_url) {
+  // Form the From header field basis on configuration panel
+  bool isRegistered = (_eXosipRegID == EXOSIP_ERROR_STD) ? false : true;
+
+  // add a @host if we are registered and there is no one inside the url
+  if (to_url.find("@") == std::string::npos && isRegistered) {
+    std::string host = getHostName();
+    if(!host.empty()) {
+      return SIPToHeader(to_url + "@" + host);
     }
-    pos_media++;
   }
-
-  return 0;
+  return SIPToHeader(to_url);
 }
 
-bool
-SipVoIPLink::behindNat(int port)
-{
-  StunAddress4 stunSvrAddr;
-  stunSvrAddr.addr = 0;
-	
-  // Stun server
-  std::string svr = Manager::instance().getConfigString(SIGNALISATION, STUN_SERVER);
-	
-  // Convert char* to StunAddress4 structure
-  bool ret = stunParseServerName ((char*)svr.data(), stunSvrAddr);
-  if (!ret) {
-    _debug("SIP: Stun server address (%s) is not valid\n", svr.data());
-    return 0;
+/**
+ * Get the sip proxy (add sip: if there is one) 
+ * @return empty string or <sip:proxy;lr> url
+ */
+std::string
+SIPVoIPLink::getSipRoute() {
+  std::string proxy = _proxy;
+  if ( !proxy.empty() ) {
+    proxy = "<sip:" + proxy + ";lr>";
   }
-	
-  // Firewall address
-  //_debug("STUN server: %s\n", svr.data());
-  return Manager::instance().getStunInfo(stunSvrAddr, port);
+  return proxy; // return empty
 }
 
-/**
- * Get the local Ip by eXosip 
- * only if the local ip address is to his default value: 127.0.0.1
- * setLocalIpAdress
- * @return false if not found
- */
-bool
-SipVoIPLink::getSipLocalIp (void) 
+std::string
+SIPVoIPLink::SIPToHeader(const std::string& to) 
 {
-  bool returnValue = true;
-  if (getLocalIpAddress() == "127.0.0.1") {
-    char* myIPAddress = new char[65];
-    if (eXosip_guess_localip(AF_INET, myIPAddress, 64) == -1) {
-      returnValue = false;
-    } else {
-      setLocalIpAddress(std::string(myIPAddress));
-      _debug("Checking network, setting local ip address to: %s\n", myIPAddress);
-    }
-    delete [] myIPAddress; myIPAddress = NULL;
+  if (to.find("sip:") == std::string::npos) {
+    return ("sip:" + to );
+  } else {
+    return to;
   }
-  return returnValue;
 }
 
-int
-SipVoIPLink::checkUrl (const std::string& url)
+bool
+SIPVoIPLink::SIPCheckUrl(const std::string& url)
 {
   int i;
-	
+
   osip_from_t *to;
   i = osip_from_init(&to);
   if (i != 0) {
-    _debug("Warning: Cannot initialize\n");
-    return EXOSIP_ERROR_STD;
+    _debug("SIP Warning: Cannot initialize osip parser\n");
+    return false;
   }
   i = osip_from_parse(to, url.data());
   if (i != 0) {
-    _debug("Warning: Cannot parse url\n");
-    return EXOSIP_ERROR_STD;
+    _debug("SIP Warning: Cannot parse url %s\n", url.data());
+    return false;
   }
 
   // Free memory
   osip_from_free (to);
-  return 0;
+  return true;
 }
 
-int
-SipVoIPLink::setAuthentication (void) 
+bool
+SIPVoIPLink::setCallAudioLocal(SIPCall* call) 
 {
-  ManagerImpl& manager = Manager::instance();
-  std::string login = manager.getConfigString(SIGNALISATION, AUTH_USER_NAME);
-  if (login.empty()) {
-    login = manager.getConfigString(SIGNALISATION, USER_PART);
-  }
-  std::string pass = manager.getConfigString(SIGNALISATION, PASSWORD);
-  if (pass.empty()) {
-    manager.displayConfigError("Fill password field");
-    return EXOSIP_ERROR_STD;
+  // Setting Audio
+  unsigned int callLocalAudioPort = RANDOM_LOCAL_PORT;
+  unsigned int callLocalExternAudioPort = callLocalAudioPort;
+  if (_useStun) {
+    // If use Stun server
+    if (Manager::instance().behindNat(callLocalAudioPort)) {
+      callLocalExternAudioPort = Manager::instance().getFirewallPort();
+    }
   }
-  eXosip_lock();
+  _debug("            Setting local audio port to: %d\n", callLocalAudioPort);
+  _debug("            Setting local audio port (external) to: %d\n", callLocalExternAudioPort);
+  
+  // Set local audio port for SIPCall(id)
+  call->setLocalIp(_localIPAddress);
+  call->setLocalAudioPort(callLocalAudioPort);
+  call->setLocalExternAudioPort(callLocalExternAudioPort);
 
-  int returnValue = eXosip_add_authentication_info(login.data(), login.data(), pass.data(), NULL, NULL);
-  eXosip_unlock();
+  return true;
+}
 
-  return returnValue;
+void
+SIPVoIPLink::SIPCallInvite(eXosip_event_t *event)
+{
+  _debug("> INVITE (receive)\n");
+
+  CallID id = Manager::instance().getNewCallID();
+
+  SIPCall* call = new SIPCall(id, Call::Incoming);
+  if (!call) {
+    _debug("SIP Failure: unable to create an incoming call");
+    return;
+  }
+  setCallAudioLocal(call);
+  call->setConnectionState(Call::Progressing);
+  if (call->SIPCallInvite(event)) {
+    if (Manager::instance().incomingCall(call, getAccountID())) {
+      addCall(call);
+    } else {
+      delete call; call = 0;
+    }
+  } else {
+    delete call; call = 0;
+  }
 }
 
-std::string
-SipVoIPLink::fromHeader (const std::string& user, const std::string& host) 
+void
+SIPVoIPLink::SIPCallReinvite(eXosip_event_t *event)
 {
-  std::string displayname = Manager::instance().getConfigString(SIGNALISATION,
-FULL_NAME);
-  return ("\"" + displayname + "\"" + " <sip:" + user + "@" + host + ">");
+  _debug("> REINVITE (receive)\n");
+  SIPCall* call = findSIPCallWithCidDid(event->cid, event->did);
+  if (call == 0) {
+    _debug("SIP Failure: unknown call\n");
+    _debug("< Send 488 Not Acceptable Here");
+    eXosip_lock();
+    eXosip_call_send_answer(event->tid, 488, NULL);
+    eXosip_unlock();
+    return;
+  }
+  if ( call->getCallId() == Manager::instance().getCurrentCallId()) {
+    // STOP tone
+    Manager::instance().stopTone();
+    // STOP old rtp session
+    _audiortp.closeRtpSession();
+    call->setAudioStart(false);
+  }
+  call->SIPCallReinvite(event);
 }
 
+void
+SIPVoIPLink::SIPCallRinging(eXosip_event_t *event)
+{
+  SIPCall* call = findSIPCallWithCidDid(event->cid, event->did);
+  if (!call) {
+    _debug("SIP Failure: unknown call\n");
+    return;
+  }
+  // we could set the cid/did/tid and get the FROM here...
+  // but we found the call with the cid/did already, why setting it again?
+  // call->ringingCall(event);
+  call->setConnectionState(Call::Ringing);
+  Manager::instance().peerRingingCall(call->getCallId());
+}
 
-std::string
-SipVoIPLink::toHeader(const std::string& to) 
+void
+SIPVoIPLink::SIPCallAnswered(eXosip_event_t *event)
 {
-  if (to.find("sip:") == std::string::npos) {
-    return ("sip:" + to );
+  SIPCall* call = findSIPCallWithCid(event->cid);
+  if (!call) {
+    _debug("SIP Failure: unknown call\n");
+    return;
+  }
+  call->setDid(event->did);
+
+  if (call->getConnectionState() != Call::Connected) {
+    call->SIPCallAnswered(event);
+    call->SIPCallAnsweredWithoutHold(event);
+
+    call->setConnectionState(Call::Connected);
+    call->setState(Call::Active);
+
+    Manager::instance().peerAnsweredCall(call->getCallId());
+    if (Manager::instance().isCurrentCall(call->getCallId())) {
+      _debug("SIP: Starting AudioRTP\n");
+      if ( _audiortp.createNewSession(call) < 0) {
+        _debug("RTP Failure: unable to create new session\n");
+      } else {
+        call->setAudioStart(true);
+      }
+    }
   } else {
-    return to;
+    _debug("Answering call (on/off hold to send ACK)\n");
+     call->SIPCallAnswered(event);
   }
 }
 
-int
-SipVoIPLink::startCall(CALLID id, const std::string& from, const std::string& to, const std::string& subject, const std::string& route) 
+void
+SIPVoIPLink::SIPCallRequestFailure(eXosip_event_t *event)
 {
-  SipCall* sipcall = getSipCall(id);
-  if ( sipcall == NULL) {
-    return -1; // error, we can't find the sipcall
+  if (!event->response) { return; }
+  // 404 error
+  _debug("SIP Event: Request Failure, receive code %d\n", event->response->status_code);
+  // Handle 4XX errors
+  switch (event->response->status_code) {
+  case SIP_PROXY_AUTHENTICATION_REQUIRED: 
+    _debug("SIP Server ask required authentification: logging...\n");
+    sendSIPAuthentification();
+    eXosip_lock();
+    eXosip_automatic_action();
+    eXosip_unlock();
+    break;
+  case SIP_UNAUTHORIZED:
+    _debug("Request is unauthorized. SIP Server ask authentification: logging...\n");
+    sendSIPAuthentification();
+    break;
+
+  case SIP_BUSY_HERE:  // 486
+    {
+      SIPCall* call = findSIPCallWithCid(event->cid);
+      if (call!=0) {
+        CallID& id = call->getCallId();
+        call->setConnectionState(Call::Connected);
+        call->setState(Call::Busy);
+        Manager::instance().displayErrorText(id, event->response->reason_phrase);
+        Manager::instance().callBusy(id);
+        removeCall(id);
+      }
+    }
+    break;
+  case SIP_REQUEST_TERMINATED: // 487
+    break;
+
+  default:
+  /*case SIP_BAD_REQUEST:
+  case SIP_FORBIDDEN:
+  case SIP_NOT_FOUND:
+  case SIP_METHOD_NOT_ALLOWED:
+  case SIP_406_NOT_ACCEPTABLE:
+  case SIP_REQ_TIME_OUT:
+  case SIP_TEMPORARILY_UNAVAILABLE:
+  case SIP_ADDRESS_INCOMPLETE:
+  case SIP_NOT_ACCEPTABLE_HERE: // 488 */
+    // Display error on the screen phone
+    {
+      SIPCall* call = findSIPCallWithCid(event->cid);
+      if (call!=0) {
+        CallID& id = call->getCallId();
+        call->setConnectionState(Call::Connected);
+        call->setState(Call::Error);
+        Manager::instance().displayErrorText(id, event->response->reason_phrase);
+        Manager::instance().callFailure(id);
+        removeCall(id);
+      }
+    }
   }
-  osip_message_t *invite;
+}
 
-  if (checkUrl(from) != 0) {
-    Manager::instance().displayConfigError("Error in source address");
-    return -1;
+void
+SIPVoIPLink::SIPCallServerFailure(eXosip_event_t *event) 
+{
+  if (!event->response) { return; }
+  switch(event->response->status_code) {
+  case SIP_SERVICE_UNAVAILABLE: // 500
+  case SIP_BUSY_EVRYWHERE:     // 600
+  case SIP_DECLINE:             // 603
+    SIPCall* call = findSIPCallWithCid(event->cid);
+    if (call != 0) {
+      CallID id = call->getCallId();
+      Manager::instance().callFailure(id);
+      removeCall(id);
+    }
+  break;
   }
-  if (checkUrl(to) != 0) {
-    Manager::instance().displayErrorText(id, "Error in destination address");
-    return -1;
+}
+
+void
+SIPVoIPLink::SIPCallAck(eXosip_event_t *event) 
+{
+  SIPCall* call = findSIPCallWithCidDid(event->cid, event->did);
+  if (!call) { return; }
+  if (!call->isAudioStarted()) {
+    if (Manager::instance().isCurrentCall(call->getCallId())) {
+      _debug("            Starting AudioRTP\n");
+      if ( _audiortp.createNewSession(call) ) {
+        call->setAudioStart(true);
+      }
+    }
   }
-	
-  if (!Manager::instance().useStun()) {
-    // Set random port for outgoing call if no firewall
-    setLocalPort(RANDOM_LOCAL_PORT);
-    _debug("            Setting local port to random: %d\n",_localPort);
-  } else {
-    // If use Stun server
-    if (behindNat(_localPort)) {
-      setLocalIpAddress(Manager::instance().getFirewallAddress());
-      setLocalPort(Manager::instance().getFirewallPort());
-      _debug("            Setting local port to firewall port: %d\n", _localPort);
-    } else {
-      return -1;
+}
+
+void
+SIPVoIPLink::SIPCallMessageNew(eXosip_event_t *event) 
+{
+  if (0 == event->request) return;
+
+  _debug("Receive a call message\n");
+
+  if (MSG_IS_INFO(event->request)) {
+    _debug("It's a Request Info\n");
+    osip_content_type_t* c_t = event->request->content_type;
+    if (c_t != 0 && c_t->type != 0 && c_t->subtype != 0 ) {
+      _debug("  Content Type of the message: %s/%s\n", c_t->type, c_t->subtype);
+      // application/dtmf-relay
+      if (strcmp(c_t->type, "application") == 0 && strcmp(c_t->subtype, "dtmf-relay") == 0) {
+         handleDtmfRelay(event);
+      }
     }
   }
-	
-  // Set local audio port for sipcall(id)
-  sipcall->setLocalIp(getLocalIpAddress());
-  sipcall->setLocalAudioPort(_localPort);
 
+  osip_message_t *answerOKNewMessage;
   eXosip_lock();
-  int i = eXosip_call_build_initial_invite (&invite, (char*)to.data(),
-                                        (char*)from.data(),
-                                        (char*)route.data(),
-                                        (char*)subject.data());
-  
-  if (i != 0) {
-    eXosip_unlock();
-    return EXOSIP_ERROR_STD; // error when building the invite
+  if ( 0 == eXosip_call_build_answer(event->tid, SIP_OK, &answerOKNewMessage)) {
+    _debug("< Sending 200 OK\n");
+    eXosip_call_send_answer(event->tid, SIP_OK, answerOKNewMessage);
+  } else {
+    _debug("SIP Failure: Could not sent an OK message\n");
   }
+  eXosip_unlock();
 
-  std::ostringstream media_audio;
-  std::ostringstream rtpmap_attr;
-  int payload;
-  int nbChannel;
+}
 
-  // Set rtpmap according to the supported codec order
-  CodecMap map = Manager::instance().getCodecDescriptorMap().getMap();
-  CodecMap::iterator iter = map.begin();
+void
+SIPVoIPLink::SIPCallClosed(eXosip_event_t *event) 
+{
+  // it was without did before
+  SIPCall* call = findSIPCallWithCid(event->cid);
+  if (!call) { return; }
+
+  CallID id = call->getCallId();
+  call->setDid(event->did);
+  if (Manager::instance().isCurrentCall(id)) {
+    call->setAudioStart(false);
+    _audiortp.closeRtpSession();
+  }  
+  Manager::instance().peerHungupCall(id);
+  removeCall(id);
+}
 
-  while(iter != map.end()) {
-    if (iter->second!=0 && iter->second->isActive()) {
-      payload = iter->first;
-      // add each payload in the list of payload
-      media_audio << payload << " ";
+void
+SIPVoIPLink::SIPCallReleased(eXosip_event_t *event)
+{
+  // do cleanup if exists
+  // only cid because did is always 0 in these case..
+  SIPCall* call = findSIPCallWithCid(event->cid);
+  if (!call) { return; }
+
+  // if we are here.. something when wrong before...
+  CallID id = call->getCallId();
+  Manager::instance().callFailure(id);
+  removeCall(id);
+}
 
-      rtpmap_attr << "a=rtpmap: " << payload << " " << 
-      iter->second->getCodecName().data() << "/" << iter->second->getClockRate();
+void
+SIPVoIPLink::SIPMessageNew(eXosip_event_t *event)
+{
+  if (MSG_IS_OPTIONS(event->request)) {
+    // old handling was
+    // - send 200 OK if call id is not found
+    // - send nothing if call id is found
+    eXosip_lock();
+    eXosip_options_send_answer (event->tid, SIP_OK, NULL);
+    eXosip_unlock();
+  }
+  // Voice message 
+  else if (MSG_IS_NOTIFY(event->request)){
+    _debug("> NOTIFY Voice message\n");
+    int ii;
+    unsigned int pos;
+    unsigned int pos_slash;
+
+    osip_body_t *body = NULL;
+    // Get the message body
+    ii = osip_message_get_body(event->request, 0, &body);
+    if (ii != 0) {
+      _debug("  Cannot get body in a new EXOSIP_MESSAGE_NEW event\n");
+      return;
+    }
 
-      nbChannel = iter->second->getChannel();
-      if (nbChannel!=1) {
-        rtpmap_attr << "/" << nbChannel;
-      }
-      rtpmap_attr << "\r\n";
+    // Analyse message body
+    if (!body || !body->body) {
+       return;
     }
-    // go to next codec
-    iter++;
-  }
+    std::string str(body->body);
+    pos = str.find(VOICE_MSG);
 
-  // http://www.antisip.com/documentation/eXosip2/group__howto1__initialize.html
-  // tell sip if we support SIP extension like 100rel
-  // osip_message_set_supported (invite, "100rel");
+    if (pos == std::string::npos) {
+      // If the string is not found
+      return;
+    } 
 
-  /* add sdp body */
-  {
-    char tmp[4096];
-    snprintf (tmp, 4096,
-              "v=0\r\n"
-              "o=SFLphone 0 0 IN IP4 %s\r\n"
-              "s=call\r\n"
-              "c=IN IP4 %s\r\n"
-              "t=0 0\r\n"
-              "m=audio %d RTP/AVP %s\r\n"
-	            "%s",
-              getLocalIpAddress().c_str(), getLocalIpAddress().c_str(), getLocalPort(), media_audio.str().c_str(), rtpmap_attr.str().c_str());
-    // media_audio should be one, two or three numbers?
-    osip_message_set_body (invite, tmp, strlen (tmp));
-    osip_message_set_content_type (invite, "application/sdp");
-    _debug("SDP send: %s", tmp);
-  }
-  
-  // this is the cid (call id from exosip)
-  _debug("%10d: Receive INVITE\n", id);
-  int cid = eXosip_call_send_initial_invite (invite);
-  _debug("            Local IP:port: %s:%d\n", getLocalIpAddress().c_str(), getLocalPort());
+    pos_slash = str.find ("/");
+    std::string nb_msg = str.substr(pos + LENGTH_VOICE_MSG, 
+    pos_slash - (pos + LENGTH_VOICE_MSG));
 
-  // Keep the cid in case of cancelling
-  sipcall->setCid(cid);
+    // Set the number of voice-message
+    int msgVoicemail = atoi(nb_msg.data());
 
-  if (cid <= 0) {
+    if (msgVoicemail != 0) {
+      // If there is at least one voice-message, start notification
+      Manager::instance().startVoiceMessageNotification(getAccountID(), nb_msg);
+    } else {
+      // Stop notification when there is 0 voice message
+      Manager::instance().stopVoiceMessageNotification(getAccountID());
+    }
+
+  // http://www.jdrosen.net/papers/draft-ietf-simple-im-session-00.txt
+  } else if (MSG_IS_MESSAGE(event->request)) {
+    _debug("> MESSAGE received\n");
+    // osip_content_type_t* osip_message::content_type
+    osip_content_type_t* c_t = event->request->content_type;
+    if (c_t != 0 &&  c_t->type != 0 && c_t->subtype != 0 ) {
+      _debug("  Content Type of the message: %s/%s\n", c_t->type, c_t->subtype);
+
+      osip_body_t *body = NULL;
+      // Get the message body
+      if (0 == osip_message_get_body(event->request, 0, &body)) {
+        _debug("  Body length: %d\n", body->length);
+        if (body->body!=0 && 
+            strcmp(c_t->type,"text") == 0 && 
+            strcmp(c_t->subtype,"plain") == 0
+          ) {
+          _debug("  Text body: %s\n", body->body);
+          Manager::instance().incomingMessage(getAccountID(), body->body);
+        }
+      }
+    }
+    osip_message_t *answerOK;
+    eXosip_lock();
+    if ( 0 == eXosip_message_build_answer(event->tid, SIP_OK, &answerOK)) {
+        _debug("< Sending 200 OK\n");
+        eXosip_message_send_answer(event->tid, SIP_OK, answerOK);
+    }
     eXosip_unlock();
-    return EXOSIP_ERROR_STD;
-  } else {
-    eXosip_call_set_reference (cid, NULL);
   }
-  eXosip_unlock();
 
-  return cid; // this is the Cid
 }
 
-CALLID
-SipVoIPLink::findCallId (eXosip_event_t *e)
+SIPCall* 
+SIPVoIPLink::findSIPCallWithCid(int cid) 
 {
-  for (unsigned int k = 0; k < _sipcallVector.size(); k++) {
-    SipCall* sipcall = _sipcallVector.at(k);
-    if (sipcall && sipcall->getCid() == e->cid &&
-        sipcall->getDid() == e->did) {
-      return sipcall->getId();
+  if (cid < 1) {
+    _debug("Not enough information for this event\n");
+    return 0;
+  }
+  ost::MutexLock m(_callMapMutex);
+  SIPCall* call = 0;
+  CallMap::iterator iter = _callMap.begin();
+  while(iter != _callMap.end()) {
+    call = dynamic_cast<SIPCall*>(iter->second);
+    if (call && call->getCid() == cid) {
+      return call;
     }
+    iter++;
   }
   return 0;
 }
 
-/**
- * This function is used when findCallId failed (return 0)
- * ie: the dialog id change
- *     can be use when anwsering a new call or 
- *         when cancelling a call
- */
-CALLID
-SipVoIPLink::findCallIdInitial (eXosip_event_t *e)
+SIPCall* 
+SIPVoIPLink::findSIPCallWithCidDid(int cid, int did) 
 {
-  for (unsigned int k = 0; k < _sipcallVector.size(); k++) {
-    SipCall* sipcall = _sipcallVector.at(k);
-    // the dialog id is not set when you do a new call
-    // so you can't check it when you want to retreive it
-    // for the first call anwser
-    if (sipcall && sipcall->getCid() == e->cid) {
-      return sipcall->getId();
+  if (cid < 1 && did < -1) {
+    _debug("Not enough information for this event\n");
+    return 0;
+  }
+  ost::MutexLock m(_callMapMutex);
+  SIPCall* call = 0;
+  CallMap::iterator iter = _callMap.begin();
+  while(iter != _callMap.end()) {
+    call = dynamic_cast<SIPCall*>(iter->second);
+    if (call && call->getCid() == cid && call->getDid() == did) {
+      return call;
     }
+    iter++;
+  }
+  return 0;
+}
+
+SIPCall*
+SIPVoIPLink::getSIPCall(const CallID& id) 
+{
+  Call* call = getCall(id);
+  if (call) {
+    return dynamic_cast<SIPCall*>(call);
   }
   return 0;
 }
@@ -1568,7 +1467,12 @@ SipVoIPLink::findCallIdInitial (eXosip_event_t *e)
  * @param event eXosip Event
  */
 bool
-SipVoIPLink::handleDtmfRelay(eXosip_event_t* event) {
+SIPVoIPLink::handleDtmfRelay(eXosip_event_t* event) {
+
+  SIPCall* call = findSIPCallWithCidDid(event->cid, event->did);
+  if (call==0) { return false; }
+
+
   bool returnValue = false;
   osip_body_t *body = NULL;
   // Get the message body
@@ -1591,9 +1495,9 @@ SipVoIPLink::handleDtmfRelay(eXosip_event_t* event) {
       _debug("Signal value: %s\n", signal.c_str());
       
       if (!signal.empty()) {
-        unsigned int id = findCallId(event);
-        if (id !=0 && id == Manager::instance().getCurrentCallId()) {
+        if (Manager::instance().isCurrentCall(call->getCallId())) {
           Manager::instance().playDtmf(signal[0]);
+          returnValue = true;
         }
       }
 /*
@@ -1616,77 +1520,89 @@ SipVoIPLink::handleDtmfRelay(eXosip_event_t* event) {
   return returnValue;
 }
 
-// http://www.ietf.org/rfc/rfc3428.txt
-// The size of MESSAGE requests outside of a media session MUST NOT
-// exceed 1300 bytes, unless the UAC has positive knowledge that the
-// message will not traverse a congestion-unsafe link at any hop, or
-// that the message size is at least 200 bytes less than the lowest MTU
-// value found en route to the UAS.  
-bool
-SipVoIPLink::sendMessage(const std::string& to, const std::string& body) {
-  bool returnValue = false;
-
-  // fast return
-  if (body.empty()) {return returnValue; }
-
-  osip_message_t* message = 0;
-  const char* method = "MESSAGE";
-
-  std::string sipFrom = getSipFrom();
-  std::string sipTo   = getSipTo(to);
-  std::string sipRoute = getSipRoute();
+///////////////////////////////////////////////////////////////////////////////
+// Private functions
+///////////////////////////////////////////////////////////////////////////////
+int
+SIPVoIPLink::sdp_hold_call (sdp_message_t * sdp)
+{
+  int pos;
+  int pos_media = -1;
+  char *rcvsnd;
+  int recv_send = -1;
 
-  if (checkUrl(sipFrom) != 0) {
-    Manager::instance().displayConfigError("Error in source address");
-    return returnValue;
-  }
-  if (checkUrl(sipTo) != 0) {
-    Manager::instance().displayError("Error in destination address");
-    return returnValue;
+  pos = 0;
+  rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
+  while (rcvsnd != NULL) {
+    if (rcvsnd != NULL && 0 == strcmp (rcvsnd, "sendonly")) {
+      recv_send = 0;
+    } else if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "recvonly")
+          || 0 == strcmp (rcvsnd, "sendrecv"))) {
+      recv_send = 0;
+      sprintf (rcvsnd, "sendonly");
+    }
+    pos++;
+    rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
   }
 
-  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());
+  pos_media = 0;
+  while (!sdp_message_endof_media (sdp, pos_media)) {
+    pos = 0;
+    rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
+    while (rcvsnd != NULL) {
+      if (rcvsnd != NULL && 0 == strcmp (rcvsnd, "sendonly")) {
+        recv_send = 0;
+      } else if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "recvonly")
+            || 0 == strcmp (rcvsnd, "sendrecv"))) {
+        recv_send = 0;
+        sprintf (rcvsnd, "sendonly");
+      }
+      pos++;
+      rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
+    }
+    pos_media++;
   }
 
-  if (eXosipError == EXOSIP_ERROR_NO) {
-    // add body
-    // add message
-    // src: http://www.atosc.org/pipermail/public/osip/2005-October/006007.html
-    osip_message_set_expires(message, "120");
-    osip_message_set_body(message, body.c_str(), body.length());
-    osip_message_set_content_type(message, "text/plain");
-
-    eXosipError = eXosip_message_send_request(message);
-    if (eXosipError == EXOSIP_ERROR_NO) {
-      // correctly send the message
-      returnValue = true;
-    }
+  if (recv_send == -1) {
+    /* we need to add a global attribute with a field set to "sendonly" */
+    sdp_message_a_attribute_add (sdp, -1, osip_strdup ("sendonly"), NULL);
   }
-  eXosip_unlock();
-  return returnValue;
+
+  return 0;
 }
 
-bool
-SipVoIPLink::setAllows(eXosip_event_t *event) {
-  bool returnValue = false;
+int
+SIPVoIPLink::sdp_off_hold_call (sdp_message_t * sdp)
+{
+  int pos;
+  int pos_media = -1;
+  char *rcvsnd;
 
-  _allowList.clear();
+  pos = 0;
+  rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
+  while (rcvsnd != NULL) {
+    if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "sendonly")
+         || 0 == strcmp (rcvsnd, "recvonly"))) {
+      sprintf (rcvsnd, "sendrecv");
+    }
+    pos++;
+    rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
+  }
 
-  if (event->response!=0 && event->response->allows!=0) {
-    int allowsSize = osip_list_size(event->response->allows);
-    if (allowsSize != 0) { returnValue = true;}
-    osip_allow_t *allows = 0;
-    for(int pos=0; pos<allowsSize; pos++) {
-      allows = (osip_allow_t*)osip_list_get(event->response->allows, pos);
-      if (allows!=0 && allows->value!=0) {
-        _allowList.push_back(std::string(allows->value));
+  pos_media = 0;
+  while (!sdp_message_endof_media (sdp, pos_media)) {
+    pos = 0;
+    rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
+    while (rcvsnd != NULL) {
+      if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "sendonly")
+           || 0 == strcmp (rcvsnd, "recvonly"))) {
+        sprintf (rcvsnd, "sendrecv");
       }
+      pos++;
+      rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
     }
+    pos_media++;
   }
-  return returnValue;
+
+  return 0;
 }
diff --git a/src/sipvoiplink.h b/src/sipvoiplink.h
index 392209dbab16f6552aae536acd485296a30a9a18..b9f87bab7582ae0722eae87e6116bac04ccfca12 100644
--- a/src/sipvoiplink.h
+++ b/src/sipvoiplink.h
@@ -1,10 +1,8 @@
 /*
- *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
+ *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *
- *	Portions Copyright (C) 2002,2003   Aymeric Moizard <jack@atosc.org>
- *
  *  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
  *  the Free Software Foundation; either version 2 of the License, or
@@ -19,216 +17,251 @@
  *  along with this program; if not, write to the Free Software
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
-#ifndef __SIP_VOIP_LINK_H__
-#define __SIP_VOIP_LINK_H__
-
-#include <vector>
-#include <map> // for allowed
-#include <eXosip2/eXosip.h>
+#ifndef SIPVOIPLINK_H
+#define SIPVOIPLINK_H
 
 #include "voIPLink.h"
+#include <string>
+#include <eXosip2/eXosip.h>
 #include "audio/audiortp.h"
-#include "call.h" // for CALLID
-
-#define EXPIRES_VALUE	180
-// To build request
-#define INVITE_METHOD	"INVITE"
-// 1XX responses
-#define DIALOG_ESTABLISHED 101
-#define RINGING			180
-// 2XX
-#define OK				200
-// 4XX Errors
-#define	BAD_REQ			400
-#define	UNAUTHORIZED	401
-#define	FORBIDDEN		403
-#define NOT_FOUND		404
-#define NOT_ALLOWED		405
-#define NOT_ACCEPTABLE	406
-#define AUTH_REQUIRED	407
-#define REQ_TIMEOUT		408
-#define UNSUP_MEDIA_TYPE	415
-#define TEMP_UNAVAILABLE 480
-#define	ADDR_INCOMPLETE	484
-#define	BUSY_HERE		486
-#define	REQ_TERMINATED	487
-#define NOT_ACCEPTABLE_HERE 488 // Not Acceptable Here
-// 5XX errors
-#define SERVICE_UNAVAILABLE	503
-// 6XX errors
-#define	BUSY_EVERYWHERE	600
-#define DECLINE			603
-
-class AudioCodec;
-class CodecDescriptor;
-class SipCall;
-class EventThread;
 
-typedef std::vector< CodecDescriptor* > CodecDescriptorVector;
-typedef std::list<std::string> AllowList;
+class EventThread;
+class SIPCall;
 
-class SipVoIPLink : public VoIPLink {
+/**
+	@author Yan Morin <yan.morin@gmail.com>
+*/
+class SIPVoIPLink : public VoIPLink
+{
 public:
-  SipVoIPLink();
-  virtual ~SipVoIPLink();
-	
-	virtual bool init (void);
-	virtual bool checkNetwork (void);
-	virtual void terminate (void);
-	virtual int setRegister (void);
-	virtual int setUnregister (void);
-	virtual int outgoingInvite (CALLID id, const std::string& to_url);	
-	virtual int answer (CALLID id);
-	virtual int hangup (CALLID id);
-	virtual int cancel (CALLID id);
-	virtual int onhold (CALLID id);
-	virtual int offhold (CALLID id);
-	virtual int transfer (CALLID id, const std::string& to);
-	virtual int refuse (CALLID id);	
-	virtual int getEvent (void);
-	virtual void carryingDTMFdigits (CALLID id, char code);
-	
-	/*
-	 * To handle the local port
-	 */
-	int	getLocalPort (void);
-	void setLocalPort (int);
-  bool getSipLocalIp (void);
-
-	/*
-	 * Add a new SipCall at the end of the SipCallVector with identifiant 'id'
-	 */
-	void newOutgoingCall(CALLID callid);
-	void newIncomingCall(CALLID callid);
-
-	/*
-	 * Erase the SipCall(id) from the SipCallVector
-	 */
-	void deleteSipCall(CALLID callid);
-	
-	/*
-	 * Return a pointer to the SipCall with identifiant 'id'
-	 */
-	SipCall* getSipCall(CALLID callid);
-
-	/*
-	 * Accessor to the audio codec of SipCall with identifiant 'id'
-	 */
-	AudioCodec* getAudioCodec(CALLID callid);
-
-// Handle voice-message
-	inline void setMsgVoicemail (int nMsg) { _nMsgVoicemail = nMsg; }
-	inline int getMsgVoicemail (void) { return _nMsgVoicemail; }
-
-  /**
-  * send text message
-  * the size of message should not exceed 1300 bytes
-  */
-  virtual bool sendMessage(const std::string& to, const std::string& body);
-	
+    SIPVoIPLink(const AccountID& accountID);
+
+    ~SIPVoIPLink();
+
+  /** try to initiate the eXosip engine/thread and set config */
+  bool init(void);
+  void terminate(void);
+  bool checkNetwork(void);
+  void getEvent(void);
+
+  bool setRegister(void);
+  bool setUnregister(void);
+
+  Call* newOutgoingCall(const CallID& id, const std::string& toUrl);
+  bool answer(const CallID& id);
+
+  bool hangup(const CallID& id);
+  bool cancel(const CallID& id);
+  bool onhold(const CallID& id);
+  bool offhold(const CallID& id);
+  bool transfer(const CallID& id, const std::string& to);
+  bool refuse (const CallID& id);
+  bool carryingDTMFdigits(const CallID& id, char code);
+  bool sendMessage(const std::string& to, const std::string& body);
+
+
+
+  // SIP Specific
+  /** If set to true, we check for a firewall
+   * @param use true if we use STUN
+   */
+  void setUseStun(bool use) { _useStun = use; }
+  void setProxy(const std::string& proxy) { _proxy = proxy; }
+  void setUserPart(const std::string& userpart) { _userpart = userpart; }
+  void setAuthName(const std::string& authname) { _authname = authname; }
+  void setPassword(const std::string& password) { _password = password; }
+
+
 private:
-	/*
-	 * If you are behind a NAT, you have to use STUN server, specified in 
-	 * STUN configuration(you can change this one by default) to give you an 
-	 * public IP address and assign a port number.
-         * @param port : on which port we want to listen to
-	 * 
-	 * Return false if an error occured and true if no error.
-	 */
-	bool behindNat(int port);
-
-	/*
-	 * Return -1 if an error occured and 0 if no error
-	 */
-	int checkUrl(const std::string& url);
-
-	/*
-	 * Allow the authentication when you want register
-   	 * Return -1 if an error occured and 0 if no error 
-	 */	 
-	int setAuthentication (void);
-
-	/*
-	 * Build a sip address from the user configuration
-	 * Example: "Display user name" <sip:user@host.com>
-	 * Return the result in a string
-	 */
-	std::string fromHeader (const std::string& user, const std::string& host);
-
-	/*
-	 * Build a sip address with the number that you want to call
-	 * Example: sip:124@domain.com
-	 * Return the result in a string
-	 */
-	std::string toHeader(const std::string& to);
-
-	/*
-	 * Beginning point to make outgoing call.
-	 * Check the 'from' and 'to' url.
-	 * Allocate local audio port.
-	 * Build SDP body.
-	 * Return -1 if an error occured and 0 if no error
-	 */
-	int startCall (CALLID id, const std::string& from, const std::string& to, const std::string& subject, const std::string& route);
+  /** Terminate every call not hangup | brutal | Protected by mutex */
+  void terminateSIPCall(); 
+
+  /**
+  * Get the local Ip by eXosip 
+  * only if the local ip address is to his default value: 127.0.0.1
+  * setLocalIpAdress
+  * @return false if not found
+  */
+  bool loadSIPLocalIP();
+
+  /**
+   * send SIP authentification
+   * @return true if sending succeed
+   */
+  bool sendSIPAuthentification();
+
+  /**
+   * Get a SIP From header ("fullname" <sip:userpart@hostpart>)
+   * @param userpart
+   * @param hostpart
+   * @return SIP URI for from Header
+   */
+  std::string SIPFromHeader(const std::string& userpart, const std::string& hostpart);
+
+  /**
+   * Build a sip address with the number that you want to call
+   * Example: sip:124@domain.com
+   * @return result as a string
+   */
+  std::string SIPToHeader(const std::string& to);
+
+  /**
+   * Check if an url is sip-valid
+   * @return true if osip tell that is valid
+   */
+  bool SIPCheckUrl(const std::string& url);
+
+
+  /**
+   * SIPOutgoingInvite do SIPStartCall
+   * @return true if all is correct
+   */
+  bool SIPOutgoingInvite(SIPCall* call);
 
+  /**
+   * Start a SIP Call
+   * @return true if all is correct
+   */
+  bool SIPStartCall(SIPCall* call, const std::string& subject);
   std::string getSipFrom();
   std::string getSipRoute();
   std::string getSipTo(const std::string& to_url);
 
+  /**
+   * Set audio (SDP) configuration for a call
+   * localport, localip, localexternalport
+   * @param call a SIPCall valid pointer
+   * @return true
+   */
+  bool setCallAudioLocal(SIPCall* call);
 
+  /**
+   * Create a new call and send a incoming call notification to the user
+   * @param event eXosip Event
+   */
+  void SIPCallInvite(eXosip_event_t *event);
 
-	/*
-	 * Look for call with same cid/did 
-	 * Return the id of the found call
-	 */
-	CALLID findCallId (eXosip_event_t *e);
-  CALLID findCallIdInitial (eXosip_event_t *e);
+  /**
+   * Use a exisiting call to restart the audio
+   * @param event eXosip Event
+   */
+  void SIPCallReinvite(eXosip_event_t *event);
 
-	/*
-	 * To build sdp when call is on-hold
-	 */
-	int sdp_hold_call (sdp_message_t * sdp);
-	
-	/*
-	 * To build sdp when call is off-hold
-	 */
-	int sdp_off_hold_call (sdp_message_t * sdp);
+  /**
+   * Tell the user that the call is ringing
+   * @param event eXosip Event
+   */
+  void SIPCallRinging(eXosip_event_t *event);
+
+  /**
+   * Tell the user that the call was answered
+   * @param event eXosip Event
+   */
+  void SIPCallAnswered(eXosip_event_t *event);
+
+  /**
+   * Handling 4XX error
+   * @param event eXosip Event
+   */
+  void SIPCallRequestFailure(eXosip_event_t *event);
+
+  /**
+   * Handling 5XX/6XX error
+   * @param event eXosip Event
+   */
+  void SIPCallServerFailure(eXosip_event_t *event);
 
   /**
-   * Subscribe to message summary
+   * Handling ack (restart audio if reinvite)
+   * @param event eXosip Event
    */
-	void subscribeMessageSummary();
+  void SIPCallAck(eXosip_event_t *event);
 
   /**
-   * End all sip call not deleted
+   * Handling message inside a call (like dtmf)
+   * @param event eXosip Event
    */
-  void endSipCalls();
+  void SIPCallMessageNew(eXosip_event_t *event);
+  bool handleDtmfRelay(eXosip_event_t *event);
 
   /**
-   * Handle DTMF Relay INFO Request
+   * Peer close the connection
+   * @param event eXosip Event
    */
-  bool handleDtmfRelay(eXosip_event_t* event);
+  void SIPCallClosed(eXosip_event_t *event);
 
   /**
-   * Get from a response event, all allowed request
+   * The call pointer was released
+   * If the call was not cleared before, report an error
+   * @param event eXosip Event
    */
-  bool setAllows(eXosip_event_t *event);
+  void SIPCallReleased(eXosip_event_t *event);
+
+  /**
+   * Receive a new Message request
+   * Option/Notify/Message
+   * @param event eXosip Event
+   */
+  void SIPMessageNew(eXosip_event_t *event);
+
+  /**
+  * Find a SIPCall with cid from eXosip Event
+  * Explication there is no DID when the dialog is not establish...
+  * @param cid call ID
+  * @return 0 or SIPCall pointer
+  */
+  SIPCall* findSIPCallWithCid(int cid);
+
+  /**
+  * Find a SIPCall with cid and did from eXosip Event
+  * @param cid call ID
+  * @param did domain ID
+  * @return 0 or SIPCall pointer
+  */
+  SIPCall* findSIPCallWithCidDid(int cid, int did);
+  SIPCall* getSIPCall(const CallID& id);
+
+  /** To build sdp when call is on-hold */
+  int sdp_hold_call (sdp_message_t * sdp);
+  /** To build sdp when call is off-hold */
+  int sdp_off_hold_call (sdp_message_t * sdp);
+
+
+
+  /** EventThread get every incoming events */
+  EventThread* _evThread;
+  /** Tell if eXosip was stared (eXosip_init) */
+  bool _eXosipStarted;
+  /** Registration identifier, needed by unregister to build message */
+  int _eXosipRegID;
+  /** Number of voicemail */
+  int _nMsgVoicemail;
+
+  /** when we init the listener, how many times we try to bind a port? */
+  int _nbTryListenAddr;
+
+  /** Do we use stun? */
+  bool _useStun;
+
+  /** Local Extern Address is the IP address seens by peers for SIP listener */
+  std::string _localExternAddress;
+
+  /** Local Extern Port is the port seens by peers for SIP listener */
+  unsigned int _localExternPort;  
+
+  /** SIP Proxy URL */
+  std::string _proxy;
+  /** SIP UserPart */
+  std::string _userpart;
 
-	///////////////////////////
-	// Private member variables
-	///////////////////////////
-	EventThread 	*_evThread;
-	std::vector< SipCall * > _sipcallVector;
-  AllowList _allowList;
+  /** SIP Authenfication name */
+  std::string _authname;
 
-	AudioRtp 		_audiortp;
-	int 			_localPort;
-	int 			_reg_id;
-	int 			_nMsgVoicemail;
+  /** SIP Authenfication password */
+  std::string _password; 
 
-  bool _registrationSend; // unregistered 
-  bool _started; // eXosip_init and eXosip_start
+  /** Starting sound */
+  AudioRtp _audiortp;
 };
 
-#endif // __SIP_VOIP_LINK_H__
+#endif
diff --git a/src/user_cfg.h b/src/user_cfg.h
index 9d55dfe455ad6c6c305a7c96a589793e3091d5b3..1237e55a32f80c4493360fafab843f0abf0862d1 100644
--- a/src/user_cfg.h
+++ b/src/user_cfg.h
@@ -38,7 +38,7 @@
 #define PREFERENCES		"Preferences"
 
 #define ACCOUNT_SIP0  "SIP0"
-#define ACCOUNT_AIX0  "AIX0"
+#define ACCOUNT_IAX0  "IAX0"
 
 
 // Fields to fill
diff --git a/src/voIPLink.cpp b/src/voIPLink.cpp
index 6ff6b561721a50bc8905e0506537e413da953069..4612ae53fc3132d698317df9e9c6900e4b3bf108 100644
--- a/src/voIPLink.cpp
+++ b/src/voIPLink.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2005 Savoir-Faire Linux inc.
+ *  Copyright (C) 2005-2006 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *
@@ -22,48 +22,61 @@
 
 #include "user_cfg.h"
 #include "voIPLink.h"
-#include "manager.h"
 
-VoIPLink::VoIPLink ()
+VoIPLink::VoIPLink(const AccountID& accountID) : _accountID(accountID), _localIPAddress("127.0.0.1"), _localPort(0)
 {
+  
 }
 
 VoIPLink::~VoIPLink (void) 
 {
+  clearCallMap();
 }
 
-void 
-VoIPLink::setFullName (const std::string& fullname)
+bool
+VoIPLink::addCall(Call* call)
 {
-	_fullname = fullname;
+  if (call) {
+    if (getCall(call->getCallId()) == 0) {
+      ost::MutexLock m(_callMapMutex);
+      _callMap[call->getCallId()] = call;
+    }
+  }  
+  return false;
 }
 
-std::string
-VoIPLink::getFullName (void)
+bool
+VoIPLink::removeCall(const CallID& id)
 {
-	return _fullname;
+  ost::MutexLock m(_callMapMutex);
+  if (_callMap.erase(id)) {
+    return true;
+  }  
+  return false;
 }
 
-void 
-VoIPLink::setHostName (const std::string& hostname)
+Call*
+VoIPLink::getCall(const CallID& id)
 {
-	_hostname = hostname;
+  ost::MutexLock m(_callMapMutex);
+  CallMap::iterator iter = _callMap.find(id);
+  if ( iter != 0 && iter != _callMap.end() ) {
+    return iter->second;
+  }
+  return 0;
 }
 
-std::string
-VoIPLink::getHostName (void)
+bool
+VoIPLink::clearCallMap()
 {
-	return _hostname;
-} 
-
-void 
-VoIPLink::setLocalIpAddress (const std::string& ipAdress)
-{
-	_localIpAddress = ipAdress;
+  ost::MutexLock m(_callMapMutex);
+  CallMap::iterator iter = _callMap.begin();
+  while( iter != _callMap.end() ) {
+    // if (iter) ?
+    delete iter->second; iter->second = 0;
+    iter++;
+  }
+  _callMap.clear();
+  return true;
 }
 
-std::string 
-VoIPLink::getLocalIpAddress (void)
-{
-	return _localIpAddress;
-} 
diff --git a/src/voIPLink.h b/src/voIPLink.h
index bfd7f957eea9d7174ad6593f957aec70dad31342..e0644bb2209303eb9d6eafd034da63fed2c62624 100644
--- a/src/voIPLink.h
+++ b/src/voIPLink.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2005 Savoir-Faire Linux inc.
+ *  Copyright (C) 2005-2006 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *
@@ -22,49 +22,87 @@
 #define __VOIP_LINK_H__
 
 #include <string>
+#include "account.h" // for AccountID
 #include "call.h"
+#include <map>
+#include <cc++/thread.h> // for mutex
 
 class AudioCodec;
-class Call;
+
+typedef std::map<CallID, Call*> CallMap;
 
 class VoIPLink {
 public:
-	VoIPLink ();
+	VoIPLink(const AccountID& accountID);
 	virtual ~VoIPLink (void);
 
 	// Pure virtual functions
-	virtual int getEvent (void) = 0;
+	virtual void getEvent (void) = 0;
 	virtual bool init (void) = 0;
 	virtual bool checkNetwork (void) = 0;
 	virtual void terminate (void) = 0;
-	virtual void newOutgoingCall (CALLID id) = 0;
-	virtual void newIncomingCall (CALLID id) = 0;
-	virtual int outgoingInvite (CALLID id, const std::string& to_url) = 0;
-	virtual int answer (CALLID id) = 0;
-	virtual int hangup (CALLID id) = 0;
-	virtual int cancel (CALLID id) = 0;
-	virtual int onhold (CALLID id) = 0;
-	virtual int offhold (CALLID id) = 0;
-	virtual int transfer (CALLID id, const std::string& to) = 0;
-	virtual int refuse (CALLID id) = 0;
-	virtual int setRegister (void) = 0;
-	virtual int setUnregister (void) = 0;
-	virtual void carryingDTMFdigits(CALLID id, char code) = 0;
-	virtual AudioCodec* getAudioCodec (CALLID id) = 0;
+  virtual bool setRegister (void) = 0;
+  virtual bool setUnregister (void) = 0;
+
+  /** Add a new outgoing call and return the call pointer or 0 if and error occurs */
+  virtual Call* newOutgoingCall(const CallID& id, const std::string& toUrl) = 0;
+  virtual bool answer(const CallID& id) = 0;
+
+	virtual bool hangup(const CallID& id) = 0;
+	virtual bool cancel(const CallID& id) = 0;
+	virtual bool onhold(const CallID& id) = 0;
+	virtual bool offhold(const CallID& id) = 0;
+	virtual bool transfer(const CallID& id, const std::string& to) = 0;
+	virtual bool refuse(const CallID& id) = 0;
+	virtual bool carryingDTMFdigits(const CallID& id, char code) = 0;
   virtual bool sendMessage(const std::string& to, const std::string& body) = 0;
 
-	void setFullName (const std::string& fullname);
-	std::string getFullName (void);
-	void setHostName (const std::string& hostname);
-	std::string getHostName (void);
-	void setLocalIpAddress (const std::string& ipAdress);
-  std::string getLocalIpAddress (void);
+  // these method are set only with 'Account init'  and can be get by everyone
+  void setFullName (const std::string& fullname) { _fullname = fullname; }
+  std::string& getFullName (void) { return _fullname; }
+  void setHostName (const std::string& hostname) {  _hostname = hostname; }
+  std::string& getHostName (void) { return _hostname; } 
+  AccountID& getAccountID(void) { return _accountID; }
+
+  /** Get the call pointer from the call map (protected by mutex)
+   * @param id A Call ID
+   * @return call pointer or 0
+   */
+  Call* getCall(const CallID& id);
+
+
+private:
+  std::string _fullname;
+  std::string _hostname;
+  AccountID _accountID;
 
 protected:
-	
-	std::string _fullname;
-	std::string _hostname;
-	std::string _localIpAddress;
+  /** Add a call to the call map (protected by mutex)
+   * @param call A call pointer with a unique pointer
+   * @return true if the call was unique and added
+   */
+  bool addCall(Call* call);
+
+  /** remove a call from the call map (protected by mutex)
+   * @param id A Call ID
+   * @return true if the call was correctly removed
+   */
+  bool removeCall(const CallID& id);
+
+  /**
+   * Remove all the call from the map
+   */
+  bool clearCallMap();
+
+  /** Contains all the calls for this Link, protected by mutex */
+  CallMap _callMap;
+  /** Mutex to protect call map */
+  ost::Mutex _callMapMutex;
+
+  /** Get Local IP Address (ie: 127.0.0.1, 192.168.0.1, ...) */
+  std::string _localIPAddress;
+  /** Get local listening port (5060 for SIP, ...) */
+  unsigned int _localPort;
 };
 
 #endif // __VOIP_LINK_H__