Commit 7d340f74 authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

Add a map to associate a call id to a call configuration (IP-to-IP)

parent 97e4eec4
......@@ -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()
{
......
/*
* 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
......@@ -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 */