Commit d054a328 authored by Rafaël Carré's avatar Rafaël Carré
Browse files

SIP: simplify

parent d81435fa
......@@ -60,7 +60,6 @@ AudioRtpSession::AudioRtpSession (SIPCall * sipcall, RtpMethod type, ost::RTPDat
AudioRtpSession::~AudioRtpSession()
{
_info ("AudioRtpSession: Delete AudioRtpSession instance");
_queue->disableStack();
}
......
......@@ -33,6 +33,8 @@
void UrlHook::runAction (std::string command, std::string args)
{
if (args.empty())
return;
//FIXME : use fork and execve, so no need to escape shell arguments
std::string cmd = command + "\"" + args + "\" &";
system(cmd.c_str());
......
......@@ -474,36 +474,29 @@ IAXVoIPLink::refuse (const std::string& id)
}
bool
void
IAXVoIPLink::carryingDTMFdigits (const std::string& id, char code)
{
IAXCall* call = getIAXCall (id);
CHK_VALID_CALL;
mutexIAX_.enterMutex();
iax_send_dtmf (call->getSession(), code);
mutexIAX_.leaveMutex();
return true;
if (call) {
mutexIAX_.enterMutex();
iax_send_dtmf (call->getSession(), code);
mutexIAX_.leaveMutex();
}
}
bool
void
IAXVoIPLink::sendTextMessage (sfl::InstantMessaging *module,
const std::string& callID, const std::string& message,
const std::string& /*from*/)
{
IAXCall* call = getIAXCall (callID);
CHK_VALID_CALL;
if (!call)
return;
// Must active the mutex for this session
mutexIAX_.enterMutex();
module->send_iax_message (call->getSession(), callID, message.c_str());
// iax_send_text (call->getSession(), message.c_str());
mutexIAX_.leaveMutex();
return true;
}
......@@ -649,28 +642,17 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call)
break;
case IAX_IE_MSGCOUNT:
break;
case IAX_EVENT_TIMEOUT:
case IAX_EVENT_PONG:
default:
break;
case IAX_EVENT_URL:
if (Manager::instance().getConfigString (HOOKS, URLHOOK_IAX2_ENABLED) == "1") {
if (*event->data) {
_debug ("> IAX_EVENT_URL received: %s", event->data);
UrlHook::runAction (Manager::instance().getConfigString (HOOKS, URLHOOK_COMMAND), (char*) event->data);
}
}
if (Manager::instance().getConfigString (HOOKS, URLHOOK_IAX2_ENABLED) == "1")
UrlHook::runAction (Manager::instance().getConfigString (HOOKS, URLHOOK_COMMAND), (char*) event->data);
break;
case IAX_EVENT_TIMEOUT:
break;
default:
_debug ("iaxHandleCallEvent: Unknown event type (in call event): %d", event->etype);
}
}
......
......@@ -175,13 +175,11 @@ class IAXVoIPLink : public VoIPLink
* Send DTMF
* @param id The ID of the call
* @param code The code of the DTMF
* @return bool true on success
* false otherwise
*/
virtual bool carryingDTMFdigits (const std::string& id, char code);
virtual void carryingDTMFdigits (const std::string& id, char code);
virtual bool sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from);
virtual void sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from);
/**
* Return the codec protocol used for this call
......
......@@ -54,9 +54,7 @@ static void XMLCALL endElementCallback (void * /*userData*/, const char * /*name
}
InstantMessaging::InstantMessaging()
: imFiles ()
, messageMaxSize (MAXIMUM_MESSAGE_LENGTH) {}
InstantMessaging::InstantMessaging() {}
InstantMessaging::~InstantMessaging() {}
......@@ -110,17 +108,12 @@ void InstantMessaging::send_sip_message (pjsip_inv_session *session, const std::
}
void InstantMessaging::iax_send (iax_session* session, const std::string& /*id*/, const std::string& message)
{
iax_send_text(session, message.c_str()) != -1;
}
void InstantMessaging::send_iax_message (iax_session* session, const std::string& id, const std::string& message)
{
std::vector<std::string> msgs = split_message (message);
std::vector<std::string>::const_iterator iter;
for (iter = msgs.begin(); iter != msgs.end(); ++iter)
iax_send(session, id, *iter);
iax_send_text(session, (*iter).c_str());
}
......
......@@ -86,19 +86,12 @@ class InstantMessaging
*/
~InstantMessaging();
/**
* Set maximum size fo this module.
*/
void setMessageMaximumSize (unsigned int max) {
messageMaxSize = max;
}
/**
* Return the maximum number if character for a single SIP MESSAGE.
* Longer messages should be splitted in several smaller messages using split_message
*/
unsigned int getMessageMaximumSize (void) {
return messageMaxSize;
size_t getMessageMaximumSize (void) {
return MAXIMUM_MESSAGE_LENGTH;
}
/*
......@@ -120,9 +113,6 @@ class InstantMessaging
void sip_send (pjsip_inv_session*, const std::string& id, const std::string&);
void send_sip_message (pjsip_inv_session*, const std::string& id, const std::string&);
void iax_send (iax_session* session, const std::string& id, const std::string& message);
void send_iax_message (iax_session *session, const std::string& id, const std::string&);
std::vector<std::string> split_message(std::string);
......@@ -177,24 +167,8 @@ class InstantMessaging
private:
/**
* A queue to handle messages
*/
// std::queue<std::string> queuedMessages;
/**
* A map to handle opened file descriptors
* A file descriptor is associated to a call ID
*/
std::map<std::string, std::ofstream*> imFiles;
InstantMessaging (const InstantMessaging&); //No Copy Constructor
InstantMessaging& operator= (const InstantMessaging&); //No Assignment Operator
/**
* Maximum size in char of an instant message
*/
unsigned int messageMaxSize;
};
}
#endif // _INSTANT_MESSAGING_H
......@@ -128,7 +128,6 @@ void ManagerImpl::init (std::string config_file)
audioLayerMutexUnlock();
_history->load_history (preferences.getHistoryLimit());
_imModule->init();
registerAccounts();
}
......@@ -591,21 +590,15 @@ void ManagerImpl::transferSucceded ()
bool ManagerImpl::attendedTransfer(const std::string& transferID, const std::string& targetID)
{
bool returnValue = false;
_debug("Manager: Attended transfer");
bool returnValue;;
// Direct IP to IP call
if (getConfigFromCall (transferID) == Call::IPtoIP)
returnValue = SIPVoIPLink::instance ()-> attendedTransfer(transferID, targetID);
else { // Classic call, attached to an account
std::string accountid = getAccountFromCall (transferID);
if (accountid.empty()) {
_warn ("Manager: Call doesn't exists");
if (accountid.empty())
return false;
}
returnValue = getAccountLink (accountid)->attendedTransfer (transferID, targetID);
}
......@@ -618,20 +611,11 @@ bool ManagerImpl::attendedTransfer(const std::string& transferID, const std::str
//THREAD=Main : Call:Incoming
bool ManagerImpl::refuseCall (const std::string& id)
{
std::string accountid;
bool returnValue;
_debug ("Manager: Refuse call %s", id.c_str());
std::string current_call_id = getCurrentCallId();
stopTone();
int nbCalls = getCallList().size();
if (nbCalls <= 1) {
_debug (" refuseCall: stop audio stream, there is only %d call(s) remaining", nbCalls);
if (getCallList().size() <= 1) {
audioLayerMutexLock();
_audiodriver->stopStream();
audioLayerMutexUnlock();
......@@ -643,12 +627,9 @@ bool ManagerImpl::refuseCall (const std::string& id)
returnValue = SIPVoIPLink::instance ()-> refuse (id);
else {
/* Classic call, attached to an account */
accountid = getAccountFromCall (id);
if (accountid.empty()) {
_warn ("Manager: Call doesn't exists");
std::string accountid = getAccountFromCall (id);
if (accountid.empty())
return false;
}
returnValue = getAccountLink (accountid)->refuse (id);
......@@ -659,7 +640,6 @@ bool ManagerImpl::refuseCall (const std::string& id)
// so the method did nothing
if (returnValue) {
removeWaitingCall (id);
_dbus.getCallManager()->callStateChanged (id, "HUNGUP");
}
......@@ -1329,11 +1309,11 @@ void ManagerImpl::saveConfig (void)
}
//THREAD=Main
bool ManagerImpl::sendDtmf (const std::string& id, char code)
void ManagerImpl::sendDtmf (const std::string& id, char code)
{
std::string accountid(getAccountFromCall(id));
playDtmf (code);
return getAccountLink (accountid)->carryingDTMFdigits (id, code);
getAccountLink (accountid)->carryingDTMFdigits (id, code);
}
//THREAD=Main | VoIPLink
......@@ -2866,7 +2846,7 @@ ManagerImpl::getAccount (const std::string& accountID) const
if (iter != _accountMap.end())
return iter->second;
_debug ("Manager: Did not found account %s, returning IP2IP account", accountID.c_str());
_debug ("Manager: Did not found account \"%s\", returning IP2IP account", accountID.c_str());
return getAccount(IP2IP_PROFILE);
}
......
......@@ -339,7 +339,7 @@ class ManagerImpl
* @param id: callid of the line.
* @param code: pressed key.
*/
bool sendDtmf (const std::string& id, char code);
void sendDtmf (const std::string& id, char code);
/**
* Play a ringtone
......
......@@ -99,11 +99,6 @@ static const char * const transactionStateMap[] = {
"PJSIP_TSX_STATE_MAX"
};
struct result {
pj_status_t status;
pjsip_server_addresses servers;
};
/** The default transport (5060) */
pjsip_transport *_localUDPTransport = NULL;
......@@ -164,11 +159,6 @@ pjsip_module _mod_ua;
pj_thread_t *thread;
pj_thread_desc desc;
/**
* Get the number of voicemail waiting in a SIP message
*/
void setVoicemailInfo (const std::string &account, pjsip_msg_body *body);
/*
* Session callback
* Called after SDP offer/answer session has completed.
......@@ -547,11 +537,7 @@ Call *SIPVoIPLink::newOutgoingCall (const std::string& id, const std::string& to
call->getLocalSDP()->setLocalIP (addrSdp);
call->getLocalSDP()->createOffer(account->getActiveCodecs());
if (SIPStartCall(call)) {
call->setConnectionState (Call::Progressing);
call->setState (Call::Active);
addCall (call);
} else {
if (!SIPStartCall(call)) {
delete call;
throw VoipLinkException("Could not send outgoing INVITE request for new call");
}
......@@ -614,14 +600,8 @@ SIPVoIPLink::hangup (const std::string& id)
// Make sure user data is NULL in callbacks
inv->mod_data[getModId()] = NULL;
// Release RTP thread
try {
if (Manager::instance().isCurrentCall (id))
call->getAudioRtp()->stop();
}
catch (...) {
throw VoipLinkException("Could not stop audio rtp session");
}
if (Manager::instance().isCurrentCall (id))
call->getAudioRtp()->stop();
removeCall (id);
}
......@@ -629,8 +609,6 @@ SIPVoIPLink::hangup (const std::string& id)
void
SIPVoIPLink::peerHungup (const std::string& id)
{
_info ("UserAgent: Peer hungup");
SIPCall* call = getSIPCall(id);
// User hangup current call. Notify peer
......@@ -644,44 +622,18 @@ SIPVoIPLink::peerHungup (const std::string& id)
// Make sure user data is NULL in callbacks
call->inv->mod_data[getModId() ] = NULL;
// Release RTP thread
try {
if (Manager::instance().isCurrentCall (id)) {
_debug ("UserAgent: Stopping AudioRTP for hangup");
call->getAudioRtp()->stop();
}
}
catch (...) {
throw VoipLinkException("Could not stop audio rtp session");
}
removeCall (id);
}
if (Manager::instance().isCurrentCall (id))
call->getAudioRtp()->stop();
void
SIPVoIPLink::cancel (const std::string& id)
{
_info ("UserAgent: Cancel call %s", id.c_str());
removeCall (id);
}
void
SIPVoIPLink::onhold (const std::string& id)
{
SIPCall *call = getSIPCall(id);
// Stop sound
call->setState (Call::Hold);
try {
call->getAudioRtp()->stop();
}
catch (...) {
throw VoipLinkException("Could not stop audio rtp session");
}
_debug ("UserAgent: Stopping RTP session for on hold action");
call->getAudioRtp()->stop();
Sdp *sdpSession = call->getLocalSDP();
if (!sdpSession)
......@@ -689,18 +641,14 @@ SIPVoIPLink::onhold (const std::string& id)
sdpSession->removeAttributeFromLocalAudioMedia("sendrecv");
sdpSession->removeAttributeFromLocalAudioMedia("sendonly");
sdpSession->addAttributeToLocalAudioMedia("sendonly");
// Create re-INVITE with new offer
SIPSessionReinvite (call);
}
void
SIPVoIPLink::offhold (const std::string& id)
{
_debug ("UserAgent: retrive call from hold status");
SIPCall *call = getSIPCall (id);
Sdp *sdpSession = call->getLocalSDP();
......@@ -750,16 +698,15 @@ SIPVoIPLink::offhold (const std::string& id)
call->setState (Call::Active);
}
bool
void
SIPVoIPLink::sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from)
{
_debug ("SipVoipLink: Send text message to %s, from %s", callID.c_str(), from.c_str());
SIPCall *call;
try {
call = getSIPCall (callID);
}
catch (const VoipLinkException &e) {
return !PJ_SUCCESS;
return;
}
/* Send IM message */
......@@ -769,9 +716,7 @@ SIPVoIPLink::sendTextMessage (sfl::InstantMessaging *module, const std::string&
list.push_front (entry);
std::string formatedMessage = module->appendUriList (message, list);
return module->send_sip_message (call->inv, callID, formatedMessage);
module->send_sip_message (call->inv, callID, module->appendUriList (message, list));
}
bool
......@@ -908,35 +853,20 @@ bool SIPVoIPLink::attendedTransfer(const std::string& transferId, const std::str
bool
SIPVoIPLink::refuse (const std::string& id)
{
_debug ("UserAgent: Refuse call %s", id.c_str());
SIPCall *call;
try {
call = getSIPCall (id);
}
catch (const VoipLinkException &e) {
_error ("UserAgent: Error: %s", e.what());
return false;
}
SIPCall *call = getSIPCall (id);
// can't refuse outgoing call or connected
if (!call->isIncoming() or call->getConnectionState() == Call::Connected) {
_debug ("UserAgent: Call %s is not in state incoming, or is already answered");
if (!call->isIncoming() or call->getConnectionState() == Call::Connected)
return false;
}
// Stop Audio RTP session
call->getAudioRtp()->stop();
// User refuse current call. Notify peer
pjsip_tx_data *tdata;
pj_status_t status = pjsip_inv_end_session (call->inv, PJSIP_SC_DECLINE, NULL, &tdata); //603
if (status != PJ_SUCCESS)
if (pjsip_inv_end_session (call->inv, PJSIP_SC_DECLINE, NULL, &tdata) != PJ_SUCCESS)
return false;
status = pjsip_inv_send_msg (call->inv, tdata);
if (status != PJ_SUCCESS)
if (pjsip_inv_send_msg (call->inv, tdata) != PJ_SUCCESS)
return false;
// Make sure the pointer is NULL in callbacks
......@@ -944,133 +874,79 @@ SIPVoIPLink::refuse (const std::string& id)
removeCall (id);
_debug ("UserAgent: Refuse call completed");
return true;
}
std::string
SIPVoIPLink::getCurrentCodecName(Call *call) const
{
return dynamic_cast<SIPCall*>(call)->getLocalSDP()->getCodecName();
}
bool
void
SIPVoIPLink::carryingDTMFdigits (const std::string& id, char code)
{
SIPCall *call;
try {
call = getSIPCall (id);
}
catch (VoipLinkException &e) {
return false;
}
std::string accountID(Manager::instance().getAccountFromCall (id));
std::string accountID(Manager::instance().getAccountFromCall(id));
SIPAccount *account = static_cast<SIPAccount*>(Manager::instance().getAccount(accountID));
if (!account) {
_error ("UserAgent: Error: Account not found while sending DTMF");
return false;
if (account) try {
dtmfSend(getSIPCall(id), code, account->getDtmfType());
} catch (VoipLinkException) {
// don't do anything if call doesn't exist
}
DtmfType type = account->getDtmfType();
if (type == OVERRTP)
dtmfOverRtp (call, code);
else if (type == SIPINFO)
dtmfSipInfo (call, code);
else {
_error ("UserAgent: Error: Dtmf type does not exist");
return false;
}
return true;
}
void
SIPVoIPLink::dtmfSipInfo (SIPCall *call, char code)
SIPVoIPLink::dtmfSend (SIPCall *call, char code, DtmfType dtmf)
{
if (dtmf == OVERRTP) {
call->getAudioRtp()->sendDtmfDigit(code - '0');
return;
}
// else : dtmf == SIPINFO
// Create a temporary memory pool
pj_pool_t *tmp_pool = pj_pool_create (&_cp->factory, "tmpdtmf10", 1000, 1000, NULL);
if (tmp_pool == NULL)
throw VoipLinkException("UserAgent: Could not initialize memory pool while sending DTMF");
pj_str_t methodName;
pj_strdup2 (tmp_pool, &methodName, "INFO");
pj_str_t methodName = pj_str((char*)"INFO");
pjsip_method method;
pjsip_method_init_np (&method, &methodName);
/* Create request message. */
pjsip_tx_data *tdata;
pj_status_t status = pjsip_dlg_create_request (call->inv->dlg, &method, -1, &tdata);
if (status != PJ_SUCCESS) {
_debug ("UserAgent: Unable to create INFO request -- %d", status);
if (pjsip_dlg_create_request (call->inv->dlg, &method, -1, &tdata) != PJ_SUCCESS) {
pj_pool_release(tmp_pool);
return;
}
/* Get MIME type */
pjsip_media_type ctype;
pj_strdup2 (tmp_pool, &ctype.type, "application");
pj_strdup2 (tmp_pool, &ctype.subtype, "dtmf-relay");
int duration = Manager::instance().voipPreferences.getPulseLength();
char dtmf_body[1000];
snprintf(dtmf_body, sizeof dtmf_body - 1, "Signal=%c\r\nDuration=%d\r\n", code, duration);
/* Create "application/dtmf-relay" message body. */
pj_str_t content;
pj_strdup2 (tmp_pool, &content, dtmf_body);
pj_str_t content = pj_str(dtmf_body);
pj_str_t type = pj_str((char*)"application");
pj_str_t subtype = pj_str((char*)"dtmf-relay");
tdata->msg->body = pjsip_msg_body_create (tdata->pool, &type, &subtype, &content);
tdata->msg->body = pjsip_msg_body_create (tdata->pool, &ctype.type, &ctype.subtype, &content);
if (tdata->msg->body == NULL) {
_debug ("UserAgent: Unable to create msg body!");
if (tdata->msg->body == NULL)
pjsip_tx_data_dec_ref (tdata);
pj_pool_release(tmp_pool);
return;