diff --git a/src/call.cpp b/src/call.cpp
index b1625d346e3bc726bb6c48c66cf91a49e1323ad5..45ee195eee3aa6bfb5a32c6410e70983c166db05 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -30,6 +30,7 @@ Call::Call(const CallID& id, Call::CallType type)
            , _type(type) 
            , _connectionState(Call::Disconnected)
            , _callState(Call::Inactive)
+           , _callConfig (Call::Classic)
            , _peerName()
            , _peerNumber()
 {
diff --git a/src/call.h b/src/call.h
index d82ff7ba583c2253571532ddcd7f80561cf3aad2..836ee3daa6cf444ee65e1531d9f5ac6d8a7d89a8 100644
--- a/src/call.h
+++ b/src/call.h
@@ -1,5 +1,6 @@
 /*
- *  Copyright (C) 2004-2006 Savoir-Faire Linux inc.
+ *  Copyright (C) 2004-2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *
@@ -25,6 +26,9 @@
 
 #include "plug-in/audiorecorder/audiorecord.h"
 
+#define IP_TO_IP_PATTERN       "ip:"
+
+#define CallConfigNULL          NULL
 /* 
  * @file call.h 
  * @brief A call is the base class for protocol-based calls
@@ -35,219 +39,232 @@ typedef std::string CallID;
 class AudioRecord;
 
 class Call{
-  public:
-    /**
-     * This determines if the call originated from the local user (Outgoing)
-     * or from some remote peer (Incoming).
-     */
-    enum CallType {Incoming, Outgoing};
-
-    /**
-     * Tell where we're at with the call. The call gets Connected when we know
-     * from the other end what happened with out call. A call can be 'Connected'
-     * even if the call state is Busy, Refused, or Error.
-     *
-     * Audio should be transmitted when ConnectionState = Connected AND
-     * CallState = Active.
-     */
-    enum ConnectionState {Disconnected, Trying, Progressing, Ringing, Connected};
-
-    /**
-     * The Call State.
-     */
-    enum CallState {Inactive, Active, Hold, Busy, Refused, Error};
-
-    /**
-     * 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; }
-
-    /** 
-     * 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; }
-
-    /** 
-     * Get the peer number (destination on outgoing)
-     * not protected by mutex (when created)
-     * @return std::string The peer number
-     */
-    const std::string& getPeerNumber() {  return _peerNumber; }
-
-    /** 
-     * Set the peer name (caller in ingoing)
-     * not protected by mutex (when created)
-     * @param name The peer name
-     */
-    void setPeerName(const std::string& name) {  _peerName = name; }
-
-    /** 
-     * Get the peer name (caller in ingoing)
-     * not protected by mutex (when created)
-     * @return std::string The peer name
-     */
-    const std::string& getPeerName() {  return _peerName; }
-
-    /**
-     * Tell if the call is incoming
-     * @return true if yes
-     *	      false otherwise
-     */
-    bool isIncoming() { return (_type == Incoming) ? true : false; }
-
-    /** 
-     * Set the connection state of the call (protected by mutex)
-     * @param state The connection state
-     */
-    void setConnectionState(ConnectionState state);
-    
-    /** 
-     * Get the connection state of the call (protected by mutex)
-     * @return ConnectionState The connection state
-     */
-    ConnectionState getConnectionState();
-
-    /**
-     * Set the state of the call (protected by mutex)
-     * @param state The call state
-     */
-    void setState(CallState state);
-
-    /** 
-     * Get the call state of the call (protected by mutex)
-     * @return CallState  The call state
-     */
-    CallState getState();
-
-    /**
-     * Set the audio start boolean (protected by mutex)
-     * @param start true if we start the audio
-     *		    false otherwise
-     */
-    void setAudioStart(bool start);
-
-    /**
-     * Tell if the audio is started (protected by mutex)
-     * @return true if it's already started
-     *	      false otherwise
-     */
-    bool isAudioStarted();
+    public:
+
+        /**
+         * This determines if the call is a direct IP-to-IP call or a classic call, made with an existing account
+         */
+        enum CallConfiguration {Classic, IPtoIP};
+
+        /**
+         * This determines if the call originated from the local user (Outgoing)
+         * or from some remote peer (Incoming).
+         */
+        enum CallType {Incoming, Outgoing};
+
+        /**
+         * Tell where we're at with the call. The call gets Connected when we know
+         * from the other end what happened with out call. A call can be 'Connected'
+         * even if the call state is Busy, Refused, or Error.
+         *
+         * Audio should be transmitted when ConnectionState = Connected AND
+         * CallState = Active.
+         */
+        enum ConnectionState {Disconnected, Trying, Progressing, Ringing, Connected};
+
+        /**
+         * The Call State.
+         */
+        enum CallState {Inactive, Active, Hold, Busy, Refused, Error};
+
+        /**
+         * 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; }
+
+        /** 
+         * 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; }
+
+        /** 
+         * Get the peer number (destination on outgoing)
+         * not protected by mutex (when created)
+         * @return std::string The peer number
+         */
+        const std::string& getPeerNumber() {  return _peerNumber; }
+
+        /** 
+         * Set the peer name (caller in ingoing)
+         * not protected by mutex (when created)
+         * @param name The peer name
+         */
+        void setPeerName(const std::string& name) {  _peerName = name; }
+
+        /** 
+         * Get the peer name (caller in ingoing)
+         * not protected by mutex (when created)
+         * @return std::string The peer name
+         */
+        const std::string& getPeerName() {  return _peerName; }
+
+        /**
+         * Tell if the call is incoming
+         * @return true if yes
+         *	      false otherwise
+         */
+        bool isIncoming() { return (_type == Incoming) ? true : false; }
+
+        /** 
+         * Set the connection state of the call (protected by mutex)
+         * @param state The connection state
+         */
+        void setConnectionState(ConnectionState state);
+
+        /** 
+         * Get the connection state of the call (protected by mutex)
+         * @return ConnectionState The connection state
+         */
+        ConnectionState getConnectionState();
+
+        /**
+         * Set the state of the call (protected by mutex)
+         * @param state The call state
+         */
+        void setState(CallState state);
+
+        /** 
+         * Get the call state of the call (protected by mutex)
+         * @return CallState  The call state
+         */
+        CallState getState();
+
+        void setCallConfiguration (Call::CallConfiguration callConfig) { _callConfig = callConfig; }
+        
+        Call::CallConfiguration getCallConfiguration (void) { return _callConfig; }
+        
+        /**
+         * Set the audio start boolean (protected by mutex)
+         * @param start true if we start the audio
+         *		    false otherwise
+         */
+        void setAudioStart(bool start);
+
+        /**
+         * Tell if the audio is started (protected by mutex)
+         * @return true if it's already started
+         *	      false otherwise
+         */
+        bool isAudioStarted();
+
+        /** 
+         * Set my IP [not protected] 
+         * @param ip  The local IP address
+         */
+        void setLocalIp(const std::string& ip)     { _localIPAddress = ip; }
+
+        /** 
+         * Set local audio port, as seen by me [not protected]
+         * @param port  The local audio port
+         */
+        void setLocalAudioPort(unsigned int port)  { _localAudioPort = port;}
+
+        /** 
+         * Set the audio port that remote will see.
+         * @param port  The external audio port
+         */
+        void setLocalExternAudioPort(unsigned int port) { _localExternalAudioPort = port; }
 
         /** 
-     * Set my IP [not protected] 
-     * @param ip  The local IP address
-     */
-    void setLocalIp(const std::string& ip)     { _localIPAddress = ip; }
-
-    /** 
-     * Set local audio port, as seen by me [not protected]
-     * @param port  The local audio port
-     */
-    void setLocalAudioPort(unsigned int port)  { _localAudioPort = port;}
-
-    /** 
-     * Set the audio port that remote will see.
-     * @param port  The external audio port
-     */
-    void setLocalExternAudioPort(unsigned int port) { _localExternalAudioPort = port; }
-
-    /** 
-     * Return the audio port seen by the remote side. 
-     * @return unsigned int The external audio port
-    */
-    unsigned int getLocalExternAudioPort() { return _localExternalAudioPort; }
-
-    /** 
-     * Return my IP [mutex protected] 
-     * @return std::string The local IP
-     */
-    const std::string& getLocalIp();
-
-    /** 
-     * Return port used locally (for my machine) [mutex protected] 
-     * @return unsigned int  The local audio port
-     */
-    unsigned int getLocalAudioPort();
-
-    /**
-     * @return Return the file name for this call
-     */
-    std::string getFileName() {return _filename;}
-
-    /**
-     * A recorder for this call
-     */
-    AudioRecord recAudio;
-  
-    /**
-     * SetRecording
-     */
-    void setRecording();
-
-    /**
-     * stopRecording, make sure the recording is stopped (whe transfering call)
-     */
-    void stopRecording();
-    
-    /**
-     * Return Recording state
-     */
-    bool isRecording(); 
-
-    /**
-     *
-     */
-    void initRecFileName();
-
-  protected:
-    /** Protect every attribute that can be changed by two threads */
-    ost::Mutex _callMutex;
-
-    bool _audioStarted;
-
-    // Informations about call socket / audio
-
-    /** My IP address */
-    std::string  _localIPAddress;
-
-    /** Local audio port, as seen by me. */
-    unsigned int _localAudioPort;
-
-    /** Port assigned to my machine by the NAT, as seen by remote peer (he connects there) */
-    unsigned int _localExternalAudioPort;
-
-    
-  private:  
-  
-    /** Unique ID of the call */
-    CallID _id;
-
-    /** Type of the call */
-    CallType _type;
-    /** Disconnected/Progressing/Trying/Ringing/Connected */
-    ConnectionState _connectionState;
-    /** Inactive/Active/Hold/Busy/Refused/Error */
-    CallState _callState;
-
-    /** Name of the peer */
-    std::string _peerName;
-
-    /** Number of the peer */
-    std::string _peerNumber;
-
-    /** File name for his call : time YY-MM-DD */
-    std::string _filename;
+         * Return the audio port seen by the remote side. 
+         * @return unsigned int The external audio port
+         */
+        unsigned int getLocalExternAudioPort() { return _localExternalAudioPort; }
+
+        /** 
+         * Return my IP [mutex protected] 
+         * @return std::string The local IP
+         */
+        const std::string& getLocalIp();
+
+        /** 
+         * Return port used locally (for my machine) [mutex protected] 
+         * @return unsigned int  The local audio port
+         */
+        unsigned int getLocalAudioPort();
+
+        /**
+         * @return Return the file name for this call
+         */
+        std::string getFileName() {return _filename;}
+
+        /**
+         * A recorder for this call
+         */
+        AudioRecord recAudio;
+
+        /**
+         * SetRecording
+         */
+        void setRecording();
+
+        /**
+         * stopRecording, make sure the recording is stopped (whe transfering call)
+         */
+        void stopRecording();
+
+        /**
+         * Return Recording state
+         */
+        bool isRecording(); 
+
+        /**
+         *
+         */
+        void initRecFileName();
+
+    protected:
+        /** Protect every attribute that can be changed by two threads */
+        ost::Mutex _callMutex;
+
+        bool _audioStarted;
+
+        // Informations about call socket / audio
+
+        /** My IP address */
+        std::string  _localIPAddress;
+
+        /** Local audio port, as seen by me. */
+        unsigned int _localAudioPort;
+
+        /** Port assigned to my machine by the NAT, as seen by remote peer (he connects there) */
+        unsigned int _localExternalAudioPort;
+
+
+    private:  
+
+        /** Unique ID of the call */
+        CallID _id;
+
+        /** Type of the call */
+        CallType _type;
+        /** Disconnected/Progressing/Trying/Ringing/Connected */
+        ConnectionState _connectionState;
+        /** Inactive/Active/Hold/Busy/Refused/Error */
+        CallState _callState;
+
+        /** Direct IP-to-IP or classic call */
+        CallConfiguration _callConfig;
+
+        /** Name of the peer */
+        std::string _peerName;
+
+        /** Number of the peer */
+        std::string _peerNumber;
+
+        /** File name for his call : time YY-MM-DD */
+        std::string _filename;
 };
 
 #endif
diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp
index 4ad23121b347059f92cc050def291349b38f7c52..356170a29ab9bbb624ffbeac70f3153d37dce500 100644
--- a/src/managerimpl.cpp
+++ b/src/managerimpl.cpp
@@ -80,6 +80,7 @@ ManagerImpl::ManagerImpl (void)
         , _hasZeroconf(false)
         , _callAccountMap()
         , _callAccountMapMutex()
+        , _callConfigMap()
         , _accountMap()
 {
   
@@ -188,14 +189,36 @@ ManagerImpl::switchCall(const CallID& id ) {
 // Management of events' IP-phone user
 ///////////////////////////////////////////////////////////////////////////////
 /* Main Thread */ 
+
   bool
 ManagerImpl::outgoingCall(const std::string& accountid, const CallID& id, const std::string& to)
 {
+    std::string pattern;
+    Call::CallConfiguration callConfig;
+    SIPVoIPLink *siplink;
+    
     _debug("ManagerImpl::outgoingCall() method \n");
 
     stopTone(false);
     playTone();
 
+    /* Check what kind of call we are dealing with */
+    check_call_configuration (id, to, &callConfig);
+    
+    if (callConfig == Call::IPtoIP) {
+        _debug ("Start IP to IP call\n");
+        /* We need to retrieve the sip voiplink instance */
+        siplink = SIPVoIPLink::instance("");     
+        if (siplink->new_ip_to_ip_call (id, to)) {
+            switchCall (id);
+            return true;
+        }
+        else {
+            callFailure (id);
+        }
+        return false;
+    } 
+
     if (!accountExists(accountid)) {
         _debug("! Manager Error: Outgoing Call: account doesn't exist\n");
         return false;
@@ -277,9 +300,9 @@ ManagerImpl::answerCall(const CallID& id)
   removeWaitingCall(id);
   switchCall(id);
  
-  std::string codecName = getCurrentCodecName(id);
-  _debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str());
-  if (_dbus) _dbus->getCallManager()->currentSelectedCodec(id,codecName.c_str());
+  //std::string codecName = getCurrentCodecName(id);
+  //_debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str());
+  //if (_dbus) _dbus->getCallManager()->currentSelectedCodec(id,codecName.c_str());
 
   return true;
 }
@@ -297,19 +320,24 @@ ManagerImpl::hangupCall(const CallID& id)
 
     /* Broadcast a signal over DBus */
     if (_dbus) _dbus->getCallManager()->callStateChanged(id, "HUNGUP");
-  
-    accountid = getAccountFromCall( id );
-    if (accountid == AccountNULL) {
-        /** @todo We should tell the GUI that the call doesn't exist, so
-        * it clears up. This can happen. */
-        _debug("! Manager Hangup Call: Call doesn't exists\n");
-        return false;
+    
+    /* Direct IP to IP call */
+    if (getConfigFromCall (id) == Call::IPtoIP) {
+        returnValue = SIPVoIPLink::instance (AccountNULL)->hangup (id);        
     }
 
-    returnValue = getAccountLink(accountid)->hangup(id);
+    /* Classic call, attached to an account */
+    else { 
+        accountid = getAccountFromCall( id );
+        if (accountid == AccountNULL) {
+            _debug("! Manager Hangup Call: Call doesn't exists\n");
+            return false;
+        }
+    
+        returnValue = getAccountLink(accountid)->hangup(id);
+        removeCallAccount(id);
+    }
 
-    _debug("After voip link hungup!\n");
-    removeCallAccount(id);
     switchCall("");
 
     if( _audiodriver->getLayerType() == PULSEAUDIO && getConfigInt( PREFERENCES , CONFIG_PA_VOLUME_CTRL ) ) {
@@ -691,14 +719,15 @@ ManagerImpl::incomingMessage(const AccountID& accountId, const std::string& mess
   void
 ManagerImpl::peerAnsweredCall(const CallID& id)
 {
-  if (isCurrentCall(id)) {
-    stopTone(false);
-  }
-  if (_dbus) _dbus->getCallManager()->callStateChanged(id, "CURRENT");
+    if (isCurrentCall(id)) {
+        stopTone(false);
+    }
   
-  std::string codecName = getCurrentCodecName(id);
-  _debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str());
-  if (_dbus) _dbus->getCallManager()->currentSelectedCodec(id,codecName.c_str());
+    if (_dbus) _dbus->getCallManager()->callStateChanged(id, "CURRENT");
+  
+  //std::string codecName = getCurrentCodecName(id);
+  //_debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str());
+  //if (_dbus) _dbus->getCallManager()->currentSelectedCodec(id,codecName.c_str());
 }
 
 //THREAD=VoIP Call=Outgoing
@@ -2371,11 +2400,15 @@ void ManagerImpl::restartPJSIP (void)
 
 VoIPLink* ManagerImpl::getAccountLink(const AccountID& accountID)
 {
-  Account* acc = getAccount(accountID);
-  if ( acc ) {
-    return acc->getVoIPLink();
-  }
-  return 0;
+    if (accountID!=AccountNULL) {
+        Account* acc = getAccount(accountID);
+        if ( acc ) {
+            return acc->getVoIPLink();
+        }
+        return 0;
+    }
+    else
+        return SIPVoIPLink::instance("");
 }
 
 VoIPLink* ManagerImpl::getSIPAccountLink()
@@ -2438,65 +2471,51 @@ void ManagerImpl::registerCurSIPAccounts(VoIPLink *link)
     }    
 }
 
-#ifdef TEST
-/** 
- * Test accountMap
- */
-bool ManagerImpl::testCallAccountMap()
-{
-  if ( getAccountFromCall(1) != AccountNULL ) {
-    _debug("TEST: getAccountFromCall with empty list failed\n");
-  }
-  if ( removeCallAccount(1) != false ) {
-    _debug("TEST: removeCallAccount with empty list failed\n");
-  }
-  CallID newid = getNewCallID();
-  if ( associateCallToAccount(newid, "acc0") == false ) {
-    _debug("TEST: associateCallToAccount with new CallID empty list failed\n");
-  }
-  if ( associateCallToAccount(newid, "acc1") == true ) {
-    _debug("TEST: associateCallToAccount with a known CallID failed\n");
-  }
-  if ( getAccountFromCall( newid ) != "acc0" ) {
-    _debug("TEST: getAccountFromCall don't return the good account id\n");
-  }
-  CallID secondnewid = getNewCallID();
-  if ( associateCallToAccount(secondnewid, "xxxx") == true ) {
-    _debug("TEST: associateCallToAccount with unknown account id failed\n");
-  }
-  if ( removeCallAccount( newid ) != true ) {
-    _debug("TEST: removeCallAccount don't remove the association\n");
-  }
+void ManagerImpl::check_call_configuration (const CallID& id, const std::string &to, Call::CallConfiguration *callConfig) {
 
-  return true;
+    std::string pattern;
+    Call::CallConfiguration config;
+
+    /* Check if the call is an IP-to-IP call */
+    /* For an IP-to-IP call, we don't need any account */
+    /* Pattern looked for : ip:xxx.xxx.xxx.xxx */
+    pattern = to.substr (0,3);
+    if (pattern==IP_TO_IP_PATTERN) {
+        config = Call::IPtoIP;
+    } else {
+        config = Call::Classic;
+    }
+    associateConfigToCall (id, config);
+    *callConfig = config;
 }
 
-/**
- * Test AccountMap
- */
-bool ManagerImpl::testAccountMap() 
-{
-  if (loadAccountMap() != 2) {
-    _debug("TEST: loadAccountMap didn't load 2 account\n");
-  }
-  if (accountExists("acc0") == false) {
-    _debug("TEST: accountExists didn't find acc0\n");
-  }
-  if (accountExists("accZ") != false) {
-    _debug("TEST: accountExists found an unknown account\n");
-  }
-  if (getAccount("acc0") == 0) {
-    _debug("TEST: getAccount didn't find acc0\n");
-  }
-  if (getAccount("accZ") != 0) {
-    _debug("TEST: getAccount found an unknown account\n");
-  }
-  unloadAccountMap();
-  if ( accountExists("acc0") == true ) {
-    _debug("TEST: accountExists found an account after unloadAccount\n");
-  }
-  return true;
+
+bool ManagerImpl::associateConfigToCall (const CallID& callID, Call::CallConfiguration config) {
+
+    if (getConfigFromCall(callID) == CallConfigNULL) { // nothing with the same ID
+        _callConfigMap[callID] = config;
+        _debug("Associate Call %s with config %i\n", callID.data(), config);
+        return true;
+    } else {
+        return false;
+    }
 }
 
+Call::CallConfiguration ManagerImpl::getConfigFromCall(const CallID& callID) {
+
+    CallConfigMap::iterator iter = _callConfigMap.find(callID);
+    if ( iter == _callConfigMap.end()) {
+        return (Call::CallConfiguration)CallConfigNULL;
+    } else {
+        return iter->second;
+    }
+}
+
+bool ManagerImpl::removeCallConfig(const CallID& callID) {
+
+    if ( _callConfigMap.erase(callID) ) {
+        return true;
+    }
+    return false;
+}
 
-#endif
diff --git a/src/managerimpl.h b/src/managerimpl.h
index 0765bac47619e05229a9f0fbca829f97a17611f1..dcc63e54b30684920032fc326a964c958508e901 100644
--- a/src/managerimpl.h
+++ b/src/managerimpl.h
@@ -58,6 +58,8 @@ 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, Call::CallConfiguration> CallConfigMap;
+
 /** Define a type for CallID vector (waiting list, incoming not answered) */
 typedef std::set<CallID> CallIDSet;
 
@@ -989,6 +991,14 @@ class ManagerImpl {
     /** Mutex to lock the call account map (main thread + voiplink thread) */
     ost::Mutex _callAccountMapMutex;
 
+    CallConfigMap _callConfigMap;
+
+    bool associateConfigToCall (const CallID& callID, Call::CallConfiguration config);
+
+    Call::CallConfiguration getConfigFromCall(const CallID& callID);
+
+    bool removeCallConfig(const CallID& callID);
+
     /** Associate a new CallID to a AccountID
      * Protected by mutex
      * @param callID the new CallID not in the list yet
@@ -1053,7 +1063,7 @@ public:
      * @param accountID	  Account ID to get
      * @return VoIPLink*   The voip link from the account pointer or 0
      */
-    VoIPLink* getAccountLink(const AccountID& accountID);
+    VoIPLink* getAccountLink(const AccountID& accountID=AccountNULL);
 
     VoIPLink* getSIPAccountLink (void);
 
@@ -1076,6 +1086,11 @@ private:
     // Assignment Operator
     ManagerImpl& operator=( const ManagerImpl& rh);
 
+    /**
+     * Check if the call is a classic call or a direct IP-to-IP call
+     */
+    void check_call_configuration (const CallID& id, const std::string& to, Call::CallConfiguration *callConfig);
+
 #ifdef TEST
     bool testCallAccountMap();
     bool testAccountMap();
diff --git a/src/sdp.h b/src/sdp.h
index 9bbd0d5344e43b37594a759067e9a9f4b82f7695..a30b18807f7ee780f9257189920ad55fcda9b11b 100644
--- a/src/sdp.h
+++ b/src/sdp.h
@@ -180,6 +180,7 @@ class Sdp {
         unsigned int get_remote_audio_port() { return _remote_audio_port; }
 
         void fetch_media_transport_info_from_remote_sdp (pjmedia_sdp_session *remote_sdp);
+
     private:
         /** Codec Map */
         std::vector<sdpMedia*> _local_media_cap;
diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp
index acb8d8b0e5e38efb266f586b9cff5a078b7f8ea2..b4166d99966020ca2d8032248213cd3af0ff3a81 100644
--- a/src/sipvoiplink.cpp
+++ b/src/sipvoiplink.cpp
@@ -950,6 +950,7 @@ SIPVoIPLink::SIPStartCall(SIPCall* call, const std::string& subject UNUSED)
     pj_strdup2(_pool, &to, strTo.data());
     pj_strdup2(_pool, &contact, account->getContact().data());
 
+    _debug("%s %s %s\n", from.ptr, contact.ptr, to.ptr);
     // create the dialog (UAC)
     status = pjsip_dlg_create_uac(pjsip_ua_instance(), &from,
             &contact,
@@ -1091,7 +1092,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
                 _debug ("Get remote media information from offer\n");
                 call->getLocalSDP()->fetch_media_transport_info_from_remote_sdp (r_sdp);
 
-                _debug ("Update call state\n");
+                _debug ("Update call state , id = %s\n", call->getCallId().c_str());
                 call->setConnectionState(Call::Connected);
                 call->setState(Call::Active);
 
@@ -1133,6 +1134,84 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
         }
     }
 
+    bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to) {
+
+        SIPCall *call;
+        pj_status_t status;
+        std::string uri_from, uri_to, hostname;
+        std::ostringstream uri_contact;
+        pj_str_t from, str_to, contact;
+        pjsip_dialog *dialog;
+        pjsip_inv_session *inv;
+        pjsip_tx_data *tdata;
+
+        /* Create the call */
+        call = new SIPCall(id, Call::Outgoing, _pool);
+
+        if (call) {
+        
+            call->setCallConfiguration (Call::IPtoIP);
+            call->setPeerNumber(getSipTo(to, getLocalIPAddress()));
+
+            // Generate the from URI
+            hostname = pj_gethostname()->ptr;
+            uri_from = "sip:" + hostname + "@" + getLocalIPAddress() ;
+
+            // Generate the from URI
+            uri_to = "sip:" + to.substr (3, to.length());
+
+            // Generate the to URI
+            setCallAudioLocal(call, getLocalIPAddress(), useStun(), getStunServer());
+
+            call->initRecFileName();
+
+            // Building the local SDP offer
+            call->getLocalSDP()->set_ip_address(getLocalIP());
+            call->getLocalSDP()->create_initial_offer();
+
+            // Generate the contact URI
+            uri_contact << "<" << uri_from << ":" << call->getLocalSDP()->get_local_extern_audio_port() << ">";
+
+            // pjsip need the from and to information in pj_str_t format
+            pj_strdup2(_pool, &from, uri_from.data());
+            pj_strdup2(_pool, &str_to, uri_to.data());
+            pj_strdup2(_pool, &contact, uri_contact.str().data());
+
+            // create the dialog (UAC)
+            _debug("Try to make a call %s -  %s -  %s - \n", from.ptr, contact.ptr, str_to.ptr);
+            status = pjsip_dlg_create_uac(pjsip_ua_instance(), &from, &contact, &str_to, NULL, &dialog);
+            PJ_ASSERT_RETURN(status == PJ_SUCCESS, false);
+
+            // Create the invite session for this call
+            status = pjsip_inv_create_uac(dialog, call->getLocalSDP()->get_local_sdp_session(), 0, &inv);
+            PJ_ASSERT_RETURN(status == PJ_SUCCESS, false);
+
+            // Associate current call in the invite session
+            inv->mod_data[getModId()] = call;
+
+            status = pjsip_inv_invite(inv, &tdata);
+            PJ_ASSERT_RETURN(status == PJ_SUCCESS, false);
+
+            // Associate current invite session in the call
+            call->setInvSession(inv);
+
+            status = pjsip_inv_send_msg(inv, tdata);
+            if(status != PJ_SUCCESS) {
+                delete call; call = 0;
+                return false;
+            }
+    
+            call->setConnectionState(Call::Progressing);
+            call->setState(Call::Active);
+            addCall(call);
+            
+            return true;
+        }
+        else
+            return false;
+    } 
+
+
     ///////////////////////////////////////////////////////////////////////////////
     // Private functions
     ///////////////////////////////////////////////////////////////////////////////
@@ -1508,11 +1587,11 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
     }
 
     void SIPVoIPLink::handle_reinvite (SIPCall *call) {
-    
+
         // Close the previous RTP session
         _audiortp->closeRtpSession ();
         call->setAudioStart (false);
-    
+
         // Create a new one with new info
         if (_audiortp->createNewSession (call) >= 0) {
             call->setAudioStart (true);
@@ -1609,8 +1688,16 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
             // We receive a ACK - The connection is established
             else if( inv->state == PJSIP_INV_STATE_CONFIRMED ){
                 _debug ("*************************** PJSIP_INV_STATE_CONFIRMED ***********************************\n");
-                accId = Manager::instance().getAccountFromCall(call->getCallId());
-                link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink(accId));
+                    
+                /* If the call is a direct IP-to-IP call */
+                if (call->getCallConfiguration () == Call::IPtoIP) {
+                    link = SIPVoIPLink::instance("");
+                }
+                else {
+                    accId = Manager::instance().getAccountFromCall(call->getCallId());
+                    link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink(accId));
+                }
+                
                 if (link)
                     link->SIPCallAnswered(call, rdata);
             }
@@ -1629,7 +1716,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
                         }
                         break; 
 
-                    /* The call connection failed */
+                        /* The call connection failed */
                     case PJSIP_SC_NOT_FOUND:            /* peer not found */
                     case PJSIP_SC_REQUEST_TIMEOUT:      /* request timeout */
                     case PJSIP_SC_NOT_ACCEPTABLE_HERE:  /* no compatible codecs */
@@ -1641,7 +1728,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
                             link->SIPCallServerFailure(call);
                         }
                         break;
-                    
+
                     default:
                         _debug ("sipvoiplink.cpp - line 1635 : Unhandled call state. This is probably a bug.\n");
                         break;
@@ -2292,7 +2379,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
     }
 
     void on_rx_offer( pjsip_inv_session *inv, const pjmedia_sdp_session *offer ){
-        
+
         _debug ( "********************************* REINVITE RECEIVED *******************************\n" );
 
 #ifdef CAN_REINVITE
@@ -2318,7 +2405,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
 
     }
 
-/*****************************************************************************************************************/
+    /*****************************************************************************************************************/
 
 
     bool setCallAudioLocal(SIPCall* call, std::string localIP, bool stun, std::string server) {
diff --git a/src/sipvoiplink.h b/src/sipvoiplink.h
index 3180dd5c2b6a6e1972cd62cbd4939a43c89b589a..92212c29353f982c147eccdf49356f0f6ce09de6 100644
--- a/src/sipvoiplink.h
+++ b/src/sipvoiplink.h
@@ -312,6 +312,7 @@ class SIPVoIPLink : public VoIPLink
       
         int inv_session_reinvite (SIPCall *call, std::string direction="");
         
+        bool new_ip_to_ip_call (const CallID& id, const std::string& to);
 
     private:
         /**