diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp index f7caef81adef27a2e7ad7ec33f6aae49c3c694e1..2b5ec76a83f04f9c163d16312348b0ddeb0b881d 100644 --- a/src/audio/audiortp.cpp +++ b/src/audio/audiortp.cpp @@ -47,13 +47,19 @@ AudioRtp::~AudioRtp (void) { int AudioRtp::createNewSession (SipCall *ca) { + ost::MutexLock m(_threadMutex); // Start RTP Send/Receive threads _symmetric = Manager::instance().getConfigInt(SIGNALISATION,SYMMETRIC) ? true : false; _RTXThread = new AudioRtpRTX (ca, Manager::instance().getAudioDriver(), _symmetric); - //_debug("AudioRtp::createNewSession: starting RTX thread\n"); - if (_RTXThread->start() != 0) { - return -1; + _debug("AudioRtp::createNewSession: starting RTX thread\n"); + try { + if (_RTXThread->start() != 0) { +// if (_RTXThread->start() != 0) { + return -1; + } + } catch(...) { + _debug("exception on start?"); } return 0; } @@ -62,6 +68,8 @@ AudioRtp::createNewSession (SipCall *ca) { void AudioRtp::closeRtpSession () { // This will make RTP threads finish. + _debug("waiting start signal...\n"); + _debug("receive start signal..."); delete _RTXThread; _RTXThread = NULL; } @@ -79,7 +87,7 @@ AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, AudioLayer* driver, bool sym) : _cod std::string localipConfig = _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); + //_debug("AudioRtpRTX ctor : Local IP:port %s:%d\tsymmetric:%d\n", local_ip.getHostname(), _ca->getLocalAudioPort(), _sym); if (!_sym) { _sessionRecv = new ost::RTPSession(local_ip, _ca->getLocalAudioPort()); @@ -93,11 +101,15 @@ AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, AudioLayer* driver, bool sym) : _cod } AudioRtpRTX::~AudioRtpRTX () { + _start.wait(); + try { - terminate(); - } catch (...) { - _debug("AudioRtpRTX: try to terminate, but catch an exception...\n"); + this->terminate(); + } catch(...) { + _debug("audiortprtx dtor catches an exception\n"); + throw; } + //_debug("terminate audiortprtx ended...\n"); _ca = NULL; if (!_sym) { @@ -113,6 +125,8 @@ AudioRtpRTX::~AudioRtpRTX () { void AudioRtpRTX::initAudioRtpSession (void) { + try { + //_debug("Init audio RTP session\n"); ost::InetHostAddress remote_ip(_ca->getRemoteSdpAudioIp()); if (!remote_ip) { _debug("RTP: Target IP address [%s] is not correct!\n", _ca->getRemoteSdpAudioIp()); @@ -148,8 +162,7 @@ AudioRtpRTX::initAudioRtpSession (void) _sessionSend->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) _ca->payload)); _sessionSend->setMark(true); - setCancel(cancelImmediate); - + //setCancel(cancelImmediate); } else { _debug("RTP(Send): Added session destination %s:%d\n", @@ -160,9 +173,13 @@ AudioRtpRTX::initAudioRtpSession (void) } _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) _ca->payload)); - setCancel(cancelImmediate); + //setCancel(cancelImmediate); } _debug("== AudioRtpRTX::initAudioRtpSession end == \n"); + } catch(...) { + _debug("initAudioRtpSession catch an exception\n"); + throw; + } } void @@ -190,7 +207,7 @@ AudioRtpRTX::sendSessionFromMic (unsigned char* data_to_send, int16* data_from_m } if ( bytesAvail != maxBytesToGet ) { // fill end with 0... - _debug("Padding mic: %d bytes\n", (maxBytesToGet-bytesAvail)/2); + //_debug("Padding mic: %d bytes\n", (maxBytesToGet-bytesAvail)/2); bzero(data_from_mic_mono + (bytesAvail/4), (maxBytesToGet-bytesAvail)/2); } @@ -203,12 +220,15 @@ AudioRtpRTX::sendSessionFromMic (unsigned char* data_to_send, int16* data_from_m int compSize = ac->codecEncode (data_to_send, data_from_mic_mono, RTP_FRAMES2SEND*2); // encode divise by two // Send encoded audio sample over the network + //fprintf(stderr, "m"); if (!_sym) { _sessionSend->putData(timestamp, data_to_send, compSize); } else { _session->putData(timestamp, data_to_send, compSize); } - } else { _debug("No AudioCodec for the mic\n"); } + } else { + _debug("No AudioCodec for the mic\n"); + } } } @@ -253,6 +273,7 @@ AudioRtpRTX::receiveSessionForSpkr (int16* data_for_speakers_stereo, int16* data // If the current call is the call which is answered // Set decoded data to sound device // expandedSize is in mono/bytes, since we double in stereo, we send two time more + //fprintf(stderr, "r"); Manager::instance().getAudioDriver()->putMain(data_for_speakers_stereo, expandedSize*2); Manager::instance().getAudioDriver()->startStream(); @@ -269,7 +290,7 @@ AudioRtpRTX::receiveSessionForSpkr (int16* data_for_speakers_stereo, int16* data } void -AudioRtpRTX::run (void) { +AudioRtpRTX::run () { //mic, we receive from soundcard in stereo, and we send encoded //encoding before sending int16 *data_from_mic_stereo = new int16[RTP_FRAMES2SEND*2]; @@ -281,53 +302,64 @@ AudioRtpRTX::run (void) { int16 *data_for_speakers_recv = new int16[RTP_FRAMES2SEND]; int16 *data_for_speakers_stereo = new int16[RTP_FRAMES2SEND*2]; - // Init the session - initAudioRtpSession(); - - // flush stream: - ManagerImpl& manager = Manager::instance(); - AudioLayer *audiolayer = manager.getAudioDriver(); - - // start running the packet queue scheduler. - //_debug("Thread: start session of AudioRtpRTX\n"); - if (!_sym) { - _sessionRecv->startRunning(); - _sessionSend->startRunning(); - } else { - _session->startRunning(); - _debug("Session is now: %d active?\n", _session->isActive()); + try { + _debug("Audio RtpRTX is running\n"); + + // Init the session + initAudioRtpSession(); + _start.post(); + + // flush stream: + AudioLayer *audiolayer = Manager::instance().getAudioDriver(); + + // start running the packet queue scheduler. + _debug("Thread: start session of AudioRtpRTX\n"); + if (!_sym) { + _sessionRecv->startRunning(); + _sessionSend->startRunning(); + } else { + _session->startRunning(); + _debug("Session is now: %d active?\n", _session->isActive()); + } + + int timestamp = 0; // for mic + int countTime = 0; // for receive + // TODO: get frameSize from user config + int frameSize = 20; // 20ms frames + TimerPort::setTimer(frameSize); + + audiolayer->flushMic(); + audiolayer->startStream(); + while (!testCancel()) { + //////////////////////////// + // Send session + //////////////////////////// + sendSessionFromMic(char_to_send, data_from_mic_stereo, data_from_mic_mono, timestamp); + timestamp += RTP_FRAMES2SEND; + + //////////////////////////// + // Recv session + //////////////////////////// + receiveSessionForSpkr(data_for_speakers_stereo, data_for_speakers_recv, countTime); + + // Let's wait for the next transmit cycle + Thread::sleep(TimerPort::getTimer()); + TimerPort::incTimer(frameSize); // 'frameSize' ms + } + //_debug("stop stream for audiortp loop\n"); + audiolayer->stopStream(); + } catch(std::exception &e) { + _debug("AudioRTP Thread, run function, has caught an exception here: %s\n", e.what()); + throw; + } catch(...) { + _debug("AudioRTP Thread, run function, has caught an unknown exception here\n"); + throw; } - - int timestamp = 0; // for mic - int countTime = 0; // for receive - // TODO: get frameSize from user config - int frameSize = 20; // 20ms frames - TimerPort::setTimer(frameSize); - - audiolayer->flushMic(); - while (!testCancel() && _ca != NULL) { - //////////////////////////// - // Send session - //////////////////////////// - sendSessionFromMic(char_to_send, data_from_mic_stereo, data_from_mic_mono, timestamp); - timestamp += RTP_FRAMES2SEND; - - //////////////////////////// - // Recv session - //////////////////////////// - receiveSessionForSpkr(data_for_speakers_stereo, data_for_speakers_recv, countTime); - - // Let's wait for the next transmit cycle - Thread::sleep(TimerPort::getTimer()); - TimerPort::incTimer(frameSize); // 'frameSize' ms - } - audiolayer->stopStream(); - - delete [] data_for_speakers_stereo; data_for_speakers_stereo = 0; + delete [] data_for_speakers_stereo; data_for_speakers_stereo = 0; delete [] data_for_speakers_recv; data_for_speakers_recv = 0; - delete [] char_to_send; char_to_send = 0; - delete [] data_from_mic_mono; data_from_mic_mono = 0; - delete [] data_from_mic_stereo; data_from_mic_stereo = 0; + delete [] char_to_send; char_to_send = 0; + delete [] data_from_mic_mono; data_from_mic_mono = 0; + delete [] data_from_mic_stereo; data_from_mic_stereo = 0; } diff --git a/src/audio/audiortp.h b/src/audio/audiortp.h index 615843881184d5ad02f58d6ffa4e3f9007ad49a7..338893ee730c0b9c13cc6cd304856bba307804e1 100644 --- a/src/audio/audiortp.h +++ b/src/audio/audiortp.h @@ -50,6 +50,7 @@ private: ost::RTPSession *_sessionSend; ost::RTPSession *_sessionRecv; ost::SymmetricRTPSession *_session; + ost::Semaphore _start; bool _sym; // build codec... @@ -76,6 +77,7 @@ public: private: AudioRtpRTX* _RTXThread; bool _symmetric; + ost::Mutex _threadMutex; }; #endif // __AUDIO_RTP_H__ diff --git a/src/gui/server/requestmanager.cpp b/src/gui/server/requestmanager.cpp index f789a84b68e26a6d23160d6dc360e9fa9d281ec8..967e2e5486a11567bc6effc7447341af1e5e8951 100644 --- a/src/gui/server/requestmanager.cpp +++ b/src/gui/server/requestmanager.cpp @@ -76,7 +76,7 @@ RequestManager::exec() { // session mutex block _debug("Closing TCP Session... \n"); _sessionMutex.enterMutex(); - if (_sessionIO) _sessionIO->sendLast(); + if (_sessionIO) _sessionIO->sendLast(); delete _sessionIO; _sessionIO = NULL; _sessionMutex.leaveMutex(); _debug("TCP Session has closed\n"); diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp index 9f7374e643a54329f305d0069e47437541fa082f..7dd8f5f2bba60a1671302f606952d54552666f46 100644 --- a/src/managerimpl.cpp +++ b/src/managerimpl.cpp @@ -882,11 +882,9 @@ ManagerImpl::stopTone() { _debug("TONE: stop tone/stream...\n"); getAudioDriver()->stopStream(); - _debug("TONE: stop tone...\n"); _toneMutex.enterMutex(); _telephoneTone->setCurrentTone(Tone::TONE_NULL); _toneMutex.leaveMutex(); - _debug("TONE: tone stopped\n"); // for ringing tone.. _toneMutex.enterMutex(); @@ -895,7 +893,6 @@ ManagerImpl::stopTone() { _tone->stopTone(); } _toneMutex.leaveMutex(); - _debug("TONE: leave stop tone function\n"); } /** diff --git a/src/sipcall.cpp b/src/sipcall.cpp index e1636b118315a399f80c0c4dbe5d70d4504c39a5..1842ab783782b749b6e85247cc86dd1be9a944c7 100644 --- a/src/sipcall.cpp +++ b/src/sipcall.cpp @@ -49,6 +49,8 @@ SipCall::SipCall (CALLID id, CodecDescriptorVector* cdv) : _localIp("127.0.0.1") _remote_sdp_audio_port = 0; _local_sendrecv = 0; /* _SENDRECV, _SENDONLY, _RECVONLY */ _remote_sendrecv = 0; + + _reinvite = false; } @@ -179,7 +181,10 @@ SipCall::newIncomingCall (eXosip_event_t *event) { osip_from_t *from; osip_from_init(&from); osip_from_parse(from, _remote_uri); - _name = osip_from_get_displayname(from); + char *name = osip_from_get_displayname(from); + if ( name != NULL ) { + _name = name; + } osip_uri_t* url = osip_from_get_url(from); if ( url != NULL ) { _number = url->username; @@ -221,6 +226,7 @@ SipCall::newIncomingCall (eXosip_event_t *event) { 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"); @@ -300,6 +306,166 @@ SipCall::newIncomingCall (eXosip_event_t *event) { return 0; } +// 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; + + if (_did < 1 && _cid < 1) { + return -1; /* not enough information for this event?? */ + } + 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); + } + + 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 ) { + _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); + + /* 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("SipCall::newIncomingCall: No remote SDP in REINVITE request. Sending 400 BAD REQUEST\n"); + // Send 400 BAD REQUEST + eXosip_lock(); + eXosip_call_send_answer (_tid, 400, NULL); + eXosip_unlock(); + return 0; + } + /* 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); + } + + // 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_message_free (remote_sdp); + return 0; + } + _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 && ( 0 == osip_strcasecmp (tmp, "0") || 0 == osip_strcasecmp (tmp, "8") )) { + break; + } + tmp = NULL; + pos++; + } + } + if (tmp != NULL) { + payload = atoi (tmp); + _debug(" Payload: %d\n", payload); + setAudioCodec(_cdv->at(0)->alloc(payload, "")); // codec builder for the mic + } else { + _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; + } + + osip_message_t *answer = 0; + eXosip_lock(); + _debug("< Building Answer 200\n"); + if (0 == eXosip_call_build_answer (_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); + _debug("< Sending Answer 415\n"); + } else { + + sdp_message_t *local_sdp = eXosip_get_sdp_info(answer); + sdp_media_t *local_med = NULL; + if (local_sdp != NULL) { + local_med = eXosip_get_audio_media(local_sdp); + } + 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); + _debug(" Remote SendRecv: %d\n", _remote_sendrecv); + _debug(" Local SendRecv: %d\n", _local_sendrecv); + if (_local_sendrecv == _SENDRECV) { + if (_remote_sendrecv == _SENDONLY) { _local_sendrecv = _RECVONLY; } + else if (_remote_sendrecv == _RECVONLY) { _local_sendrecv = _SENDONLY; } + } + _debug(" Final Local SendRecv: %d\n", _local_sendrecv); + sdp_message_free (local_sdp); + } + _debug("< Sending answer 200\n"); + if (0 != eXosip_call_send_answer (_tid, 200, answer)) { + _debug("SipCall::newIncomingCall: cannot send 200 OK?\n"); + } + } + } + eXosip_unlock (); + sdp_message_free (remote_sdp); + _reinvite = true; + return 0; +} int SipCall::ringingCall (eXosip_event_t *event) { @@ -343,61 +509,62 @@ SipCall::receivedAck (eXosip_event_t *event) int SipCall::answeredCall(eXosip_event_t *event) { - _cid = event->cid; - _did = event->did; + _cid = event->cid; + _did = event->did; if (_did < 1 && _cid < 1) { return -1; /* not enough information for this event?? */ } - osip_strncpy(this->_textinfo, event->textinfo, 255); + 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->response != NULL) { + _status_code = event->response->status_code; + snprintf (_reason_phrase, 49, "%s", event->response->reason_phrase); - if (event->request != NULL) { - char *tmp = NULL; + char *tmp = NULL; - osip_from_to_str (event->request->from, &tmp); - if (tmp != NULL) { - snprintf (_remote_uri, 255, "%s", tmp); - osip_free (tmp); - } + osip_from_to_str (event->response->from, &tmp); + if (tmp != NULL) { + snprintf (_remote_uri, 255, "%s", tmp); + osip_free (tmp); } - - eXosip_lock (); - { + } + _debug(" Status: %d %s\n", _status_code, _reason_phrase); + _debug(" From URI: %s\n", _remote_uri); + + eXosip_lock (); + { osip_message_t *ack = NULL; int i; i = eXosip_call_build_ack (_did, &ack); if (i != 0) { - _debug("SipCall::answeredCall: Cannot build ACK for call!\n"); + _debug("SipCall::answeredCall: Cannot build ACK for call!\n"); } else { - sdp_message_t *local_sdp = NULL; - sdp_message_t *remote_sdp = NULL; + sdp_message_t *local_sdp = NULL; + sdp_message_t *remote_sdp = NULL; - if (event->request != NULL && event->response != NULL) { - local_sdp = eXosip_get_sdp_info (event->request); - remote_sdp = eXosip_get_sdp_info (event->response); - } - if (local_sdp == NULL && remote_sdp != NULL) { - /* sdp in ACK */ - i = sdp_complete_message (remote_sdp, ack); - if (i != 0) { - _debug("SipCall::answeredCall: Cannot complete ACK with sdp body?!\n"); - } + if (event->request != NULL && event->response != NULL) { + local_sdp = eXosip_get_sdp_info (event->request); + remote_sdp = eXosip_get_sdp_info (event->response); + } + if (local_sdp == NULL && remote_sdp != NULL) { + /* sdp in ACK */ + i = sdp_complete_message (remote_sdp, ack); + if (i != 0) { + _debug("SipCall::answeredCall: Cannot complete ACK with sdp body?!\n"); } - sdp_message_free (local_sdp); - sdp_message_free (remote_sdp); + } + sdp_message_free (local_sdp); + sdp_message_free (remote_sdp); - eXosip_call_send_ack (_did, ack); - } - } - eXosip_unlock (); + _debug("< Send ACK\n"); + eXosip_call_send_ack (_did, ack); + } + } + eXosip_unlock (); - return 0; + return 0; } void @@ -440,6 +607,7 @@ SipCall::answeredCall_without_hold (eXosip_event_t *event) _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) { @@ -448,10 +616,10 @@ SipCall::answeredCall_without_hold (eXosip_event_t *event) if (tmp != NULL) { payload = atoi (tmp); - _debug("SipCall::answeredCall_without_hold: For outgoing call: ca->payload = %d\n", payload); setAudioCodec(_cdv->at(0)->alloc(payload, "")); } } + _debug(" Remote Payload: %d\n", payload); if (local_sdp == NULL) { _debug("SipCall::answeredCall_without_hold: SDP body was probably in the ACK (TODO)\n"); @@ -465,6 +633,7 @@ SipCall::answeredCall_without_hold (eXosip_event_t *event) if (local_med != NULL && local_med->m_port != NULL) { audio_port = atoi (local_med->m_port); } + _debug(" Local Audio port: %d\n", audio_port); if (tmp != NULL && audio_port > 0 && _remote_sdp_audio_port > 0 @@ -480,6 +649,8 @@ SipCall::answeredCall_without_hold (eXosip_event_t *event) _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); diff --git a/src/sipcall.h b/src/sipcall.h index bbeea534a273cd28cf3abdc38afb8a291ab63274..266d4b53393acf29879769e9f27653764d9a6a2e 100644 --- a/src/sipcall.h +++ b/src/sipcall.h @@ -44,11 +44,12 @@ public: ~SipCall (void); int payload; - - /* - * Store information about incoming call and negociate payload - */ - int newIncomingCall (eXosip_event_t *); + + /** + * Store information about incoming call and negociate payload + */ + int newIncomingCall(eXosip_event_t *); + int newReinviteCall(eXosip_event_t *); /* * Use to answer to a ONHOLD/OFFHOLD event @@ -72,6 +73,9 @@ public: 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 @@ -147,6 +151,8 @@ private: std::string _localIp; std::string _name; // set by incoming call std::string _number; // set by incoming call + + bool _reinvite; }; #endif // __SIP_CALL_H__ diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp index af4c86cd649342d34fe5ff4e0c0c7bd15aa08c2c..45643a385d7b9931cb138cb34975020149d2f6c9 100644 --- a/src/sipvoiplink.cpp +++ b/src/sipvoiplink.cpp @@ -93,9 +93,12 @@ SipVoIPLink::init(void) if (i != 0) { _debug("Could not initialize transport layer\n"); return -1; + } else { + _debug("VoIP Link listen on random port %d\n", RANDOM_SIP_PORT); } + } else { + _debug("VoIP Link listen on port %d\n", DEFAULT_SIP_PORT); } - // If use STUN server, firewall address setup if (Manager::instance().useStun()) { eXosip_set_user_agent(tmp.data()); @@ -217,12 +220,12 @@ SipVoIPLink::setRegister (void) int i = eXosip_register_send_register (_reg_id, reg); if (i == -2) { - _debug("cannot build registration, check the setup\n"); + _debug("Cannot build registration, check the setup\n"); eXosip_unlock(); return -1; } if (i == -1) { - _debug("Registration Failed\n"); + _debug("Registration sending failed\n"); eXosip_unlock(); return -1; } @@ -378,6 +381,7 @@ SipVoIPLink::answer (CALLID id) 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 = -1; @@ -403,6 +407,7 @@ SipVoIPLink::hangup (CALLID id) eXosip_unlock(); // Release RTP channels + _debug("Stopping AudioRTP\n"); _audiortp.closeRtpSession(); deleteSipCall(id); @@ -483,6 +488,7 @@ SipVoIPLink::onhold (CALLID id) } // Send request + _debug("Stopping AudioRTP\n"); _audiortp.closeRtpSession(); eXosip_lock (); @@ -552,10 +558,11 @@ SipVoIPLink::offhold (CALLID id) eXosip_unlock (); // Enable audio - if (_audiortp.createNewSession (getSipCall(id)) < 0) { - _debug("FATAL: Unable to start sound (%s:%d)\n", __FILE__, __LINE__); - i = -1; - } + _debug("Stopping AudioRTP\n"); + if (_audiortp.createNewSession (getSipCall(id)) < 0) { + _debug("FATAL: Unable to start sound (%s:%d)\n", __FILE__, __LINE__); + i = -1; + } return i; } @@ -659,22 +666,23 @@ SipVoIPLink::getEvent (void) break; case EXOSIP_CALL_REINVITE: - _debug("!!! EXOSIP_CALL_REINVITE: Should reinvite? !!!\n"); + _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 != NULL) { - _debug("Call reinvite : [id = %d, cid = %d, did = %d], localport=%d\n", id, event->cid, event->did,sipcall->getLocalAudioPort()); + if (sipcall != 0) { + _debug(" Info [id = %d, cid = %d, did = %d], localport=%d\n", id, event->cid, event->did,sipcall->getLocalAudioPort()); + _debug("Stopping AudioRTP\n"); _audiortp.closeRtpSession(); - sipcall->newIncomingCall(event); - if(!Manager::instance().callIsOnHold(id)) { - _audiortp.createNewSession(sipcall); - } + 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(); @@ -687,7 +695,7 @@ SipVoIPLink::getEvent (void) case EXOSIP_CALL_RINGING: // 9 peer call is ringing id = findCallIdInitial(event); - _debug("Call is ringing [id = %d, cid = %d, did = %d]\n", id, event->cid, event->did); + _debug("> Receive Call Ringing [id = %d, cid = %d, did = %d]\n", id, event->cid, event->did); if (id != 0) { getSipCall(id)->ringingCall(event); Manager::instance().peerRingingCall(id); @@ -702,60 +710,69 @@ SipVoIPLink::getEvent (void) id = findCallIdInitial(event); if ( id != 0) { sipcall = getSipCall(id); - if ( sipcall ) { - _debug("Call is answered [id = %d, cid = %d, did = %d], localport=%d\n", - id, event->cid, event->did,sipcall->getLocalAudioPort()); - } - - // Answer - if (Manager::instance().callCanBeAnswered(id)) { - sipcall->setStandBy(false); - _debug("Answering call first time\n"); - if (sipcall->answeredCall(event) != -1) { - sipcall->answeredCall_without_hold(event); - Manager::instance().peerAnsweredCall(id); - - if(!Manager::instance().callIsOnHold(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; - break; + if ( sipcall != 0 ) { + _debug("> Receive Call Answer [id = %d, 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)) { + // 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; + break; + } } } + } else { + // Answer to on/off hold to send ACK + _debug("Answering call\n"); + sipcall->answeredCall(event); } - } else { - // Answer to on/off hold to send ACK - _debug("Answering call\n"); - sipcall->answeredCall(event); } break; } else { returnValue = -1; } } - case EXOSIP_CALL_REDIRECTED: + case EXOSIP_CALL_REDIRECTED: // 11 break; - case EXOSIP_CALL_ACK: + case EXOSIP_CALL_ACK: // 15 id = findCallId(event); - _debug("ACK received [id = %d, cid = %d, did = %d]\n", id, event->cid, event->did); - if (id != 0) { - getSipCall(id)->receivedAck(event); + _debug("> Receive ACK [id = %d, 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)) { + _debug("Starting AudioRTP\n"); + _audiortp.createNewSession(sipcall); + } + } + } } else { returnValue = -1; } break; // The peer-user closed the phone call(we received BYE). - case EXOSIP_CALL_CLOSED: + case EXOSIP_CALL_CLOSED: // 25 id = findCallId(event); - _debug("Call is closed [id = %d, cid = %d, did = %d]\n", id, event->cid, event->did); + _debug("> BYE [id = %d, cid = %d, did = %d]\n", id, event->cid, event->did); if (id != 0) { if (Manager::instance().callCanBeClosed(id)) { sipcall = getSipCall(id); + _debug("Stopping AudioRTP\n"); _audiortp.closeRtpSession(); } Manager::instance().peerHungupCall(id); @@ -765,6 +782,9 @@ SipVoIPLink::getEvent (void) } 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) { //Manager::instance().peerHungupCall(id); @@ -851,7 +871,7 @@ SipVoIPLink::getEvent (void) //Manager::instance().displayError("getEvent : Registration Failure"); break; - case EXOSIP_MESSAGE_NEW: + case EXOSIP_MESSAGE_NEW: //27 unsigned int k; if (event->request != NULL && MSG_IS_OPTIONS(event->request)) { @@ -877,6 +897,7 @@ SipVoIPLink::getEvent (void) // Voice message else if (event->request != NULL && MSG_IS_NOTIFY(event->request)){ + _debug("> NOTIFY Voice message\n"); int ii; unsigned int pos; unsigned int pos_slash; @@ -1027,6 +1048,7 @@ SipVoIPLink::endSipCalls() eXosip_unlock(); // Release RTP channels + _debug("Stopping AudioRTP\n"); _audiortp.closeRtpSession(); delete *iter; *iter = NULL; } @@ -1308,20 +1330,18 @@ int SipVoIPLink::setAuthentication (void) { ManagerImpl& manager = Manager::instance(); - std::string login, pass, realm; - login = manager.getConfigString(SIGNALISATION, AUTH_USER_NAME); + std::string login = manager.getConfigString(SIGNALISATION, AUTH_USER_NAME); if (login.empty()) { login = manager.getConfigString(SIGNALISATION, USER_PART); } - pass = manager.getConfigString(SIGNALISATION, PASSWORD); + std::string pass = manager.getConfigString(SIGNALISATION, PASSWORD); if (pass.empty()) { manager.displayConfigError("Fill password field"); return -1; } int returnValue = 0; eXosip_lock(); - if (eXosip_add_authentication_info(login.data(), login.data(), - pass.data(), NULL, NULL) != 0) { + if (eXosip_add_authentication_info(login.data(), login.data(), pass.data(), NULL, NULL) != 0) { returnValue = -1; } eXosip_unlock(); @@ -1368,12 +1388,12 @@ SipVoIPLink::startCall (CALLID id, const std::string& from, const std::string& t if (!Manager::instance().useStun()) { // Set random port for outgoing call if no firewall setLocalPort(RANDOM_LOCAL_PORT); - _debug("SipVoIPLink::startCall: Local audio port: %d\n",_localPort); + _debug(" Setting local port to random: %d\n",_localPort); } else { // If use Stun server if (behindNat() != 0) { - _debug("SipVoIPLink::startCall: sip invite: firewall port = %d\n",Manager::instance().getFirewallPort()); setLocalPort(Manager::instance().getFirewallPort()); + _debug(" Setting local port to firewall port: %d\n", _localPort); } else { return -1; }