diff --git a/.gitignore b/.gitignore index c157f055e4d27c8e8ee9060185249ffccca9ddbe..c11d5fa665eb3975332b3bb41739c654af7c0aaf 100644 --- a/.gitignore +++ b/.gitignore @@ -67,5 +67,9 @@ config_auto.h # Ignore temp files *~ +# Cscope/Ctags files +cscope.* +tags + # IDE stuffs nbproject diff --git a/daemon/src/account.cpp b/daemon/src/account.cpp index 3c293e4cec9bb9a8108e5cd6d25229365c741592..a813b6434b35338674d80264e39157acaad77f78 100644 --- a/daemon/src/account.cpp +++ b/daemon/src/account.cpp @@ -32,11 +32,12 @@ #include "account.h" #include "manager.h" +#include "dbus/configurationmanager.h" #ifdef SFL_VIDEO #include "video/video_endpoint.h" #endif -Account::Account(const std::string& accountID, const std::string &type) : +Account::Account(const std::string &accountID, const std::string &type) : accountID_(accountID) , username_() , hostname_() @@ -68,7 +69,8 @@ void Account::setRegistrationState(const RegistrationState &state) registrationState_ = state; // Notify the client - Manager::instance().connectionStatusNotification(); + ConfigurationManager *c(Manager::instance().getDbusManager()->getConfigurationManager()); + c->registrationStateChanged(accountID_, registrationState_); } } diff --git a/daemon/src/account.h b/daemon/src/account.h index 8b87fef4c42d49d064dbee9d36b4bd6008047f93..afdcdf10e87bc0bd8696d4c2cba449760b2caa82 100644 --- a/daemon/src/account.h +++ b/daemon/src/account.h @@ -75,7 +75,6 @@ static const char *const CONFIG_ACCOUNT_TYPE = "Account.type"; static const char *const CONFIG_ACCOUNT_ALIAS = "Account.alias"; static const char *const CONFIG_ACCOUNT_MAILBOX = "Account.mailbox"; static const char *const CONFIG_ACCOUNT_ENABLE = "Account.enable"; -static const char *const CONFIG_ACCOUNT_RESOLVE_ONCE = "Account.resolveOnce"; static const char *const CONFIG_ACCOUNT_REGISTRATION_EXPIRE = "Account.registrationExpire"; static const char *const CONFIG_CREDENTIAL_NUMBER = "Credential.count"; static const char *const CONFIG_ACCOUNT_DTMF_TYPE = "Account.dtmfType"; diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.cpp b/daemon/src/audio/audiortp/audio_rtp_factory.cpp index 5ce37ce1f53c08fc342d4b60daff3beefc3173dd..2170b06e52a77e238fa1c4241ec4cc4bac363218 100644 --- a/daemon/src/audio/audiortp/audio_rtp_factory.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_factory.cpp @@ -43,17 +43,19 @@ namespace sfl { AudioRtpFactory::AudioRtpFactory(SIPCall *ca) : rtpSession_(NULL), - audioRtpThreadMutex_(), srtpEnabled_(false), - keyExchangeProtocol_(Symmetric), helloHashEnabled_(false), - remoteContext_(NULL), localContext_(NULL), ca_(ca) + audioRtpThreadMutex_(), srtpEnabled_(false), helloHashEnabled_(false), + cachedRemoteContext_(0), cachedLocalContext_(0), ca_(ca), + keyExchangeProtocol_(NONE) {} AudioRtpFactory::~AudioRtpFactory() { delete rtpSession_; + delete cachedLocalContext_; + delete cachedRemoteContext_; } -void AudioRtpFactory::initAudioRtpConfig() +void AudioRtpFactory::initConfig() { if (rtpSession_ != NULL) stop(); @@ -65,48 +67,48 @@ void AudioRtpFactory::initAudioRtpConfig() if (account) { srtpEnabled_ = account->getSrtpEnabled(); std::string key(account->getSrtpKeyExchange()); - - if (key == "sdes") - keyExchangeProtocol_ = Sdes; - else if (key == "zrtp") - keyExchangeProtocol_ = Zrtp; - else - keyExchangeProtocol_ = Symmetric; - + if (srtpEnabled_) { + if (key == "sdes") + keyExchangeProtocol_ = SDES; + else if (key == "zrtp") + keyExchangeProtocol_ = ZRTP; + } else { + keyExchangeProtocol_ = NONE; + } helloHashEnabled_ = account->getZrtpHelloHash(); } else { srtpEnabled_ = false; - keyExchangeProtocol_ = Symmetric; + keyExchangeProtocol_ = NONE; helloHashEnabled_ = false; } } -void AudioRtpFactory::initAudioSymmetricRtpSession() +void AudioRtpFactory::initSession() { ost::MutexLock m(audioRtpThreadMutex_); if (srtpEnabled_) { - std::string zidFilename(Manager::instance().voipPreferences.getZidFile()); + const std::string zidFilename(Manager::instance().voipPreferences.getZidFile()); switch (keyExchangeProtocol_) { - case Zrtp: - rtpSession_ = new AudioZrtpSession(ca_, zidFilename); + case ZRTP: + rtpSession_ = new AudioZrtpSession(*ca_, zidFilename); // TODO: be careful with that. The hello hash is computed asynchronously. Maybe it's // not even available at that point. if (helloHashEnabled_) ca_->getLocalSDP()->setZrtpHash(static_cast<AudioZrtpSession *>(rtpSession_)->getHelloHash()); break; - case Sdes: - rtpSession_ = new AudioSrtpSession(ca_); + case SDES: + rtpSession_ = new AudioSrtpSession(*ca_); break; default: throw UnsupportedRtpSessionType("Unsupported Rtp Session Exception Type!"); } } else - rtpSession_ = new AudioSymmetricRtpSession(ca_); + rtpSession_ = new AudioSymmetricRtpSession(*ca_); } void AudioRtpFactory::start(AudioCodec* audiocodec) @@ -114,26 +116,17 @@ void AudioRtpFactory::start(AudioCodec* audiocodec) if (rtpSession_ == NULL) throw AudioRtpFactoryException("AudioRtpFactory: Error: RTP session was null when trying to start audio thread"); - if (rtpSession_->getAudioRtpType() == Sdes) - if (localContext_ and remoteContext_) - static_cast<AudioSrtpSession *>(rtpSession_)->restoreCryptoContext(localContext_, remoteContext_); + if (keyExchangeProtocol_ == SDES and cachedLocalContext_ and cachedRemoteContext_) + static_cast<AudioSrtpSession *>(rtpSession_)->restoreCryptoContext(cachedLocalContext_, cachedRemoteContext_); - if (rtpSession_->startRtpThread(audiocodec) != 0) - throw AudioRtpFactoryException("AudioRtpFactory: Error: Failed to start AudioZrtpSession thread"); + if (rtpSession_->startRtpThread(*audiocodec) != 0) + throw AudioRtpFactoryException("AudioRtpFactory: Error: Failed to start AudioRtpSession thread"); } void AudioRtpFactory::stop() { ost::MutexLock mutex(audioRtpThreadMutex_); - if (rtpSession_ == NULL) - return; - - if (rtpSession_->getAudioRtpType() == Sdes) { - localContext_ = static_cast<AudioSrtpSession*>(rtpSession_)->localCryptoCtx_; - remoteContext_ = static_cast<AudioSrtpSession*>(rtpSession_)->remoteCryptoCtx_; - } - delete rtpSession_; rtpSession_ = NULL; } @@ -151,7 +144,7 @@ void AudioRtpFactory::updateSessionMedia(AudioCodec *audiocodec) if (rtpSession_ == NULL) throw AudioRtpFactoryException("AudioRtpFactory: Error: rtpSession_ was null when trying to update IP address"); - rtpSession_->updateSessionMedia(audiocodec); + rtpSession_->updateSessionMedia(*audiocodec); } void AudioRtpFactory::updateDestinationIpAddress() @@ -162,7 +155,7 @@ void AudioRtpFactory::updateDestinationIpAddress() sfl::AudioZrtpSession * AudioRtpFactory::getAudioZrtpSession() { - if (rtpSession_->getAudioRtpType() == Zrtp) + if (keyExchangeProtocol_ == ZRTP) return static_cast<AudioZrtpSession *>(rtpSession_); else throw AudioRtpFactoryException("RTP: Error: rtpSession_ is NULL in getAudioZrtpSession"); @@ -170,17 +163,20 @@ sfl::AudioZrtpSession * AudioRtpFactory::getAudioZrtpSession() void sfl::AudioRtpFactory::initLocalCryptoInfo() { - if (rtpSession_ && rtpSession_->getAudioRtpType() == Sdes) { - static_cast<AudioSrtpSession *>(rtpSession_)->initLocalCryptoInfo(); - ca_->getLocalSDP()->setLocalSdpCrypto(static_cast<AudioSrtpSession *>(rtpSession_)->getLocalCryptoInfo()); + if (rtpSession_ && keyExchangeProtocol_ == SDES) { + AudioSrtpSession *srtp = static_cast<AudioSrtpSession*>(rtpSession_); + // the context is invalidated and deleted by the call to initLocalCryptoInfo + cachedLocalContext_ = srtp->initLocalCryptoInfo(); + ca_->getLocalSDP()->setLocalSdpCrypto(srtp->getLocalCryptoInfo()); } } void AudioRtpFactory::setRemoteCryptoInfo(sfl::SdesNegotiator& nego) { - if (rtpSession_ && rtpSession_->getAudioRtpType() == Sdes) - static_cast<AudioSrtpSession *>(rtpSession_)->setRemoteCryptoInfo(nego); - else + if (rtpSession_ and keyExchangeProtocol_ == SDES) { + AudioSrtpSession *srtp = static_cast<AudioSrtpSession *>(rtpSession_); + cachedRemoteContext_ = srtp->setRemoteCryptoInfo(nego); + } else throw AudioRtpFactoryException("RTP: Error: rtpSession_ is NULL in setRemoteCryptoInfo"); } diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.h b/daemon/src/audio/audiortp/audio_rtp_factory.h index 9e8ca514ceb67216b48bb6408de2f1eb88d0f89d..fd15beb51ef068db1a74da0fa9b5aeb4c5ba96d6 100644 --- a/daemon/src/audio/audiortp/audio_rtp_factory.h +++ b/daemon/src/audio/audiortp/audio_rtp_factory.h @@ -62,15 +62,15 @@ class AudioRtpFactory { AudioRtpFactory(SIPCall *ca); ~AudioRtpFactory(); - void initAudioRtpConfig(); + void initConfig(); /** * Lazy instantiation method. Create a new RTP session of a given * type according to the content of the configuration file. * @param ca A pointer on a SIP call - * @return A new AudioSymmetricRtpSession object + * @return A new AudioRtpSession object */ - void initAudioSymmetricRtpSession(); + void initSession(); /** * Start the audio rtp thread of the type specified in the configuration @@ -103,7 +103,7 @@ class AudioRtpFactory { void updateDestinationIpAddress(); bool isSdesEnabled() const { - return srtpEnabled_ and keyExchangeProtocol_ == sfl::Sdes; + return srtpEnabled_ and keyExchangeProtocol_ == SDES; } /** @@ -140,28 +140,26 @@ class AudioRtpFactory { private: NON_COPYABLE(AudioRtpFactory); + enum KeyExchangeProtocol { NONE, SDES, ZRTP }; AudioRtpSession *rtpSession_; ost::Mutex audioRtpThreadMutex_; - // Field used when initializinga udio rtp session + // Field used when initializing audio rtp session // May be set manually or from config using initAudioRtpConfig bool srtpEnabled_; - // Field used when initializinga udio rtp session - // May be set manually or from config using initAudioRtpConfig - RtpMethod keyExchangeProtocol_; - // Field used when initializinga udio rtp session // May be set manually or from config using initAudioRtpConfig bool helloHashEnabled_; /** Remote srtp crypto context to be set into incoming data queue. */ - ost::CryptoContext *remoteContext_; + ost::CryptoContext *cachedRemoteContext_; /** Local srtp crypto context to be set into outgoing data queue. */ - ost::CryptoContext *localContext_; + ost::CryptoContext *cachedLocalContext_; SIPCall *ca_; + KeyExchangeProtocol keyExchangeProtocol_; }; } #endif // __AUDIO_RTP_FACTORY_H__ diff --git a/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp b/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp index 8ce03be48914e6902196162e5b23d51cba85c0d1..99c5064d94a00d36bcfba5c137f3a9ff1848e312 100644 --- a/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp @@ -67,13 +67,17 @@ AudioRtpRecord::~AudioRtpRecord() } -AudioRtpRecordHandler::AudioRtpRecordHandler(SIPCall *ca) : audioRtpRecord_(), id_(ca->getCallId()), echoCanceller(ca->getMemoryPool()), gainController(8000, -10.0) +AudioRtpRecordHandler::AudioRtpRecordHandler(SIPCall &call) : + audioRtpRecord_(), + id_(call.getCallId()), + echoCanceller(call.getMemoryPool()), + gainController(8000, -10.0) {} AudioRtpRecordHandler::~AudioRtpRecordHandler() {} -void AudioRtpRecordHandler::setRtpMedia(AudioCodec* audioCodec) +void AudioRtpRecordHandler::setRtpMedia(AudioCodec *audioCodec) { ost::MutexLock lock(audioRtpRecord_.audioCodecMutex_); diff --git a/daemon/src/audio/audiortp/audio_rtp_record_handler.h b/daemon/src/audio/audiortp/audio_rtp_record_handler.h index 9012049a133d1b279448835ba31e3c5d7bcb4a75..ac630e2872aac936f7aa05f8c73897c80e6b1296 100644 --- a/daemon/src/audio/audiortp/audio_rtp_record_handler.h +++ b/daemon/src/audio/audiortp/audio_rtp_record_handler.h @@ -103,7 +103,7 @@ class AudioRtpRecord { class AudioRtpRecordHandler { public: - AudioRtpRecordHandler(SIPCall *); + AudioRtpRecordHandler(SIPCall &); virtual ~AudioRtpRecordHandler(); /** diff --git a/daemon/src/audio/audiortp/audio_rtp_session.cpp b/daemon/src/audio/audiortp/audio_rtp_session.cpp index 2a6bea42e7e2f404cbe47751b1a2c1e3fb857a22..70efc7860d0c2c61825bc62830b2572cab79f027 100644 --- a/daemon/src/audio/audiortp/audio_rtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_session.cpp @@ -43,29 +43,27 @@ #include "manager.h" namespace sfl { -AudioRtpSession::AudioRtpSession(SIPCall * sipcall, RtpMethod type, ost::RTPDataQueue *queue, ost::Thread *thread) : - AudioRtpRecordHandler(sipcall) - , ca_(sipcall) - , type_(type) - , remote_ip_() - , remote_port_(0) +AudioRtpSession::AudioRtpSession(SIPCall &call, ost::RTPDataQueue &queue, ost::Thread &thread) : + AudioRtpRecordHandler(call) + , call_(call) , timestamp_(0) , timestampIncrement_(0) - , timestampCount_(0) - , isStarted_(false) , queue_(queue) + , isStarted_(false) + , remote_ip_() + , remote_port_(0) + , timestampCount_(0) , thread_(thread) { - assert(ca_); - queue_->setTypeOfService(ost::RTPDataQueue::tosEnhanced); + queue_.setTypeOfService(ost::RTPDataQueue::tosEnhanced); } AudioRtpSession::~AudioRtpSession() { - queue_->disableStack(); + queue_.disableStack(); } -void AudioRtpSession::updateSessionMedia(AudioCodec *audioCodec) +void AudioRtpSession::updateSessionMedia(AudioCodec &audioCodec) { int lastSamplingRate = audioRtpRecord_.codecSampleRate_; @@ -80,9 +78,9 @@ void AudioRtpSession::updateSessionMedia(AudioCodec *audioCodec) } -void AudioRtpSession::setSessionMedia(AudioCodec *audioCodec) +void AudioRtpSession::setSessionMedia(AudioCodec &audioCodec) { - setRtpMedia(audioCodec); + setRtpMedia(&audioCodec); // store codec info locally int payloadType = getCodecPayloadType(); @@ -96,26 +94,28 @@ void AudioRtpSession::setSessionMedia(AudioCodec *audioCodec) else timestampIncrement_ = frameSize; - DEBUG("AudioRptSession: Codec payload: %d", payloadType); - DEBUG("AudioSymmetricRtpSession: Codec sampling rate: %d", smplRate); - DEBUG("AudioSymmetricRtpSession: Codec frame size: %d", frameSize); - DEBUG("AudioSymmetricRtpSession: RTP timestamp increment: %d", timestampIncrement_); + DEBUG("AudioRtpSession: Codec payload: %d", payloadType); + DEBUG("AudioRtpSession: Codec sampling rate: %d", smplRate); + DEBUG("AudioRtpSession: Codec frame size: %d", frameSize); + DEBUG("AudioRtpSession: RTP timestamp increment: %d", timestampIncrement_); if (payloadType == g722PayloadType) { - DEBUG("AudioSymmetricRtpSession: Setting G722 payload format"); - queue_->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, g722RtpClockRate)); + DEBUG("AudioRtpSession: Setting G722 payload format"); + queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, g722RtpClockRate)); } else { if (dynamic) { - DEBUG("AudioSymmetricRtpSession: Setting dynamic payload format"); - queue_->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, smplRate)); + DEBUG("AudioRtpSession: Setting dynamic payload format"); + queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, smplRate)); } else { - DEBUG("AudioSymmetricRtpSession: Setting static payload format"); - queue_->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) payloadType)); + DEBUG("AudioRtpSession: Setting static payload format"); + queue_.setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) payloadType)); } } +} - if (type_ != Zrtp) - ca_->setRecordingSmplRate(getCodecSampleRate()); +void AudioRtpSession::incrementTimestampForDTMF() +{ + timestamp_ += timestampIncrement_; } void AudioRtpSession::sendDtmfEvent() @@ -131,26 +131,26 @@ void AudioRtpSession::sendDtmfEvent() DEBUG("AudioRtpSession: Send RTP Dtmf (%d)", payload.event); - timestamp_ += (type_ == Zrtp) ? 160 : timestampIncrement_; + incrementTimestampForDTMF(); // discard equivalent size of audio processDataEncode(); // change Payload type for DTMF payload - queue_->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) getDtmfPayloadType(), 8000)); + queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) getDtmfPayloadType(), 8000)); - queue_->setMark(true); - queue_->sendImmediate(timestamp_, (const unsigned char *)(&payload), sizeof(payload)); - queue_->setMark(false); + queue_.setMark(true); + queue_.sendImmediate(timestamp_, (const unsigned char *)(&payload), sizeof(payload)); + queue_.setMark(false); // get back the payload to audio - queue_->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) getCodecPayloadType())); + queue_.setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) getCodecPayloadType())); } void AudioRtpSession::receiveSpeakerData() { - const ost::AppDataUnit* adu = queue_->getData(queue_->getFirstTimestamp()); + const ost::AppDataUnit* adu = queue_.getData(queue_.getFirstTimestamp()); if (!adu) return; @@ -166,23 +166,19 @@ void AudioRtpSession::receiveSpeakerData() } - void AudioRtpSession::sendMicData() { int compSize = processDataEncode(); // if no data return - if (!compSize) + if (compSize == 0) return; // Increment timestamp for outgoing packet timestamp_ += timestampIncrement_; - if (type_ == Zrtp) - queue_->putData(timestamp_, getMicDataEncoded(), compSize); - - // putData put the data on RTP queue, sendImmediate bypass this queue - queue_->sendImmediate(timestamp_, getMicDataEncoded(), compSize); + // putData puts the data on RTP queue, sendImmediate bypass this queue + queue_.sendImmediate(timestamp_, getMicDataEncoded(), compSize); } @@ -190,28 +186,28 @@ void AudioRtpSession::setSessionTimeouts() { DEBUG("AudioRtpSession: Set session scheduling timeout (%d) and expireTimeout (%d)", sfl::schedulingTimeout, sfl::expireTimeout); - queue_->setSchedulingTimeout(sfl::schedulingTimeout); - queue_->setExpireTimeout(sfl::expireTimeout); + queue_.setSchedulingTimeout(sfl::schedulingTimeout); + queue_.setExpireTimeout(sfl::expireTimeout); } void AudioRtpSession::setDestinationIpAddress() { // Store remote ip in case we would need to forget current destination - remote_ip_ = ost::InetHostAddress(ca_->getLocalSDP()->getRemoteIP().c_str()); + remote_ip_ = ost::InetHostAddress(call_.getLocalSDP()->getRemoteIP().c_str()); if (!remote_ip_) { WARN("AudioRtpSession: Target IP address (%s) is not correct!", - ca_->getLocalSDP()->getRemoteIP().data()); + call_.getLocalSDP()->getRemoteIP().data()); return; } // Store remote port in case we would need to forget current destination - remote_port_ = (unsigned short) ca_->getLocalSDP()->getRemoteAudioPort(); + remote_port_ = (unsigned short) call_.getLocalSDP()->getRemoteAudioPort(); DEBUG("AudioRtpSession: New remote address for session: %s:%d", - ca_->getLocalSDP()->getRemoteIP().data(), remote_port_); + call_.getLocalSDP()->getRemoteIP().data(), remote_port_); - if (!queue_->addDestination(remote_ip_, remote_port_)) { + if (!queue_.addDestination(remote_ip_, remote_port_)) { WARN("AudioRtpSession: Can't add new destination to session!"); return; } @@ -224,7 +220,7 @@ void AudioRtpSession::updateDestinationIpAddress() // Destination address are stored in a list in ccrtp // This method remove the current destination entry - if (!queue_->forgetDestination(remote_ip_, remote_port_, remote_port_ + 1)) + if (!queue_.forgetDestination(remote_ip_, remote_port_, remote_port_ + 1)) DEBUG("AudioRtpSession: Did not remove previous destination"); // new destination is stored in call @@ -233,12 +229,12 @@ void AudioRtpSession::updateDestinationIpAddress() } -int AudioRtpSession::startRtpThread(AudioCodec* audiocodec) +int AudioRtpSession::startRtpThread(AudioCodec &audiocodec) { if (isStarted_) return 0; - DEBUG("AudioSymmetricRtpSession: Starting main thread"); + DEBUG("AudioRtpSession: Starting main thread"); isStarted_ = true; setSessionTimeouts(); @@ -246,15 +242,8 @@ int AudioRtpSession::startRtpThread(AudioCodec* audiocodec) initBuffers(); initNoiseSuppress(); - queue_->enableStack(); - int ret = thread_->start(); - - if (type_ == Zrtp) - return ret; - - AudioSymmetricRtpSession *self = dynamic_cast<AudioSymmetricRtpSession*>(this); - assert(self); - return self->startSymmetricRtpThread(); + queue_.enableStack(); + return thread_.start(); } diff --git a/daemon/src/audio/audiortp/audio_rtp_session.h b/daemon/src/audio/audiortp/audio_rtp_session.h index befeba9f6aa16d882cb9dda37b81301c3472ac9c..c6baca3f29fd81b9899922e6b1aef87a767a0478 100644 --- a/daemon/src/audio/audiortp/audio_rtp_session.h +++ b/daemon/src/audio/audiortp/audio_rtp_session.h @@ -31,44 +31,35 @@ * shall include the source code for the parts of OpenSSL used as well * as that of the covered work. */ -#ifndef SFL_AUDIO_RTP_SESSION_H_ -#define SFL_AUDIO_RTP_SESSION_H_ +#ifndef AUDIO_RTP_SESSION_H_ +#define AUDIO_RTP_SESSION_H_ #include "audio_rtp_record_handler.h" -#include <audio/codecs/audiocodec.h> #include <ccrtp/rtp.h> #include <ccrtp/formats.h> #include "noncopyable.h" class SIPCall; +namespace ost { + class Thread; +} namespace sfl { class AudioCodec; -// Possible kind of rtp session -typedef enum RtpMethod { - Symmetric, - Zrtp, - Sdes -} RtpMethod; - - class AudioRtpSession : public AudioRtpRecordHandler { public: /** * Constructor * @param sipcall The pointer on the SIP call */ - AudioRtpSession(SIPCall* sipcall, RtpMethod type, ost::RTPDataQueue *queue, ost::Thread *thread); + AudioRtpSession(SIPCall &sipcall, ost::RTPDataQueue &queue, ost::Thread &thread); virtual ~AudioRtpSession(); - RtpMethod getAudioRtpType() { - return type_; - } - void updateSessionMedia(AudioCodec *audioCodec); + void updateSessionMedia(AudioCodec &audioCodec); - int startRtpThread(AudioCodec*); + virtual int startRtpThread(AudioCodec&); /** * Used mostly when receiving a reinvite @@ -76,6 +67,11 @@ class AudioRtpSession : public AudioRtpRecordHandler { void updateDestinationIpAddress(); protected: + /** + * Set the audio codec for this RTP session + */ + virtual void setSessionMedia(AudioCodec &codec) = 0; + bool onRTPPacketRecv(ost::IncomingRTPPkt&); @@ -90,19 +86,26 @@ class AudioRtpSession : public AudioRtpRecordHandler { /** * Send encoded data to peer */ - void sendMicData(); - - SIPCall *ca_; + virtual void sendMicData(); - RtpMethod type_; + SIPCall &call_; - private: - NON_COPYABLE(AudioRtpSession); + /** + * Timestamp for this session + */ + int timestamp_; /** - * Set the audio codec for this RTP session + * Timestamp incrementation value based on codec period length (framesize) + * except for G722 which require a 8 kHz incrementation. */ - void setSessionMedia(AudioCodec*); + int timestampIncrement_; + + ost::RTPDataQueue &queue_; + + bool isStarted_; + private: + NON_COPYABLE(AudioRtpSession); /** * Set RTP Sockets send/receive timeouts @@ -119,6 +122,11 @@ class AudioRtpSession : public AudioRtpRecordHandler { */ void receiveSpeakerData(); + /** + * Increment timestamp for DTMF event + */ + virtual void incrementTimestampForDTMF(); + // Main destination address for this rtp session. // Stored in case or reINVITE, which may require to forget // this destination and update a new one. @@ -129,26 +137,12 @@ class AudioRtpSession : public AudioRtpRecordHandler { // this destination and update a new one unsigned short remote_port_; - /** - * Timestamp for this session - */ - int timestamp_; - - /** - * Timestamp incrementation value based on codec period length (framesize) - * except for G722 which require a 8 kHz incrementation. - */ - int timestampIncrement_; - /** * Timestamp reset frequency specified in number of packet sent */ short timestampCount_; - bool isStarted_; - - ost::RTPDataQueue *queue_; - ost::Thread *thread_; + ost::Thread &thread_; }; } diff --git a/daemon/src/audio/audiortp/audio_srtp_session.cpp b/daemon/src/audio/audiortp/audio_srtp_session.cpp index ed8a637fc07953ce9a04e3879bab053b62084f5a..fb14463dbb0983fa9e669a9fb03f4fa2ed6021b8 100644 --- a/daemon/src/audio/audiortp/audio_srtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_srtp_session.cpp @@ -29,8 +29,6 @@ */ #include "audio_srtp_session.h" -#include "sip/sipcall.h" - #include <openssl/sha.h> #include <openssl/hmac.h> #include <openssl/evp.h> @@ -44,10 +42,82 @@ namespace sfl { -AudioSrtpSession::AudioSrtpSession(SIPCall * sipcall) : - AudioSymmetricRtpSession(sipcall), - remoteCryptoCtx_(NULL), - localCryptoCtx_(NULL), +namespace { + std::string + encodeBase64(unsigned char *input, int length) + { + // init decoder + BIO *b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + // init internal buffer + BIO *bmem = BIO_new(BIO_s_mem()); + + // create decoder chain + b64 = BIO_push(b64, bmem); + + BIO_write(b64, input, length); + // BIO_flush (b64); + + // get pointer to data + BUF_MEM *bptr = 0; + BIO_get_mem_ptr(b64, &bptr); + + std::string output(bptr->data, bptr->length); + + BIO_free_all(bmem); + + return output; + } + + std::vector<char> decodeBase64(unsigned char *input, int length) + { + BIO *b64, *bmem; + + // init decoder and read-only BIO buffer + b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + // init internal buffer + bmem = BIO_new_mem_buf(input, length); + + // create encoder chain + bmem = BIO_push(b64, bmem); + + std::vector<char> buffer(length, 0); + BIO_read(bmem, &(*buffer.begin()), length); + + BIO_free_all(bmem); + + return buffer; + } + + // Fills the array dest with length random bytes + void buffer_fill(unsigned char dest [], size_t length) + { + DEBUG("AudioSrtp: Init local master key"); + + // @TODO key may have different length depending on cipher suite + // Allocate memory for key + std::vector<unsigned char> random_key(length); + + // Generate ryptographically strong pseudo-random bytes + int err; + + if ((err = RAND_bytes(&(*random_key.begin()), length)) != 1) + DEBUG("Error occured while generating cryptographically strong pseudo-random key"); + + assert((sizeof dest / sizeof dest[0]) <= length); + memcpy(dest, &(*random_key.begin()), length); + } +} + + + +AudioSrtpSession::AudioSrtpSession(SIPCall &call) : + AudioSymmetricRtpSession(call), + remoteCryptoCtx_(0), + localCryptoCtx_(0), localCryptoSuite_(0), remoteCryptoSuite_(0), localMasterKey_(), @@ -59,16 +129,10 @@ AudioSrtpSession::AudioSrtpSession(SIPCall * sipcall) : remoteMasterSalt_(), remoteMasterSaltLength_(0), remoteOfferIsSet_(false) -{ - type_ = Sdes; -} +{} -AudioSrtpSession::~AudioSrtpSession() -{ - DEBUG("AudioSrtp: Destroy audio srtp session"); -} -void AudioSrtpSession::initLocalCryptoInfo() +ost::CryptoContext* AudioSrtpSession::initLocalCryptoInfo() { DEBUG("AudioSrtp: Set cryptographic info for this rtp session"); @@ -81,6 +145,7 @@ void AudioSrtpSession::initLocalCryptoInfo() localCryptoCtx_->deriveSrtpKeys(0); setOutQueueCryptoContext(localCryptoCtx_); + return localCryptoCtx_; } std::vector<std::string> AudioSrtpSession::getLocalCryptoInfo() @@ -115,7 +180,8 @@ std::vector<std::string> AudioSrtpSession::getLocalCryptoInfo() return crypto_vector; } -void AudioSrtpSession::setRemoteCryptoInfo(sfl::SdesNegotiator& nego) +ost::CryptoContext* +AudioSrtpSession::setRemoteCryptoInfo(sfl::SdesNegotiator& nego) { if (not remoteOfferIsSet_) { DEBUG("%s", nego.getKeyInfo().c_str()); @@ -134,49 +200,26 @@ void AudioSrtpSession::setRemoteCryptoInfo(sfl::SdesNegotiator& nego) initializeRemoteCryptoContext(); setInQueueCryptoContext(remoteCryptoCtx_); - // initLocalCryptoInfo(); remoteOfferIsSet_ = true; } + return remoteCryptoCtx_; } void AudioSrtpSession::initializeLocalMasterKey() { DEBUG("AudioSrtp: Init local master key"); - // @TODO key may have different length depending on cipher suite localMasterKeyLength_ = sfl::CryptoSuites[localCryptoSuite_].masterKeyLength / 8; - DEBUG("AudioSrtp: Local master key length %d", localMasterKeyLength_); - - // Allocate memory for key - unsigned char *random_key = new unsigned char[localMasterKeyLength_]; - - // Generate ryptographically strong pseudo-random bytes - int err; - - if ((err = RAND_bytes(random_key, localMasterKeyLength_)) != 1) - DEBUG("Error occured while generating cryptographically strong pseudo-random key"); - - memcpy(localMasterKey_, random_key, localMasterKeyLength_); + buffer_fill(localMasterKey_, localMasterKeyLength_); } void AudioSrtpSession::initializeLocalMasterSalt() { // @TODO key may have different length depending on cipher suite localMasterSaltLength_ = sfl::CryptoSuites[localCryptoSuite_].masterSaltLength / 8; - - // Allocate memory for key - unsigned char *random_key = new unsigned char[localMasterSaltLength_]; - DEBUG("AudioSrtp: Local master salt length %d", localMasterSaltLength_); - - // Generate ryptographically strong pseudo-random bytes - int err; - - if ((err = RAND_bytes(random_key, localMasterSaltLength_)) != 1) - DEBUG("Error occured while generating cryptographically strong pseudo-random key"); - - memcpy(localMasterSalt_, random_key, localMasterSaltLength_); + buffer_fill(localMasterSalt_, localMasterSaltLength_); } std::string AudioSrtpSession::getBase64ConcatenatedKeys() @@ -207,13 +250,11 @@ void AudioSrtpSession::unBase64ConcatenatedKeys(std::string base64keys) char *dataptr = (char*) base64keys.data(); // decode concatenated binary keys - char *output = decodeBase64((unsigned char*) dataptr, strlen(dataptr)); + std::vector<char> output(decodeBase64((unsigned char*) dataptr, strlen(dataptr))); // copy master and slt respectively - memcpy((void*) remoteMasterKey_, (void*) output, remoteMasterKeyLength_); - memcpy((void*) remoteMasterSalt_, (void*)(output + remoteMasterKeyLength_), remoteMasterSaltLength_); - - delete[] output; + memcpy((void*) remoteMasterKey_, &(*output.begin()), remoteMasterKeyLength_); + memcpy((void*) remoteMasterSalt_, &(*output.begin()) + remoteMasterKeyLength_, remoteMasterSaltLength_); } void AudioSrtpSession::initializeRemoteCryptoContext() @@ -222,24 +263,20 @@ void AudioSrtpSession::initializeRemoteCryptoContext() CryptoSuiteDefinition crypto = sfl::CryptoSuites[remoteCryptoSuite_]; - if (remoteCryptoCtx_) { - delete remoteCryptoCtx_; - remoteCryptoCtx_ = NULL; - } - + delete remoteCryptoCtx_; remoteCryptoCtx_ = new ost::CryptoContext(0x0, - 0, // roc, - 0L, // keydr, - SrtpEncryptionAESCM, // encryption algo - SrtpAuthenticationSha1Hmac, // authtication algo - remoteMasterKey_, - remoteMasterKeyLength_, - remoteMasterSalt_, - remoteMasterSaltLength_, - crypto.encryptionKeyLength / 8, - crypto.srtpAuthKeyLength / 8, - crypto.masterSaltLength / 8, // session salt len - crypto.srtpAuthTagLength / 8); + 0, // roc, + 0L, // keydr, + SrtpEncryptionAESCM, + SrtpAuthenticationSha1Hmac, + remoteMasterKey_, + remoteMasterKeyLength_, + remoteMasterSalt_, + remoteMasterSaltLength_, + crypto.encryptionKeyLength / 8, + crypto.srtpAuthKeyLength / 8, + crypto.masterSaltLength / 8, + crypto.srtpAuthTagLength / 8); } @@ -249,81 +286,31 @@ void AudioSrtpSession::initializeLocalCryptoContext() CryptoSuiteDefinition crypto = sfl::CryptoSuites[localCryptoSuite_]; - if (localCryptoCtx_) { - delete localCryptoCtx_; - localCryptoCtx_ = NULL; - } - + delete localCryptoCtx_; localCryptoCtx_ = new ost::CryptoContext(OutgoingDataQueue::getLocalSSRC(), - 0, // roc, - 0L, // keydr, - SrtpEncryptionAESCM, // encryption algo - SrtpAuthenticationSha1Hmac, // authtication algo - localMasterKey_, - localMasterKeyLength_, - localMasterSalt_, - localMasterSaltLength_, - crypto.encryptionKeyLength / 8, - crypto.srtpAuthKeyLength / 8, - crypto.masterSaltLength / 8, // session salt len - crypto.srtpAuthTagLength / 8); + 0, // roc, + 0L, // keydr, + SrtpEncryptionAESCM, + SrtpAuthenticationSha1Hmac, + localMasterKey_, + localMasterKeyLength_, + localMasterSalt_, + localMasterSaltLength_, + crypto.encryptionKeyLength / 8, + crypto.srtpAuthKeyLength / 8, + crypto.masterSaltLength / 8, + crypto.srtpAuthTagLength / 8); } -void AudioSrtpSession::restoreCryptoContext(ost::CryptoContext *localContext, ost::CryptoContext *remoteContext) +void AudioSrtpSession::restoreCryptoContext(ost::CryptoContext *localContext, + ost::CryptoContext *remoteContext) { - setInQueueCryptoContext(remoteContext); - setOutQueueCryptoContext(localContext); -} - -std::string AudioSrtpSession::encodeBase64(unsigned char *input, int length) -{ - BIO *b64, *bmem; - BUF_MEM *bptr ; - - // init decoder - b64 = BIO_new(BIO_f_base64()); - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - - // init internal buffer - bmem = BIO_new(BIO_s_mem()); - - // create decoder chain - b64 = BIO_push(b64, bmem); - - BIO_write(b64, input, length); - // BIO_flush (b64); - - // get pointer to data - BIO_get_mem_ptr(b64, &bptr); - - std::string output(bptr->data, bptr->length); - - BIO_free_all(bmem); - - return output; + delete remoteCryptoCtx_; + remoteCryptoCtx_ = remoteContext; + delete localCryptoCtx_; + localCryptoCtx_ = localContext; + setInQueueCryptoContext(remoteCryptoCtx_); + setOutQueueCryptoContext(localCryptoCtx_); } -char* AudioSrtpSession::decodeBase64(unsigned char *input, int length) -{ - BIO *b64, *bmem; - - // init decoder and read-only BIO buffer - b64 = BIO_new(BIO_f_base64()); - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - - // init internal buffer - bmem = BIO_new_mem_buf(input, length); - - // create encoder chain - bmem = BIO_push(b64, bmem); - - char *buffer = new char[length]; - memset(buffer, 0, length); - - BIO_read(bmem, buffer, length); - - BIO_free_all(bmem); - - return buffer; -} } diff --git a/daemon/src/audio/audiortp/audio_srtp_session.h b/daemon/src/audio/audiortp/audio_srtp_session.h index f641e8eaa55b21065e7efcee35eb87f3543f93eb..97b9b2ce675dbd848ea6c76c235a2f50e2e33dc3 100644 --- a/daemon/src/audio/audiortp/audio_srtp_session.h +++ b/daemon/src/audio/audiortp/audio_srtp_session.h @@ -27,10 +27,9 @@ * shall include the source code for the parts of OpenSSL used as well * as that of the covered work. */ -#ifndef __AUDIO_SRTP_SESSION_H__ -#define __AUDIO_SRTP_SESSION_H__ +#ifndef AUDIO_SRTP_SESSION_H_ +#define AUDIO_SRTP_SESSION_H_ -#include "audio_rtp_session.h" #include "audio_symmetric_rtp_session.h" #include "sip/sdes_negotiator.h" #include "noncopyable.h" @@ -73,9 +72,7 @@ class AudioSrtpSession : public AudioSymmetricRtpSession { /** * Constructor for this rtp session */ - AudioSrtpSession(SIPCall * sipcall); - - ~AudioSrtpSession(); + AudioSrtpSession(SIPCall &call); /** * Used to get sdp crypto header to be included in sdp session. This @@ -86,15 +83,17 @@ class AudioSrtpSession : public AudioSymmetricRtpSession { /** * Set remote crypto header from incoming sdp offer + * @return The new remote crypto context, to be cached by the caller */ - void setRemoteCryptoInfo(sfl::SdesNegotiator& nego); + ost::CryptoContext* setRemoteCryptoInfo(sfl::SdesNegotiator &nego); /** * Init local crypto context for outgoing data - * this method must be called before sending first Invite request - * with SDP offer. - */ - void initLocalCryptoInfo(); + * this method must be called before sending first Invite request + * with SDP offer. + * @return The new local crypto context, to be cached by the caller + */ + ost::CryptoContext* initLocalCryptoInfo(); /** * Restore the cryptographic context. most likely useful to restore @@ -102,6 +101,8 @@ class AudioSrtpSession : public AudioSymmetricRtpSession { */ void restoreCryptoContext(ost::CryptoContext *, ost::CryptoContext *); + private: + NON_COPYABLE(AudioSrtpSession); /** Remote srtp crypto context to be set into incoming data queue. */ ost::CryptoContext* remoteCryptoCtx_; @@ -109,9 +110,6 @@ class AudioSrtpSession : public AudioSymmetricRtpSession { /** Local srtp crypto context to be set into outgoing data queue. */ ost::CryptoContext* localCryptoCtx_; - private: - NON_COPYABLE(AudioSrtpSession); - /** * Init local master key according to current crypto context * as defined in SdesNegotiator.h @@ -146,16 +144,6 @@ class AudioSrtpSession : public AudioSymmetricRtpSession { */ void unBase64ConcatenatedKeys(std::string base64keys); - /** - * Encode input data as base64 - */ - std::string encodeBase64(unsigned char *input, int length); - - /** - * Decode base64 data - */ - char* decodeBase64(unsigned char *input, int length); - /** Default local crypto suite is AES_CM_128_HMAC_SHA1_80*/ int localCryptoSuite_; diff --git a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp index cc5d9ba37e068ad94c070a739cde6d6079b5116d..3324f22ff4358f7713cf8e024decb2eff9f4abc1 100644 --- a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp @@ -41,24 +41,25 @@ namespace sfl { -AudioSymmetricRtpSession::AudioSymmetricRtpSession(SIPCall * sipcall) : +AudioSymmetricRtpSession::AudioSymmetricRtpSession(SIPCall &call) : ost::TimerPort() - , ost::SymmetricRTPSession(ost::InetHostAddress(sipcall->getLocalIp().c_str()), sipcall->getLocalAudioPort()) - , AudioRtpSession(sipcall, Symmetric, this, this) - , echoCanceller() - , rtpThread_(new AudioRtpThread(this)) + , ost::SymmetricRTPSession(ost::InetHostAddress(call.getLocalIp().c_str()), call.getLocalAudioPort()) + , AudioRtpSession(call, *this, *this) + , rtpThread_(*this) { - DEBUG("AudioSymmetricRtpSession: Setting new RTP session with destination %s:%d", ca_->getLocalIp().c_str(), ca_->getLocalAudioPort()); - audioRtpRecord_.callId_ = ca_->getCallId(); + DEBUG("AudioSymmetricRtpSession: Setting new RTP session with destination %s:%d", call_.getLocalIp().c_str(), call_.getLocalAudioPort()); + audioRtpRecord_.callId_ = call_.getCallId(); } AudioSymmetricRtpSession::~AudioSymmetricRtpSession() { - rtpThread_->running = false; - delete rtpThread_; + if (rtpThread_.running_) { + rtpThread_.running_ = false; + rtpThread_.join(); + } } -AudioSymmetricRtpSession::AudioRtpThread::AudioRtpThread(AudioSymmetricRtpSession *session) : running(true), rtpSession(session) +AudioSymmetricRtpSession::AudioRtpThread::AudioRtpThread(AudioSymmetricRtpSession &session) : running_(true), rtpSession_(session) {} void AudioSymmetricRtpSession::AudioRtpThread::run() @@ -69,12 +70,12 @@ void AudioSymmetricRtpSession::AudioRtpThread::run() DEBUG("AudioRtpThread: Entering Audio rtp thread main loop"); - while (running) { + while (running_) { // Send session - if (rtpSession->DtmfPending()) - rtpSession->sendDtmfEvent(); + if (rtpSession_.DtmfPending()) + rtpSession_.sendDtmfEvent(); else - rtpSession->sendMicData(); + rtpSession_.sendMicData(); Thread::sleep(TimerPort::getTimer()); @@ -84,4 +85,20 @@ void AudioSymmetricRtpSession::AudioRtpThread::run() DEBUG("AudioRtpThread: Leaving audio rtp thread loop"); } +void AudioSymmetricRtpSession::setSessionMedia(AudioCodec &audioCodec) +{ + AudioRtpSession::setSessionMedia(audioCodec); + call_.setRecordingSmplRate(getCodecSampleRate()); +} + +int AudioSymmetricRtpSession::startRtpThread(AudioCodec &audiocodec) +{ + DEBUG("AudioSymmetricRtpSession: Starting main thread"); + if (isStarted_) + return 0; + + AudioRtpSession::startRtpThread(audiocodec); + return startSymmetricRtpThread(); +} + } diff --git a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h index 256e55ae69f53ab36f349dbd7bb478e4f311ffd7..b0fda2be3d926de11341e7c546ce5f69327c03f6 100644 --- a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h +++ b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h @@ -47,7 +47,6 @@ using std::ptrdiff_t; #pragma GCC diagnostic ignored "-Weffc++" #include <ccrtp/rtp.h> #include <ccrtp/iqueue.h> -#include <cc++/numbers.h> // ost::Time class SIPCall; @@ -57,10 +56,9 @@ class AudioSymmetricRtpSession : public ost::TimerPort, public ost::SymmetricRTP public: /** * Constructor - * @param sipcall The pointer on the SIP call + * @param call The SIP call */ - AudioSymmetricRtpSession(SIPCall* sipcall); - + AudioSymmetricRtpSession(SIPCall &call); ~AudioSymmetricRtpSession(); virtual bool onRTPPacketRecv(ost::IncomingRTPPkt& pkt) { @@ -68,8 +66,7 @@ class AudioSymmetricRtpSession : public ost::TimerPort, public ost::SymmetricRTP } int startSymmetricRtpThread() { - assert(rtpThread_); - return rtpThread_->start(); + return rtpThread_.start(); } private: @@ -77,21 +74,20 @@ class AudioSymmetricRtpSession : public ost::TimerPort, public ost::SymmetricRTP class AudioRtpThread : public ost::Thread, public ost::TimerPort { public: - AudioRtpThread(AudioSymmetricRtpSession *session); - ~AudioRtpThread(){} + AudioRtpThread(AudioSymmetricRtpSession &session); virtual void run(); - bool running; + bool running_; private: NON_COPYABLE(AudioRtpThread); - AudioSymmetricRtpSession *rtpSession; + AudioSymmetricRtpSession &rtpSession_; }; - SpeexEchoCancel echoCanceller; + void setSessionMedia(AudioCodec &codec); + int startRtpThread(AudioCodec &audiocodec); - private: - AudioRtpThread *rtpThread_; + AudioRtpThread rtpThread_; }; } diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.cpp b/daemon/src/audio/audiortp/audio_zrtp_session.cpp index ebdb8f839e421b1494341b8a19bf846f9c6218c2..222adb89c1f3c84440fe6363002043d5e0e800ed 100644 --- a/daemon/src/audio/audiortp/audio_zrtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_zrtp_session.cpp @@ -49,13 +49,13 @@ namespace sfl { -AudioZrtpSession::AudioZrtpSession(SIPCall * sipcall, const std::string& zidFilename) : - AudioRtpSession(sipcall, Zrtp, this, this), - ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue>(ost::InetHostAddress(sipcall->getLocalIp().c_str()), - sipcall->getLocalAudioPort(), - 0, - ost::MembershipBookkeeping::defaultMembersHashSize, - ost::defaultApplication()), +AudioZrtpSession::AudioZrtpSession(SIPCall &call, const std::string& zidFilename) : + AudioRtpSession(call, *this, *this), + ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue>(ost::InetHostAddress(call_.getLocalIp().c_str()), + call_.getLocalAudioPort(), + 0, + ost::MembershipBookkeeping::defaultMembersHashSize, + ost::defaultApplication()), zidFilename_(zidFilename) { DEBUG("AudioZrtpSession initialized"); @@ -63,13 +63,14 @@ AudioZrtpSession::AudioZrtpSession(SIPCall * sipcall, const std::string& zidFile setCancel(cancelDefault); - DEBUG("AudioZrtpSession: Setting new RTP session with destination %s:%d", ca_->getLocalIp().c_str(), ca_->getLocalAudioPort()); + DEBUG("AudioZrtpSession: Setting new RTP session with destination %s:%d", + call_.getLocalIp().c_str(), call_.getLocalAudioPort()); } AudioZrtpSession::~AudioZrtpSession() { ost::Thread::terminate(); - Manager::instance().getMainBuffer()->unBindAll(ca_->getCallId()); + Manager::instance().getMainBuffer()->unBindAll(call_.getCallId()); } void AudioZrtpSession::final() @@ -102,7 +103,7 @@ void AudioZrtpSession::initializeZid() if (initialize(zidCompleteFilename.c_str()) >= 0) { DEBUG("Register callbacks"); setEnableZrtp(true); - setUserCallback(new ZrtpSessionCallback(ca_)); + setUserCallback(new ZrtpSessionCallback(call_)); return; } @@ -117,11 +118,29 @@ void AudioZrtpSession::initializeZid() return; } +void AudioZrtpSession::sendMicData() +{ + int compSize = processDataEncode(); + + // if no data return + if (compSize == 0) + return; + + // Increment timestamp for outgoing packet + timestamp_ += timestampIncrement_; + + // this step is only needed for ZRTP + queue_.putData(timestamp_, getMicDataEncoded(), compSize); + + // putData puts the data on RTP queue, sendImmediate bypasses this queue + queue_.sendImmediate(timestamp_, getMicDataEncoded(), compSize); +} + void AudioZrtpSession::run() { // Set recording sampling rate - ca_->setRecordingSmplRate(getCodecSampleRate()); - DEBUG("AudioZrtpSession: Entering mainloop for call %s", ca_->getCallId().c_str()); + call_.setRecordingSmplRate(getCodecSampleRate()); + DEBUG("AudioZrtpSession: Entering mainloop for call %s", call_.getCallId().c_str()); uint32 timeout = 0; @@ -151,7 +170,7 @@ void AudioZrtpSession::run() setCancel(cancelImmediate); timerTick(); } else { - if (isPendingData(timeout/1000)) { + if (isPendingData(timeout / 1000)) { setCancel(cancelDeferred); if (isActive()) @@ -163,6 +182,17 @@ void AudioZrtpSession::run() } } - DEBUG("AudioZrtpSession: Left main loop for call %s", ca_->getCallId().c_str()); + DEBUG("AudioZrtpSession: Left main loop for call %s", call_.getCallId().c_str()); } + +void AudioZrtpSession::incrementTimestampForDTMF() +{ + timestamp_ += 160; +} + +void AudioZrtpSession::setSessionMedia(AudioCodec &audioCodec) +{ + AudioRtpSession::setSessionMedia(audioCodec); +} + } diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.h b/daemon/src/audio/audiortp/audio_zrtp_session.h index 3a19a5e3fd148e2e9090965a0b058bb56296407f..9e7c196e3dcf91646c91ac61ce8957cfe176995d 100644 --- a/daemon/src/audio/audiortp/audio_zrtp_session.h +++ b/daemon/src/audio/audiortp/audio_zrtp_session.h @@ -43,19 +43,21 @@ using std::ptrdiff_t; #include <cc++/numbers.h> // OST::Time class SIPCall; +class AudioCodec; namespace sfl { -class ZrtpZidException: public std::runtime_error { +class ZrtpZidException : public std::runtime_error { public: ZrtpZidException(const std::string& str = "") : std::runtime_error("ZRTP ZID initialization failed." + str) {} }; -// class AudioZrtpSession : public ost::TimerPort, public ost::SymmetricZRTPSession, public AudioRtpRecordHandler -class AudioZrtpSession : public AudioRtpSession, protected ost::Thread, public ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue> { +class AudioZrtpSession : + public AudioRtpSession, protected ost::Thread, + public ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue> { public: - AudioZrtpSession(SIPCall * sipcall, const std::string& zidFilename); + AudioZrtpSession(SIPCall &call, const std::string& zidFilename); ~AudioZrtpSession(); virtual void final(); @@ -63,13 +65,16 @@ class AudioZrtpSession : public AudioRtpSession, protected ost::Thread, public o // Thread associated method virtual void run(); - virtual bool onRTPPacketRecv(ost::IncomingRTPPkt& pkt) { + virtual bool onRTPPacketRecv(ost::IncomingRTPPkt &pkt) { return AudioRtpSession::onRTPPacketRecv(pkt); } private: + void sendMicData(); void initializeZid(); std::string zidFilename_; + void incrementTimestampForDTMF(); + void setSessionMedia(AudioCodec &codec); }; } diff --git a/daemon/src/audio/audiortp/zrtp_session_callback.cpp b/daemon/src/audio/audiortp/zrtp_session_callback.cpp index 270468a80ea2a8fc8e683d515610d31dce7d0a17..061cf1c64c22b66f270e80302085e149d5328de8 100644 --- a/daemon/src/audio/audiortp/zrtp_session_callback.cpp +++ b/daemon/src/audio/audiortp/zrtp_session_callback.cpp @@ -45,8 +45,8 @@ using namespace ost; namespace sfl { -ZrtpSessionCallback::ZrtpSessionCallback(SIPCall *sipcall) : - sipcall_(sipcall) +ZrtpSessionCallback::ZrtpSessionCallback(SIPCall &call) : + call_(call) { using std::pair; using std::string; @@ -112,21 +112,21 @@ void ZrtpSessionCallback::secureOn(std::string cipher) { DEBUG("Zrtp: Secure mode is on with cipher %s", cipher.c_str()); - Manager::instance().getDbusManager()->getCallManager()->secureZrtpOn(sipcall_->getCallId(), cipher); + Manager::instance().getDbusManager()->getCallManager()->secureZrtpOn(call_.getCallId(), cipher); } void ZrtpSessionCallback::secureOff() { DEBUG("Zrtp: Secure mode is off"); - Manager::instance().getDbusManager()->getCallManager()->secureZrtpOff(sipcall_->getCallId()); + Manager::instance().getDbusManager()->getCallManager()->secureZrtpOff(call_.getCallId()); } void ZrtpSessionCallback::showSAS(std::string sas, bool verified) { DEBUG("Zrtp: SAS is: %s", sas.c_str()); - Manager::instance().getDbusManager()->getCallManager()->showSAS(sipcall_->getCallId(), sas, verified); + Manager::instance().getDbusManager()->getCallManager()->showSAS(call_.getCallId(), sas, verified); } @@ -134,7 +134,7 @@ void ZrtpSessionCallback::zrtpNotSuppOther() { DEBUG("Zrtp: Callee does not support ZRTP"); - Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(sipcall_->getCallId()); + Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(call_.getCallId()); } @@ -163,13 +163,13 @@ ZrtpSessionCallback::zrtpNegotiationFailed(MessageSeverity severity, int subCode std::map<int32, std::string>::const_iterator iter = zrtpMap_.find(subCode); if (iter != zrtpMap_.end()) { DEBUG("%s", iter->second.c_str()); - Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(sipcall_->getCallId(), iter->second, "ZRTP"); + Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(call_.getCallId(), iter->second, "ZRTP"); } } else { std::map<int32, std::string>::const_iterator iter = severeMap_.find(subCode); if (iter != severeMap_.end()) { DEBUG("%s", iter->second.c_str()); - Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(sipcall_->getCallId(), iter->second, "severe"); + Manager::instance().getDbusManager()->getCallManager()->zrtpNegotiationFailed(call_.getCallId(), iter->second, "severe"); } } } @@ -178,7 +178,7 @@ void ZrtpSessionCallback::confirmGoClear() { DEBUG("Zrtp: Received go clear message. Until confirmation, ZRTP won't send any data"); - Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(sipcall_->getCallId()); + Manager::instance().getDbusManager()->getCallManager()->zrtpNotSuppOther(call_.getCallId()); } std::map<int32, std::string> ZrtpSessionCallback::infoMap_; diff --git a/daemon/src/audio/audiortp/zrtp_session_callback.h b/daemon/src/audio/audiortp/zrtp_session_callback.h index 08bb9cf4fb4c9bffd2f9fbc49d50520dda88a6c3..e9e92a9c2cda8c02dec10a562bb9831dd410cef4 100644 --- a/daemon/src/audio/audiortp/zrtp_session_callback.h +++ b/daemon/src/audio/audiortp/zrtp_session_callback.h @@ -28,8 +28,8 @@ * as that of the covered work. */ -#ifndef __ZRTP_SESSION_CALLBACK_H__ -#define __ZRTP_SESSION_CALLBACK_H__ +#ifndef ZRTP_SESSION_CALLBACK_H_ +#define ZRTP_SESSION_CALLBACK_H_ #include <cstddef> using std::ptrdiff_t; @@ -39,7 +39,6 @@ using std::ptrdiff_t; #include <libzrtpcpp/ZrtpUserCallback.h> #include <exception> #include <map> -#include "noncopyable.h" class SIPCall; @@ -47,7 +46,7 @@ namespace sfl { class ZrtpSessionCallback: public ZrtpUserCallback { public: - ZrtpSessionCallback(SIPCall *sipcall); + ZrtpSessionCallback(SIPCall &call); void secureOn(std::string cipher); void secureOff(); @@ -58,12 +57,11 @@ class ZrtpSessionCallback: public ZrtpUserCallback { void confirmGoClear(); private: - NON_COPYABLE(ZrtpSessionCallback); - SIPCall* sipcall_; + SIPCall &call_; static std::map<int32, std::string> infoMap_; static std::map<int32, std::string> warningMap_; static std::map<int32, std::string> severeMap_; static std::map<int32, std::string> zrtpMap_; }; } -#endif // __ZRTP_SESSION_CALLBACK_H__ +#endif // ZRTP_SESSION_CALLBACK_H_ diff --git a/daemon/src/dbus/configurationmanager-introspec.xml b/daemon/src/dbus/configurationmanager-introspec.xml index 19ded470d6556d8a549c7fbcc625f7f7c07baeae..2021a4b3e54216fd0b7c272020f332ae8e97e66d 100644 --- a/daemon/src/dbus/configurationmanager-introspec.xml +++ b/daemon/src/dbus/configurationmanager-introspec.xml @@ -449,6 +449,21 @@ <signal name="accountsChanged" tp:name-for-bindings="accountsChanged"> </signal> + <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged"> + <arg type="s" name="accountID"/> + <arg type="i" name="registration_state"/> + </signal> + + <signal name="stunStatusFailure" tp:name-for_bindings="stunStatusFailure"> + <arg type="s" name="reason"> + </arg> + </signal> + + <signal name="stunStatusSuccess" tp:name-for_bindings="stunStatusSuccess"> + <arg type="s" name="message"> + </arg> + </signal> + <signal name="errorAlert" tp:name-for-bindings="errorAlert"> <arg type="i" name="code"> </arg> diff --git a/daemon/src/dbus/configurationmanager.cpp b/daemon/src/dbus/configurationmanager.cpp index 58771b21adb5d23e4e522581c4aff22e1322c854..a991393b0a0c3299b3a616c8b1caf65b7f1f221a 100644 --- a/daemon/src/dbus/configurationmanager.cpp +++ b/daemon/src/dbus/configurationmanager.cpp @@ -37,6 +37,7 @@ #include "config.h" #include "../manager.h" #include "sip/sipvoiplink.h" +#include "sip/siptransport.h" #include "account.h" #include "sip/sipaccount.h" @@ -387,13 +388,13 @@ void ConfigurationManager::setAddressbookList(const std::vector<std::string>& li std::map<std::string, std::string> ConfigurationManager::getHookSettings() { - return Manager::instance().getHookSettings(); + return Manager::instance().hookPreference.toMap(); } void ConfigurationManager::setHookSettings(const std::map<std::string, std::string>& settings) { - Manager::instance().setHookSettings(settings); + Manager::instance().hookPreference = HookPreference(settings); } void ConfigurationManager::setAccountsOrder(const std::string& order) @@ -409,17 +410,17 @@ std::vector<std::map<std::string, std::string> > ConfigurationManager::getHistor std::string ConfigurationManager::getAddrFromInterfaceName(const std::string& interface) { - return SIPVoIPLink::getInterfaceAddrFromName(interface); + return SipTransport::getInterfaceAddrFromName(interface); } std::vector<std::string> ConfigurationManager::getAllIpInterface() { - return SIPVoIPLink::getAllIpInterface(); + return SipTransport::getAllIpInterface(); } std::vector<std::string> ConfigurationManager::getAllIpInterfaceByName() { - return SIPVoIPLink::getAllIpInterfaceByName(); + return SipTransport::getAllIpInterfaceByName(); } std::map<std::string, std::string> ConfigurationManager::getShortcuts() diff --git a/daemon/src/iax/iaxvoiplink.h b/daemon/src/iax/iaxvoiplink.h index 3f7720131ff629291dc2de12fdc4715f95440a25..228ae39ba4ee49d9116ed6a647081dc14e7de531 100644 --- a/daemon/src/iax/iaxvoiplink.h +++ b/daemon/src/iax/iaxvoiplink.h @@ -76,7 +76,7 @@ class IAXVoIPLink : public VoIPLink { /** * Terminate a voip link by clearing the call list */ - virtual void terminate(); + void terminate(); /** * Send out registration diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index d9f9aa795b2407753324730218151c2a40e45656..398d21daae746b94d79a2a2ff0d68faeb4ed6ce9 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -131,10 +131,12 @@ void ManagerImpl::terminate() saveConfig(); - unloadAccountMap(); - delete SIPVoIPLink::instance(); + // Unload account map AFTER destroying + // the SIPVoIPLink, the link still needs the accounts for pjsip cleanup + unloadAccountMap(); + ost::MutexLock lock(audioLayerMutex_); delete audiodriver_; @@ -191,9 +193,7 @@ bool ManagerImpl::outgoingCall(const std::string& account_id, std::string current_call_id(getCurrentCallId()); - std::string prefix; - if (hookPreference.getNumberEnabled()) - prefix = hookPreference.getNumberAddPrefix(); + std::string prefix(hookPreference.getNumberAddPrefix()); std::string to_cleaned(NumberCleaner::clean(to, prefix)); @@ -1628,11 +1628,6 @@ void ManagerImpl::startVoiceMessageNotification(const std::string& accountId, dbus_.getCallManager()->voiceMailNotify(accountId, nb_msg); } -void ManagerImpl::connectionStatusNotification() -{ - dbus_.getConfigurationManager()->accountsChanged(); -} - /** * Multi Thread */ @@ -2572,7 +2567,7 @@ void ManagerImpl::loadDefaultAccountMap() { // build a default IP2IP account with default parameters accountMap_[SIPAccount::IP2IP_PROFILE] = new SIPAccount(SIPAccount::IP2IP_PROFILE); - SIPVoIPLink::instance()->createDefaultSipUdpTransport(); + SIPVoIPLink::instance()->sipTransport.createDefaultSipUdpTransport(); accountMap_[SIPAccount::IP2IP_PROFILE]->registerVoIPLink(); } @@ -2636,7 +2631,7 @@ void ManagerImpl::loadAccountMap(Conf::YamlParser &parser) // Initialize default UDP transport according to // IP to IP settings (most likely using port 5060) - SIPVoIPLink::instance()->createDefaultSipUdpTransport(); + SIPVoIPLink::instance()->sipTransport.createDefaultSipUdpTransport(); // Force IP2IP settings to be loaded to be loaded // No registration in the sense of the REGISTER method is performed. @@ -2757,30 +2752,6 @@ std::vector<std::string> ManagerImpl::getAddressbookList() const return unserialize(addressbookPreference.getList()); } -std::map<std::string, std::string> ManagerImpl::getHookSettings() const -{ - std::map<std::string, std::string> settings; - - settings["URLHOOK_IAX2_ENABLED"] = hookPreference.getIax2Enabled() ? "true" : "false"; - settings["PHONE_NUMBER_HOOK_ADD_PREFIX"] = hookPreference.getNumberAddPrefix(); - settings["PHONE_NUMBER_HOOK_ENABLED"] = hookPreference.getNumberEnabled() ? "true" : "false"; - settings["URLHOOK_SIP_ENABLED"] = hookPreference.getSipEnabled() ? "true" : "false"; - settings["URLHOOK_COMMAND"] = hookPreference.getUrlCommand(); - settings["URLHOOK_SIP_FIELD"] = hookPreference.getUrlSipField(); - - return settings; -} - -void ManagerImpl::setHookSettings(const std::map<std::string, std::string>& settings) -{ - hookPreference.setIax2Enabled(settings.find("URLHOOK_IAX2_ENABLED")->second == "true"); - hookPreference.setNumberAddPrefix(settings.find("PHONE_NUMBER_HOOK_ADD_PREFIX")->second); - hookPreference.setNumberEnabled(settings.find("PHONE_NUMBER_HOOK_ENABLED")->second == "true"); - hookPreference.setSipEnabled(settings.find("URLHOOK_SIP_ENABLED")->second == "true"); - hookPreference.setUrlCommand(settings.find("URLHOOK_COMMAND")->second); - hookPreference.setUrlSipField(settings.find("URLHOOK_SIP_FIELD")->second); -} - void ManagerImpl::setIPToIPForCall(const std::string& callID, bool IPToIP) { if (not isIPToIP(callID)) // no IPToIP calls with the same ID diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h index 78df72b2b446d9fba778c13e7abda3c7c962de9b..1454fce90c6968e2cbfe11bb4f8b81af64810d10 100644 --- a/daemon/src/managerimpl.h +++ b/daemon/src/managerimpl.h @@ -399,11 +399,6 @@ class ManagerImpl { */ void startVoiceMessageNotification(const std::string& accountId, int nb_msg); - /** - * Notify the client through DBus that registration state has been updated - */ - void connectionStatusNotification(); - /** * ConfigurationManager - Send registration request * @param accountId The account to register/unregister @@ -694,17 +689,6 @@ class ManagerImpl { */ std::vector <std::string> getAddressbookList() const; - /** - * Hook configuration - */ - std::map<std::string, std::string> getHookSettings() const; - - /** - * Hook configuration - */ - void setHookSettings(const std::map<std::string, std::string>& settings); - - /** * Get the audio manager * @return int The audio manager diff --git a/daemon/src/preferences.cpp b/daemon/src/preferences.cpp index 102150ac0e41c21afadf71ab340a215bd615b7dc..44b314d193632b3102c3ffff15148031320b646e 100644 --- a/daemon/src/preferences.cpp +++ b/daemon/src/preferences.cpp @@ -33,6 +33,8 @@ #include "audio/pulseaudio/pulselayer.h" #include "config/yamlemitter.h" #include "config/yamlnode.h" +#include "hooks/urlhook.h" +#include "sip/sip_utils.h" #include <sstream> #include "global.h" #include <cassert> @@ -216,6 +218,28 @@ HookPreference::HookPreference() : iax2Enabled_(false) , urlSipField_("X-sflphone-url") {} +HookPreference::HookPreference(const std::map<std::string, std::string> &settings) : + iax2Enabled_(settings.find("URLHOOK_IAX2_ENABLED")->second == "true") + , numberAddPrefix_(settings.find("PHONE_NUMBER_HOOK_ADD_PREFIX")->second) + , numberEnabled_(settings.find("PHONE_NUMBER_HOOK_ENABLED")->second == "true") + , sipEnabled_(settings.find("URLHOOK_SIP_ENABLED")->second == "true") + , urlCommand_(settings.find("URLHOOK_COMMAND")->second) + , urlSipField_(settings.find("URLHOOK_SIP_FIELD")->second) +{} + +std::map<std::string, std::string> HookPreference::toMap() const +{ + std::map<std::string, std::string> settings; + settings["URLHOOK_IAX2_ENABLED"] = iax2Enabled_ ? "true" : "false"; + settings["PHONE_NUMBER_HOOK_ADD_PREFIX"] = numberAddPrefix_; + settings["PHONE_NUMBER_HOOK_ENABLED"] = numberEnabled_ ? "true" : "false"; + settings["URLHOOK_SIP_ENABLED"] = sipEnabled_ ? "true" : "false"; + settings["URLHOOK_COMMAND"] = urlCommand_; + settings["URLHOOK_SIP_FIELD"] = urlSipField_; + + return settings; +} + void HookPreference::serialize(Conf::YamlEmitter *emitter) { Conf::MappingNode preferencemap(NULL); @@ -252,6 +276,14 @@ void HookPreference::unserialize(const Conf::MappingNode *map) map->getValue(urlSipFieldKey, &urlSipField_); } +void HookPreference::runHook(pjsip_msg *msg) +{ + if (sipEnabled_) { + std::string header(sip_utils::fetchHeaderValue(msg, urlSipField_)); + UrlHook::runAction(urlCommand_, header); + } +} + AudioPreference::AudioPreference() : audioApi_(PULSEAUDIO_API_STR) , cardin_(atoi(ALSA_DFT_CARD)) // ALSA_DFT_CARD @@ -345,11 +377,9 @@ void AudioPreference::serialize(Conf::YamlEmitter *emitter) Conf::ScalarNode noise(noisereduce_); Conf::ScalarNode echo(echocancel_); std::stringstream tailstr; - DEBUG("************************************************** serialize echotail %d", echoCancelTailLength_); tailstr << echoCancelTailLength_; Conf::ScalarNode echotail(tailstr.str()); std::stringstream delaystr; - DEBUG("************************************************** serialize echodelay %d", echoCancelTailLength_); delaystr << echoCancelDelay_; Conf::ScalarNode echodelay(delaystr.str()); diff --git a/daemon/src/preferences.h b/daemon/src/preferences.h index 3ee5d66fb9057202de508372eea8c124d243bc94..ea8564a24a36ee4a698e637b9dd3706621a14ad5 100644 --- a/daemon/src/preferences.h +++ b/daemon/src/preferences.h @@ -328,63 +328,29 @@ class AddressbookPreference : public Serializable { bool business_; bool home_; bool mobile_; - }; +class pjsip_msg; + class HookPreference : public Serializable { public: HookPreference(); + HookPreference(const std::map<std::string, std::string> &settings); virtual void serialize(Conf::YamlEmitter *emitter); virtual void unserialize(const Conf::MappingNode *map); - bool getIax2Enabled() const { - return iax2Enabled_; - } - - void setIax2Enabled(bool i) { - iax2Enabled_ = i; - } - std::string getNumberAddPrefix() const { - return numberAddPrefix_; - } - - void setNumberAddPrefix(const std::string &n) { - numberAddPrefix_ = n; - } - - bool getNumberEnabled() const { - return numberEnabled_; - } - - void setNumberEnabled(bool n) { - numberEnabled_ = n; - } - - bool getSipEnabled() const { - return sipEnabled_; + if (numberEnabled_) + return numberAddPrefix_; + else + return ""; } - void setSipEnabled(bool s) { - sipEnabled_ = s; - } - - std::string getUrlCommand() const { - return urlCommand_; - } - void setUrlCommand(const std::string &u) { - urlCommand_ = u; - } - - std::string getUrlSipField() const { - return urlSipField_; - } - void setUrlSipField(const std::string &u) { - urlSipField_ = u; - } + std::map<std::string, std::string> toMap() const; + void runHook(pjsip_msg *msg); private: bool iax2Enabled_; @@ -393,7 +359,6 @@ class HookPreference : public Serializable { bool sipEnabled_; std::string urlCommand_; std::string urlSipField_; - }; class AudioPreference : public Serializable { diff --git a/daemon/src/sip/Makefile.am b/daemon/src/sip/Makefile.am index 539a041feb29a3b10efcf1f47980c79c501b4482..6ad33a74a4e1ad6832b1162ec9658c64f09a4328 100644 --- a/daemon/src/sip/Makefile.am +++ b/daemon/src/sip/Makefile.am @@ -9,12 +9,16 @@ libsiplink_la_SOURCES = \ sipaccount.cpp \ sipcall.cpp \ sipvoiplink.cpp \ + siptransport.cpp \ pattern.h \ sdes_negotiator.h \ sdp.h \ sipaccount.h \ sipcall.h \ - sipvoiplink.h + sipvoiplink.h \ + siptransport.h \ + sip_utils.cpp \ + sip_utils.h libsiplink_la_CXXFLAGS = \ @PCRE_LIBS@ diff --git a/daemon/src/sip/sdes_negotiator.h b/daemon/src/sip/sdes_negotiator.h index 7fb4213555d670af6bd32f68073584107a886c09..416f940b011eecd97d00e196a44e07cb146e688f 100644 --- a/daemon/src/sip/sdes_negotiator.h +++ b/daemon/src/sip/sdes_negotiator.h @@ -80,7 +80,7 @@ struct CryptoSuiteDefinition { * List of accepted Crypto-Suites * as defined in RFC4568 (6.2) */ -const CryptoSuiteDefinition CryptoSuites[3] = { +static const CryptoSuiteDefinition CryptoSuites[] = { { (char*) "AES_CM_128_HMAC_SHA1_80", 128, 112, 48, 31, AESCounterMode, 128, HMACSHA1, 80, 80, 160, 160 }, { (char*) "AES_CM_128_HMAC_SHA1_32", 128, 112, 48, 31, AESCounterMode, 128, HMACSHA1, 32, 80, 160, 160 }, { (char*) "F8_128_HMAC_SHA1_80", 128, 112, 48, 31, AESF8Mode, 128, HMACSHA1, 80, 80, 160, 160 } diff --git a/daemon/src/sip/sip_utils.cpp b/daemon/src/sip/sip_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b98f0c44967b399ef4b7c1cb985b5321fdea296 --- /dev/null +++ b/daemon/src/sip/sip_utils.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include "sip_utils.h" +#include "pj/string.h" +#include "pjsip/sip_msg.h" + +std::string +sip_utils::fetchHeaderValue(pjsip_msg *msg, const std::string &field) +{ + pj_str_t name = pj_str((char*) field.c_str()); + pjsip_generic_string_hdr *hdr = static_cast<pjsip_generic_string_hdr*>(pjsip_msg_find_hdr_by_name(msg, &name, NULL)); + + if (!hdr) + return ""; + + std::string value(hdr->hvalue.ptr, hdr->hvalue.slen); + + size_t pos = value.find("\n"); + + if (pos != std::string::npos) + return value.substr(0, pos); + else + return ""; +} diff --git a/daemon/src/sip/sip_utils.h b/daemon/src/sip/sip_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..1a8d8bff4200e02312286fd8cad5e3dedfa01e84 --- /dev/null +++ b/daemon/src/sip/sip_utils.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2004-2012 Savoir-Faire Linux Inc. + * + * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef SIP_UTILS_H_ +#define SIP_UTILS_H_ + +#include <string> + +class pjsip_msg; + +namespace sip_utils { + /** + * Helper function to parser header from incoming sip messages + * @return Header from SIP message + */ + std::string fetchHeaderValue(pjsip_msg *msg, const std::string &field); +} + +#endif // SIP_UTILS_H_ diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp index b5c02ae9ed51df925e336a3bf37d8c3ac366883e..7303c053b41af908f787e9d423e674ca5e726afb 100644 --- a/daemon/src/sip/sipaccount.cpp +++ b/daemon/src/sip/sipaccount.cpp @@ -66,7 +66,7 @@ SIPAccount::SIPAccount(const std::string& accountID) , serviceRoute_() , tlsListenerPort_(DEFAULT_SIP_TLS_PORT) , transportType_(PJSIP_TRANSPORT_UNSPECIFIED) - , cred_(NULL) + , cred_() , tlsSetting_() , contactHeader_() , contactUpdateEnabled_(false) @@ -101,11 +101,6 @@ SIPAccount::SIPAccount(const std::string& accountID) , link_(SIPVoIPLink::instance()) {} -SIPAccount::~SIPAccount() -{ - delete [] cred_; -} - void SIPAccount::serialize(Conf::YamlEmitter *emitter) { using namespace Conf; @@ -434,6 +429,11 @@ void SIPAccount::setAccountDetails(std::map<std::string, std::string> details) publishedIpAddress_ = details[CONFIG_PUBLISHED_ADDRESS]; localPort_ = atoi(details[CONFIG_LOCAL_PORT].c_str()); publishedPort_ = atoi(details[CONFIG_PUBLISHED_PORT].c_str()); + if(stunServer_ != details[CONFIG_STUN_SERVER]) { + DEBUG("Stun server changed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + link_->sipTransport.destroyStunResolver(stunServer_); + // pj_stun_sock_destroy(pj_stun_sock *stun_sock); + } stunServer_ = details[CONFIG_STUN_SERVER]; stunEnabled_ = details[CONFIG_STUN_ENABLE] == "true"; dtmfType_ = details[CONFIG_ACCOUNT_DTMF_TYPE]; @@ -631,7 +631,7 @@ void SIPAccount::startKeepAliveTimer() { keepAliveDelay_.sec = 60; } else { - DEBUG("Regsitration Expire == %d", registrationExpire_); + DEBUG("Registration Expire == %d", registrationExpire_); keepAliveDelay_.sec = registrationExpire_; } @@ -840,7 +840,7 @@ std::string SIPAccount::getContactHeader() const // Else we determine this infor based on transport information std::string address, port; - link_->findLocalAddressFromTransport(transport_, transportType, address, port); + link_->sipTransport.findLocalAddressFromTransport(transport_, transportType, address, port); // UDP does not require the transport specification std::string scheme; @@ -951,11 +951,9 @@ void SIPAccount::setCredentials(const std::vector<std::map<std::string, std::str } // Create the credential array - delete[] cred_; - cred_ = new pjsip_cred_info[credentials_.size()]; + cred_.resize(credentials_.size()); size_t i = 0; - for (vector<map<string, string > >::const_iterator iter = credentials_.begin(); iter != credentials_.end(); ++iter) { map<string, string>::const_iterator val = (*iter).find(CONFIG_ACCOUNT_PASSWORD); diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h index dd645c7293987f4126d2a4d145f1968b5c76efe0..0237f253f7dc658c12c03d63333aff74f0b72940 100644 --- a/daemon/src/sip/sipaccount.h +++ b/daemon/src/sip/sipaccount.h @@ -110,11 +110,6 @@ class SIPAccount : public Account { */ SIPAccount(const std::string& accountID); - /** - * Virtual destructor - */ - virtual ~SIPAccount(); - virtual VoIPLink* getVoIPLink(); std::string getUserAgentName() const; @@ -196,8 +191,8 @@ class SIPAccount : public Account { void stopKeepAliveTimer(); - pjsip_cred_info *getCredInfo() const { - return cred_; + const pjsip_cred_info* getCredInfo() const { + return &(*cred_.begin()); } /** @@ -605,7 +600,7 @@ class SIPAccount : public Account { /** * Credential information stored for further registration. */ - pjsip_cred_info *cred_; + std::vector<pjsip_cred_info> cred_; /** * The TLS settings, used only if tls is chosen as a sip transport. diff --git a/daemon/src/sip/siptransport.cpp b/daemon/src/sip/siptransport.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c43ed74c52a7a8a490674ddda9eeedc8a4b31909 --- /dev/null +++ b/daemon/src/sip/siptransport.cpp @@ -0,0 +1,556 @@ +/* + * Copyright (C) [2004, 2012] Savoir-Faire Linux Inc. + * + * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include <map> + +#include <pjsip.h> +#include <pjlib.h> +#include <pjsip_ua.h> +#include <pjlib-util.h> +#include <pjnath.h> +#include <pjnath/stun_config.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <linux/if.h> + +#include "siptransport.h" +#include "manager.h" + +#include "sip/sdp.h" +#include "sipcall.h" +#include "sipaccount.h" +#include "eventthread.h" +#include "sdes_negotiator.h" + +#include "dbus/dbusmanager.h" +#include "dbus/callmanager.h" +#include "dbus/configurationmanager.h" + +static pjsip_transport *localUDPTransport_ = NULL; /** The default transport (5060) */ + +std::string SipTransport::getSIPLocalIP() +{ + pj_sockaddr ip_addr; + + if (pj_gethostip(pj_AF_INET(), &ip_addr) == PJ_SUCCESS) + return pj_inet_ntoa(ip_addr.ipv4.sin_addr); + else { + ERROR("SipTransport: Could not get local IP"); + return ""; + } +} + +std::vector<std::string> SipTransport::getAllIpInterfaceByName() +{ + static ifreq ifreqs[20]; + ifconf ifconf; + + std::vector<std::string> ifaceList; + ifaceList.push_back("default"); + + ifconf.ifc_buf = (char*) (ifreqs); + ifconf.ifc_len = sizeof(ifreqs); + + int sock = socket(AF_INET,SOCK_STREAM,0); + + if (sock >= 0) { + if (ioctl(sock, SIOCGIFCONF, &ifconf) >= 0) + for (unsigned i = 0; i < ifconf.ifc_len / sizeof(ifreq); ++i) + ifaceList.push_back(std::string(ifreqs[i].ifr_name)); + + close(sock); + } + + return ifaceList; +} + +std::string SipTransport::getInterfaceAddrFromName(const std::string &ifaceName) +{ + int fd = socket(AF_INET, SOCK_DGRAM,0); + + if (fd < 0) { + ERROR("SipTransport: Error: could not open socket: %m"); + return ""; + } + + ifreq ifr; + strcpy(ifr.ifr_name, ifaceName.c_str()); + memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); + ifr.ifr_addr.sa_family = AF_INET; + + ioctl(fd, SIOCGIFADDR, &ifr); + close(fd); + + sockaddr_in *saddr_in = (sockaddr_in *) &ifr.ifr_addr; + return inet_ntoa(saddr_in->sin_addr); +} + +std::vector<std::string> SipTransport::getAllIpInterface() +{ + pj_sockaddr addrList[16]; + unsigned addrCnt = PJ_ARRAY_SIZE(addrList); + + std::vector<std::string> ifaceList; + + if (pj_enum_ip_interface(pj_AF_INET(), &addrCnt, addrList) == PJ_SUCCESS) { + for (unsigned i = 0; i < addrCnt; i++) { + char addr[PJ_INET_ADDRSTRLEN]; + pj_sockaddr_print(&addrList[i], addr, sizeof(addr), 0); + ifaceList.push_back(std::string(addr)); + } + } + + return ifaceList; +} + +SipTransport::SipTransport(pjsip_endpoint *endpt, pj_caching_pool *cp, pj_pool_t *pool) : transportMap_(), stunSocketMap_(), cp_(cp), pool_(pool), endpt_(endpt) +{ +} + +SipTransport::~SipTransport() +{ +} + +pj_bool_t +stun_sock_on_status_cb(pj_stun_sock * /*stun_sock*/, pj_stun_sock_op op, + pj_status_t status) +{ + switch (op) { + case PJ_STUN_SOCK_DNS_OP: + DEBUG("SipTransport: Stun operation dns resolution"); + break; + case PJ_STUN_SOCK_BINDING_OP: + DEBUG("SipTransport: Stun operation binding"); + break; + case PJ_STUN_SOCK_KEEP_ALIVE_OP: + DEBUG("SipTransport: Stun operation keep alive"); + break; + case PJ_STUN_SOCK_MAPPED_ADDR_CHANGE: + DEBUG("SipTransport: Stun operation address mapping change"); + break; + default: + DEBUG("SipTransport: Stun unknown operation"); + break; + } + + if (status == PJ_SUCCESS) { + DEBUG("SipTransport: Stun operation success"); + } else { + ERROR("SipTransport: Stun operation failure"); + } + + // Always return true so the stun transport registration retry even on failure + return true; +} + +static pj_bool_t +stun_sock_on_rx_data_cb(pj_stun_sock * /*stun_sock*/, void * /*pkt*/, + unsigned /*pkt_len*/, + const pj_sockaddr_t * /*src_addr*/, + unsigned /*addr_len*/) +{ + return PJ_TRUE; +} + + +pj_status_t SipTransport::createStunResolver(pj_str_t serverName, pj_uint16_t port) +{ + pj_stun_config stunCfg; + pj_stun_config_init(&stunCfg, &cp_->factory, 0, pjsip_endpt_get_ioqueue(endpt_), pjsip_endpt_get_timer_heap(endpt_)); + + DEBUG("***************** Create Stun Resolver *********************"); + + static const pj_stun_sock_cb stun_sock_cb = { + stun_sock_on_rx_data_cb, + NULL, + stun_sock_on_status_cb + }; + + pj_stun_sock *stun_sock; + std::string stunResolverName(serverName.ptr, serverName.slen); + pj_status_t status = pj_stun_sock_create(&stunCfg, stunResolverName.c_str(), pj_AF_INET(), &stun_sock_cb, NULL, NULL, &stun_sock); + + // store socket inside list + DEBUG(" insert %s resolver in map", stunResolverName.c_str()); + stunSocketMap_.insert(std::pair<std::string, pj_stun_sock *>(stunResolverName, stun_sock)); + + if (status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; + pj_strerror(status, errmsg, sizeof(errmsg)); + ERROR("SipTransport: Error creating STUN socket for %.*s: %s", (int) serverName.slen, serverName.ptr, errmsg); + return status; + } + + status = pj_stun_sock_start(stun_sock, &serverName, port, NULL); + + if (status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; + pj_strerror(status, errmsg, sizeof(errmsg)); + DEBUG("SipTransport: Error starting STUN socket for %.*s: %s", (int) serverName.slen, serverName.ptr, errmsg); + pj_stun_sock_destroy(stun_sock); + } + + return status; +} + +pj_status_t SipTransport::destroyStunResolver(const std::string &serverName) +{ + std::map<std::string, pj_stun_sock *>::iterator it; + it = stunSocketMap_.find(serverName); + + DEBUG("***************** Destroy Stun Resolver *********************"); + + if (it != stunSocketMap_.end()) { + DEBUG("SipTransport: Deleting stun resolver %s", it->first.c_str()); + pj_stun_sock_destroy(it->second); + stunSocketMap_.erase(it); + } + + return PJ_SUCCESS; +} + + +void SipTransport::createTlsListener(pj_uint16_t tlsListenerPort, pjsip_tls_setting *tlsSetting, pjsip_tpfactory **listener) +{ + pj_sockaddr_in local_addr; + pj_sockaddr_in_init(&local_addr, 0, 0); + local_addr.sin_port = pj_htons(tlsListenerPort); + + if (tlsSetting == NULL) { + ERROR("SipTransport: Error TLS settings not specified"); + return; + } + + if (listener == NULL) { + ERROR("SipTransport: Error no pointer to store new TLS listener"); + return; + } + + pj_str_t pjAddress; + pj_cstr(&pjAddress, PJ_INADDR_ANY); + pj_sockaddr_in_set_str_addr(&local_addr, &pjAddress); + std::string localIP(getSIPLocalIP()); + + pjsip_host_port a_name = { + pj_str((char*) localIP.c_str()), + local_addr.sin_port + }; + + pjsip_tls_transport_start(endpt_, tlsSetting, &local_addr, &a_name, 1, listener); +} + + +pjsip_transport * +SipTransport::createTlsTransport(const std::string &remoteAddr, + pj_uint16_t tlsListenerPort, + pjsip_tls_setting *tlsSettings) +{ + pjsip_transport *transport = NULL; + + pj_str_t remote; + pj_cstr(&remote, remoteAddr.c_str()); + + pj_sockaddr_in rem_addr; + pj_sockaddr_in_init(&rem_addr, &remote, (pj_uint16_t) DEFAULT_SIP_TLS_PORT); + + // The local tls listener + static pjsip_tpfactory *localTlsListener = NULL; + + if (localTlsListener == NULL) + createTlsListener(tlsListenerPort, tlsSettings, &localTlsListener); + + pjsip_endpt_acquire_transport(endpt_, PJSIP_TRANSPORT_TLS, &rem_addr, + sizeof rem_addr, NULL, &transport); + + if (transport == NULL) + ERROR("SipTransport: Could not create new TLS transport\n"); + + return transport; +} + +void SipTransport::createSipTransport(SIPAccount *account) +{ + if (account == NULL) { + ERROR("SipTransport: Account is NULL while creating sip transport"); + return; + } + + shutdownSipTransport(account); + + if (account->isTlsEnabled()) { + std::string remoteSipUri(account->getServerUri()); + static const char SIPS_PREFIX[] = "<sips:"; + size_t sips = remoteSipUri.find(SIPS_PREFIX) + (sizeof SIPS_PREFIX) - 1; + size_t trns = remoteSipUri.find(";transport"); + std::string remoteAddr(remoteSipUri.substr(sips, trns-sips)); + + pjsip_transport *transport = createTlsTransport(remoteAddr, account->getTlsListenerPort(), account->getTlsSetting()); + account->transport_ = transport; + } else if (account->isStunEnabled()) { + pjsip_transport *transport = createStunTransport(account->getStunServerName(), account->getStunPort()); + account->transport_ = transport; + } + else { + pjsip_transport *transport = createUdpTransport(account->getLocalInterface(), account->getLocalPort()); + account->transport_ = transport; + } + + if (!account->transport_) { + // Could not create new transport, this transport may already exists + account->transport_ = transportMap_[account->getLocalPort()]; + + if (account->transport_) + pjsip_transport_add_ref(account->transport_); + else { + account->transport_ = localUDPTransport_; + account->setLocalPort(localUDPTransport_->local_name.port); + } + } +} + +void SipTransport::createDefaultSipUdpTransport() +{ + pj_uint16_t port = 0; + int counter = 0; + + DEBUG("SipTransport: Create default sip udp transport"); + + SIPAccount *account = Manager::instance().getIP2IPAccount(); + + pjsip_transport *transport = NULL; + static const int DEFAULT_TRANSPORT_ATTEMPTS = 5; + for (; transport == NULL and counter < DEFAULT_TRANSPORT_ATTEMPTS; ++counter) { + // if default udp transport fails to init on 5060, try other ports + // with 2 step size increment (i.e. 5062, 5064, ...) + port = account->getLocalPort() + (counter * 2); + transport = createUdpTransport(account->getLocalInterface(), port); + } + + if (transport == NULL) { + ERROR("SipTransport: Create UDP transport"); + return; + } + + DEBUG("SipTransport: Created default sip transport on %d", port); + + // set transport for this account + account->transport_ = transport; + + // set local udp transport + localUDPTransport_ = account->transport_; +} + +pjsip_transport * +SipTransport::createUdpTransport(const std::string &interface, unsigned int port) +{ + // init socket to bind this transport to + pj_uint16_t listeningPort = (pj_uint16_t) port; + + DEBUG("SipTransport: Create UDP transport on %s:%d", interface.c_str(), port); + + // determine the ip address for this transport + static const char * const DEFAULT_INTERFACE = "default"; + std::string listeningAddress; + if (interface == DEFAULT_INTERFACE) + listeningAddress = getSIPLocalIP(); + else + listeningAddress = getInterfaceAddrFromName(interface); + + if (listeningAddress.empty()) { + ERROR("SipTransport: Could not determine ip address for this transport"); + return NULL; + } + + if (listeningPort == 0) { + ERROR("SipTransport: Could not determine port for this transport"); + return NULL; + } + + pj_sockaddr boundAddr; + pj_str_t udpString; + pj_cstr(&udpString, listeningAddress.c_str()); + pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &udpString, &boundAddr); + pj_status_t status; + pjsip_transport *transport = NULL; + if (boundAddr.addr.sa_family == pj_AF_INET()) { + status = pjsip_udp_transport_start(endpt_, &boundAddr.ipv4, NULL, 1, &transport); + if (status != PJ_SUCCESS) { + ERROR("Failed to create IPv4 UDP transport"); + return NULL; + } + } else if (boundAddr.addr.sa_family == pj_AF_INET6()) { + status = pjsip_udp_transport_start6(endpt_, &boundAddr.ipv6, NULL, 1, &transport); + if (status != PJ_SUCCESS) { + ERROR("Failed to create IPv6 UDP transport"); + return NULL; + } + } + + DEBUG("SipTransport: Listening address %s, listening port %d", listeningAddress.c_str(), listeningPort); + // dump debug information to stdout + pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_)); + transportMap_[listeningPort] = transport; + + return transport; +} + +pjsip_tpselector *SipTransport::initTransportSelector(pjsip_transport *transport, pj_pool_t *tp_pool) const +{ + assert(transport); + pjsip_tpselector *tp = (pjsip_tpselector *) pj_pool_zalloc(tp_pool, sizeof(pjsip_tpselector)); + tp->type = PJSIP_TPSELECTOR_TRANSPORT; + tp->u.transport = transport; + return tp; +} + +pjsip_transport *SipTransport::createStunTransport(pj_str_t serverName, pj_uint16_t port) +{ + pjsip_transport *transport; + + DEBUG("SipTransport: Create stun transport server name: %s, port: %d", serverName, port);// account->getStunPort()); + if (createStunResolver(serverName, port) != PJ_SUCCESS) { + ERROR("SipTransport: Can't resolve STUN server"); + Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure(""); + return NULL; + } + + pj_sock_t sock = PJ_INVALID_SOCKET; + + pj_sockaddr_in boundAddr; + + if (pj_sockaddr_in_init(&boundAddr, &serverName, 0) != PJ_SUCCESS) { + ERROR("SipTransport: Can't initialize IPv4 socket on %*s:%i", serverName.slen, serverName.ptr, port); + Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure(""); + return NULL; + } + + if (pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock) != PJ_SUCCESS) { + ERROR("SipTransport: Can't create or bind socket"); + Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure(""); + return NULL; + } + + // Query the mapped IP address and port on the 'outside' of the NAT + pj_sockaddr_in pub_addr; + + if (pjstun_get_mapped_addr(&cp_->factory, 1, &sock, &serverName, port, &serverName, port, &pub_addr) != PJ_SUCCESS) { + ERROR("SipTransport: Can't contact STUN server"); + pj_sock_close(sock); + Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure(""); + return NULL; + } + + pjsip_host_port a_name = { + pj_str(pj_inet_ntoa(pub_addr.sin_addr)), + pj_ntohs(pub_addr.sin_port) + }; + + pjsip_udp_transport_attach2(endpt_, PJSIP_TRANSPORT_UDP, sock, &a_name, 1, + &transport); + + pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_)); + + return transport; +} + +void SipTransport::shutdownSipTransport(SIPAccount *account) +{ + if (account->isStunEnabled()) { + pj_str_t stunServerName = account->getStunServerName(); + std::string server(stunServerName.ptr, stunServerName.slen); + destroyStunResolver(server); + } + + if (account->transport_) { + pjsip_transport_dec_ref(account->transport_); + account->transport_ = NULL; + } +} + +void SipTransport::findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &addr, std::string &port) const +{ + // Initialize the sip port with the default SIP port + std::stringstream ss; + ss << DEFAULT_SIP_PORT; + port = ss.str(); + + // Initialize the sip address with the hostname + const pj_str_t *pjMachineName = pj_gethostname(); + addr = std::string(pjMachineName->ptr, pjMachineName->slen); + + // Update address and port with active transport + if (!transport) { + ERROR("SipTransport: Transport is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str()); + return; + } + + // get the transport manager associated with the SIP enpoint + pjsip_tpmgr *tpmgr = pjsip_endpt_get_tpmgr(endpt_); + if (!tpmgr) { + ERROR("SipTransport: Transport manager is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str()); + return; + } + + // initialize a transport selector + // TODO Need to determine why we exclude TLS here... + // if (transportType == PJSIP_TRANSPORT_UDP and transport_) + pjsip_tpselector *tp_sel = initTransportSelector(transport, pool_); + if (!tp_sel) { + ERROR("SipTransport: Could not initialize transport selector, using local address %s:%s", addr.c_str(), port.c_str()); + return; + } + + pj_str_t localAddress = {0,0}; + int i_port = 0; + + // Find the local address and port for this transport + if (pjsip_tpmgr_find_local_addr(tpmgr, pool_, transportType, tp_sel, &localAddress, &i_port) != PJ_SUCCESS) { + WARN("SipTransport: Could not retrieve local address and port from transport, using %s:%s", addr.c_str(), port.c_str()); + return; + } + + // Update local address based on the transport type + addr = std::string(localAddress.ptr, localAddress.slen); + + // Fallback on local ip provided by pj_gethostip() + if (addr == "0.0.0.0") + addr = getSIPLocalIP(); + + // Determine the local port based on transport information + ss.str(""); + ss << i_port; + port = ss.str(); +} diff --git a/daemon/src/sip/siptransport.h b/daemon/src/sip/siptransport.h new file mode 100644 index 0000000000000000000000000000000000000000..21e2c8780157f153f81f01f5357afca75a97a0fd --- /dev/null +++ b/daemon/src/sip/siptransport.h @@ -0,0 +1,201 @@ +/* + * Copyright (C) [2004, 2012] Savoir-Faire Linux Inc. + * + * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef SIPTRANSPORT_H_ +#define SIPTRANSPORT_H_ + +#include <string> +#include <vector> + +#include <pjsip.h> +#include <pjlib.h> +#include <pjsip_ua.h> +#include <pjlib-util.h> +#include <pjnath.h> +#include <pjnath/stun_config.h> +#include "noncopyable.h" + +class SIPAccount; + +class SipTransport { + public: + SipTransport(pjsip_endpoint *endpt, pj_caching_pool *cp, pj_pool_t *pool); + ~SipTransport(); + + static std::string getSIPLocalIP(); + + /** + * List all the interfaces on the system and return + * a vector list containing their name (eth0, eth0:1 ...). + * @param void + * @return std::vector<std::string> A std::string vector + * of interface name available on all of the interfaces on + * the system. + */ + static std::vector<std::string> getAllIpInterfaceByName(); + + /** + * List all the interfaces on the system and return + * a vector list containing their name (eth0, eth0:1 ...). + * @param void + * @return std::vector<std::string> A std::string vector + * of interface name available on all of the interfaces on + * the system. + */ + static std::string getInterfaceAddrFromName(const std::string &ifaceName); + + /** + * List all the interfaces on the system and return + * a vector list containing their IPV4 address. + * @param void + * @return std::vector<std::string> A std::string vector + * of IPV4 address available on all of the interfaces on + * the system. + */ + static std::vector<std::string> getAllIpInterface(); + + void setEndpoint(pjsip_endpoint *endpt) { + endpt_ = endpt; + } + + void setCachingPool(pj_caching_pool *cp) { + cp_ = cp; + } + + void setPool(pj_pool_t *pool) { + pool_ = pool; + } + + /** + * Create a new stun resolver. Store it inside the array. Resolve public address for this + * server name. + * @param serverName The name of the stun server + * @param port number + */ + pj_status_t createStunResolver(pj_str_t serverName, pj_uint16_t port); + + pj_status_t destroyStunResolver(const std::string &serverName); + + /** + * General Sip transport creation method according to the + * transport type specified in account settings + * @param account The account for which a transport must be created. + */ + void createSipTransport(SIPAccount *account); + + void createDefaultSipUdpTransport(); + + /** + * Create SIP UDP transport from account's setting + * @param account The account for which a transport must be created. + */ + pjsip_transport *createUdpTransport(const std::string &interface, + unsigned int port); + + /** + * Initialize the transport selector + * @param transport A transport associated with an account + * + * @return A pointer to the transport selector structure + */ + pjsip_tpselector *initTransportSelector(pjsip_transport *transport, pj_pool_t *tp_pool) const; + + /** + * Create The default TLS listener which is global to the application. This means that + * only one TLS connection can be established for the momment. + * @param the port number to create the TCP socket + * @param pjsip's tls settings for the transport to be created which contains: + * - path to ca certificate list file + * - path to certertificate file + * - path to private key file + * - the password for the file + * - the TLS method + * @param a pointer to store the listener created, in our case this is a static pointer + */ + void createTlsListener(pj_uint16_t, pjsip_tls_setting *, pjsip_tpfactory **); + + /** + * Create a connection oriented TLS transport and register to the specified remote address. + * First, initialize the TLS listener sole instance. This means that, for the momment, only one TLS transport + * is allowed to be created in the application. Any subsequent account attempting to + * register a new using this transport even if new settings are specified. + * @param the remote address for this transport to be connected + * @param the local port to initialize the TCP socket + * @param pjsip's tls transport parameters + */ + pjsip_transport * + createTlsTransport(const std::string &remoteAddr, + pj_uint16_t tlsListenerPort, + pjsip_tls_setting *tlsSetting); + + /** + * Create a UDP transport using stun server to resove public address + * @param account The account for which a transport must be created. + */ + pjsip_transport *createStunTransport(pj_str_t serverName, pj_uint16_t port); + + /** + * This function unset the transport for a given account. + */ + void shutdownSipTransport(SIPAccount *account); + + /** + * Get the correct address to use (ie advertised) from + * a uri. The corresponding transport that should be used + * with that uri will be discovered. + * + * @param uri The uri from which we want to discover the address to use + * @param transport The transport to use to discover the address + */ + void findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &address, std::string &port) const; + + private: + NON_COPYABLE(SipTransport); + + /** + * UDP Transports are stored in this map in order to retreive them in case + * several accounts would share the same port number. + */ + std::map<pj_uint16_t, pjsip_transport*> transportMap_; + + /** + * Stun resolver array + */ + std::map<std::string, pj_stun_sock *> stunSocketMap_; + + pj_caching_pool *cp_; + + pj_pool_t *pool_; + + pjsip_endpoint *endpt_; +}; + +#endif // SIPTRANSPORT_H_ diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 3f36d20290b7b9f848ecd88c393793f56b60e76e..bb1b6da1cca027dca08149abca1fb349975fc655 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -36,6 +36,7 @@ #include "config.h" #endif + #include "sipvoiplink.h" #include "manager.h" @@ -48,8 +49,8 @@ #include "dbus/dbusmanager.h" #include "dbus/callmanager.h" +#include "dbus/configurationmanager.h" -#include "hooks/urlhook.h" #include "im/instant_messaging.h" #include "audio/audiolayer.h" @@ -61,7 +62,7 @@ #include "pjsip/sip_endpoint.h" #include "pjsip/sip_transport_tls.h" #include "pjsip/sip_uri.h" -#include <pjnath.h> +#include "pjnath.h" #include <netinet/in.h> #include <arpa/nameser.h> @@ -80,8 +81,6 @@ using namespace sfl; namespace { -static pjsip_transport *localUDPTransport_ = NULL; /** The default transport (5060) */ - /** A map to retreive SFLphone internal call id * Given a SIP call ID (usefull for transaction sucha as transfer)*/ static std::map<std::string, std::string> transferCallID; @@ -93,12 +92,7 @@ static std::map<std::string, std::string> transferCallID; * localport, localip, localexternalport * @param call a SIPCall valid pointer */ -static void setCallMediaLocal(SIPCall* call, const std::string &localIP); - -/** - * Helper function to parser header from incoming sip messages - */ -std::string fetchHeaderValue(pjsip_msg *msg, const std::string &field); +void setCallMediaLocal(SIPCall* call, const std::string &localIP); static pj_caching_pool pool_cache, *cp_ = &pool_cache; static pj_pool_t *pool_; @@ -106,17 +100,17 @@ static pjsip_endpoint *endpt_; static pjsip_module mod_ua_; static pj_thread_t *thread; -static void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status UNUSED); -static void sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *offer); -static void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer); -static void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e); -static void outgoing_request_forked_cb(pjsip_inv_session *inv, pjsip_event *e); -static void transaction_state_changed_cb(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e); -static void registration_cb(pjsip_regc_cbparam *param); -static pj_bool_t transaction_request_cb(pjsip_rx_data *rdata); -static pj_bool_t transaction_response_cb(pjsip_rx_data *rdata UNUSED) ; +void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status); +void sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *offer); +void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer); +void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e); +void outgoing_request_forked_cb(pjsip_inv_session *inv, pjsip_event *e); +void transaction_state_changed_cb(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e); +void registration_cb(pjsip_regc_cbparam *param); +pj_bool_t transaction_request_cb(pjsip_rx_data *rdata); +pj_bool_t transaction_response_cb(pjsip_rx_data *rdata) ; -static void transfer_client_cb(pjsip_evsub *sub, pjsip_event *event); +void transfer_client_cb(pjsip_evsub *sub, pjsip_event *event); /** * Send a reINVITE inside an active dialog to modify its state @@ -130,18 +124,6 @@ int SIPSessionReinvite(SIPCall *); */ void onCallTransfered(pjsip_inv_session *inv, pjsip_rx_data *rdata); -std::string getSIPLocalIP() -{ - pj_sockaddr ip_addr; - - if (pj_gethostip(pj_AF_INET(), &ip_addr) == PJ_SUCCESS) - return pj_inet_ntoa(ip_addr.ipv4.sin_addr); - else { - ERROR("SIPVoIPLink: Could not get local IP"); - return ""; - } -} - pjsip_route_hdr *createRouteSet(const std::string &route, pj_pool_t *hdr_pool) { int port = 0; @@ -312,24 +294,21 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) return true; } - if (Manager::instance().hookPreference.getSipEnabled()) { - std::string header_value(fetchHeaderValue(rdata->msg_info.msg, Manager::instance().hookPreference.getUrlSipField())); - UrlHook::runAction(Manager::instance().hookPreference.getUrlCommand(), header_value); - } + Manager::instance().hookPreference.runHook(rdata->msg_info.msg); SIPCall* call = new SIPCall(Manager::instance().getNewCallID(), Call::INCOMING, cp_); Manager::instance().associateCallToAccount(call->getCallId(), account_id); // May use the published address as well - std::string addrToUse = SIPVoIPLink::instance()->getInterfaceAddrFromName(account->getLocalInterface()); + std::string addrToUse = SipTransport::getInterfaceAddrFromName(account->getLocalInterface()); std::string addrSdp = account->isStunEnabled() ? account->getPublishedAddress() : addrToUse; - pjsip_tpselector *tp = SIPVoIPLink::instance()->initTransportSelector(account->transport_, call->getMemoryPool()); + pjsip_tpselector *tp = SIPVoIPLink::instance()->sipTransport.initTransportSelector(account->transport_, call->getMemoryPool()); if (addrToUse == "0.0.0.0") - addrToUse = getSIPLocalIP(); + addrToUse = SipTransport::getSIPLocalIP(); if (addrSdp == "0.0.0.0") addrSdp = addrToUse; @@ -348,8 +327,8 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) call->getLocalSDP()->setLocalIP(addrSdp); - call->getAudioRtp().initAudioRtpConfig(); - call->getAudioRtp().initAudioSymmetricRtpSession(); + call->getAudioRtp().initConfig(); + call->getAudioRtp().initSession(); if (rdata->msg_info.msg->body) { char sdpbuffer[1000]; @@ -366,7 +345,7 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) CryptoOffer crypto_offer; crypto_offer.push_back(std::string(sdpoffer.substr(start, (sdpoffer.size() - start) - 1))); - std::vector<sfl::CryptoSuiteDefinition>localCapabilities; + std::vector<sfl::CryptoSuiteDefinition> localCapabilities; for (int i = 0; i < 3; i++) localCapabilities.push_back(sfl::CryptoSuites[i]); @@ -443,7 +422,7 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) /*************************************************************************************************/ -SIPVoIPLink::SIPVoIPLink() : transportMap_(), evThread_(new EventThread(this)) +SIPVoIPLink::SIPVoIPLink() : sipTransport(endpt_, cp_, pool_), evThread_(new EventThread(this)) { #define TRY(ret) do { \ if (ret != PJ_SUCCESS) \ @@ -466,7 +445,11 @@ SIPVoIPLink::SIPVoIPLink() : transportMap_(), evThread_(new EventThread(this)) TRY(pjsip_endpt_create(&cp_->factory, pj_gethostname()->ptr, &endpt_)); - if (getSIPLocalIP().empty()) + sipTransport.setEndpoint(endpt_); + sipTransport.setCachingPool(cp_); + sipTransport.setPool(pool_); + + if (SipTransport::getSIPLocalIP().empty()) throw VoipLinkException("UserAgent: Unable to determine network capabilities"); TRY(pjsip_tsx_layer_init_module(endpt_)); @@ -540,10 +523,6 @@ SIPVoIPLink* SIPVoIPLink::instance() return instance; } -void SIPVoIPLink::init() {} - -void SIPVoIPLink::terminate() {} - void SIPVoIPLink::getEvent() { @@ -560,7 +539,7 @@ SIPVoIPLink::getEvent() void SIPVoIPLink::sendRegister(Account *a) { SIPAccount *account = dynamic_cast<SIPAccount*>(a); - createSipTransport(account); + sipTransport.createSipTransport(account); account->setRegister(true); account->setRegistrationState(Trying); @@ -592,7 +571,6 @@ void SIPVoIPLink::sendRegister(Account *a) pjsip_regc_set_credentials(regc, account->getCredentialCount(), account->getCredInfo()); - pjsip_hdr hdr_list; pj_list_init(&hdr_list); std::string useragent(account->getUserAgentName()); @@ -609,7 +587,7 @@ void SIPVoIPLink::sendRegister(Account *a) if (pjsip_regc_register(regc, PJ_TRUE, &tdata) != PJ_SUCCESS) throw VoipLinkException("Unable to initialize transaction data for account registration"); - if (pjsip_regc_set_transport(regc, initTransportSelector(account->transport_, pool_)) != PJ_SUCCESS) + if (pjsip_regc_set_transport(regc, sipTransport.initTransportSelector(account->transport_, pool_)) != PJ_SUCCESS) throw VoipLinkException("Unable to set transport"); // decrease transport's ref count, counter incrementation is managed when acquiring transport @@ -704,20 +682,20 @@ Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toU toUri = account->getToUri(toUrl); call->setPeerNumber(toUri); - std::string localAddr(getInterfaceAddrFromName(account->getLocalInterface())); + std::string localAddr(SipTransport::getInterfaceAddrFromName(account->getLocalInterface())); if (localAddr == "0.0.0.0") - localAddr = getSIPLocalIP(); + localAddr = SipTransport::getSIPLocalIP(); setCallMediaLocal(call, localAddr); // May use the published address as well std::string addrSdp = account->isStunEnabled() ? account->getPublishedAddress() : - getInterfaceAddrFromName(account->getLocalInterface()); + SipTransport::getInterfaceAddrFromName(account->getLocalInterface()); if (addrSdp == "0.0.0.0") - addrSdp = getSIPLocalIP(); + addrSdp = SipTransport::getSIPLocalIP(); // Initialize the session using ULAW as default codec in case of early media // The session should be ready to receive media once the first INVITE is sent, before @@ -730,8 +708,8 @@ Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toU } try { - call->getAudioRtp().initAudioRtpConfig(); - call->getAudioRtp().initAudioSymmetricRtpSession(); + call->getAudioRtp().initConfig(); + call->getAudioRtp().initSession(); call->getAudioRtp().initLocalCryptoInfo(); call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec)); } catch (...) { @@ -884,15 +862,16 @@ SIPVoIPLink::offhold(const std::string& id) // Create a new instance for this codec sfl::Codec* audiocodec = Manager::instance().audioCodecFactory.instantiateCodec(pl); - call->getAudioRtp().initAudioRtpConfig (); - call->getAudioRtp().initAudioSymmetricRtpSession (); - call->getAudioRtp().start (static_cast<sfl::AudioCodec *>(audiocodec)); - } - catch (const SdpException &e) { - ERROR("UserAgent: Exception: %s", e.what()); - } - catch (...) { - throw VoipLinkException("Could not create audio rtp session"); + if (audiocodec == NULL) + throw VoipLinkException("Could not instantiate codec"); + + call->getAudioRtp().initConfig(); + call->getAudioRtp().initSession(); + call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec)); + } catch (const SdpException &e) { + ERROR("UserAgent: Exception: %s", e.what()); + } catch (...) { + throw VoipLinkException("Could not create audio rtp session"); } sdpSession->removeAttributeFromLocalAudioMedia("sendrecv"); @@ -1127,9 +1106,6 @@ SIPVoIPLink::SIPStartCall(SIPCall *call) std::string toUri(call->getPeerNumber()); // expecting a fully well formed sip uri - // std::string address, port; - // findLocalAddressFromUri(toUri, account->transport_, address, port); - pj_str_t pjTo = pj_str((char*) toUri.c_str()); // Create the from header @@ -1160,7 +1136,7 @@ SIPVoIPLink::SIPStartCall(SIPCall *call) if (pjsip_inv_invite(call->inv, &tdata) != PJ_SUCCESS) return false; - pjsip_tpselector *tp = initTransportSelector(account->transport_, call->inv->pool); + pjsip_tpselector *tp = sipTransport.initTransportSelector(account->transport_, call->inv->pool); if (pjsip_dlg_set_transport(dialog, tp) != PJ_SUCCESS) return false; @@ -1200,7 +1176,7 @@ SIPVoIPLink::SIPCallClosed(SIPCall *call) } void -SIPVoIPLink::SIPCallAnswered(SIPCall *call, pjsip_rx_data *rdata UNUSED) +SIPVoIPLink::SIPCallAnswered(SIPCall *call, pjsip_rx_data * /*rdata*/) { if (call->getConnectionState() != Call::CONNECTED) { call->setConnectionState(Call::CONNECTED); @@ -1246,17 +1222,19 @@ bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to) { SIPAccount *account = Manager::instance().getIP2IPAccount(); - if (!account) + if (!account) { + ERROR("Error could not retrieve default account for IP2IP call"); return false; + } SIPCall *call = new SIPCall(id, Call::OUTGOING, cp_); call->setIPToIP(true); call->initRecFilename(to); - std::string localAddress(getInterfaceAddrFromName(account->getLocalInterface())); + std::string localAddress(SipTransport::getInterfaceAddrFromName(account->getLocalInterface())); if (localAddress == "0.0.0.0") - localAddress = getSIPLocalIP(); + localAddress = SipTransport::getSIPLocalIP(); setCallMediaLocal(call, localAddress); @@ -1267,8 +1245,8 @@ bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to) // Audio Rtp Session must be initialized before creating initial offer in SDP session // since SDES require crypto attribute. - call->getAudioRtp().initAudioRtpConfig(); - call->getAudioRtp().initAudioSymmetricRtpSession(); + call->getAudioRtp().initConfig(); + call->getAudioRtp().initSession(); call->getAudioRtp().initLocalCryptoInfo(); call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec)); @@ -1298,13 +1276,17 @@ bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to) return false; } - shutdownSipTransport(account); - createTlsTransport(account, remoteAddr); + sipTransport.shutdownSipTransport(account); + pjsip_transport *transport = sipTransport.createTlsTransport(remoteAddr, account->getTlsListenerPort(), + account->getTlsSetting()); - if (!account->transport_) { + if (transport == NULL) { + ERROR("Error could not create TLS transport for IP2IP call"); delete call; return false; } + + account->transport_ = transport; } if (!SIPStartCall(call)) { @@ -1320,340 +1302,11 @@ bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to) // Private functions /////////////////////////////////////////////////////////////////////////////// -pj_bool_t stun_sock_on_status_cb(pj_stun_sock *stun_sock UNUSED, pj_stun_sock_op op UNUSED, pj_status_t status) -{ - return status == PJ_SUCCESS; -} - -pj_bool_t stun_sock_on_rx_data_cb(pj_stun_sock *stun_sock UNUSED, void *pkt UNUSED, unsigned pkt_len UNUSED, const pj_sockaddr_t *src_addr UNUSED, unsigned addr_len UNUSED) -{ - return PJ_TRUE; -} - - -pj_status_t SIPVoIPLink::stunServerResolve(SIPAccount *account) -{ - pj_stun_config stunCfg; - pj_stun_config_init(&stunCfg, &cp_->factory, 0, pjsip_endpt_get_ioqueue(endpt_), pjsip_endpt_get_timer_heap(endpt_)); - - static const pj_stun_sock_cb stun_sock_cb = { - stun_sock_on_rx_data_cb, - NULL, - stun_sock_on_status_cb - }; - - pj_stun_sock *stun_sock; - pj_status_t status = pj_stun_sock_create(&stunCfg, "stunresolve", pj_AF_INET(), &stun_sock_cb, NULL, NULL, &stun_sock); - - pj_str_t stunServer = account->getStunServerName(); - - if (status != PJ_SUCCESS) { - char errmsg[PJ_ERR_MSG_SIZE]; - pj_strerror(status, errmsg, sizeof(errmsg)); - ERROR("Error creating STUN socket for %.*s: %s", (int) stunServer.slen, stunServer.ptr, errmsg); - return status; - } - - status = pj_stun_sock_start(stun_sock, &stunServer, account->getStunPort(), NULL); - - if (status != PJ_SUCCESS) { - char errmsg[PJ_ERR_MSG_SIZE]; - pj_strerror(status, errmsg, sizeof(errmsg)); - DEBUG("Error starting STUN socket for %.*s: %s", (int) stunServer.slen, stunServer.ptr, errmsg); - pj_stun_sock_destroy(stun_sock); - } - - return status; -} - -void SIPVoIPLink::createDefaultSipUdpTransport() -{ - pj_uint16_t port = 0; - int counter = 0; - - SIPAccount *account = Manager::instance().getIP2IPAccount(); - - pjsip_transport *transport = NULL; - static const int DEFAULT_TRANSPORT_ATTEMPTS = 5; - while ((transport == NULL) and (counter < DEFAULT_TRANSPORT_ATTEMPTS)) { - // if default udp transport fails to init on 5060, try other ports with 2 step size increment (i.e. 5062, 5064, ...) - port = account->getLocalPort() + (counter * 2); - transport = createUdpTransport(account->getLocalInterface(), port); - ++counter; - } - - if (transport == NULL) { - ERROR("UserAgent: Create UDP transport"); - return; - } - - DEBUG("UserAgent: Created default sip transport on %d", port); - - // set transport for this account - account->transport_ = transport; - - // set local udp transport - localUDPTransport_ = account->transport_; -} - -void SIPVoIPLink::createTlsListener(SIPAccount *account, pjsip_tpfactory **listener) -{ - pj_sockaddr_in local_addr; - pj_sockaddr_in_init(&local_addr, 0, 0); - local_addr.sin_port = pj_htons(account->getTlsListenerPort()); - - pj_str_t pjAddress; - pj_cstr(&pjAddress, PJ_INADDR_ANY); - pj_sockaddr_in_set_str_addr(&local_addr, &pjAddress); - std::string localIP(getSIPLocalIP()); - - pjsip_host_port a_name = { - pj_str((char*) localIP.c_str()), - local_addr.sin_port - }; - - pjsip_tls_transport_start(endpt_, account->getTlsSetting(), &local_addr, &a_name, 1, listener); -} - - -void SIPVoIPLink::createTlsTransport(SIPAccount *account, std::string remoteAddr) -{ - pj_str_t remote; - pj_cstr(&remote, remoteAddr.c_str()); - - pj_sockaddr_in rem_addr; - pj_sockaddr_in_init(&rem_addr, &remote, (pj_uint16_t) DEFAULT_SIP_TLS_PORT); - - static pjsip_tpfactory *localTlsListener = NULL; /** The local tls listener */ - - if (localTlsListener == NULL) - createTlsListener(account, &localTlsListener); - - pjsip_endpt_acquire_transport(endpt_, PJSIP_TRANSPORT_TLS, &rem_addr, - sizeof rem_addr, NULL, &account->transport_); -} - - -void SIPVoIPLink::createSipTransport(SIPAccount *account) -{ - shutdownSipTransport(account); - - if (account == NULL) { - ERROR("Account is NULL while creating sip transport"); - return; - } - - if (account->isTlsEnabled()) { - std::string remoteSipUri(account->getServerUri()); - static const char SIPS_PREFIX[] = "<sips:"; - size_t sips = remoteSipUri.find(SIPS_PREFIX) + (sizeof SIPS_PREFIX) - 1; - size_t trns = remoteSipUri.find(";transport"); - std::string remoteAddr(remoteSipUri.substr(sips, trns-sips)); - - createTlsTransport(account, remoteAddr); - } else if (account->isStunEnabled()) - createStunTransport(account); - else { - pjsip_transport *transport = createUdpTransport(account->getLocalInterface(), account->getLocalPort()); - account->transport_ = transport; - } - - if (!account->transport_) { - // Could not create new transport, this transport may already exists - account->transport_ = transportMap_[account->getLocalPort()]; - - if (account->transport_) - pjsip_transport_add_ref(account->transport_); - else { - account->transport_ = localUDPTransport_; - account->setLocalPort(localUDPTransport_->local_name.port); - } - } -} - -pjsip_transport *SIPVoIPLink::createUdpTransport(std::string interface, unsigned int port) -{ - // init socket to bind this transport to - pj_sockaddr_in bound_addr; - pj_bzero(&bound_addr, sizeof(bound_addr)); - pj_uint16_t listeningPort = (pj_uint16_t) port; - bound_addr.sin_port = pj_htons(listeningPort); - bound_addr.sin_family = PJ_AF_INET; - - // determine the ip address for this transport - static const char * const DEFAULT_INTERFACE = "default"; - std::string listeningAddress; - if (interface == DEFAULT_INTERFACE) { - listeningAddress = getSIPLocalIP(); - bound_addr.sin_addr.s_addr = pj_htonl(PJ_INADDR_ANY); - } else { - listeningAddress = getInterfaceAddrFromName(interface); - bound_addr.sin_addr = pj_inet_addr2(listeningAddress.c_str()); - } - - if (listeningAddress.empty()) { - ERROR("SIP: Could not determine ip address for this transport"); - return NULL; - } - - if (listeningPort == 0) { - ERROR("SIP: Could not determine port for this transport"); - return NULL; - } - - // The published address for this transport - const pjsip_host_port a_name = { - pj_str((char*) listeningAddress.c_str()), - listeningPort - }; - - pjsip_transport *transport = NULL; - pj_status_t status = pjsip_udp_transport_start(endpt_, &bound_addr, &a_name, 1, &transport); - if (status != PJ_SUCCESS) { - ERROR("SIP: Could not create UDP transport for port %u", port); - return NULL; - } - - // dump debug information to stdout - pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_)); - transportMap_[listeningPort] = transport; - - return transport; -} - -pjsip_tpselector *SIPVoIPLink::initTransportSelector(pjsip_transport *transport, pj_pool_t *tp_pool) const -{ - assert(transport); - pjsip_tpselector *tp = (pjsip_tpselector *) pj_pool_zalloc(tp_pool, sizeof(pjsip_tpselector)); - - tp->type = PJSIP_TPSELECTOR_TRANSPORT; - tp->u.transport = transport; - return tp; -} - -void SIPVoIPLink::createStunTransport(SIPAccount *account) -{ - pj_str_t stunServer = account->getStunServerName(); - pj_uint16_t stunPort = PJ_STUN_PORT; // account->getStunPort(); - - DEBUG("UserAgent: Create stun transport server name: %s, port: %d", account->getStunServerName(), stunPort);// account->getStunPort()); - - if (stunServerResolve(account) != PJ_SUCCESS) { - ERROR("Can't resolve STUN server"); - return; - } - - pj_sock_t sock = PJ_INVALID_SOCKET; - - pj_sockaddr_in boundAddr; - - if (pj_sockaddr_in_init(&boundAddr, &stunServer, 0) != PJ_SUCCESS) { - ERROR("Can't initialize IPv4 socket on %*s:%i", stunServer.slen, stunServer.ptr, stunPort); - return; - } - - if (pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock) != PJ_SUCCESS) { - ERROR("Can't create or bind socket"); - return; - } - - // Query the mapped IP address and port on the 'outside' of the NAT - pj_sockaddr_in pub_addr; - - if (pjstun_get_mapped_addr(&cp_->factory, 1, &sock, &stunServer, stunPort, - &stunServer, stunPort, &pub_addr) != PJ_SUCCESS) { - ERROR("Can't contact STUN server"); - pj_sock_close(sock); - return; - } - - pjsip_host_port a_name = { - pj_str(pj_inet_ntoa(pub_addr.sin_addr)), - pj_ntohs(pub_addr.sin_port) - }; - - std::string listeningAddress = std::string(a_name.host.ptr, a_name.host.slen); - - account->setPublishedAddress(listeningAddress); - account->setPublishedPort(a_name.port); - - pjsip_udp_transport_attach2(endpt_, PJSIP_TRANSPORT_UDP, sock, &a_name, 1, - &account->transport_); - - pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_)); -} - -void SIPVoIPLink::shutdownSipTransport(SIPAccount *account) -{ - if (account->transport_) { - pjsip_transport_dec_ref(account->transport_); - account->transport_ = NULL; - } -} - -void SIPVoIPLink::findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &addr, std::string &port) const -{ - // Initialize the sip port with the default SIP port - std::stringstream ss; - ss << DEFAULT_SIP_PORT; - port = ss.str(); - - // Initialize the sip address with the hostname - const pj_str_t *pjMachineName = pj_gethostname(); - addr = std::string(pjMachineName->ptr, pjMachineName->slen); - - // Update address and port with active transport - if (!transport) { - ERROR("SIPVoIPLink: Transport is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str()); - return; - } - - // get the transport manager associated with the SIP enpoint - pjsip_tpmgr *tpmgr = pjsip_endpt_get_tpmgr(endpt_); - if (!tpmgr) { - ERROR("SIPVoIPLink: Transport manager is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str()); - return; - } - - // initialize a transport selector - // TODO Need to determine why we exclude TLS here... - // if (transportType == PJSIP_TRANSPORT_UDP and transport_) - pjsip_tpselector *tp_sel = initTransportSelector(transport, pool_); - if (!tp_sel) { - ERROR("SIPVoIPLink: Could not initialize transport selector, using local address %s:%s", addr.c_str(), port.c_str()); - return; - } - - pj_str_t localAddress = {0,0}; - int i_port = 0; - - // Find the local address and port for this transport - DEBUG("transportType: %d\n", transportType); - if (pjsip_tpmgr_find_local_addr(tpmgr, pool_, transportType, tp_sel, &localAddress, &i_port) != PJ_SUCCESS) { - WARN("SIPVoIPLink: Could not retreive local address and port from transport, using %s:%s", addr.c_str(), port.c_str()); - return; - } - - // Update local address based on the transport type - addr = std::string(localAddress.ptr, localAddress.slen); - - // Fallback on local ip provided by pj_gethostip() - if (addr == "0.0.0.0") - addr = getSIPLocalIP(); - - // Determine the local port based on transport information - ss.str(""); - ss << i_port; - port = ss.str(); -} - namespace { int SIPSessionReinvite(SIPCall *call) { - pjsip_tx_data *tdata; - pjmedia_sdp_session *local_sdp = call->getLocalSDP()->getLocalSdpSession(); - + pjsip_tx_data *tdata; if (local_sdp && pjsip_inv_reinvite(call->inv, NULL, local_sdp, &tdata) == PJ_SUCCESS) return pjsip_inv_send_msg(call->inv, tdata); @@ -1667,8 +1320,6 @@ void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e) if (call == NULL) return; - SIPVoIPLink *link = SIPVoIPLink::instance(); - if (inv->state != PJSIP_INV_STATE_CONFIRMED) { // Update UI with the current status code and description pjsip_transaction * tsx = e->body.tsx_state.tsx; @@ -1676,10 +1327,13 @@ void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e) if (statusCode) { const pj_str_t * description = pjsip_get_status_text(statusCode); - Manager::instance().getDbusManager()->getCallManager()->sipCallStateChanged(call->getCallId(), std::string(description->ptr, description->slen), statusCode); + std::string desc(description->ptr, description->slen); + CallManager *cm = Manager::instance().getDbusManager()->getCallManager(); + cm->sipCallStateChanged(call->getCallId(), desc, statusCode); } } + SIPVoIPLink *link = SIPVoIPLink::instance(); if (inv->state == PJSIP_INV_STATE_EARLY and e->body.tsx_state.tsx->role == PJSIP_ROLE_UAC) { call->setConnectionState(Call::RINGING); Manager::instance().peerRingingCall(call->getCallId()); @@ -1696,7 +1350,6 @@ void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e) link->SIPCallClosed(call); break; case PJSIP_SC_DECLINE: - if (inv->role != PJSIP_ROLE_UAC) break; @@ -1743,11 +1396,11 @@ void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer) SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(accountid)); - std::string localAddress(SIPVoIPLink::instance()->getInterfaceAddrFromName(account->getLocalInterface())); + std::string localAddress(SipTransport::getInterfaceAddrFromName(account->getLocalInterface())); std::string addrSdp(localAddress); if (localAddress == "0.0.0.0") - localAddress = getSIPLocalIP(); + localAddress = SipTransport::getSIPLocalIP(); if (addrSdp == "0.0.0.0") addrSdp = localAddress; @@ -1849,8 +1502,7 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) } } - - // We did not found any crypto context for this media, RTP fallback + // We did not find any crypto context for this media, RTP fallback if (!nego_success && call->getAudioRtp().isSdesEnabled()) { call->getAudioRtp().stop(); call->getAudioRtp().setSrtpEnabled(false); @@ -1858,7 +1510,7 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) std::string accountID = Manager::instance().getAccountFromCall(call->getCallId()); if (dynamic_cast<SIPAccount*>(Manager::instance().getAccount(accountID))->getSrtpFallback()) - call->getAudioRtp().initAudioSymmetricRtpSession(); + call->getAudioRtp().initSession(); } if (!sdpSession) @@ -1882,33 +1534,33 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) } } catch (const SdpException &e) { ERROR("UserAgent: Exception: %s", e.what()); - } catch (const std::exception& rtpException) { + } catch (const std::exception &rtpException) { ERROR("UserAgent: Exception: %s", rtpException.what()); } } -void outgoing_request_forked_cb(pjsip_inv_session *inv UNUSED, pjsip_event *e UNUSED) -{ -} +void outgoing_request_forked_cb(pjsip_inv_session * /*inv*/, pjsip_event * /*e*/) +{} -void transaction_state_changed_cb(pjsip_inv_session *inv UNUSED, pjsip_transaction *tsx, pjsip_event *e) +void transaction_state_changed_cb(pjsip_inv_session * inv, + pjsip_transaction *tsx, pjsip_event *event) { assert(tsx); - assert(e); + assert(event); if (tsx->role != PJSIP_ROLE_UAS || tsx->state != PJSIP_TSX_STATE_TRYING) return; if (pjsip_method_cmp(&tsx->method, &pjsip_refer_method) ==0) { - onCallTransfered(inv, e->body.tsx_state.src.rdata); /** Handle the refer method **/ + onCallTransfered(inv, event->body.tsx_state.src.rdata); /** Handle the refer method **/ return; } pjsip_tx_data* t_data; - if (e->body.rx_msg.rdata) { - pjsip_rx_data *r_data = e->body.rx_msg.rdata; + if (event->body.rx_msg.rdata) { + pjsip_rx_data *r_data = event->body.rx_msg.rdata; if (r_data && r_data->msg_info.msg->line.req.method.id == PJSIP_OTHER_METHOD) { std::string request = pjsip_rx_data_get_info(r_data); @@ -1922,13 +1574,13 @@ void transaction_state_changed_cb(pjsip_inv_session *inv UNUSED, pjsip_transacti } } - if (!e->body.tsx_state.src.rdata) + if (!event->body.tsx_state.src.rdata) return; // Incoming TEXT message // Get the message inside the transaction - pjsip_rx_data *r_data = e->body.tsx_state.src.rdata; + pjsip_rx_data *r_data = event->body.tsx_state.src.rdata; std::string formattedMessage(static_cast<char*>(r_data->msg_info.msg->body->data)); // Try to determine who is the recipient of the message @@ -2012,7 +1664,7 @@ void update_contact_header(pjsip_regc_cbparam *param, SIPAccount *account) std::string recvContactPort = ss.str(); std::string currentAddress, currentPort; - siplink->findLocalAddressFromTransport(account->transport_, PJSIP_TRANSPORT_UDP, currentAddress, currentPort); + siplink->sipTransport.findLocalAddressFromTransport(account->transport_, PJSIP_TRANSPORT_UDP, currentAddress, currentPort); bool updateContact = false; std::string currentContactHeader = account->getContactHeader(); @@ -2038,12 +1690,12 @@ void registration_cb(pjsip_regc_cbparam *param) SIPAccount *account = static_cast<SIPAccount *>(param->token); if (account == NULL) { - ERROR("SipVoipLink: account does'nt exist in registration callback"); + ERROR("SipVoipLink: account doesn't exist in registration callback"); return; } if (param == NULL) { - ERROR("SipVoipLink: regsitration callback param is NULL"); + ERROR("SipVoipLink: registration callback parameter is NULL"); return; } @@ -2058,7 +1710,6 @@ void registration_cb(pjsip_regc_cbparam *param) std::pair<int, std::string> details(param->code, state); // TODO: there id a race condition for this ressource when closing the application account->setRegistrationStateDetailed(details); - account->setRegistrationExpire(param->expiration); } @@ -2066,7 +1717,7 @@ void registration_cb(pjsip_regc_cbparam *param) account->setRegistrationState(ErrorAuth); account->setRegister(false); - SIPVoIPLink::instance()->shutdownSipTransport(account); + SIPVoIPLink::instance()->sipTransport.shutdownSipTransport(account); return; } @@ -2087,11 +1738,11 @@ void registration_cb(pjsip_regc_cbparam *param) account->setRegistrationState(ErrorAuth); break; - case 423: { // Expiration Interval Too Brief + case 423: + // Expiration Interval Too Brief account->doubleRegistrationExpire(); account->registerVoIPLink(); - } - break; + break; default: account->setRegistrationState(Error); @@ -2100,14 +1751,14 @@ void registration_cb(pjsip_regc_cbparam *param) account->setRegister(false); - SIPVoIPLink::instance()->shutdownSipTransport(account); + SIPVoIPLink::instance()->sipTransport.shutdownSipTransport(account); } else { if (account->isRegistered()) account->setRegistrationState(Registered); else { account->setRegistrationState(Unregistered); - SIPVoIPLink::instance()->shutdownSipTransport(account); + SIPVoIPLink::instance()->sipTransport.shutdownSipTransport(account); } } } @@ -2179,7 +1830,7 @@ void transfer_client_cb(pjsip_evsub *sub, pjsip_event *event) if (!call) return; - if (status_line.code/100 == 2) { + if (status_line.code / 100 == 2) { pjsip_tx_data *tdata; if (pjsip_inv_end_session(call->inv, PJSIP_SC_GONE, NULL, &tdata) == PJ_SUCCESS) @@ -2217,86 +1868,4 @@ void setCallMediaLocal(SIPCall* call, const std::string &localIP) call->getLocalSDP()->setLocalPublishedVideoPort(callLocalVideoPort); #endif } - -std::string fetchHeaderValue(pjsip_msg *msg, const std::string &field) -{ - pj_str_t name = pj_str((char*) field.c_str()); - - pjsip_generic_string_hdr *hdr = static_cast<pjsip_generic_string_hdr*>(pjsip_msg_find_hdr_by_name(msg, &name, NULL)); - - if (!hdr) - return ""; - - std::string value(std::string(hdr->hvalue.ptr, hdr->hvalue.slen)); - - size_t pos = value.find("\n"); - - if (pos == std::string::npos) - return ""; - - return value.substr(0, pos); -} } // end anonymous namespace - -std::vector<std::string> SIPVoIPLink::getAllIpInterfaceByName() -{ - static ifreq ifreqs[20]; - ifconf ifconf; - - std::vector<std::string> ifaceList; - ifaceList.push_back("default"); - - ifconf.ifc_buf = (char*) (ifreqs); - ifconf.ifc_len = sizeof(ifreqs); - - int sock = socket(AF_INET,SOCK_STREAM,0); - - if (sock >= 0) { - if (ioctl(sock, SIOCGIFCONF, &ifconf) >= 0) - for (unsigned i = 0; i < ifconf.ifc_len / sizeof(ifreq); ++i) - ifaceList.push_back(std::string(ifreqs[i].ifr_name)); - - close(sock); - } - - return ifaceList; -} - -std::string SIPVoIPLink::getInterfaceAddrFromName(const std::string &ifaceName) -{ - int fd = socket(AF_INET, SOCK_DGRAM,0); - - if (fd < 0) { - ERROR("UserAgent: Error: could not open socket: %m"); - return ""; - } - - ifreq ifr; - strcpy(ifr.ifr_name, ifaceName.c_str()); - memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); - ifr.ifr_addr.sa_family = AF_INET; - - ioctl(fd, SIOCGIFADDR, &ifr); - close(fd); - - sockaddr_in *saddr_in = (sockaddr_in *) &ifr.ifr_addr; - return inet_ntoa(saddr_in->sin_addr); -} - -std::vector<std::string> SIPVoIPLink::getAllIpInterface() -{ - pj_sockaddr addrList[16]; - unsigned addrCnt = PJ_ARRAY_SIZE(addrList); - - std::vector<std::string> ifaceList; - - if (pj_enum_ip_interface(pj_AF_INET(), &addrCnt, addrList) == PJ_SUCCESS) { - for (unsigned i = 0; i < addrCnt; i++) { - char addr[PJ_INET_ADDRSTRLEN]; - pj_sockaddr_print(&addrList[i], addr, sizeof(addr), 0); - ifaceList.push_back(std::string(addr)); - } - } - - return ifaceList; -} diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h index e91f7c5237301c1179c789f136ea72330634369b..cb15c0a49cad9ca7b99f3e5467b970f2c57b31fd 100644 --- a/daemon/src/sip/sipvoiplink.h +++ b/daemon/src/sip/sipvoiplink.h @@ -47,11 +47,13 @@ #include <pjlib.h> #include <pjsip_ua.h> #include <pjlib-util.h> +#include <pjnath.h> #include <pjnath/stun_config.h> /////////////////////////////// #include "sipaccount.h" #include "voiplink.h" +#include "siptransport.h" class EventThread; class SIPCall; @@ -74,16 +76,6 @@ class SIPVoIPLink : public VoIPLink { */ static SIPVoIPLink* instance(); - /** - * Try to initiate the pjsip engine/thread and set config - */ - virtual void init(); - - /** - * Shut the library and clean up - */ - virtual void terminate(); - /** * Event listener. Each event send by the call manager is received and handled from here */ @@ -227,49 +219,6 @@ class SIPVoIPLink : public VoIPLink { */ std::string getUseragentName(SIPAccount *) const; - /** - * List all the interfaces on the system and return - * a vector list containing their IPV4 address. - * @param void - * @return std::vector<std::string> A std::string vector - * of IPV4 address available on all of the interfaces on - * the system. - */ - static std::vector<std::string> getAllIpInterface(); - - /** - * List all the interfaces on the system and return - * a vector list containing their name (eth0, eth0:1 ...). - * @param void - * @return std::vector<std::string> A std::string vector - * of interface name available on all of the interfaces on - * the system. - */ - static std::vector<std::string> getAllIpInterfaceByName(); - - /** - * List all the interfaces on the system and return - * a vector list containing their name (eth0, eth0:1 ...). - * @param void - * @return std::vector<std::string> A std::string vector - * of interface name available on all of the interfaces on - * the system. - */ - static std::string getInterfaceAddrFromName(const std::string &ifaceName); - - /** - * Initialize the transport selector - * @param transport A transport associated with an account - * - * @return A pointer to the transport selector structure - */ - pjsip_tpselector *initTransportSelector(pjsip_transport *, pj_pool_t *) const; - - /** - * This function unset the transport for a given account. - */ - void shutdownSipTransport(SIPAccount *account); - /** * Send a SIP message to a call identified by its callid * @@ -286,16 +235,7 @@ class SIPVoIPLink : public VoIPLink { */ void createDefaultSipUdpTransport(); - /** - * Get the correct address to use (ie advertised) from - * a uri. The corresponding transport that should be used - * with that uri will be discovered. - * - * @param uri The uri from which we want to discover the address to use - * @param transport The transport to use to discover the address - */ - void findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &address, std::string &port) const; - + SipTransport sipTransport; private: /** * Start a SIP Call @@ -310,47 +250,6 @@ class SIPVoIPLink : public VoIPLink { SIPVoIPLink(); - /** - * Resolve public address for this account - */ - pj_status_t stunServerResolve(SIPAccount *); - - /** - * Create the default TLS listener. - */ - void createTlsListener(SIPAccount*, pjsip_tpfactory **listener); - - /** - * General Sip transport creation method according to the - * transport type specified in account settings - * @param account The account for which a transport must be created. - */ - void createSipTransport(SIPAccount *account); - - /** - * Create SIP UDP transport from account's setting - * @param account The account for which a transport must be created. - */ - pjsip_transport *createUdpTransport(std::string interface, unsigned int port); - - /** - * Create a TLS transport from the default TLS listener from - * @param account The account for which a transport must be created. - */ - void createTlsTransport(SIPAccount *, std::string remoteAddr); - - /** - * Create a UDP transport using stun server to resove public address - * @param account The account for which a transport must be created. - */ - void createStunTransport(SIPAccount *account); - - /** - * UDP Transports are stored in this map in order to retreive them in case - * several accounts would share the same port number. - */ - std::map<pj_uint16_t, pjsip_transport*> transportMap_; - /** * Threading object */ diff --git a/daemon/src/voiplink.h b/daemon/src/voiplink.h index ec48f2e0ab962bbf81853880f45c2775a7960f1f..b5c556062ce1c7570db6e4da8f55823b18f868d3 100644 --- a/daemon/src/voiplink.h +++ b/daemon/src/voiplink.h @@ -65,12 +65,6 @@ class VoIPLink { */ virtual void getEvent() = 0; - /** - * Virtual method - * Try to initiate the communication layer and set config - */ - virtual void init() = 0; - /** * Virtual method * Build and send account registration request diff --git a/daemon/test/sflphoned-sample.yml b/daemon/test/sflphoned-sample.yml index 942b1541229737aa284302e7a7c0239b30c02b2f..3bac267c832a84b794e539dc90e7fa26c9550b35 100644 --- a/daemon/test/sflphoned-sample.yml +++ b/daemon/test/sflphoned-sample.yml @@ -1,5 +1,54 @@ --- accounts: +- alias: SFL test + codecs: 0/3/8/9/110/111/112/ + credential: + - Account.password: 1234 + Account.realm: + Account.username: sfltest + displayName: + dtmfType: overrtp + enable: false + hostname: localhost + id: Account:1334389473 + interface: default + mailbox: + port: 5060 + publishAddr: 0.0.0.0 + publishPort: 5060 + registrationexpire: 600 + ringtoneEnabled: true + ringtonePath: /usr/share/sflphone/ringtones/konga.ul + sameasLocal: true + serviceRoute: + srtp: + enable: false + keyExchange: + rtpFallback: false + stunEnabled: false + stunServer: stun.sflphone.org + tls: + calist: + certificate: + ciphers: + enable: false + method: TLSv1 + password: + privateKey: + requireCertif: true + server: + timeout: 2 + tlsPort: 5061 + verifyClient: true + verifyServer: true + type: SIP + updateContact: false + username: sfltest + zrtp: + displaySas: true + displaySasOnce: false + helloHashEnabled: true + notSuppWarning: true - alias: codecs: 0/ credential: diff --git a/gnome/src/accountlist.c b/gnome/src/accountlist.c index 2c639ce0fb962476216cb50c35811cb707ac76c5..91b649826b84b6265244fc50a6763472fbb780c7 100644 --- a/gnome/src/accountlist.c +++ b/gnome/src/accountlist.c @@ -31,7 +31,9 @@ #include <glib/gi18n.h> #include "str_utils.h" +#include "dbus.h" #include "accountlist.h" +#include "logger.h" #include "actions.h" #include "unused.h" @@ -44,7 +46,7 @@ static guint account_list_get_position(account_t *account) for (guint i = 0; i < size; i++) { account_t *tmp = account_list_get_nth(i); - if (utf8_case_cmp(tmp->accountID, account->accountID) == 0) + if (utf8_case_equal(tmp->accountID, account->accountID)) return i; } @@ -52,7 +54,6 @@ static guint account_list_get_position(account_t *account) return -1; } - /* GCompareFunc to compare a accountID (gchar* and a account_t) */ static gint is_accountID_struct(gconstpointer a, gconstpointer b) { @@ -75,6 +76,7 @@ static gint get_state_struct(gconstpointer a, gconstpointer b) void account_list_init() { + account_list_free(); accountQueue = g_queue_new(); } @@ -98,6 +100,7 @@ account_list_get_by_state(account_state_t state) account_t * account_list_get_by_id(const gchar * const accountID) { + g_assert(accountID); GList * c = g_queue_find_custom(accountQueue, accountID, is_accountID_struct); if (c) @@ -125,9 +128,7 @@ account_list_get_current() // if we are here, it means that we have at least one registered account in the list // So we get the first one - account_t *current = account_list_get_by_state(ACCOUNT_STATE_REGISTERED); - - return current; + return account_list_get_by_state(ACCOUNT_STATE_REGISTERED); } void account_list_set_current(account_t *current) @@ -146,58 +147,47 @@ void account_list_set_current(account_t *current) const gchar * account_state_name(account_state_t s) { - gchar * state; - switch (s) { case ACCOUNT_STATE_REGISTERED: - state = _("Registered"); - break; + return _("Registered"); case ACCOUNT_STATE_UNREGISTERED: - state = _("Not Registered"); - break; + return _("Not Registered"); case ACCOUNT_STATE_TRYING: - state = _("Trying..."); - break; + return _("Trying..."); case ACCOUNT_STATE_ERROR: - state = _("Error"); - break; + return _("Error"); case ACCOUNT_STATE_ERROR_AUTH: - state = _("Authentication Failed"); - break; + return _("Authentication Failed"); case ACCOUNT_STATE_ERROR_NETWORK: - state = _("Network unreachable"); - break; + return _("Network unreachable"); case ACCOUNT_STATE_ERROR_HOST: - state = _("Host unreachable"); - break; + return _("Host unreachable"); case ACCOUNT_STATE_ERROR_CONF_STUN: - state = _("Stun configuration error"); - break; + return _("Stun configuration error"); case ACCOUNT_STATE_ERROR_EXIST_STUN: - state = _("Stun server invalid"); - break; - case IP2IP_PROFILE_STATUS: - state = _("Ready"); - break; + return _("Stun server invalid"); + case ACCOUNT_STATE_IP2IP_READY: + return _("Ready"); default: - state = _("Invalid"); - break; + return _("Invalid"); } - - return state; } void account_list_free_elm(gpointer elm, gpointer data UNUSED) { account_t *a = elm; g_free(a->accountID); + a->accountID = NULL; g_free(a); } void account_list_free() { - g_queue_foreach(accountQueue, account_list_free_elm, NULL); - g_queue_free(accountQueue); + if (accountQueue) { + g_queue_foreach(accountQueue, account_list_free_elm, NULL); + g_queue_free(accountQueue); + accountQueue = NULL; + } } void @@ -224,20 +214,34 @@ account_list_get_registered_accounts(void) guint res = 0; for (guint i = 0; i < account_list_get_size(); i++) - if (account_list_get_nth(i) -> state == (ACCOUNT_STATE_REGISTERED)) + if (account_list_get_nth(i)->state == (ACCOUNT_STATE_REGISTERED)) res++; return res; } -gchar* account_list_get_current_id(void) +const gchar* account_list_get_current_id(void) { account_t *current = account_list_get_current(); if (current) return current->accountID; else - return ""; + return NULL; +} + +void account_list_remove(const gchar *accountID) +{ + account_t *target = account_list_get_by_id(accountID); + if (target) { +#if GLIB_CHECK_VERSION(2, 30, 0) + if (!g_queue_remove(accountQueue, target)) + ERROR("Could not remove account with ID %s", accountID); +#else + g_queue_remove(accountQueue, target); +#endif + } + } gchar * account_list_get_ordered_list(void) @@ -245,10 +249,8 @@ gchar * account_list_get_ordered_list(void) gchar *order = strdup(""); for (guint i = 0; i < account_list_get_size(); i++) { - account_t * account = NULL; - account = account_list_get_nth(i); - - if (account != NULL) { + account_t * account = account_list_get_nth(i); + if (account) { gchar *new_order = g_strconcat(order, account->accountID, "/", NULL); g_free(order); order = new_order; @@ -265,9 +267,9 @@ gboolean current_account_has_mailbox(void) account_t *current = account_list_get_current(); if (current) { - gchar * account_mailbox = g_hash_table_lookup(current->properties, ACCOUNT_MAILBOX); + gchar * account_mailbox = account_lookup(current, ACCOUNT_MAILBOX); - if (account_mailbox && utf8_case_cmp(account_mailbox, "") != 0) + if (account_mailbox && !utf8_case_equal(account_mailbox, "")) return TRUE; } @@ -277,7 +279,6 @@ gboolean current_account_has_mailbox(void) void current_account_set_message_number(guint nb) { account_t *current = account_list_get_current(); - if (current) current->_messages_number = nb; } @@ -285,7 +286,6 @@ void current_account_set_message_number(guint nb) guint current_account_get_message_number(void) { account_t *current = account_list_get_current(); - if (current) return current->_messages_number; else @@ -295,9 +295,77 @@ guint current_account_get_message_number(void) gboolean current_account_has_new_message(void) { account_t *current = account_list_get_current(); + return current && current->_messages_number > 0; +} - if (current) - return (current->_messages_number > 0); +gboolean account_is_IP2IP(const account_t *account) +{ + g_assert(account); + return g_strcmp0(account->accountID, IP2IP_PROFILE) == 0; +} - return FALSE; +static gboolean is_type(const account_t *account, const gchar *type) +{ + const gchar *account_type = account_lookup(account, ACCOUNT_TYPE); + return g_strcmp0(account_type, type) == 0; +} + +gboolean account_is_SIP(const account_t *account) +{ + return is_type(account, "SIP"); +} + +gboolean account_is_IAX(const account_t *account) +{ + return is_type(account, "IAX"); +} + +account_t *create_default_account() +{ + account_t *account = g_new0(account_t, 1); + account->accountID = g_strdup("new"); // FIXME: maybe replace with NULL? + account->properties = dbus_get_account_details(""); + sflphone_fill_codec_list_per_account(account); + initialize_credential_information(account); + return account; +} + +account_t *create_account_with_ID(const gchar *ID) +{ + account_t *account = g_new0(account_t, 1); + account->accountID = g_strdup(ID); + account->properties = dbus_get_account_details(ID); + sflphone_fill_codec_list_per_account(account); + initialize_credential_information(account); + return account; +} + +void initialize_credential_information(account_t *account) +{ + if (!account->credential_information) { + account->credential_information = g_ptr_array_sized_new(1); + GHashTable * new_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + g_hash_table_insert(new_table, g_strdup(ACCOUNT_REALM), g_strdup("*")); + g_hash_table_insert(new_table, g_strdup(ACCOUNT_USERNAME), g_strdup("")); + g_hash_table_insert(new_table, g_strdup(ACCOUNT_PASSWORD), g_strdup("")); + g_ptr_array_add(account->credential_information, new_table); + } +} + +void account_replace(account_t *account, const gchar *key, const gchar *value) +{ + g_assert(account && account->properties); + g_hash_table_replace(account->properties, g_strdup(key), g_strdup(value)); +} + +void account_insert(account_t *account, const gchar *key, const gchar *value) +{ + g_assert(account && account->properties); + g_hash_table_insert(account->properties, g_strdup(key), g_strdup(value)); +} + +gpointer account_lookup(const account_t *account, gconstpointer key) +{ + g_assert(account && account->properties); + return g_hash_table_lookup(account->properties, key); } diff --git a/gnome/src/accountlist.h b/gnome/src/accountlist.h index 806349eb8a50ed46831bc1470d518bc17ee26259..cad7bd9a0abad686fc87bceaf4170aed6e1de05c 100644 --- a/gnome/src/accountlist.h +++ b/gnome/src/accountlist.h @@ -29,8 +29,8 @@ * as that of the covered work. */ -#ifndef __ACCOUNTLIST_H__ -#define __ACCOUNTLIST_H__ +#ifndef ACCOUNTLIST_H__ +#define ACCOUNTLIST_H__ #include <gtk/gtk.h> /** @file accountlist.h @@ -41,14 +41,12 @@ * This enum have all the states an account can take. */ typedef enum { - /** Invalid state */ - ACCOUNT_STATE_INVALID = 0, - /** The account is registered */ - ACCOUNT_STATE_REGISTERED, /** The account is not registered */ ACCOUNT_STATE_UNREGISTERED, /** The account is trying to register */ ACCOUNT_STATE_TRYING, + /** The account is registered */ + ACCOUNT_STATE_REGISTERED, /** Error state. The account is not registered */ ACCOUNT_STATE_ERROR, /** An authentification error occured. Wrong password or wrong username. The account is not registered */ @@ -57,12 +55,14 @@ typedef enum { ACCOUNT_STATE_ERROR_NETWORK, /** Host is unreachable. The account is not registered */ ACCOUNT_STATE_ERROR_HOST, - /** Stun server configuration error. The account is not registered */ - ACCOUNT_STATE_ERROR_CONF_STUN, /** Stun server is not existing. The account is not registered */ ACCOUNT_STATE_ERROR_EXIST_STUN, - /** IP profile status **/ - IP2IP_PROFILE_STATUS + /** Stun server configuration error. The account is not registered */ + ACCOUNT_STATE_ERROR_CONF_STUN, + /** IP2IP Account is always ready */ + ACCOUNT_STATE_IP2IP_READY, + /** Invalid state */ + ACCOUNT_STATE_INVALID } account_state_t; /** @struct account_t @@ -172,7 +172,7 @@ void account_list_move_down(guint index); * Return the ID of the current default account * @return gchar* The id */ -gchar* account_list_get_current_id(void); +const gchar* account_list_get_current_id (void); gchar * account_list_get_ordered_list(void); @@ -184,4 +184,18 @@ void current_account_set_message_number(guint nb); gboolean current_account_has_new_message(void); +gboolean account_is_IP2IP(const account_t *account); +gboolean account_is_SIP(const account_t *account); +gboolean account_is_IAX(const account_t *account); + +account_t *create_default_account(); +account_t *create_account_with_ID(const gchar *ID); + +void initialize_credential_information(account_t *account); + +void account_replace(account_t *account, const gchar *key, const gchar *value); +void account_insert(account_t *account, const gchar *key, const gchar *value); +gpointer account_lookup(const account_t *account, gconstpointer key); +void account_list_remove(const gchar *accountID); + #endif diff --git a/gnome/src/actions.c b/gnome/src/actions.c index 108d4f41cfe1abbb935d7f6de18d906fb951017b..491481c0daf70e11c5edfb039fc2e7e8a7fb2d2d 100644 --- a/gnome/src/actions.c +++ b/gnome/src/actions.c @@ -82,7 +82,8 @@ sflphone_notify_voice_mail(const gchar* accountID , guint count) DEBUG("sflphone_notify_voice_mail begin"); - if (g_ascii_strcasecmp(id, current_id) != 0 || account_list_get_size() == 0) + if (g_ascii_strcasecmp(id, current_id) != 0 || + account_list_get_size() == 0) return; // Set the number of voice messages for the current account @@ -107,7 +108,7 @@ sflphone_notify_voice_mail(const gchar* accountID , guint count) static gboolean is_direct_call(callable_obj_t * c) { - if (utf8_case_cmp(c->_accountID, "empty") == 0) { + if (utf8_case_equal(c->_accountID, "empty")) { if (!g_str_has_prefix(c->_peer_number, "sip:")) { gchar * new_number = g_strconcat("sip:", c->_peer_number, NULL); g_free(c->_peer_number); @@ -125,18 +126,17 @@ static gboolean is_direct_call(callable_obj_t * c) void status_bar_display_account() { - gchar* msg; - statusbar_pop_message(__MSG_ACCOUNT_DEFAULT); account_t *acc = account_list_get_current(); status_tray_icon_online(acc != NULL); + gchar* msg; if (acc) { msg = g_markup_printf_escaped("%s %s (%s)" , _("Using account"), - (gchar*) g_hash_table_lookup(acc->properties, ACCOUNT_ALIAS), - (gchar*) g_hash_table_lookup(acc->properties, ACCOUNT_TYPE)); + (gchar*) account_lookup(acc, ACCOUNT_ALIAS), + (gchar*) account_lookup(acc, ACCOUNT_TYPE)); } else { msg = g_markup_printf_escaped(_("No registered accounts")); } @@ -205,85 +205,56 @@ sflphone_hung_up(callable_obj_t * c) statusbar_update_clock(""); } -/** Internal to actions: Fill account list */ void sflphone_fill_account_list(void) { - int count = current_account_get_message_number(); - - account_list_free(); account_list_init(); - gchar **array = dbus_account_list(); - if (array) { - for (gchar **accountID = array; accountID && *accountID; accountID++) { - account_t * a = g_new0(account_t, 1); - a->accountID = g_strdup(*accountID); - a->credential_information = NULL; - account_list_add(a); - } - - g_strfreev(array); - } - - for (unsigned i = 0; i < account_list_get_size(); i++) { - account_t * a = account_list_get_nth(i); - - if (a == NULL) { - ERROR("SFLphone: Error: Could not find account %d in list", i); + for (gchar **accountID = array; accountID && *accountID; ++accountID) { + account_t *acc = create_account_with_ID(*accountID); + if (acc->properties == NULL) { + ERROR("SFLphone: Error: Could not fetch details for account %s", + accountID); break; } - - GHashTable * details = (GHashTable *) dbus_get_account_details(a->accountID); - - if (details == NULL) { - ERROR("SFLphone: Error: Could not fetch detais for account %s", a->accountID); - break; - } - - a->properties = details; - + account_list_add(acc); /* Fill the actual array of credentials */ - dbus_get_credentials(a); - - gchar * status = g_hash_table_lookup(details, REGISTRATION_STATUS); + dbus_get_credentials(acc); + gchar * status = account_lookup(acc, REGISTRATION_STATUS); if (g_strcmp0(status, "REGISTERED") == 0) - a->state = ACCOUNT_STATE_REGISTERED; + acc->state = ACCOUNT_STATE_REGISTERED; else if (g_strcmp0(status, "UNREGISTERED") == 0) - a->state = ACCOUNT_STATE_UNREGISTERED; + acc->state = ACCOUNT_STATE_UNREGISTERED; else if (g_strcmp0(status, "TRYING") == 0) - a->state = ACCOUNT_STATE_TRYING; + acc->state = ACCOUNT_STATE_TRYING; else if (g_strcmp0(status, "ERROR") == 0) - a->state = ACCOUNT_STATE_ERROR; + acc->state = ACCOUNT_STATE_ERROR; else if (g_strcmp0(status , "ERROR_AUTH") == 0) - a->state = ACCOUNT_STATE_ERROR_AUTH; + acc->state = ACCOUNT_STATE_ERROR_AUTH; else if (g_strcmp0(status , "ERROR_NETWORK") == 0) - a->state = ACCOUNT_STATE_ERROR_NETWORK; + acc->state = ACCOUNT_STATE_ERROR_NETWORK; else if (g_strcmp0(status , "ERROR_HOST") == 0) - a->state = ACCOUNT_STATE_ERROR_HOST; + acc->state = ACCOUNT_STATE_ERROR_HOST; else if (g_strcmp0(status , "ERROR_CONF_STUN") == 0) - a->state = ACCOUNT_STATE_ERROR_CONF_STUN; + acc->state = ACCOUNT_STATE_ERROR_CONF_STUN; else if (g_strcmp0(status , "ERROR_EXIST_STUN") == 0) - a->state = ACCOUNT_STATE_ERROR_EXIST_STUN; - else if (g_strcmp0(status, "READY") == 0) - a->state = IP2IP_PROFILE_STATUS; + acc->state = ACCOUNT_STATE_ERROR_EXIST_STUN; + else if (g_strcmp0(status , "ACCOUNT_STATE_IP2IP_READY") == 0) + acc->state = ACCOUNT_STATE_IP2IP_READY; else - a->state = ACCOUNT_STATE_INVALID; - - gchar * code = g_hash_table_lookup(details, REGISTRATION_STATE_CODE); + acc->state = ACCOUNT_STATE_INVALID; + gchar * code = account_lookup(acc, REGISTRATION_STATE_CODE); if (code != NULL) - a->protocol_state_code = atoi(code); - - g_free(a->protocol_state_description); - a->protocol_state_description = g_hash_table_lookup(details, REGISTRATION_STATE_DESCRIPTION); + acc->protocol_state_code = atoi(code); + acc->protocol_state_description = account_lookup(acc, REGISTRATION_STATE_DESCRIPTION); } - // Set the current account message number - current_account_set_message_number(count); + g_strfreev(array); - sflphone_fill_codec_list(); + // Set the current account message number + current_account_set_message_number(current_account_get_message_number()); } gboolean sflphone_init(GError **error) @@ -300,13 +271,6 @@ gboolean sflphone_init(GError **error) contacts_tab = calltab_init(TRUE, CONTACTS); history_tab = calltab_init(TRUE, HISTORY); - account_list_init (); - if (!codecs_load()) { - ERROR ("No codecs found"); - dbus_unregister(getpid()); - exit(EXIT_FAILURE); - } - conferencelist_init(current_calls_tab); // Fetch the configured accounts @@ -821,7 +785,7 @@ static int place_registered_call(callable_obj_t * c) } gpointer status = g_hash_table_lookup(current->properties, "Status"); - if (status && utf8_case_cmp(status, "REGISTERED") == 0) { + if (utf8_case_equal(status, "REGISTERED")) { /* The call is made with the current account */ // free memory for previous account id and get a new one g_free(c->_accountID); @@ -967,16 +931,6 @@ sflphone_mute_call() toggle_slider_mute_microphone(); } -void sflphone_fill_codec_list() -{ - guint account_list_size = account_list_get_size (); - for (guint i = 0; i < account_list_size; i++) { - account_t *current = account_list_get_nth(i); - if (current) - sflphone_fill_codec_list_per_account(current); - } -} - #ifdef SFL_VIDEO static void sflphone_fill_video_codec_list_per_account(account_t *account) diff --git a/gnome/src/actions.h b/gnome/src/actions.h index 145ba402505d43bfdbfa9c2c7a424af1e0cca032..4c3899836a2eab2e4140838b0a0344db18677391 100644 --- a/gnome/src/actions.h +++ b/gnome/src/actions.h @@ -52,27 +52,27 @@ * Initialize lists and configurations * @return TRUE if succeeded, FALSE otherwise */ -gboolean sflphone_init () ; +gboolean sflphone_init(); /** * Steps when closing the application. Will ask for confirmation if a call is in progress. */ -void sflphone_quit () ; +void sflphone_quit(); /** * Hang up / refuse the current call */ -void sflphone_hang_up (); +void sflphone_hang_up(); /** * Put the selected call on hold */ -void sflphone_on_hold (); +void sflphone_on_hold(); /** * Put the selected call off hold */ -void sflphone_off_hold (); +void sflphone_off_hold(); /** * Open a new call @@ -85,7 +85,7 @@ callable_obj_t * sflphone_new_call(); * @param accountID The account the voice mails are for * @param count The number of voice mails */ -void sflphone_notify_voice_mail (const gchar* accountID , guint count); +void sflphone_notify_voice_mail(const gchar* accountID, guint count); /** * Prepare SFLphone to transfer a call and wait for the user to dial the number to transfer to @@ -101,49 +101,49 @@ void sflphone_unset_transfer(); /** * Accept / dial the current call */ -void sflphone_pick_up (); +void sflphone_pick_up(); /** * Put the call on hold state * @param c The current call */ -void sflphone_hold (callable_obj_t * c); +void sflphone_hold(callable_obj_t * c); /** * Put the call in Ringing state * @param c* The current call */ -void sflphone_ringing (callable_obj_t * c); +void sflphone_ringing(callable_obj_t * c); /** * Put the call in Busy state * @param c* The current call */ -void sflphone_busy (callable_obj_t * c); +void sflphone_busy(callable_obj_t * c); /** * Put the call in Failure state * @param c* The current call */ -void sflphone_fail (callable_obj_t * c); +void sflphone_fail(callable_obj_t * c); /** * Put the call in Current state * @param c The current call */ -void sflphone_current (callable_obj_t * c); +void sflphone_current(callable_obj_t * c); /** * The callee has hung up * @param c The current call */ -void sflphone_hung_up (callable_obj_t * c); +void sflphone_hung_up(callable_obj_t * c); /** * Incoming call * @param c The incoming call */ -void sflphone_incoming_call (callable_obj_t * c); +void sflphone_incoming_call(callable_obj_t * c); /** * Dial the number @@ -151,19 +151,19 @@ void sflphone_incoming_call (callable_obj_t * c); * @param keyval The unique int representing the key * @param key The char value of the key */ -void sflphone_keypad (guint keyval, gchar * key); +void sflphone_keypad(guint keyval, gchar * key); /** * Place a call with a filled callable_obj_t.to * @param c A call in CALL_STATE_DIALING state */ -void sflphone_place_call (callable_obj_t * c); +void sflphone_place_call(callable_obj_t * c); /** * Fetch the ip2ip profile through dbus and fill * the internal hash table. */ -void sflphone_fill_ip2ip_profile (void); +void sflphone_fill_ip2ip_profile(void); /** * @return The internal hash table representing @@ -172,53 +172,52 @@ void sflphone_fill_ip2ip_profile (void); GHashTable *sflphone_get_ip2ip_properties(void); /** - * Initialize the accounts data structure + * Get a list of accounts from the daemon and load them into account_t + * structures. */ -void sflphone_fill_account_list (); +void sflphone_fill_account_list(); -void sflphone_fill_call_list (void); +void sflphone_fill_call_list(void); /** * Set an account as current. The current account is to one used to place calls with by default - * The current account is the first in the account list ( index 0 ) + * The current account is the first in the account list( index 0 ) */ void sflphone_set_current_account(); /** * Initialialize the codecs data structure */ -void sflphone_fill_codec_list (); - -void sflphone_fill_codec_list_per_account (account_t *); +void sflphone_fill_codec_list_per_account(account_t *); void sflphone_add_participant(); -void sflphone_record (callable_obj_t *c); +void sflphone_record(callable_obj_t *c); -void sflphone_rec_call (void); +void sflphone_rec_call(void); -void sflphone_mute_call (void); +void sflphone_mute_call(void); -void status_bar_display_account (); +void status_bar_display_account(); -void sflphone_fill_history (void); +void sflphone_fill_history(void); /** * Action called when a new participant is dragged in */ -void sflphone_add_participant (const gchar* callID, const gchar* confID); +void sflphone_add_participant(const gchar* callID, const gchar* confID); /** * Action called when a conference participant is draged out */ -void sflphone_detach_participant (const gchar* callID); +void sflphone_detach_participant(const gchar* callID); /** * Nofity that the communication is * now secured using SRTP/SDES. * @param c* The current call */ -void sflphone_srtp_sdes_on (callable_obj_t * c); +void sflphone_srtp_sdes_on(callable_obj_t * c); /** * Notify that the SRTP/SDES session @@ -230,14 +229,14 @@ void sflphone_srtp_sdes_on (callable_obj_t * c); * now secured using ZRTP. * @param c* The current call */ -void sflphone_srtp_zrtp_on (callable_obj_t * c); +void sflphone_srtp_zrtp_on(callable_obj_t * c); /** * Called when the ZRTP session goes * unsecured. * @param c* The current call */ -void sflphone_srtp_zrtp_off (callable_obj_t * c); +void sflphone_srtp_zrtp_off(callable_obj_t * c); /** * Called when the sas has been computed @@ -246,13 +245,14 @@ void sflphone_srtp_zrtp_off (callable_obj_t * c); * @param sas* The Short Authentication String * @param verified* Weather the SAS was confirmed or not. */ -void sflphone_srtp_zrtp_show_sas (callable_obj_t * c, const gchar* sas, const gboolean verified); +void sflphone_srtp_zrtp_show_sas(callable_obj_t * c, const gchar* sas, const gboolean verified); /** * Called when user wants to clear. * @param c* The call on which to go clear */ -void sflphone_request_go_clear (void); + +void sflphone_request_go_clear(void); /** * Called when the UI needs to be refreshed to @@ -262,12 +262,12 @@ void sflphone_request_go_clear (void); * @param description A textual description of the code * @param code The status code as in SIP or IAX */ -void sflphone_call_state_changed (callable_obj_t * c, const gchar * description, const guint code); +void sflphone_call_state_changed(callable_obj_t * c, const gchar * description, const guint code); -void sflphone_add_main_participant (const conference_obj_t * c); +void sflphone_add_main_participant(const conference_obj_t * c); -void sflphone_srtp_sdes_off (callable_obj_t * c); +void sflphone_srtp_sdes_off(callable_obj_t * c); -void sflphone_fill_conference_list (void); +void sflphone_fill_conference_list(void); #endif diff --git a/gnome/src/callable_obj.c b/gnome/src/callable_obj.c index 10011287e0729052ec63d2dfc456631b86b8607c..61a009ab6a2b461100f87e559d7a2b5f1f319325 100644 --- a/gnome/src/callable_obj.c +++ b/gnome/src/callable_obj.c @@ -142,15 +142,15 @@ callable_obj_t *create_new_call_from_details(const gchar *call_id, GHashTable *d const gchar * const display_name = g_hash_table_lookup(details, "DISPLAY_NAME"); const gchar * const state_str = g_hash_table_lookup(details, "CALL_STATE"); - if (utf8_case_cmp(state_str, "CURRENT") == 0) + if (utf8_case_equal(state_str, "CURRENT")) state = CALL_STATE_CURRENT; - else if (utf8_case_cmp(state_str, "RINGING") == 0) + else if (utf8_case_equal(state_str, "RINGING")) state = CALL_STATE_RINGING; - else if (utf8_case_cmp(state_str, "INCOMING") == 0) + else if (utf8_case_equal(state_str, "INCOMING")) state = CALL_STATE_INCOMING; - else if (utf8_case_cmp(state_str, "HOLD") == 0) + else if (utf8_case_equal(state_str, "HOLD")) state = CALL_STATE_HOLD; - else if (utf8_case_cmp(state_str, "BUSY") == 0) + else if (utf8_case_equal(state_str, "BUSY")) state = CALL_STATE_BUSY; else state = CALL_STATE_FAILURE; diff --git a/gnome/src/codeclist.c b/gnome/src/codeclist.c index aa47f3355649126aa9484796f3be00e0c52f7648..37d966563dcb99b23d60af190d181c6ecf65ff1c 100644 --- a/gnome/src/codeclist.c +++ b/gnome/src/codeclist.c @@ -197,7 +197,7 @@ void codec_list_move(guint codec_index, GQueue *q, gboolean up) /* FIXME:tmatth: Clean this up, shouldn't have to do all the reallocs * explicitly if we use a nicer data structure */ static void -codec_list_update_to_daemon_audio(account_t *acc) +codec_list_update_to_daemon_audio(const account_t *acc) { guint c = 0; @@ -228,7 +228,7 @@ codec_list_update_to_daemon_audio(account_t *acc) } #ifdef SFL_VIDEO -static void codec_list_update_to_daemon_video(account_t *acc) +static void codec_list_update_to_daemon_video(const account_t *acc) { gchar** codecList = NULL; // Get all codecs in queue @@ -259,7 +259,7 @@ static void codec_list_update_to_daemon_video(account_t *acc) } #endif -void codec_list_update_to_daemon(account_t *acc) +void codec_list_update_to_daemon(const account_t *acc) { codec_list_update_to_daemon_audio(acc); #ifdef SFL_VIDEO diff --git a/gnome/src/codeclist.h b/gnome/src/codeclist.h index fcc3d726ecf188cdf88445877dbf3f2e4cb3bea7..7aafef3dd25c07295814e9160ca4e7e376fbeb5f 100644 --- a/gnome/src/codeclist.h +++ b/gnome/src/codeclist.h @@ -90,7 +90,7 @@ void codec_list_move(guint index, GQueue *q, gboolean up); /** * Notify modifications on codecs to the server */ -void codec_list_update_to_daemon(account_t *acc); +void codec_list_update_to_daemon(const account_t *acc); codec_t* codec_list_get_by_payload(gint payload, GQueue *q); diff --git a/gnome/src/conference_obj.c b/gnome/src/conference_obj.c index f91617458266d8171cd8e405610f45b15bd4d85b..84ecb0348f8b8c9af9233814771d725d1cda4d65 100644 --- a/gnome/src/conference_obj.c +++ b/gnome/src/conference_obj.c @@ -81,17 +81,17 @@ conference_obj_t *create_new_conference_from_details(const gchar *conf_id, GHash gchar *state_str = g_hash_table_lookup(details, "CONF_STATE"); - if (utf8_case_cmp(state_str, "ACTIVE_ATTACHED") == 0) + if (utf8_case_equal(state_str, "ACTIVE_ATTACHED")) new_conf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED; - else if (utf8_case_cmp(state_str, "ACTIVE_ATTACHED_REC") == 0) + else if (utf8_case_equal(state_str, "ACTIVE_ATTACHED_REC")) new_conf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD; - else if (utf8_case_cmp(state_str, "ACTIVE_DETACHED") == 0) + else if (utf8_case_equal(state_str, "ACTIVE_DETACHED")) new_conf->_state = CONFERENCE_STATE_ACTIVE_DETACHED; - else if (utf8_case_cmp(state_str, "ACTIVE_DETACHED_REC") == 0) + else if (utf8_case_equal(state_str, "ACTIVE_DETACHED_REC")) new_conf->_state = CONFERENCE_STATE_ACTIVE_DETACHED_RECORD; - else if (utf8_case_cmp(state_str, "HOLD") == 0) + else if (utf8_case_equal(state_str, "HOLD")) new_conf->_state = CONFERENCE_STATE_HOLD; - else if (utf8_case_cmp(state_str, "HOLD_REC") == 0) + else if (utf8_case_equal(state_str, "HOLD_REC")) new_conf->_state = CONFERENCE_STATE_HOLD_RECORD; return new_conf; diff --git a/gnome/src/config/accountconfigdialog.c b/gnome/src/config/accountconfigdialog.c index e722f2893ea08f8780ec510894c07d73edf38a71..c5562d3fb0b78b5ccb73a9b738bb350e4e7687fb 100644 --- a/gnome/src/config/accountconfigdialog.c +++ b/gnome/src/config/accountconfigdialog.c @@ -64,42 +64,38 @@ * in a private structure. * Local variables */ -static GtkWidget * entryAlias; -static GtkWidget * protocolComboBox; -static GtkWidget * entryUsername; -static GtkWidget * entryRouteSet; -static GtkWidget * entryHostname; -static GtkWidget * entryPassword; -static GtkWidget * entryMailbox; -static GtkWidget * entryUseragent; -static GtkWidget * entryResolveNameOnlyOnce; -static GtkWidget * expireSpinBox; -static GtkListStore * credentialStore; -static GtkWidget * deleteCredButton; -static GtkWidget * treeViewCredential; -static GtkWidget * advancedZrtpButton; -static GtkWidget * keyExchangeCombo; -static GtkWidget * useSipTlsCheckBox; - -static GtkWidget * localAddressEntry; -static GtkWidget * publishedAddressEntry; -static GtkWidget * localAddressCombo; -static GtkWidget * useStunCheckBox; -static GtkWidget * sameAsLocalRadioButton; -static GtkWidget * publishedAddrRadioButton; -static GtkWidget * publishedPortSpinBox; -static GtkWidget * localPortSpinBox; -static GtkWidget * publishedAddressLabel; -static GtkWidget * publishedPortLabel; -static GtkWidget * stunServerLabel; -static GtkWidget * stunServerEntry; -static GtkWidget * enableTone; -static GtkWidget * fileChooser; - -static GtkWidget * security_tab; -static GtkWidget * advanced_tab; - -static GtkWidget * overrtp; +static GtkWidget *entry_alias; +static GtkWidget *protocol_combo; +static GtkWidget *entry_username; +static GtkWidget *entry_route_set; +static GtkWidget *entry_hostname; +static GtkWidget *entry_password; +static GtkWidget *entry_mailbox; +static GtkWidget *entry_user_agent; +static GtkWidget *expire_spin_box; +static GtkListStore *credential_store; +static GtkWidget *delete_cred_button; +static GtkWidget *treeview_credential; +static GtkWidget *zrtp_button; +static GtkWidget *key_exchange_combo; +static GtkWidget *use_sip_tls_check_box; +static GtkWidget *local_address_entry; +static GtkWidget *published_address_entry; +static GtkWidget *local_address_combo; +static GtkWidget *use_stun_check_box; +static GtkWidget *same_as_local_radio_button; +static GtkWidget *published_addr_radio_button; +static GtkWidget *published_port_spin_box; +static GtkWidget *local_port_spin_box; +static GtkWidget *published_address_label; +static GtkWidget *published_port_label; +static GtkWidget *stun_server_label; +static GtkWidget *stun_server_entry; +static GtkWidget *enable_tone; +static GtkWidget *file_chooser; +static GtkWidget *security_tab; +static GtkWidget *advanced_tab; +static GtkWidget *overrtp; // Credentials enum { @@ -116,13 +112,13 @@ enum { */ static void reset() { - entryAlias = NULL; - protocolComboBox = NULL; - entryHostname = NULL; - entryUsername = NULL; - entryPassword = NULL; - entryUseragent = NULL; - entryMailbox = NULL; + entry_alias = NULL; + protocol_combo = NULL; + entry_hostname = NULL; + entry_username = NULL; + entry_password = NULL; + entry_user_agent = NULL; + entry_mailbox = NULL; } /* @@ -133,14 +129,14 @@ static void show_password_cb(GtkWidget *widget UNUSED, gpointer data) gtk_entry_set_visibility(GTK_ENTRY(data), !gtk_entry_get_visibility(GTK_ENTRY(data))); } -/* Signal to protocolComboBox 'changed' */ -void change_protocol_cb(account_t *currentAccount UNUSED) +/* Signal to protocol_combo 'changed' */ +void change_protocol_cb() { - gchar *protocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocolComboBox)); + gchar *protocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocol_combo)); // Only if tabs are not NULL if (security_tab && advanced_tab) { - if (utf8_case_cmp(protocol, "IAX") == 0) { + if (utf8_case_equal(protocol, "IAX")) { gtk_widget_hide(security_tab); gtk_widget_hide(advanced_tab); } else { @@ -161,22 +157,20 @@ select_dtmf_type(void) DEBUG("Selected DTMF over SIP"); } -static GPtrArray* getNewCredential(void) +static GPtrArray* get_new_credential(void) { - GtkTreeIter iter; gint row_count = 0; GPtrArray *credential_array = g_ptr_array_new(); - gboolean valid; - - for (valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(credentialStore), &iter) ; - valid; - valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(credentialStore), &iter)) { + GtkTreeIter iter; + for (gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(credential_store), &iter); + valid; + valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(credential_store), &iter)) { gchar *username; gchar *realm; gchar *password; - gtk_tree_model_get(GTK_TREE_MODEL(credentialStore), &iter, + gtk_tree_model_get(GTK_TREE_MODEL(credential_store), &iter, COLUMN_CREDENTIAL_REALM, &realm, COLUMN_CREDENTIAL_USERNAME, &username, COLUMN_CREDENTIAL_PASSWORD, &password, @@ -184,7 +178,8 @@ static GPtrArray* getNewCredential(void) DEBUG("Row %d: %s %s %s", row_count++, username, password, realm); - GHashTable * new_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + GHashTable * new_table = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); g_hash_table_insert(new_table, g_strdup(ACCOUNT_REALM), realm); g_hash_table_insert(new_table, g_strdup(ACCOUNT_USERNAME), username); g_hash_table_insert(new_table, g_strdup(ACCOUNT_PASSWORD), password); @@ -199,53 +194,36 @@ static void update_credential_cb(GtkWidget *widget, gpointer data UNUSED) { GtkTreeIter iter; - if (credentialStore && gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(credentialStore), &iter, "0")) { + if (credential_store && gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(credential_store), &iter, "0")) { gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "column")); - gtk_list_store_set(GTK_LIST_STORE(credentialStore), &iter, column,(gchar *) gtk_entry_get_text(GTK_ENTRY(widget)), -1); + gtk_list_store_set(GTK_LIST_STORE(credential_store), &iter, column, gtk_entry_get_text(GTK_ENTRY(widget)), -1); } } -static GtkWidget* create_basic_tab(account_t *currentAccount) +static GtkWidget* create_basic_tab(const account_t *account) { - g_assert(currentAccount); - - // Load from SIP/IAX/Unknown ? - gchar *curAccountType = g_hash_table_lookup(currentAccount->properties, ACCOUNT_TYPE); - gchar *curAlias = g_hash_table_lookup(currentAccount->properties, ACCOUNT_ALIAS); - gchar *curHostname = g_hash_table_lookup(currentAccount->properties, ACCOUNT_HOSTNAME); - gchar *curPassword; - gchar *curUsername; - gchar *curUseragent; - gchar *curRouteSet; - gchar *curMailbox; - - if (g_strcmp0(curAccountType, "SIP") == 0) { + g_assert(account); + gchar *password = NULL; + if (account_is_SIP(account)) { /* get password from credentials list */ - if (currentAccount->credential_information) { - GHashTable * element = g_ptr_array_index(currentAccount->credential_information, 0); - curPassword = g_hash_table_lookup(element, ACCOUNT_PASSWORD); - } else - curPassword = ""; + if (account->credential_information) { + GHashTable * element = g_ptr_array_index(account->credential_information, 0); + password = g_hash_table_lookup(element, ACCOUNT_PASSWORD); + } } else - curPassword = g_hash_table_lookup(currentAccount->properties, ACCOUNT_PASSWORD); - - curUsername = g_hash_table_lookup(currentAccount->properties, ACCOUNT_USERNAME); - curRouteSet = g_hash_table_lookup(currentAccount->properties, ACCOUNT_ROUTE); - curMailbox = g_hash_table_lookup(currentAccount->properties, ACCOUNT_MAILBOX); - curMailbox = curMailbox != NULL ? curMailbox : ""; - curUseragent = g_hash_table_lookup(currentAccount->properties, ACCOUNT_USERAGENT); + password = account_lookup(account, ACCOUNT_PASSWORD); GtkWidget *frame = gnome_main_section_new(_("Account Parameters")); gtk_widget_show(frame); - GtkWidget * table = NULL; + GtkWidget *table = NULL; - if (g_strcmp0(curAccountType, "SIP") == 0) - table = gtk_table_new(9, 2, FALSE/* homogeneous */); - else if (g_strcmp0(curAccountType, "IAX") == 0) + if (account_is_SIP(account)) + table = gtk_table_new(9, 2, FALSE /* homogeneous */); + else if (account_is_IAX(account)) table = gtk_table_new(8, 2, FALSE); else { - ERROR("Unknown account type \"%s\"", curAccountType); + ERROR("Unknown account type"); return NULL; } @@ -256,113 +234,137 @@ static GtkWidget* create_basic_tab(account_t *currentAccount) GtkWidget *label = gtk_label_new_with_mnemonic(_("_Alias")); gint row = 0; - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryAlias = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryAlias); - gtk_entry_set_text(GTK_ENTRY(entryAlias), curAlias); - gtk_table_attach(GTK_TABLE(table), entryAlias, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entry_alias = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_alias); + gchar *alias = account_lookup(account, ACCOUNT_ALIAS); + gtk_entry_set_text(GTK_ENTRY(entry_alias), alias); + gtk_table_attach(GTK_TABLE(table), entry_alias, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Protocol")); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - protocolComboBox = gtk_combo_box_text_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), protocolComboBox); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocolComboBox), "SIP"); + protocol_combo = gtk_combo_box_text_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), protocol_combo); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocol_combo), "SIP"); if (dbus_is_iax2_enabled()) - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocolComboBox), "IAX"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocol_combo), "IAX"); - if (g_strcmp0(curAccountType, "SIP") == 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(protocolComboBox),0); - else if (g_strcmp0(curAccountType, "IAX") == 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(protocolComboBox),1); + if (account_is_SIP(account)) + gtk_combo_box_set_active(GTK_COMBO_BOX(protocol_combo), 0); + else if (account_is_IAX(account)) + gtk_combo_box_set_active(GTK_COMBO_BOX(protocol_combo), 1); else { DEBUG("Config: Error: Account protocol not valid"); /* Should never come here, add debug message. */ - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocolComboBox), _("Unknown")); - gtk_combo_box_set_active(GTK_COMBO_BOX(protocolComboBox), 2); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(protocol_combo), _("Unknown")); + gtk_combo_box_set_active(GTK_COMBO_BOX(protocol_combo), 2); } - gtk_table_attach(GTK_TABLE(table), protocolComboBox, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), protocol_combo, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); /* Link signal 'changed' */ - g_signal_connect(G_OBJECT(GTK_COMBO_BOX(protocolComboBox)), "changed", - G_CALLBACK(change_protocol_cb), - currentAccount); + g_signal_connect(G_OBJECT(GTK_COMBO_BOX(protocol_combo)), "changed", + G_CALLBACK(change_protocol_cb), NULL); row++; label = gtk_label_new_with_mnemonic(_("_Host name")); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryHostname = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryHostname); - gtk_entry_set_text(GTK_ENTRY(entryHostname), curHostname); - gtk_table_attach(GTK_TABLE(table), entryHostname, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entry_hostname = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_hostname); + const gchar *hostname = account_lookup(account, ACCOUNT_HOSTNAME); + gtk_entry_set_text(GTK_ENTRY(entry_hostname), hostname); + gtk_table_attach(GTK_TABLE(table), entry_hostname, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_User name")); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryUsername = gtk_entry_new(); - gtk_entry_set_icon_from_pixbuf(GTK_ENTRY(entryUsername), GTK_ENTRY_ICON_PRIMARY, gdk_pixbuf_new_from_file(ICONS_DIR "/stock_person.svg", NULL)); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryUsername); - gtk_entry_set_text(GTK_ENTRY(entryUsername), curUsername); - gtk_table_attach(GTK_TABLE(table), entryUsername, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - if (g_strcmp0(curAccountType, "SIP") == 0) { - g_signal_connect(G_OBJECT(entryUsername), "changed", G_CALLBACK(update_credential_cb), NULL); - g_object_set_data(G_OBJECT(entryUsername), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_USERNAME)); + entry_username = gtk_entry_new(); + const gchar *PERSON_IMG = ICONS_DIR "/stock_person.svg"; + gtk_entry_set_icon_from_pixbuf(GTK_ENTRY(entry_username), + GTK_ENTRY_ICON_PRIMARY, + gdk_pixbuf_new_from_file(PERSON_IMG, NULL)); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_username); + gchar *username = account_lookup(account, ACCOUNT_USERNAME); + gtk_entry_set_text(GTK_ENTRY(entry_username), username); + gtk_table_attach(GTK_TABLE(table), entry_username, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + + if (account_is_SIP(account)) { + g_signal_connect(G_OBJECT(entry_username), "changed", + G_CALLBACK(update_credential_cb), NULL); + g_object_set_data(G_OBJECT(entry_username), "column", + GINT_TO_POINTER(COLUMN_CREDENTIAL_USERNAME)); } row++; label = gtk_label_new_with_mnemonic(_("_Password")); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryPassword = gtk_entry_new(); - gtk_entry_set_icon_from_stock(GTK_ENTRY(entryPassword), GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_DIALOG_AUTHENTICATION); - gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryPassword); - gtk_entry_set_text(GTK_ENTRY(entryPassword), curPassword); - gtk_table_attach(GTK_TABLE(table), entryPassword, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - if (g_strcmp0(curAccountType, "SIP") == 0) { - g_signal_connect(G_OBJECT(entryPassword), "changed", G_CALLBACK(update_credential_cb), NULL); - g_object_set_data(G_OBJECT(entryPassword), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_PASSWORD)); + entry_password = gtk_entry_new(); + gtk_entry_set_icon_from_stock(GTK_ENTRY(entry_password), + GTK_ENTRY_ICON_PRIMARY, + GTK_STOCK_DIALOG_AUTHENTICATION); + gtk_entry_set_visibility(GTK_ENTRY(entry_password), FALSE); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_password); + password = password ? password : ""; + gtk_entry_set_text(GTK_ENTRY(entry_password), password); + gtk_table_attach(GTK_TABLE(table), entry_password, 1, 2, row, row + 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + + if (account_is_SIP(account)) { + g_signal_connect(G_OBJECT(entry_password), "changed", G_CALLBACK(update_credential_cb), NULL); + g_object_set_data(G_OBJECT(entry_password), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_PASSWORD)); } row++; - GtkWidget *clearTextCheckbox = gtk_check_button_new_with_mnemonic(_("Show password")); - g_signal_connect(clearTextCheckbox, "toggled", G_CALLBACK(show_password_cb), entryPassword); - gtk_table_attach(GTK_TABLE(table), clearTextCheckbox, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + GtkWidget *clearTextcheck_box = gtk_check_button_new_with_mnemonic(_("Show password")); + g_signal_connect(clearTextcheck_box, "toggled", G_CALLBACK(show_password_cb), entry_password); + gtk_table_attach(GTK_TABLE(table), clearTextcheck_box, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Proxy")); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryRouteSet = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryRouteSet); - gtk_entry_set_text(GTK_ENTRY(entryRouteSet), curRouteSet); - gtk_table_attach(GTK_TABLE(table), entryRouteSet, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entry_route_set = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_route_set); + gchar *route_set = account_lookup(account, ACCOUNT_ROUTE); + gtk_entry_set_text(GTK_ENTRY(entry_route_set), route_set); + gtk_table_attach(GTK_TABLE(table), entry_route_set, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Voicemail number")); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryMailbox = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryMailbox); - gtk_entry_set_text(GTK_ENTRY(entryMailbox), curMailbox); - gtk_table_attach(GTK_TABLE(table), entryMailbox, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entry_mailbox = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_mailbox); + gchar *mailbox = account_lookup(account, ACCOUNT_MAILBOX); + mailbox = mailbox ? mailbox : ""; + gtk_entry_set_text(GTK_ENTRY(entry_mailbox), mailbox); + gtk_table_attach(GTK_TABLE(table), entry_mailbox, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_User-agent")); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entryUseragent = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), entryUseragent); - gtk_entry_set_text(GTK_ENTRY(entryUseragent), curUseragent); - gtk_table_attach(GTK_TABLE(table), entryUseragent, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + entry_user_agent = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry_user_agent); + gchar *user_agent = account_lookup(account, ACCOUNT_USERAGENT); + gtk_entry_set_text(GTK_ENTRY(entry_user_agent), user_agent); + gtk_table_attach(GTK_TABLE(table), entry_user_agent, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show_all(table); gtk_container_set_border_width(GTK_CONTAINER(table), 10); @@ -370,25 +372,15 @@ static GtkWidget* create_basic_tab(account_t *currentAccount) return frame; } -static void fill_treeview_with_credential(account_t * account) +static void fill_treeview_with_credential(const account_t * account) { GtkTreeIter iter; - gtk_list_store_clear(credentialStore); - - if (!account->credential_information) { - account->credential_information = g_ptr_array_sized_new(1); - GHashTable * new_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_insert(new_table, g_strdup(ACCOUNT_REALM), g_strdup("*")); - g_hash_table_insert(new_table, g_strdup(ACCOUNT_USERNAME), g_strdup("")); - g_hash_table_insert(new_table, g_strdup(ACCOUNT_PASSWORD), g_strdup("")); - g_ptr_array_add(account->credential_information, new_table); - } + gtk_list_store_clear(credential_store); for (unsigned i = 0; i < account->credential_information->len; i++) { GHashTable * element = g_ptr_array_index(account->credential_information, i); - gtk_list_store_append(credentialStore, &iter); - gtk_list_store_set(credentialStore, &iter, - COLUMN_CREDENTIAL_REALM, g_hash_table_lookup(element, ACCOUNT_REALM), + gtk_list_store_append(credential_store, &iter); + gtk_list_store_set(credential_store, &iter, COLUMN_CREDENTIAL_REALM, g_hash_table_lookup(element, ACCOUNT_REALM), COLUMN_CREDENTIAL_USERNAME, g_hash_table_lookup(element, ACCOUNT_USERNAME), COLUMN_CREDENTIAL_PASSWORD, g_hash_table_lookup(element, ACCOUNT_PASSWORD), COLUMN_CREDENTIAL_DATA, element, -1); @@ -398,22 +390,19 @@ static void fill_treeview_with_credential(account_t * account) static void select_credential_cb(GtkTreeSelection *selection, GtkTreeModel *model) { GtkTreeIter iter; - if (gtk_tree_selection_get_selected(selection, NULL, &iter)) { GtkTreePath *path = gtk_tree_model_get_path(model, &iter); - if (gtk_tree_path_get_indices(path)[0] == 0) - gtk_widget_set_sensitive(deleteCredButton, FALSE); - else - gtk_widget_set_sensitive(deleteCredButton, TRUE); + const gboolean sensitive = gtk_tree_path_get_indices(path)[0] != 0; + gtk_widget_set_sensitive(delete_cred_button, sensitive); } } static void add_credential_cb(GtkWidget *button UNUSED, gpointer data) { - GtkTreeIter iter; - GtkTreeModel *model =(GtkTreeModel *) data; + GtkTreeModel *model = (GtkTreeModel *) data; + GtkTreeIter iter; gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_CREDENTIAL_REALM, "*", @@ -421,10 +410,11 @@ static void add_credential_cb(GtkWidget *button UNUSED, gpointer data) COLUMN_CREDENTIAL_PASSWORD, _("Secret"), -1); } -static void delete_credential_cb(GtkWidget *button UNUSED, gpointer data) +static void +delete_credential_cb(GtkWidget *button UNUSED, gpointer data) { GtkTreeIter iter; - GtkTreeView *treeview =(GtkTreeView *) data; + GtkTreeView *treeview = (GtkTreeView *) data; GtkTreeModel *model = gtk_tree_view_get_model(treeview); GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); @@ -432,13 +422,13 @@ static void delete_credential_cb(GtkWidget *button UNUSED, gpointer data) GtkTreePath *path; path = gtk_tree_model_get_path(model, &iter); gtk_list_store_remove(GTK_LIST_STORE(model), &iter); - gtk_tree_path_free(path); } - } -static void cell_edited_cb(GtkCellRendererText *renderer, gchar *path_desc, gchar *text, gpointer data) +static void +cell_edited_cb(GtkCellRendererText *renderer, gchar *path_desc, gchar *text, + gpointer data) { GtkTreeModel *model =(GtkTreeModel *) data; GtkTreePath *path = gtk_tree_path_new_from_string(path_desc); @@ -446,9 +436,11 @@ static void cell_edited_cb(GtkCellRendererText *renderer, gchar *path_desc, gcha gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(renderer), "column")); DEBUG("path desc in cell_edited_cb: %s\n", text); - if ((utf8_case_cmp(path_desc, "0") == 0) && - utf8_case_cmp(text, gtk_entry_get_text(GTK_ENTRY(entryUsername))) != 0) - g_signal_handlers_disconnect_by_func(G_OBJECT(entryUsername), G_CALLBACK(update_credential_cb), NULL); + if ((utf8_case_equal(path_desc, "0")) && + !utf8_case_equal(text, gtk_entry_get_text(GTK_ENTRY(entry_username)))) + g_signal_handlers_disconnect_by_func(G_OBJECT(entry_username), + G_CALLBACK(update_credential_cb), + NULL); GtkTreeIter iter; gtk_tree_model_get_iter(model, &iter, path); @@ -456,48 +448,50 @@ static void cell_edited_cb(GtkCellRendererText *renderer, gchar *path_desc, gcha gtk_tree_path_free(path); } -static void editing_started_cb(GtkCellRenderer *cell UNUSED, GtkCellEditable * editable, const gchar * path, gpointer data UNUSED) +static void +editing_started_cb(GtkCellRenderer *cell UNUSED, GtkCellEditable * editable, + const gchar * path, gpointer data UNUSED) { DEBUG("Editing started"); DEBUG("path desc in editing_started_cb: %s\n", path); // If we are dealing the first row - if (utf8_case_cmp(path, "0") == 0) - gtk_entry_set_text(GTK_ENTRY(editable), gtk_entry_get_text(GTK_ENTRY(entryPassword))); + if (utf8_case_equal(path, "0")) + gtk_entry_set_text(GTK_ENTRY(editable), gtk_entry_get_text(GTK_ENTRY(entry_password))); } static void show_advanced_zrtp_options_cb(GtkWidget *widget UNUSED, gpointer data) { - gchar *proto = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo)); + account_t *account = (account_t *) data; + gchar *proto = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(key_exchange_combo)); - if (utf8_case_cmp(proto, "ZRTP") == 0) - show_advanced_zrtp_options((GHashTable *) data); + if (utf8_case_equal(proto, "ZRTP")) + show_advanced_zrtp_options(account); else - show_advanced_sdes_options((GHashTable *) data); + show_advanced_sdes_options(account); g_free(proto); } -static void show_advanced_tls_options_cb(GtkWidget *widget UNUSED, gpointer data) +static void +show_advanced_tls_options_cb(GtkWidget *widget UNUSED, gpointer data) { - show_advanced_tls_options((GHashTable *) data); + account_t *account = (account_t *) data; + show_advanced_tls_options(account); } -static void key_exchange_changed_cb(GtkWidget *widget UNUSED, gpointer data UNUSED) +static void +key_exchange_changed_cb(GtkWidget *widget UNUSED, gpointer data UNUSED) { - gchar *active_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo)); + gchar *active_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(key_exchange_combo)); DEBUG("Key exchange changed %s", active_text); - gboolean set_sensitive = FALSE; - set_sensitive |= utf8_case_cmp(active_text, "SDES") == 0; - set_sensitive |= utf8_case_cmp(active_text, "ZRTP") == 0; + gboolean sensitive = FALSE; + sensitive |= utf8_case_equal(active_text, "SDES"); + sensitive |= utf8_case_equal(active_text, "ZRTP"); g_free(active_text); - - if (set_sensitive) - gtk_widget_set_sensitive(advancedZrtpButton, TRUE); - else - gtk_widget_set_sensitive(advancedZrtpButton, FALSE); + gtk_widget_set_sensitive(zrtp_button, sensitive); } @@ -507,37 +501,37 @@ static void use_sip_tls_cb(GtkWidget *widget, gpointer data) DEBUG("Using sips"); gtk_widget_set_sensitive(data, TRUE); // Uncheck stun - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(useStunCheckBox), FALSE); - gtk_widget_set_sensitive(useStunCheckBox, FALSE); - gtk_widget_set_sensitive(sameAsLocalRadioButton, TRUE); - gtk_widget_set_sensitive(publishedAddrRadioButton, TRUE); - gtk_widget_hide(stunServerLabel); - gtk_widget_hide(stunServerEntry); - - if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton))) { - gtk_widget_show(publishedAddressEntry); - gtk_widget_show(publishedPortSpinBox); - gtk_widget_show(publishedAddressLabel); - gtk_widget_show(publishedPortLabel); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_stun_check_box), FALSE); + gtk_widget_set_sensitive(use_stun_check_box, FALSE); + gtk_widget_set_sensitive(same_as_local_radio_button, TRUE); + gtk_widget_set_sensitive(published_addr_radio_button, TRUE); + gtk_widget_hide(stun_server_label); + gtk_widget_hide(stun_server_entry); + + if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button))) { + gtk_widget_show(published_address_entry); + gtk_widget_show(published_port_spin_box); + gtk_widget_show(published_address_label); + gtk_widget_show(published_port_label); } } else { gtk_widget_set_sensitive(data, FALSE); - gtk_widget_set_sensitive(useStunCheckBox, TRUE); - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(useStunCheckBox))) { - gtk_widget_set_sensitive(sameAsLocalRadioButton, FALSE); - gtk_widget_set_sensitive(publishedAddrRadioButton, FALSE); - gtk_widget_show(stunServerLabel); - gtk_widget_show(stunServerEntry); - gtk_widget_hide(publishedAddressEntry); - gtk_widget_hide(publishedPortSpinBox); - gtk_widget_hide(publishedAddressLabel); - gtk_widget_hide(publishedPortLabel); + gtk_widget_set_sensitive(use_stun_check_box, TRUE); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_stun_check_box))) { + gtk_widget_set_sensitive(same_as_local_radio_button, FALSE); + gtk_widget_set_sensitive(published_addr_radio_button, FALSE); + gtk_widget_show(stun_server_label); + gtk_widget_show(stun_server_entry); + gtk_widget_hide(published_address_entry); + gtk_widget_hide(published_port_spin_box); + gtk_widget_hide(published_address_label); + gtk_widget_hide(published_port_label); } else { - gtk_widget_set_sensitive(sameAsLocalRadioButton, TRUE); - gtk_widget_set_sensitive(publishedAddrRadioButton, TRUE); - gtk_widget_hide(stunServerLabel); - gtk_widget_hide(stunServerEntry); + gtk_widget_set_sensitive(same_as_local_radio_button, TRUE); + gtk_widget_set_sensitive(published_addr_radio_button, TRUE); + gtk_widget_hide(stun_server_label); + gtk_widget_hide(stun_server_entry); } } } @@ -577,12 +571,12 @@ get_interface_addr_from_name(const gchar * const iface_name) static void local_interface_changed_cb(GtkWidget * widget UNUSED, gpointer data UNUSED) { - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton))) { - gchar *local_iface_name = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(localAddressCombo)); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button))) { + gchar *local_iface_name = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(local_address_combo)); gchar *local_iface_addr = get_interface_addr_from_name(local_iface_name); - gtk_entry_set_text(GTK_ENTRY(localAddressEntry), local_iface_addr); - gtk_entry_set_text(GTK_ENTRY(publishedAddressEntry), local_iface_addr); + gtk_entry_set_text(GTK_ENTRY(local_address_entry), local_iface_addr); + gtk_entry_set_text(GTK_ENTRY(published_address_entry), local_iface_addr); g_free(local_iface_addr); g_free(local_iface_name); } @@ -592,16 +586,16 @@ static void set_published_addr_manually_cb(GtkWidget * widget, gpointer data UNU { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { DEBUG("Config: Showing manual publishing options"); - gtk_widget_show(publishedPortLabel); - gtk_widget_show(publishedPortSpinBox); - gtk_widget_show(publishedAddressLabel); - gtk_widget_show(publishedAddressEntry); + gtk_widget_show(published_port_label); + gtk_widget_show(published_port_spin_box); + gtk_widget_show(published_address_label); + gtk_widget_show(published_address_entry); } else { DEBUG("Config: Hiding manual publishing options"); - gtk_widget_hide(publishedPortLabel); - gtk_widget_hide(publishedPortSpinBox); - gtk_widget_hide(publishedAddressLabel); - gtk_widget_hide(publishedAddressEntry); + gtk_widget_hide(published_port_label); + gtk_widget_hide(published_port_spin_box); + gtk_widget_hide(published_address_label); + gtk_widget_hide(published_address_entry); } } @@ -609,27 +603,27 @@ static void use_stun_cb(GtkWidget *widget, gpointer data UNUSED) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { DEBUG("Config: Showing stun options, hiding Local/Published info"); - gtk_widget_show(stunServerLabel); - gtk_widget_show(stunServerEntry); - gtk_widget_set_sensitive(sameAsLocalRadioButton, FALSE); - gtk_widget_set_sensitive(publishedAddrRadioButton, FALSE); - - gtk_widget_hide(publishedAddressLabel); - gtk_widget_hide(publishedPortLabel); - gtk_widget_hide(publishedAddressEntry); - gtk_widget_hide(publishedPortSpinBox); + gtk_widget_show(stun_server_label); + gtk_widget_show(stun_server_entry); + gtk_widget_set_sensitive(same_as_local_radio_button, FALSE); + gtk_widget_set_sensitive(published_addr_radio_button, FALSE); + + gtk_widget_hide(published_address_label); + gtk_widget_hide(published_port_label); + gtk_widget_hide(published_address_entry); + gtk_widget_hide(published_port_spin_box); } else { DEBUG("Config: hiding stun options, showing Local/Published info"); - gtk_widget_hide(stunServerLabel); - gtk_widget_hide(stunServerEntry); - gtk_widget_set_sensitive(sameAsLocalRadioButton, TRUE); - gtk_widget_set_sensitive(publishedAddrRadioButton, TRUE); - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(publishedAddrRadioButton))) { - gtk_widget_show(publishedAddressLabel); - gtk_widget_show(publishedPortLabel); - gtk_widget_show(publishedAddressEntry); - gtk_widget_show(publishedPortSpinBox); + gtk_widget_hide(stun_server_label); + gtk_widget_hide(stun_server_entry); + gtk_widget_set_sensitive(same_as_local_radio_button, TRUE); + gtk_widget_set_sensitive(published_addr_radio_button, TRUE); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(published_addr_radio_button))) { + gtk_widget_show(published_address_label); + gtk_widget_show(published_port_label); + gtk_widget_show(published_address_entry); + gtk_widget_show(published_port_spin_box); } } @@ -640,173 +634,170 @@ static void use_stun_cb(GtkWidget *widget, gpointer data UNUSED) static void same_as_local_cb(GtkWidget * widget, gpointer data UNUSED) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { - gchar *local_interface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(localAddressCombo)); + gchar *local_interface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(local_address_combo)); gchar *local_address = dbus_get_address_from_interface_name(local_interface); - gtk_entry_set_text(GTK_ENTRY(publishedAddressEntry), local_address); + gtk_entry_set_text(GTK_ENTRY(published_address_entry), local_address); - const gchar * local_port = gtk_entry_get_text(GTK_ENTRY(localPortSpinBox)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(publishedPortSpinBox), g_ascii_strtod(local_port, NULL)); + const gchar * local_port = gtk_entry_get_text(GTK_ENTRY(local_port_spin_box)); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(published_port_spin_box), g_ascii_strtod(local_port, NULL)); g_free(local_interface); } } -GtkWidget* create_credential_widget(account_t *a) +static GtkWidget* create_credential_widget(const account_t *account) { - - GtkWidget *frame, *table, *scrolledWindowCredential, *addButton; - GtkCellRenderer * renderer; - GtkTreeViewColumn * treeViewColumn; - GtkTreeSelection * treeSelection; - /* Credentials tree view */ + GtkWidget *frame, *table; gnome_main_section_new_with_table(_("Credential"), &frame, &table, 1, 1); gtk_container_set_border_width(GTK_CONTAINER(table), 10); gtk_table_set_row_spacings(GTK_TABLE(table), 10); - scrolledWindowCredential = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindowCredential), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledWindowCredential), GTK_SHADOW_IN); - gtk_table_attach_defaults(GTK_TABLE(table), scrolledWindowCredential, 0, 1, 0, 1); + GtkWidget *scrolled_window_credential = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window_credential), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window_credential), GTK_SHADOW_IN); + gtk_table_attach_defaults(GTK_TABLE(table), scrolled_window_credential, 0, 1, 0, 1); - credentialStore = gtk_list_store_new(COLUMN_CREDENTIAL_COUNT, + credential_store = gtk_list_store_new(COLUMN_CREDENTIAL_COUNT, G_TYPE_STRING, // Realm G_TYPE_STRING, // Username G_TYPE_STRING, // Password G_TYPE_POINTER // Pointer to the Objectc - ); + ); - treeViewCredential = gtk_tree_view_new_with_model(GTK_TREE_MODEL(credentialStore)); - treeSelection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeViewCredential)); - g_signal_connect(G_OBJECT(treeSelection), "changed", G_CALLBACK(select_credential_cb), credentialStore); + treeview_credential = gtk_tree_view_new_with_model(GTK_TREE_MODEL(credential_store)); + GtkTreeSelection * tree_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview_credential)); + g_signal_connect(G_OBJECT(tree_selection), "changed", G_CALLBACK(select_credential_cb), credential_store); - renderer = gtk_cell_renderer_text_new(); + GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); g_object_set(renderer, "editable", TRUE, "editable-set", TRUE, NULL); - g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credentialStore); + g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credential_store); g_object_set_data(G_OBJECT(renderer), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_REALM)); - treeViewColumn = gtk_tree_view_column_new_with_attributes("Realm", - renderer, - "markup", COLUMN_CREDENTIAL_REALM, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeViewCredential), treeViewColumn); + + GtkTreeViewColumn *tree_view_column = gtk_tree_view_column_new_with_attributes("Realm", renderer, "markup", COLUMN_CREDENTIAL_REALM, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_credential), tree_view_column); renderer = gtk_cell_renderer_text_new(); g_object_set(renderer, "editable", TRUE, "editable-set", TRUE, NULL); - g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credentialStore); + g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credential_store); g_object_set_data(G_OBJECT(renderer), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_USERNAME)); - treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Authentication name"), + tree_view_column = gtk_tree_view_column_new_with_attributes(_("Authentication name"), renderer, "markup", COLUMN_CREDENTIAL_USERNAME, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeViewCredential), treeViewColumn); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_credential), tree_view_column); renderer = gtk_cell_renderer_text_new(); g_object_set(renderer, "editable", TRUE, "editable-set", TRUE, NULL); - g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credentialStore); + g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_edited_cb), credential_store); g_signal_connect(renderer, "editing-started", G_CALLBACK(editing_started_cb), NULL); g_object_set_data(G_OBJECT(renderer), "column", GINT_TO_POINTER(COLUMN_CREDENTIAL_PASSWORD)); - treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Password"), - renderer, - "markup", COLUMN_CREDENTIAL_PASSWORD, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeViewCredential), treeViewColumn); + tree_view_column = gtk_tree_view_column_new_with_attributes(_("Password"), + renderer, "markup", COLUMN_CREDENTIAL_PASSWORD, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_credential), tree_view_column); - gtk_container_add(GTK_CONTAINER(scrolledWindowCredential), treeViewCredential); + gtk_container_add(GTK_CONTAINER(scrolled_window_credential), treeview_credential); - fill_treeview_with_credential(a); + fill_treeview_with_credential(account); /* Credential Buttons */ GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 3, 1, 2); - addButton = gtk_button_new_from_stock(GTK_STOCK_ADD); - g_signal_connect(addButton, "clicked", G_CALLBACK(add_credential_cb), credentialStore); + GtkWidget *addButton = gtk_button_new_from_stock(GTK_STOCK_ADD); + g_signal_connect(addButton, "clicked", G_CALLBACK(add_credential_cb), credential_store); gtk_box_pack_start(GTK_BOX(hbox), addButton, FALSE, FALSE, 0); - deleteCredButton = gtk_button_new_from_stock(GTK_STOCK_REMOVE); - g_signal_connect(deleteCredButton, "clicked", G_CALLBACK(delete_credential_cb), treeViewCredential); - gtk_box_pack_start(GTK_BOX(hbox), deleteCredButton, FALSE, FALSE, 0); + delete_cred_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); + g_signal_connect(delete_cred_button, "clicked", G_CALLBACK(delete_credential_cb), treeview_credential); + gtk_box_pack_start(GTK_BOX(hbox), delete_cred_button, FALSE, FALSE, 0); /* Dynamically resize the window to fit the scrolled window */ - gtk_widget_set_size_request(scrolledWindowCredential, 400, 120); + gtk_widget_set_size_request(scrolled_window_credential, 400, 120); return frame; } -GtkWidget* create_security_widget(account_t *a) +static GtkWidget* +create_security_widget(const account_t *account) { - - GtkWidget *frame, *table, *sipTlsAdvancedButton, *label; - gchar *curSRTPEnabled = NULL, *curKeyExchange = NULL, *curTLSEnabled = NULL; + gchar *curSRTPEnabled = NULL, *curKeyExchange = NULL, + *curTLSEnabled = NULL; // Load from SIP/IAX/Unknown ? - if (a) { - curKeyExchange = g_hash_table_lookup(a->properties, ACCOUNT_KEY_EXCHANGE); - + if (account && account->properties) { + curKeyExchange = account_lookup(account, ACCOUNT_KEY_EXCHANGE); if (curKeyExchange == NULL) curKeyExchange = "none"; - curSRTPEnabled = g_hash_table_lookup(a->properties, ACCOUNT_SRTP_ENABLED); + curSRTPEnabled = account_lookup(account, ACCOUNT_SRTP_ENABLED); if (curSRTPEnabled == NULL) curSRTPEnabled = "false"; - curTLSEnabled = g_hash_table_lookup(a->properties, TLS_ENABLE); + curTLSEnabled = account_lookup(account, TLS_ENABLE); if (curTLSEnabled == NULL) curTLSEnabled = "false"; } + GtkWidget *frame, *table; gnome_main_section_new_with_table(_("Security"), &frame, &table, 2, 3); gtk_container_set_border_width(GTK_CONTAINER(table), 10); gtk_table_set_row_spacings(GTK_TABLE(table), 10); gtk_table_set_col_spacings(GTK_TABLE(table), 10); /* TLS subsection */ - sipTlsAdvancedButton = gtk_button_new_from_stock(GTK_STOCK_EDIT); - gtk_table_attach_defaults(GTK_TABLE(table), sipTlsAdvancedButton, 2, 3, 0, 1); - gtk_widget_set_sensitive(sipTlsAdvancedButton, FALSE); - g_signal_connect(G_OBJECT(sipTlsAdvancedButton), "clicked", G_CALLBACK(show_advanced_tls_options_cb),a->properties); - - useSipTlsCheckBox = gtk_check_button_new_with_mnemonic(_("Use TLS transport(sips)")); - g_signal_connect(useSipTlsCheckBox, "toggled", G_CALLBACK(use_sip_tls_cb), sipTlsAdvancedButton); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(useSipTlsCheckBox),(g_strcmp0(curTLSEnabled, "true") == 0) ? TRUE:FALSE); - gtk_table_attach_defaults(GTK_TABLE(table), useSipTlsCheckBox, 0, 2, 0, 1); + GtkWidget *sip_tls_advanced_button = gtk_button_new_from_stock(GTK_STOCK_EDIT); + gtk_table_attach_defaults(GTK_TABLE(table), sip_tls_advanced_button, 2, 3, 0, 1); + gtk_widget_set_sensitive(sip_tls_advanced_button, FALSE); + g_signal_connect(G_OBJECT(sip_tls_advanced_button), "clicked", + G_CALLBACK(show_advanced_tls_options_cb), + (gpointer) account); + + use_sip_tls_check_box = gtk_check_button_new_with_mnemonic(_("Use TLS transport(sips)")); + g_signal_connect(use_sip_tls_check_box, "toggled", G_CALLBACK(use_sip_tls_cb), sip_tls_advanced_button); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_sip_tls_check_box), + g_strcmp0(curTLSEnabled, "true") == 0); + gtk_table_attach_defaults(GTK_TABLE(table), use_sip_tls_check_box, 0, 2, 0, 1); /* ZRTP subsection */ - label = gtk_label_new_with_mnemonic(_("SRTP key exchange")); + GtkWidget *label = gtk_label_new_with_mnemonic(_("SRTP key exchange")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - keyExchangeCombo = gtk_combo_box_text_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), keyExchangeCombo); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo), "ZRTP"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo), "SDES"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo), _("Disabled")); + key_exchange_combo = gtk_combo_box_text_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), key_exchange_combo); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(key_exchange_combo), "ZRTP"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(key_exchange_combo), "SDES"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(key_exchange_combo), _("Disabled")); - advancedZrtpButton = gtk_button_new_from_stock(GTK_STOCK_PREFERENCES); - g_signal_connect(G_OBJECT(advancedZrtpButton), "clicked", G_CALLBACK(show_advanced_zrtp_options_cb),a->properties); + zrtp_button = gtk_button_new_from_stock(GTK_STOCK_PREFERENCES); + g_signal_connect(G_OBJECT(zrtp_button), "clicked", + G_CALLBACK(show_advanced_zrtp_options_cb), + (gpointer) account); if (g_strcmp0(curSRTPEnabled, "false") == 0) { - gtk_combo_box_set_active(GTK_COMBO_BOX(keyExchangeCombo), 2); - gtk_widget_set_sensitive(advancedZrtpButton, FALSE); + gtk_combo_box_set_active(GTK_COMBO_BOX(key_exchange_combo), 2); + gtk_widget_set_sensitive(zrtp_button, FALSE); } else { if (g_strcmp0(curKeyExchange, ZRTP) == 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(keyExchangeCombo),0); + gtk_combo_box_set_active(GTK_COMBO_BOX(key_exchange_combo),0); else if (g_strcmp0(curKeyExchange, SDES) == 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(keyExchangeCombo),1); + gtk_combo_box_set_active(GTK_COMBO_BOX(key_exchange_combo),1); else { - gtk_combo_box_set_active(GTK_COMBO_BOX(keyExchangeCombo), 2); - gtk_widget_set_sensitive(advancedZrtpButton, FALSE); + gtk_combo_box_set_active(GTK_COMBO_BOX(key_exchange_combo), 2); + gtk_widget_set_sensitive(zrtp_button, FALSE); } } - g_signal_connect(G_OBJECT(GTK_COMBO_BOX(keyExchangeCombo)), "changed", G_CALLBACK(key_exchange_changed_cb), a); + g_signal_connect(G_OBJECT(GTK_COMBO_BOX(key_exchange_combo)), "changed", + G_CALLBACK(key_exchange_changed_cb), NULL); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); - gtk_table_attach_defaults(GTK_TABLE(table), keyExchangeCombo, 1, 2, 1, 2); - gtk_table_attach_defaults(GTK_TABLE(table), advancedZrtpButton, 2, 3, 1, 2); + gtk_table_attach_defaults(GTK_TABLE(table), key_exchange_combo, 1, 2, 1, 2); + gtk_table_attach_defaults(GTK_TABLE(table), zrtp_button, 2, 3, 1, 2); gtk_widget_show_all(table); @@ -814,20 +805,17 @@ GtkWidget* create_security_widget(account_t *a) } -GtkWidget * create_security_tab(account_t *a) +static GtkWidget * create_security_tab(const account_t *account) { - GtkWidget * frame; - GtkWidget * ret; - - ret = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); + GtkWidget * ret = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_container_set_border_width(GTK_CONTAINER(ret), 10); // Credentials frame - frame = create_credential_widget(a); + GtkWidget * frame = create_credential_widget(account); gtk_box_pack_start(GTK_BOX(ret), frame, FALSE, FALSE, 0); // Security frame - frame = create_security_widget(a); + frame = create_security_widget(account); gtk_box_pack_start(GTK_BOX(ret), frame, FALSE, FALSE, 0); gtk_widget_show_all(ret); @@ -835,70 +823,55 @@ GtkWidget * create_security_tab(account_t *a) return ret; } -static GtkWidget* create_registration_expire(account_t *a) +static GtkWidget* create_registration_expire(const account_t *account) { + gchar *account_expire = NULL; + void *orig_key = NULL; + if (account && account->properties) + if (!g_hash_table_lookup_extended(account->properties, ACCOUNT_REGISTRATION_EXPIRE, + &orig_key, (gpointer) &account_expire)) + ERROR("Could not retrieve %s from account properties", + ACCOUNT_REGISTRATION_EXPIRE); - GtkWidget *table, *frame, *label; - - gchar *resolve_once=NULL, *account_expire=NULL; - gchar *orig_key = NULL; - if (a) { - gboolean gotkey = FALSE; - gotkey = g_hash_table_lookup_extended(a->properties, ACCOUNT_RESOLVE_ONCE, (gpointer)&orig_key, (gpointer)&resolve_once); - if(gotkey == FALSE) { - ERROR("could not retreive resolve_once from account properties"); - } - gotkey = g_hash_table_lookup_extended(a->properties, ACCOUNT_REGISTRATION_EXPIRE, (gpointer)&orig_key, (gpointer)&account_expire); - if(gotkey == FALSE) { - ERROR("could not retreive %s from account properties", ACCOUNT_REGISTRATION_EXPIRE); - } - } - - + GtkWidget *table, *frame; gnome_main_section_new_with_table(_("Registration"), &frame, &table, 2, 3); gtk_container_set_border_width(GTK_CONTAINER(table), 10); gtk_table_set_row_spacings(GTK_TABLE(table), 5); - label = gtk_label_new_with_mnemonic(_("Registration expire")); + GtkWidget *label = gtk_label_new_with_mnemonic(_("Registration expire")); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - expireSpinBox = gtk_spin_button_new_with_range(1, 65535, 1); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), expireSpinBox); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(expireSpinBox), g_ascii_strtod(account_expire, NULL)); - gtk_table_attach_defaults(GTK_TABLE(table), expireSpinBox, 1, 2, 0, 1); - - entryResolveNameOnlyOnce = gtk_check_button_new_with_mnemonic(_("_Comply with RFC 3263")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(entryResolveNameOnlyOnce), - utf8_case_cmp(resolve_once,"false") == 0 ? TRUE: FALSE); - gtk_table_attach_defaults(GTK_TABLE(table), entryResolveNameOnlyOnce, 0, 2, 1, 2); - gtk_widget_set_sensitive(entryResolveNameOnlyOnce , TRUE); + expire_spin_box = gtk_spin_button_new_with_range(1, 65535, 1); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), expire_spin_box); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(expire_spin_box), g_ascii_strtod(account_expire, NULL)); + gtk_table_attach_defaults(GTK_TABLE(table), expire_spin_box, 1, 2, 0, 1); return frame; } -GtkWidget* create_network(account_t *a) +static GtkWidget* +create_network(const account_t *account) { - GtkWidget *table, *frame, *label; gchar *local_interface = NULL; gchar *local_port = NULL; - if (a) { - local_interface = g_hash_table_lookup(a->properties, LOCAL_INTERFACE); - local_port = g_hash_table_lookup(a->properties, LOCAL_PORT); + if (account) { + local_interface = account_lookup(account, LOCAL_INTERFACE); + local_port = account_lookup(account, LOCAL_PORT); } + GtkWidget *table, *frame; gnome_main_section_new_with_table(_("Network Interface"), &frame, &table, 2, 3); gtk_container_set_border_width(GTK_CONTAINER(table), 10); gtk_table_set_row_spacings(GTK_TABLE(table), 5); /** - * Retreive the list of IP interface from the + * Retrieve the list of IP interface from the * the daemon and build the combo box. */ - localAddressCombo = gtk_combo_box_text_new(); - + local_address_combo = gtk_combo_box_text_new(); - label = gtk_label_new_with_mnemonic(_("Local address")); + GtkWidget *label = gtk_label_new_with_mnemonic(_("Local address")); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); @@ -906,46 +879,43 @@ GtkWidget* create_network(account_t *a) int idx = 0; for (gchar **iface = iface_list; iface && *iface; iface++, idx++) { - - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(localAddressCombo), NULL, *iface); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(local_address_combo), NULL, *iface); if (g_strcmp0(*iface, local_interface) == 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(localAddressCombo), idx); + gtk_combo_box_set_active(GTK_COMBO_BOX(local_address_combo), idx); } if (!local_interface) - gtk_combo_box_set_active(GTK_COMBO_BOX(localAddressCombo), 0); - + gtk_combo_box_set_active(GTK_COMBO_BOX(local_address_combo), 0); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), localAddressCombo); - gtk_table_attach(GTK_TABLE(table), localAddressCombo, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), local_address_combo); + gtk_table_attach(GTK_TABLE(table), local_address_combo, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); // Fill the text entry with the ip address of local interface selected - localAddressEntry = gtk_entry_new(); - gchar *local_iface_name = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(localAddressCombo)); + local_address_entry = gtk_entry_new(); + gchar *local_iface_name = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(local_address_combo)); gchar *local_iface_addr = get_interface_addr_from_name(local_iface_name); g_free(local_iface_name); - gtk_entry_set_text(GTK_ENTRY(localAddressEntry), local_iface_addr); + gtk_entry_set_text(GTK_ENTRY(local_address_entry), local_iface_addr); g_free(local_iface_addr); - gtk_widget_set_sensitive(localAddressEntry, FALSE); - gtk_table_attach(GTK_TABLE(table), localAddressEntry, 2, 3, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_set_sensitive(local_address_entry, FALSE); + gtk_table_attach(GTK_TABLE(table), local_address_entry, 2, 3, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); // Local port widget label = gtk_label_new_with_mnemonic(_("Local port")); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - localPortSpinBox = gtk_spin_button_new_with_range(1, 65535, 1); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), localPortSpinBox); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(localPortSpinBox), g_ascii_strtod(local_port, NULL)); + local_port_spin_box = gtk_spin_button_new_with_range(1, 65535, 1); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), local_port_spin_box); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(local_port_spin_box), g_ascii_strtod(local_port, NULL)); - gtk_table_attach_defaults(GTK_TABLE(table), localPortSpinBox, 1, 2, 1, 2); + gtk_table_attach_defaults(GTK_TABLE(table), local_port_spin_box, 1, 2, 1, 2); return frame; } -GtkWidget* create_published_address(account_t *a) +GtkWidget* create_published_address(const account_t *account) { - GtkWidget *table, *frame; - gchar *use_tls =NULL; + gchar *use_tls = NULL; gchar *published_address = NULL; gchar *published_port = NULL; gchar *stun_enable = NULL; @@ -953,132 +923,127 @@ GtkWidget* create_published_address(account_t *a) gchar *published_sameas_local = NULL; // Get the user configuration - if (a) { + if (account) { + use_tls = account_lookup(account, TLS_ENABLE); + published_sameas_local = account_lookup(account, PUBLISHED_SAMEAS_LOCAL); - use_tls = g_hash_table_lookup(a->properties, TLS_ENABLE); - published_sameas_local = g_hash_table_lookup(a->properties, PUBLISHED_SAMEAS_LOCAL); - - if (utf8_case_cmp(published_sameas_local, "true") == 0) { - published_address = dbus_get_address_from_interface_name(g_hash_table_lookup(a->properties, LOCAL_INTERFACE)); - published_port = g_hash_table_lookup(a->properties, LOCAL_PORT); + if (utf8_case_equal(published_sameas_local, "true")) { + published_address = dbus_get_address_from_interface_name(account_lookup(account, LOCAL_INTERFACE)); + published_port = account_lookup(account, LOCAL_PORT); } else { - published_address = g_hash_table_lookup(a->properties, PUBLISHED_ADDRESS); - published_port = g_hash_table_lookup(a->properties, PUBLISHED_PORT); + published_address = account_lookup(account, PUBLISHED_ADDRESS); + published_port = account_lookup(account, PUBLISHED_PORT); } - stun_enable = g_hash_table_lookup(a->properties, ACCOUNT_SIP_STUN_ENABLED); - stun_server = g_hash_table_lookup(a->properties, ACCOUNT_SIP_STUN_SERVER); - published_sameas_local = g_hash_table_lookup(a->properties, PUBLISHED_SAMEAS_LOCAL); + stun_enable = account_lookup(account, ACCOUNT_SIP_STUN_ENABLED); + stun_server = account_lookup(account, ACCOUNT_SIP_STUN_SERVER); + published_sameas_local = account_lookup(account, PUBLISHED_SAMEAS_LOCAL); } gnome_main_section_new_with_table(_("Published address"), &frame, &table, 2, 3); gtk_container_set_border_width(GTK_CONTAINER(table), 10); gtk_table_set_row_spacings(GTK_TABLE(table), 5); - useStunCheckBox = gtk_check_button_new_with_mnemonic(_("Using STUN")); - gtk_table_attach_defaults(GTK_TABLE(table), useStunCheckBox, 0, 1, 0, 1); - g_signal_connect(useStunCheckBox, "toggled", G_CALLBACK(use_stun_cb), a); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(useStunCheckBox), - utf8_case_cmp(stun_enable, "true") == 0 ? TRUE: FALSE); - gtk_widget_set_sensitive(useStunCheckBox, - utf8_case_cmp(use_tls, "true") == 0 ? FALSE: TRUE); - - stunServerLabel = gtk_label_new_with_mnemonic(_("STUN server URL")); - gtk_table_attach_defaults(GTK_TABLE(table), stunServerLabel, 0, 1, 1, 2); - gtk_misc_set_alignment(GTK_MISC(stunServerLabel), 0, 0.5); - stunServerEntry = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(stunServerLabel), stunServerEntry); - gtk_entry_set_text(GTK_ENTRY(stunServerEntry), stun_server); - gtk_table_attach_defaults(GTK_TABLE(table), stunServerEntry, 1, 2, 1, 2); - - sameAsLocalRadioButton = gtk_radio_button_new_with_mnemonic_from_widget(NULL, _("Same as local parameters")); - gtk_table_attach_defaults(GTK_TABLE(table), sameAsLocalRadioButton, 0, 2, 3, 4); - - publishedAddrRadioButton = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(sameAsLocalRadioButton), _("Set published address and port:")); - gtk_table_attach_defaults(GTK_TABLE(table), publishedAddrRadioButton, 0, 2, 4, 5); - - if (utf8_case_cmp(published_sameas_local, "true") == 0) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton), TRUE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(publishedAddrRadioButton), FALSE); + use_stun_check_box = gtk_check_button_new_with_mnemonic(_("Using STUN")); + gtk_table_attach_defaults(GTK_TABLE(table), use_stun_check_box, 0, 1, 0, 1); + g_signal_connect(use_stun_check_box, "toggled", G_CALLBACK(use_stun_cb), NULL); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_stun_check_box), + utf8_case_equal(stun_enable, "true")); + gtk_widget_set_sensitive(use_stun_check_box, !utf8_case_equal(use_tls, "true")); + + stun_server_label = gtk_label_new_with_mnemonic(_("STUN server URL")); + gtk_table_attach_defaults(GTK_TABLE(table), stun_server_label, 0, 1, 1, 2); + gtk_misc_set_alignment(GTK_MISC(stun_server_label), 0, 0.5); + stun_server_entry = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(stun_server_label), stun_server_entry); + gtk_entry_set_text(GTK_ENTRY(stun_server_entry), stun_server); + gtk_table_attach_defaults(GTK_TABLE(table), stun_server_entry, 1, 2, 1, 2); + + same_as_local_radio_button = gtk_radio_button_new_with_mnemonic_from_widget(NULL, _("Same as local parameters")); + gtk_table_attach_defaults(GTK_TABLE(table), same_as_local_radio_button, 0, 2, 3, 4); + + published_addr_radio_button = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(same_as_local_radio_button), _("Set published address and port:")); + gtk_table_attach_defaults(GTK_TABLE(table), published_addr_radio_button, 0, 2, 4, 5); + + if (utf8_case_equal(published_sameas_local, "true")) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button), TRUE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(published_addr_radio_button), FALSE); } else { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton), FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(publishedAddrRadioButton), TRUE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button), FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(published_addr_radio_button), TRUE); } - publishedAddressLabel = gtk_label_new_with_mnemonic(_("Published address")); - gtk_table_attach_defaults(GTK_TABLE(table), publishedAddressLabel, 0, 1, 5, 6); - gtk_misc_set_alignment(GTK_MISC(publishedAddressLabel), 0, 0.5); - publishedAddressEntry = gtk_entry_new(); - gtk_label_set_mnemonic_widget(GTK_LABEL(publishedAddressLabel), publishedAddressEntry); + published_address_label = gtk_label_new_with_mnemonic(_("Published address")); + gtk_table_attach_defaults(GTK_TABLE(table), published_address_label, 0, 1, 5, 6); + gtk_misc_set_alignment(GTK_MISC(published_address_label), 0, 0.5); + published_address_entry = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(published_address_label), published_address_entry); - gtk_entry_set_text(GTK_ENTRY(publishedAddressEntry), published_address); - gtk_table_attach_defaults(GTK_TABLE(table), publishedAddressEntry, 1, 2, 5, 6); + gtk_entry_set_text(GTK_ENTRY(published_address_entry), published_address); + gtk_table_attach_defaults(GTK_TABLE(table), published_address_entry, 1, 2, 5, 6); - publishedPortLabel = gtk_label_new_with_mnemonic(_("Published port")); - gtk_table_attach_defaults(GTK_TABLE(table), publishedPortLabel, 0, 1, 6, 7); - gtk_misc_set_alignment(GTK_MISC(publishedPortLabel), 0, 0.5); - publishedPortSpinBox = gtk_spin_button_new_with_range(1, 65535, 1); - gtk_label_set_mnemonic_widget(GTK_LABEL(publishedPortLabel), publishedPortSpinBox); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(publishedPortSpinBox), g_ascii_strtod(published_port, NULL)); + published_port_label = gtk_label_new_with_mnemonic(_("Published port")); + gtk_table_attach_defaults(GTK_TABLE(table), published_port_label, 0, 1, 6, 7); + gtk_misc_set_alignment(GTK_MISC(published_port_label), 0, 0.5); + published_port_spin_box = gtk_spin_button_new_with_range(1, 65535, 1); + gtk_label_set_mnemonic_widget(GTK_LABEL(published_port_label), published_port_spin_box); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(published_port_spin_box), g_ascii_strtod(published_port, NULL)); - gtk_table_attach_defaults(GTK_TABLE(table), publishedPortSpinBox, 1, 2, 6, 7); + gtk_table_attach_defaults(GTK_TABLE(table), published_port_spin_box, 1, 2, 6, 7); // This will trigger a signal, and the above two // widgets need to be instanciated before that. - g_signal_connect(localAddressCombo, "changed", G_CALLBACK(local_interface_changed_cb), localAddressCombo); - + g_signal_connect(local_address_combo, "changed", G_CALLBACK(local_interface_changed_cb), local_address_combo); - g_signal_connect(sameAsLocalRadioButton, "toggled", G_CALLBACK(same_as_local_cb), sameAsLocalRadioButton); - g_signal_connect(publishedAddrRadioButton, "toggled", G_CALLBACK(set_published_addr_manually_cb), publishedAddrRadioButton); + g_signal_connect(same_as_local_radio_button, "toggled", G_CALLBACK(same_as_local_cb), same_as_local_radio_button); + g_signal_connect(published_addr_radio_button, "toggled", G_CALLBACK(set_published_addr_manually_cb), published_addr_radio_button); - set_published_addr_manually_cb(publishedAddrRadioButton, NULL); + set_published_addr_manually_cb(published_addr_radio_button, NULL); return frame; } -GtkWidget* create_advanced_tab(account_t *a) +GtkWidget* create_advanced_tab(const account_t *account) { - // Build the advanced tab, to appear on the account configuration panel DEBUG("Config: Build advanced tab"); - GtkWidget *vbox, *frame; - - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); + GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_container_set_border_width(GTK_CONTAINER(vbox), 10); - frame = create_registration_expire(a); + GtkWidget *frame = create_registration_expire(account); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); - frame = create_network(a); + frame = create_network(account); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); - frame = create_published_address(a); + frame = create_published_address(account); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); gtk_widget_show_all(vbox); - use_stun_cb(useStunCheckBox, NULL); + use_stun_cb(use_stun_check_box, NULL); - set_published_addr_manually_cb(publishedAddrRadioButton, NULL); + set_published_addr_manually_cb(published_addr_radio_button, NULL); return vbox; } -void ringtone_enabled(GtkWidget *widget UNUSED, gpointer data, const gchar *accountID UNUSED) +static void ringtone_enabled_cb(GtkWidget *widget UNUSED, gpointer data, const gchar *accountID UNUSED) { /* toggle sensitivity */ gtk_widget_set_sensitive(data, !gtk_widget_is_sensitive(data)); } -static GtkWidget* create_audiocodecs_configuration(account_t *currentAccount) +static GtkWidget* +create_audiocodecs_configuration(const account_t *account) { GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_container_set_border_width(GTK_CONTAINER(vbox), 10); - GtkWidget *box = audiocodecs_box(currentAccount); + GtkWidget *box = audiocodecs_box(account); // Box for the audiocodecs GtkWidget *audiocodecs = gnome_main_section_new(_("Audio")); @@ -1088,25 +1053,18 @@ static GtkWidget* create_audiocodecs_configuration(account_t *currentAccount) gtk_container_add(GTK_CONTAINER(audiocodecs), box); // Add DTMF type selection for SIP account only - gpointer p = g_hash_table_lookup(currentAccount->properties, ACCOUNT_TYPE); - GtkWidget *table; - if (g_strcmp0(p, "SIP") == 0) { + if (account_is_SIP(account)) { // Box for dtmf GtkWidget *dtmf; gnome_main_section_new_with_table(_("DTMF"), &dtmf, &table, 1, 2); gtk_box_pack_start(GTK_BOX(vbox), dtmf, FALSE, FALSE, 0); gtk_widget_show(dtmf); - const gchar * const currentDtmfType = g_hash_table_lookup(currentAccount->properties, ACCOUNT_DTMF_TYPE); - - gboolean dtmf_are_rtp = TRUE; - - if (utf8_case_cmp(currentDtmfType, OVERRTP) != 0) - dtmf_are_rtp = FALSE; - overrtp = gtk_radio_button_new_with_label(NULL, _("RTP")); + const gchar * const dtmf_type = account_lookup(account, ACCOUNT_DTMF_TYPE); + const gboolean dtmf_are_rtp = utf8_case_equal(dtmf_type, OVERRTP); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(overrtp), dtmf_are_rtp); gtk_table_attach(GTK_TABLE(table), overrtp, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); @@ -1121,21 +1079,20 @@ static GtkWidget* create_audiocodecs_configuration(account_t *currentAccount) gnome_main_section_new_with_table(_("Ringtones"), &frame, &table, 1, 2); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); - fileChooser = gtk_file_chooser_button_new(_("Choose a ringtone"), GTK_FILE_CHOOSER_ACTION_OPEN); - - p = g_hash_table_lookup(currentAccount->properties, CONFIG_RINGTONE_ENABLED); - gboolean ringtoneEnabled =(g_strcmp0(p, "true") == 0) ? TRUE : FALSE; + file_chooser = gtk_file_chooser_button_new(_("Choose a ringtone"), GTK_FILE_CHOOSER_ACTION_OPEN); - enableTone = gtk_check_button_new_with_mnemonic(_("_Enable ringtones")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableTone), ringtoneEnabled); - g_signal_connect(G_OBJECT(enableTone) , "clicked" , G_CALLBACK(ringtone_enabled), fileChooser); - gtk_table_attach(GTK_TABLE(table), enableTone, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gpointer ptr = account_lookup(account, CONFIG_RINGTONE_ENABLED); + enable_tone = gtk_check_button_new_with_mnemonic(_("_Enable ringtones")); + const gboolean ringtone_enabled = g_strcmp0(ptr, "true") == 0; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_tone), ringtone_enabled); + g_signal_connect(G_OBJECT(enable_tone) , "clicked", G_CALLBACK(ringtone_enabled_cb), file_chooser); + gtk_table_attach(GTK_TABLE(table), enable_tone, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); // file chooser button - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileChooser) , g_get_home_dir()); - p = g_hash_table_lookup(currentAccount->properties, CONFIG_RINGTONE_PATH); - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileChooser) , p); - gtk_widget_set_sensitive(fileChooser, ringtoneEnabled); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser) , g_get_home_dir()); + ptr = account_lookup(account, CONFIG_RINGTONE_PATH); + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(file_chooser) , ptr); + gtk_widget_set_sensitive(file_chooser, ringtone_enabled); GtkFileFilter *filter = gtk_file_filter_new(); gtk_file_filter_set_name(filter, _("Audio Files")); @@ -1143,8 +1100,9 @@ static GtkWidget* create_audiocodecs_configuration(account_t *currentAccount) gtk_file_filter_add_pattern(filter, "*.ul"); gtk_file_filter_add_pattern(filter, "*.au"); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser) , filter); - gtk_table_attach(GTK_TABLE(table), fileChooser, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), filter); + gtk_table_attach(GTK_TABLE(table), file_chooser, 0, 1, 1, 2, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show_all (vbox); @@ -1152,8 +1110,8 @@ static GtkWidget* create_audiocodecs_configuration(account_t *currentAccount) } #ifdef SFL_VIDEO -GtkWidget * -create_videocodecs_configuration (account_t *a) +static GtkWidget * +create_videocodecs_configuration(const account_t *a) { // Main widget GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); @@ -1174,7 +1132,7 @@ create_videocodecs_configuration (account_t *a) } #endif -GtkWidget* create_direct_ip_calls_tab(account_t *a) +static GtkWidget* create_direct_ip_calls_tab(const account_t *account) { GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_container_set_border_width(GTK_CONTAINER(vbox), 10); @@ -1192,30 +1150,159 @@ GtkWidget* create_direct_ip_calls_tab(account_t *a) gtk_widget_set_size_request(label, 350, -1); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); - GtkWidget *frame = create_network(a); + GtkWidget *frame = create_network(account); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); - frame = create_security_widget(a); + frame = create_security_widget(account); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); gtk_widget_show_all(vbox); return vbox; } -void show_account_window(account_t * currentAccount) +static const gchar *bool_to_string(gboolean v) { - // Firstly we reset - reset(); + return v ? "true" : "false"; +} + +static void update_account_from_basic_tab(account_t *account) +{ + // Update protocol in case it changed + gchar *proto; + if (protocol_combo) + proto = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocol_combo)); + else + proto = g_strdup("SIP"); + + if (g_strcmp0(proto, "SIP") == 0) { + if (!account_is_IP2IP(account)) { + account_replace(account, ACCOUNT_REGISTRATION_EXPIRE, + gtk_entry_get_text(GTK_ENTRY(expire_spin_box))); + + account_replace(account, ACCOUNT_ROUTE, + gtk_entry_get_text(GTK_ENTRY(entry_route_set))); + + account_replace(account, ACCOUNT_USERAGENT, + gtk_entry_get_text(GTK_ENTRY(entry_user_agent))); + + gboolean v = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_stun_check_box)); + account_replace(account, ACCOUNT_SIP_STUN_ENABLED, + bool_to_string(v)); + + account_replace(account, ACCOUNT_SIP_STUN_SERVER, + gtk_entry_get_text(GTK_ENTRY(stun_server_entry))); + + v = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button)); + account_replace(account, PUBLISHED_SAMEAS_LOCAL, bool_to_string(v)); + + if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(same_as_local_radio_button))) { + account_replace(account, PUBLISHED_PORT, + gtk_entry_get_text(GTK_ENTRY(published_port_spin_box))); + + account_replace(account, PUBLISHED_ADDRESS, + gtk_entry_get_text(GTK_ENTRY(published_address_entry))); + } else { + account_replace(account, PUBLISHED_PORT, + gtk_entry_get_text(GTK_ENTRY(local_port_spin_box))); + gchar *local_interface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(local_address_combo)); + + gchar *published_address = dbus_get_address_from_interface_name(local_interface); + g_free(local_interface); + + account_replace(account, PUBLISHED_ADDRESS, published_address); + } + } + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overrtp))) { + DEBUG("Config: Set dtmf over rtp"); + account_replace(account, ACCOUNT_DTMF_TYPE, OVERRTP); + } else { + DEBUG("Config: Set dtmf over sip"); + account_replace(account, ACCOUNT_DTMF_TYPE, SIPINFO); + } + + gchar* key_exchange = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(key_exchange_combo)); + + if (utf8_case_equal(key_exchange, "ZRTP")) { + account_replace(account, ACCOUNT_SRTP_ENABLED, "true"); + account_replace(account, ACCOUNT_KEY_EXCHANGE, ZRTP); + } else if (utf8_case_equal(key_exchange, "SDES")) { + account_replace(account, ACCOUNT_SRTP_ENABLED, "true"); + account_replace(account, ACCOUNT_KEY_EXCHANGE, SDES); + } else { + account_replace(account, ACCOUNT_SRTP_ENABLED, "false"); + account_replace(account, ACCOUNT_KEY_EXCHANGE, ""); + } + + g_free(key_exchange); + const gboolean tls_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_sip_tls_check_box)); + account_replace(account, TLS_ENABLE, bool_to_string(tls_enabled)); + + const gboolean tone_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enable_tone)); + account_replace(account, CONFIG_RINGTONE_ENABLED, bool_to_string(tone_enabled)); + + account_replace(account, CONFIG_RINGTONE_PATH, + gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser))); - if (currentAccount == NULL) { - DEBUG("Config: Fetching default values for new account"); - currentAccount = g_new0(account_t, 1); - currentAccount->properties = dbus_get_account_details(NULL); - currentAccount->accountID = g_strdup("new"); //FIXME : replace with NULL for new accounts - currentAccount->credential_information = NULL; - sflphone_fill_codec_list_per_account(currentAccount); + gchar *address_combo_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(local_address_combo)); + account_replace(account, LOCAL_INTERFACE, address_combo_text); + g_free(address_combo_text); + + account_replace(account, LOCAL_PORT, + gtk_entry_get_text(GTK_ENTRY(local_port_spin_box))); } + account_replace(account, ACCOUNT_ALIAS, gtk_entry_get_text(GTK_ENTRY(entry_alias))); + account_replace(account, ACCOUNT_TYPE, proto); + account_replace(account, ACCOUNT_HOSTNAME, gtk_entry_get_text(GTK_ENTRY(entry_hostname))); + account_replace(account, ACCOUNT_USERNAME, gtk_entry_get_text(GTK_ENTRY(entry_username))); + account_replace(account, ACCOUNT_PASSWORD, gtk_entry_get_text(GTK_ENTRY(entry_password))); + account_replace(account, ACCOUNT_MAILBOX, gtk_entry_get_text(GTK_ENTRY(entry_mailbox))); + g_free(proto); +} + +void update_account_from_dialog(GtkWidget *dialog, account_t *account) +{ + if (!dialog) + return; + + const gboolean IS_IP2IP = account_is_IP2IP(account); + if (!IS_IP2IP) + update_account_from_basic_tab(account); + + // Get current protocol for this account + gchar *current_protocol; + if (protocol_combo) + current_protocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocol_combo)); + else + current_protocol = g_strdup("SIP"); + + if (!IS_IP2IP && g_strcmp0(current_protocol, "SIP") == 0) + account->credential_information = get_new_credential(); + + /** @todo Verify if it's the best condition to check */ + if (g_strcmp0(account->accountID, "new") == 0) { + dbus_add_account(account); + if (account->credential_information) + dbus_set_credentials(account); + } else { + if (account->credential_information) + dbus_set_credentials(account); + dbus_set_account_details(account); + } + + // propagate changes to the daemon + codec_list_update_to_daemon(account); + + g_free(current_protocol); + gtk_widget_destroy(dialog); +} + +GtkWidget *show_account_window(const account_t *account) +{ + // First we reset + reset(); + GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Account settings"), GTK_WINDOW(get_main_window()), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, @@ -1231,226 +1318,61 @@ void show_account_window(account_t * currentAccount) gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), notebook, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(notebook), 10); gtk_widget_show(notebook); + const gboolean IS_IP2IP = account_is_IP2IP(account); // We do not need the global settings for the IP2IP account - if (utf8_case_cmp(currentAccount->accountID, IP2IP) != 0) { + if (!IS_IP2IP) { /* General Settings */ - GtkWidget *basic_tab = create_basic_tab(currentAccount); + GtkWidget *basic_tab = create_basic_tab(account); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), basic_tab, gtk_label_new(_("Basic"))); gtk_notebook_page_num(GTK_NOTEBOOK(notebook), basic_tab); } /* Audio Codecs */ - GtkWidget *audiocodecs_tab = create_audiocodecs_configuration(currentAccount); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), audiocodecs_tab, gtk_label_new (_("Audio"))); + GtkWidget *audiocodecs_tab = create_audiocodecs_configuration(account); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), audiocodecs_tab, gtk_label_new(_("Audio"))); gtk_notebook_page_num(GTK_NOTEBOOK(notebook), audiocodecs_tab); #ifdef SFL_VIDEO /* Video Codecs */ - GtkWidget *videocodecs_tab = create_videocodecs_configuration(currentAccount); + GtkWidget *videocodecs_tab = create_videocodecs_configuration(account); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), videocodecs_tab, gtk_label_new(_("Video"))); gtk_notebook_page_num(GTK_NOTEBOOK(notebook), videocodecs_tab); #endif - // Get current protocol for this account protocol - gchar *currentProtocol; - - if (protocolComboBox) - currentProtocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocolComboBox)); - else - currentProtocol = g_strdup("SIP"); - // Do not need advanced or security one for the IP2IP account - if (utf8_case_cmp(currentAccount->accountID, IP2IP) != 0) { - + if (!IS_IP2IP) { /* Advanced */ - advanced_tab = create_advanced_tab(currentAccount); + advanced_tab = create_advanced_tab(account); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), advanced_tab, gtk_label_new(_("Advanced"))); gtk_notebook_page_num(GTK_NOTEBOOK(notebook), advanced_tab); /* Security */ - security_tab = create_security_tab(currentAccount); + security_tab = create_security_tab(account); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), security_tab, gtk_label_new(_("Security"))); - gtk_notebook_page_num(GTK_NOTEBOOK(notebook),security_tab); - + gtk_notebook_page_num(GTK_NOTEBOOK(notebook), security_tab); } else { /* Custom tab for the IP to IP profile */ - GtkWidget *ip_tab = create_direct_ip_calls_tab(currentAccount); + GtkWidget *ip_tab = create_direct_ip_calls_tab(account); gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), ip_tab, gtk_label_new(_("Network"))); gtk_notebook_page_num(GTK_NOTEBOOK(notebook), ip_tab); } // Emit signal to hide advanced and security tabs in case of IAX - if (protocolComboBox) - g_signal_emit_by_name(protocolComboBox, "changed", NULL); + if (protocol_combo) + g_signal_emit_by_name(protocol_combo, "changed", NULL); - gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook) , 0); + gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0); - /**************/ - /* Run dialog */ - /**************/ + /* Run dialog, this blocks */ gint response = gtk_dialog_run(GTK_DIALOG(dialog)); - // Update protocol in case it changed - gchar *proto; - - if (protocolComboBox) - proto = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(protocolComboBox)); - else - proto = g_strdup("SIP"); - - // If cancel button is pressed - if (response == GTK_RESPONSE_CANCEL) { + // If anything but "Apply" button is pressed + if (response != GTK_RESPONSE_ACCEPT) { gtk_widget_destroy(dialog); - g_free(proto); - return; - } - - // If accept button is - if (utf8_case_cmp(currentAccount->accountID, IP2IP) != 0) { - - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_ALIAS), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(entryAlias)))); - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_TYPE), - g_strdup(proto)); - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_HOSTNAME), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(entryHostname)))); - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_USERNAME), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(entryUsername)))); - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_PASSWORD), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(entryPassword)))); - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_MAILBOX), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(entryMailbox)))); - } - - if (g_strcmp0(proto, "SIP") == 0) { - if (utf8_case_cmp(currentAccount->accountID, IP2IP) != 0) { - - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_RESOLVE_ONCE), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(entryResolveNameOnlyOnce)) ? "false": "true")); - - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_REGISTRATION_EXPIRE), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(expireSpinBox)))); - - - // TODO: uncomment this code and implement route - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_ROUTE), - g_strdup((gchar *)gtk_entry_get_text(GTK_ENTRY(entryRouteSet)))); - - - g_hash_table_replace(currentAccount->properties, - g_strdup(ACCOUNT_USERAGENT), - g_strdup(gtk_entry_get_text(GTK_ENTRY(entryUseragent)))); - - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_SIP_STUN_ENABLED), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(useStunCheckBox)) ? "true":"false")); - - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_SIP_STUN_SERVER), - g_strdup(gtk_entry_get_text(GTK_ENTRY(stunServerEntry)))); - - g_hash_table_replace(currentAccount->properties, g_strdup(PUBLISHED_SAMEAS_LOCAL), g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton)) ? "true":"false")); - - if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sameAsLocalRadioButton))) { - g_hash_table_replace(currentAccount->properties, - g_strdup(PUBLISHED_PORT), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(publishedPortSpinBox)))); - - g_hash_table_replace(currentAccount->properties, - g_strdup(PUBLISHED_ADDRESS), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(publishedAddressEntry)))); - } else { - g_hash_table_replace(currentAccount->properties, - g_strdup(PUBLISHED_PORT), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(localPortSpinBox)))); - gchar *local_interface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(localAddressCombo)); - - gchar *published_address = dbus_get_address_from_interface_name(local_interface); - g_free(local_interface); - - g_hash_table_replace(currentAccount->properties, - g_strdup(PUBLISHED_ADDRESS), - published_address); - } - } - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overrtp))) { - DEBUG("Config: Set dtmf over rtp"); - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_DTMF_TYPE), g_strdup(OVERRTP)); - } else { - DEBUG("Config: Set dtmf over sip"); - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_DTMF_TYPE), g_strdup(SIPINFO)); - } - - gchar* keyExchange = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(keyExchangeCombo)); - - if (utf8_case_cmp(keyExchange, "ZRTP") == 0) { - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_SRTP_ENABLED), g_strdup("true")); - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_KEY_EXCHANGE), g_strdup(ZRTP)); - } else if (utf8_case_cmp(keyExchange, "SDES") == 0) { - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_SRTP_ENABLED), g_strdup("true")); - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_KEY_EXCHANGE), g_strdup(SDES)); - } else { - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_SRTP_ENABLED), g_strdup("false")); - g_hash_table_replace(currentAccount->properties, g_strdup(ACCOUNT_KEY_EXCHANGE), g_strdup("")); - } - - g_free(keyExchange); - - g_hash_table_replace(currentAccount->properties, g_strdup(TLS_ENABLE), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(useSipTlsCheckBox)) ? "true":"false")); - - gboolean toneEnabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableTone)); - g_hash_table_replace(currentAccount->properties, - g_strdup(CONFIG_RINGTONE_ENABLED), - g_strdup(toneEnabled ? "true" : "false")); - - g_hash_table_replace(currentAccount->properties, - g_strdup(CONFIG_RINGTONE_PATH), - g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileChooser)))); - - g_hash_table_replace(currentAccount->properties, - g_strdup(LOCAL_INTERFACE), - gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(localAddressCombo))); - - g_hash_table_replace(currentAccount->properties, - g_strdup(LOCAL_PORT), - g_strdup(gtk_entry_get_text(GTK_ENTRY(localPortSpinBox)))); - - } - - /** @todo Verify if it's the best condition to check */ - if (utf8_case_cmp(currentAccount->accountID, "new") == 0) - dbus_add_account(currentAccount); - else - dbus_set_account_details(currentAccount); - - if (g_strcmp0(currentProtocol, "SIP") == 0) { - /* Set new credentials if any */ - DEBUG("Config: Setting credentials"); - - if (utf8_case_cmp(currentAccount->accountID, IP2IP) != 0) { - DEBUG("Config: Get new credentials"); - currentAccount->credential_information = getNewCredential(); - - if (currentAccount->credential_information) - dbus_set_credentials(currentAccount); - } + return NULL; + } else { + return dialog; } - - // propagate changes to the daemon - codec_list_update_to_daemon(currentAccount); - - gtk_widget_destroy(dialog); - g_free(currentProtocol); - g_free(proto); } diff --git a/gnome/src/config/accountconfigdialog.h b/gnome/src/config/accountconfigdialog.h index fb91376cc1326f87ba050ca5ef38fa68757e6fa5..43cfe666e6c6fd57ece795a41bbc113280138b27 100644 --- a/gnome/src/config/accountconfigdialog.h +++ b/gnome/src/config/accountconfigdialog.h @@ -39,8 +39,19 @@ /** * Display the main account widget - * @param a The account you want to edit or null for a new account + * @param a The account you want to display + * @return The dialog with the pertinent account information */ -void show_account_window (account_t *a); +GtkWidget *show_account_window(const account_t *a); + +/* + * @param dialog The dialog the account will be update from + * @param a The account you want to display + */ +void update_account_from_dialog(GtkWidget *dialog, account_t *a); + +/** + * Resets local cache of account pointers */ +void reset_account_store(); #endif diff --git a/gnome/src/config/accountlistconfigdialog.c b/gnome/src/config/accountlistconfigdialog.c index aef4d63db98b10f9e01e316e7a49511767c83eb8..27560b0200c74d898e506bc36f84768f53563fb5 100644 --- a/gnome/src/config/accountlistconfigdialog.c +++ b/gnome/src/config/accountlistconfigdialog.c @@ -29,11 +29,11 @@ * as that of the covered work. */ - #include "accountlistconfigdialog.h" #include "str_utils.h" #include "dbus/dbus.h" #include "accountconfigdialog.h" +#include "accountlist.h" #include "actions.h" #include "mainwindow.h" #include "utils.h" @@ -44,121 +44,160 @@ static const int CONTEXT_ID_REGISTRATION = 0; -static GtkWidget *addButton; -static GtkWidget *editButton; -static GtkWidget *deleteButton; -static GtkWidget *accountMoveDownButton; -static GtkWidget *accountMoveUpButton; -static GtkWidget * status_bar; -static GtkListStore * accountStore; - -static GtkDialog * accountListDialog = NULL; +static GtkWidget *edit_button; +static GtkWidget *delete_button; +static GtkWidget *move_down_button; +static GtkWidget *move_up_button; +static GtkWidget *account_list_status_bar; +static GtkListStore *account_store; +static GtkDialog *account_list_dialog; -static account_t * selectedAccount = NULL; // Account properties enum { COLUMN_ACCOUNT_ALIAS, COLUMN_ACCOUNT_TYPE, COLUMN_ACCOUNT_STATUS, COLUMN_ACCOUNT_ACTIVE, - COLUMN_ACCOUNT_DATA, + COLUMN_ACCOUNT_ID, COLUMN_ACCOUNT_COUNT }; -/** - * Delete an account - */ -static void delete_account_cb(void) +/* Get selected account ID from treeview + * @return copied selected_accountID, must be freed by caller */ +static gchar * +get_selected_accountID(GtkTreeView *tree_view) { - if (selectedAccount == NULL) { - ERROR("Config: Error: No selected account in delete action"); - return; - } + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view); - dbus_remove_account(selectedAccount->accountID); -} + // Find selected iteration and create a copy + GtkTreeIter iter; + gtk_tree_selection_get_selected(selection, &model, &iter); + // The Gvalue will be initialized in the following function + GValue val; + memset(&val, 0, sizeof(val)); + gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_ID, &val); + gchar *selected_accountID = g_strdup(g_value_get_string(&val)); + g_value_unset(&val); + return selected_accountID; +} -/** - * Edit an account - */ -static void edit_account_cb(void) +static gboolean +find_account_in_account_store(const gchar *accountID, GtkTreeModel *model, + GtkTreeIter *iter) { - if (selectedAccount == NULL) { - ERROR("Config: Error: No selected account in edit action"); - return; + gboolean valid = gtk_tree_model_get_iter_first(model, iter); + gboolean found = FALSE; + while (valid && !found) { + gchar *id; + gtk_tree_model_get(model, iter, COLUMN_ACCOUNT_ID, &id, -1); + if (g_strcmp0(id, accountID) == 0) + found = TRUE; + else + valid = gtk_tree_model_iter_next(model, iter); + g_free(id); } - - show_account_window(selectedAccount); + return found; } -/** - * Add an account - */ -static void add_account_cb(void) + +static void delete_account_cb(GtkButton *button UNUSED, gpointer data) { - show_account_window(NULL); + gchar *selected_accountID = get_selected_accountID(data); + RETURN_IF_NULL(selected_accountID, "No selected account in delete action"); + GtkTreeModel *model = GTK_TREE_MODEL(account_store); + GtkTreeIter iter; + if (find_account_in_account_store(selected_accountID, model, &iter)) + gtk_list_store_remove(account_store, &iter); + + dbus_remove_account(selected_accountID); + g_free(selected_accountID); } -/** - * Fills the treelist with accounts - */ -void account_list_config_dialog_fill() +static void +run_account_dialog(const gchar *selected_accountID) { - if (accountListDialog == NULL) { - DEBUG("Config: No account dialog, returning"); - return; - } - - GtkTreeIter iter; + account_t *account = account_list_get_by_id(selected_accountID); + GtkWidget *dialog = show_account_window(account); + update_account_from_dialog(dialog, account); +} - gtk_list_store_clear(accountStore); +static void row_activated_cb(GtkTreeView *view, + GtkTreePath *path UNUSED, + GtkTreeViewColumn *col UNUSED, + gpointer user_data UNUSED) +{ + gchar *selected_accountID = get_selected_accountID(view); + RETURN_IF_NULL(selected_accountID, "No selected account ID"); + run_account_dialog(selected_accountID); + g_free(selected_accountID); +} - // IP2IP account must be first - account_t *a = account_list_get_by_id("IP2IP"); +static void edit_account_cb(GtkButton *button UNUSED, gpointer data) +{ + gchar *selected_accountID = get_selected_accountID(data); + RETURN_IF_NULL(selected_accountID, "No selected account ID"); + run_account_dialog(selected_accountID); + g_free(selected_accountID); +} - if (a == NULL) { - ERROR("Config: Error: Could not find IP2IP account"); - return; - } +static void account_store_add(GtkTreeIter *iter, account_t *account) +{ + const gchar *enabled = account_lookup(account, ACCOUNT_ENABLED); + const gchar *type = account_lookup(account, ACCOUNT_TYPE); + DEBUG("Config: Adding account: Account is enabled :%s", enabled); + const gchar *state_name = account_state_name(account->state); + + gtk_list_store_set(account_store, iter, + COLUMN_ACCOUNT_ALIAS, account_lookup(account, ACCOUNT_ALIAS), + COLUMN_ACCOUNT_TYPE, type, + COLUMN_ACCOUNT_STATUS, state_name, + COLUMN_ACCOUNT_ACTIVE, utf8_case_equal(enabled, "true"), + COLUMN_ACCOUNT_ID, account->accountID, -1); +} - gtk_list_store_append(accountStore, &iter); - DEBUG("Config: Filling accounts: Account is enabled :%s", g_hash_table_lookup(a->properties, ACCOUNT_ENABLED)); - gtk_list_store_set(accountStore, &iter, - COLUMN_ACCOUNT_ALIAS, g_hash_table_lookup(a->properties, ACCOUNT_ALIAS), // Name - COLUMN_ACCOUNT_TYPE, g_hash_table_lookup(a->properties, ACCOUNT_TYPE), // Protocol - COLUMN_ACCOUNT_STATUS, account_state_name(a->state), // Status - COLUMN_ACCOUNT_ACTIVE, (utf8_case_cmp(g_hash_table_lookup(a->properties, ACCOUNT_ENABLED),"true") == 0) ? TRUE:FALSE, // Enable/Disable - COLUMN_ACCOUNT_DATA, a, // Pointer - -1); +/** + * Fills the treelist with accounts, should be called whenever the account + * list is modified. + */ +static void account_store_fill() +{ + RETURN_IF_NULL(account_list_dialog, "No account dialog"); + gtk_list_store_clear(account_store); - for (size_t i = 0; i < account_list_get_size(); i++) { - a = account_list_get_nth(i); + // IP2IP account must be first + account_t *ip2ip = account_list_get_by_id(IP2IP_PROFILE); + ip2ip->state = ACCOUNT_STATE_IP2IP_READY; + RETURN_IF_NULL(ip2ip, "Could not find IP2IP account"); - if (a == NULL) { - ERROR("Config: Error: Account %d is NULL while parsing the list", i); - return; - } + GtkTreeIter iter; + gtk_list_store_append(account_store, &iter); - // we dont wnat to process account twice - if (g_strcmp0(a->accountID, "IP2IP") != 0) { - gtk_list_store_append(accountStore, &iter); + account_store_add(&iter, ip2ip); - DEBUG("Config: Filling accounts: Account is enabled :%s", g_hash_table_lookup(a->properties, ACCOUNT_ENABLED)); + for (size_t i = 0; i < account_list_get_size(); ++i) { + account_t *a = account_list_get_nth(i); + RETURN_IF_NULL(a, "Account %d is NULL", i); - gtk_list_store_set(accountStore, &iter, - COLUMN_ACCOUNT_ALIAS, g_hash_table_lookup(a->properties, ACCOUNT_ALIAS), // Name - COLUMN_ACCOUNT_TYPE, g_hash_table_lookup(a->properties, ACCOUNT_TYPE), // Protocol - COLUMN_ACCOUNT_STATUS, account_state_name(a->state), // Status - COLUMN_ACCOUNT_ACTIVE, (utf8_case_cmp(g_hash_table_lookup(a->properties, ACCOUNT_ENABLED),"true") == 0) ? TRUE:FALSE, // Enable/Disable - COLUMN_ACCOUNT_DATA, a, // Pointer - -1); + // we don't want to process the IP2IP twice + if (a != ip2ip) { + gtk_list_store_append(account_store, &iter); + account_store_add(&iter, a); } } } +static void add_account_cb(void) +{ + account_t *new_account = create_default_account(); + account_list_add(new_account); + run_account_dialog(new_account->accountID); + account_store_fill(); +} + /** * Call back when the user click on an account in the list */ @@ -166,174 +205,131 @@ static void select_account_cb(GtkTreeSelection *selection, GtkTreeModel *model) { GtkTreeIter iter; - GValue val; - gchar *state; - - memset(&val, 0, sizeof(val)); - if (!gtk_tree_selection_get_selected(selection, &model, &iter)) { - selectedAccount = NULL; - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(editButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), FALSE); + gtk_widget_set_sensitive(move_up_button, FALSE); + gtk_widget_set_sensitive(move_down_button, FALSE); + gtk_widget_set_sensitive(edit_button, FALSE); + gtk_widget_set_sensitive(delete_button, FALSE); return; } // The Gvalue will be initialized in the following function - gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_DATA, &val); + GValue val; + memset(&val, 0, sizeof(val)); + gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_ID, &val); - selectedAccount = (account_t*) g_value_get_pointer(&val); + gchar *selected_accountID = g_value_dup_string(&val); g_value_unset(&val); - if (selectedAccount != NULL) { - gtk_widget_set_sensitive(GTK_WIDGET(editButton), TRUE); - - if (utf8_case_cmp(selectedAccount->accountID, IP2IP) != 0) { - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), TRUE); - - /* Update status bar about current registration state */ - gtk_statusbar_pop(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION); - - if (selectedAccount->protocol_state_description != NULL - && selectedAccount->protocol_state_code != 0) { - - gchar * response = g_strdup_printf( - _("Server returned \"%s\" (%d)"), - selectedAccount->protocol_state_description, - selectedAccount->protocol_state_code); - gchar * message = g_strconcat( - account_state_name(selectedAccount->state), - ". ", - response, - NULL); + DEBUG("Selected account has accountID %s", selected_accountID); + account_t *selected_account = account_list_get_by_id(selected_accountID); + RETURN_IF_NULL(selected_account, "Selected account is NULL"); - gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, message); + gtk_widget_set_sensitive(edit_button, TRUE); - g_free(response); - g_free(message); + if (!account_is_IP2IP(selected_account)) { + gtk_widget_set_sensitive(move_up_button, TRUE); + gtk_widget_set_sensitive(move_down_button, TRUE); + gtk_widget_set_sensitive(delete_button, TRUE); - } else { - state = (gchar*) account_state_name(selectedAccount->state); - gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, state); - } - } else { - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), FALSE); - } + /* Update status bar about current registration state */ + update_account_list_status_bar(selected_account); + } else { + gtk_widget_set_sensitive(move_up_button, FALSE); + gtk_widget_set_sensitive(move_down_button, FALSE); + gtk_widget_set_sensitive(delete_button, FALSE); } - - DEBUG("Selecting account in account window"); + g_free(selected_accountID); } -static void enable_account_cb(GtkCellRendererToggle *rend UNUSED, gchar* path, gpointer data) +static void +enable_account_cb(GtkCellRendererToggle *rend UNUSED, gchar* path, + gpointer data) { - - GtkTreeIter iter; - GtkTreePath *treePath; - GtkTreeModel *model; - gboolean enable; - account_t* acc ; - // The IP2IP profile can't be disabled - if (utf8_case_cmp(path, "0") == 0) + if (g_strcmp0(path, "0") == 0) return; // Get pointer on object - treePath = gtk_tree_path_new_from_string(path); - model = gtk_tree_view_get_model(GTK_TREE_VIEW(data)); - gtk_tree_model_get_iter(model, &iter, treePath); - gtk_tree_model_get(model, &iter, - COLUMN_ACCOUNT_ACTIVE, &enable, - COLUMN_ACCOUNT_DATA, &acc, - -1); + GtkTreePath *tree_path = gtk_tree_path_new_from_string(path); + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(data)); + GtkTreeIter iter; + gtk_tree_model_get_iter(model, &iter, tree_path); + gboolean enable; + gchar *id; + gtk_tree_model_get(model, &iter, COLUMN_ACCOUNT_ACTIVE, &enable, + COLUMN_ACCOUNT_ID, &id, -1); + account_t *account = account_list_get_by_id(id); + g_assert(account); enable = !enable; - DEBUG("Account is %d enabled", enable); // Store value - gtk_list_store_set(GTK_LIST_STORE(model), &iter, - COLUMN_ACCOUNT_ACTIVE, enable, - -1); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_ACCOUNT_ACTIVE, + enable, -1); // Modify account state - gchar * registrationState; - - if (enable == TRUE) - registrationState = g_strdup("true"); - else - registrationState = g_strdup("false"); + const gchar * enabled_str = enable ? "true" : "false"; + DEBUG("Account is enabled: %s", enabled_str); - DEBUG("Replacing with %s", registrationState); - g_hash_table_replace(acc->properties , g_strdup(ACCOUNT_ENABLED), registrationState); - - dbus_send_register(acc->accountID, enable); + account_replace(account, ACCOUNT_ENABLED, enabled_str); + dbus_send_register(account->accountID, enable); } /** * Move account in list depending on direction and selected account */ -static void account_move(gboolean moveUp, gpointer data) +static void +account_move(gboolean move_up, gpointer data) { - - GtkTreeIter iter; - GtkTreeIter *iter2; - GtkTreeView *treeView; - GtkTreeModel *model; - GtkTreeSelection *selection; - GtkTreePath *treePath; - gchar *path; - - // Get view, model and selection of codec store - treeView = GTK_TREE_VIEW(data); - model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeView)); - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeView)); + // Get view, model and selection of account + GtkTreeView *tree_view = GTK_TREE_VIEW(data); + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view); // Find selected iteration and create a copy - gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), &model, &iter); - iter2 = gtk_tree_iter_copy(&iter); + GtkTreeIter iter; + gtk_tree_selection_get_selected(selection, &model, &iter); + GtkTreeIter *iter_copy; + iter_copy = gtk_tree_iter_copy(&iter); // Find path of iteration - path = gtk_tree_model_get_string_from_iter(GTK_TREE_MODEL(model), &iter); + gchar *path = gtk_tree_model_get_string_from_iter(model, &iter); // The first real account in the list can't move up because of the IP2IP account // It can still move down though - if (utf8_case_cmp(path, "1") == 0 && moveUp) + if (g_strcmp0(path, "1") == 0 && move_up) return; - treePath = gtk_tree_path_new_from_string(path); - gint *indices = gtk_tree_path_get_indices(treePath); - gint indice = indices[0]; + GtkTreePath *tree_path = gtk_tree_path_new_from_string(path); + gint *indices = gtk_tree_path_get_indices(tree_path); + const gint pos = indices[0]; // Depending on button direction get new path - if (moveUp) - gtk_tree_path_prev(treePath); + if (move_up) + gtk_tree_path_prev(tree_path); else - gtk_tree_path_next(treePath); + gtk_tree_path_next(tree_path); - gtk_tree_model_get_iter(model, &iter, treePath); + gtk_tree_model_get_iter(model, &iter, tree_path); // Swap iterations if valid if (gtk_list_store_iter_is_valid(GTK_LIST_STORE(model), &iter)) - gtk_list_store_swap(GTK_LIST_STORE(model), &iter, iter2); + gtk_list_store_swap(GTK_LIST_STORE(model), &iter, iter_copy); // Scroll to new position - gtk_tree_view_scroll_to_cell(treeView, treePath, NULL, FALSE, 0, 0); + gtk_tree_view_scroll_to_cell(tree_view, tree_path, NULL, FALSE, 0, 0); // Free resources - gtk_tree_path_free(treePath); - gtk_tree_iter_free(iter2); + gtk_tree_path_free(tree_path); + gtk_tree_iter_free(iter_copy); g_free(path); // Perpetuate changes in account queue - if (moveUp) - account_list_move_up(indice); + if (move_up) + account_list_move_up(pos); else - account_list_move_down(indice); - + account_list_move_down(pos); // Set the order in the configuration file gchar *ordered_account_list = account_list_get_ordered_list(); @@ -345,9 +341,9 @@ static void account_move(gboolean moveUp, gpointer data) * Called from move up account button signal */ static void -account_move_up_cb(GtkButton *button UNUSED, gpointer data) +move_up_cb(GtkButton *button UNUSED, gpointer data) { - // Change tree view ordering and get indice changed + // Change tree view ordering and get index changed account_move(TRUE, data); } @@ -355,9 +351,9 @@ account_move_up_cb(GtkButton *button UNUSED, gpointer data) * Called from move down account button signal */ static void -account_move_down_cb(GtkButton *button UNUSED, gpointer data) +move_down_cb(GtkButton *button UNUSED, gpointer data) { - // Change tree view ordering and get indice changed + // Change tree view ordering and get index changed account_move(FALSE, data); } @@ -374,181 +370,182 @@ help_contents_cb(GtkWidget * widget UNUSED, } static void -close_dialog_cb(GtkWidget * widget UNUSED, - gpointer data UNUSED) +close_dialog_cb(GtkWidget * widget UNUSED, gpointer data UNUSED) { - gtk_dialog_response(GTK_DIALOG(accountListDialog), GTK_RESPONSE_ACCEPT); - + gtk_dialog_response(GTK_DIALOG(account_list_dialog), GTK_RESPONSE_ACCEPT); } -void highlight_ip_profile(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data UNUSED) +static void +highlight_ip_profile(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend, + GtkTreeModel *tree_model, GtkTreeIter *iter, + gpointer data UNUSED) { - GValue val; - account_t *current; - memset(&val, 0, sizeof(val)); - gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_DATA, &val); - current = (account_t*) g_value_get_pointer(&val); - + gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_ID, &val); + account_t *current = account_list_get_by_id(g_value_get_string(&val)); g_value_unset(&val); - if (current != NULL) { - - // Make the first line appear differently - (utf8_case_cmp(current->accountID, IP2IP) == 0) ? g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_THIN, - "style", PANGO_STYLE_ITALIC, - "stretch", PANGO_STRETCH_ULTRA_EXPANDED, - "scale", 0.95, - NULL) : - g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_MEDIUM, - "style", PANGO_STYLE_NORMAL, - "stretch", PANGO_STRETCH_NORMAL, - "scale", 1.0, - NULL) ; + // Make the IP2IP account appear differently + if (current) { + if (account_is_IP2IP(current)) { + g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_THIN, "style", + PANGO_STYLE_ITALIC, "stretch", + PANGO_STRETCH_ULTRA_EXPANDED, "scale", 0.95, NULL); + } else { + g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_MEDIUM, + "style", PANGO_STYLE_NORMAL, "stretch", + PANGO_STRETCH_NORMAL, "scale", 1.0, NULL); + } } } -void highlight_registration(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data UNUSED) +static const gchar* +state_color(account_t *a) { + if (!account_is_IP2IP(a)) + if (a->state == ACCOUNT_STATE_REGISTERED) + return "Dark Green"; + else + return "Dark Red"; + else + return "Black"; +} +static void +highlight_registration(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend, + GtkTreeModel *tree_model, GtkTreeIter *iter, + gpointer data UNUSED) +{ GValue val; - account_t *current; - memset(&val, 0, sizeof(val)); - gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_DATA, &val); - current = (account_t*) g_value_get_pointer(&val); - + gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_ID, &val); + account_t *current = account_list_get_by_id(g_value_get_string(&val)); g_value_unset(&val); - if (current != NULL) { - if (utf8_case_cmp(current->accountID, IP2IP) != 0) { - // Color the account state: green -> registered, otherwise red - (current->state == ACCOUNT_STATE_REGISTERED) ? g_object_set(G_OBJECT(rend), "foreground", "Dark Green", NULL) : - g_object_set(G_OBJECT(rend), "foreground", "Dark Red", NULL); - } else - g_object_set(G_OBJECT(rend), "foreground", "Black", NULL); - } - + if (current) + g_object_set(G_OBJECT(rend), "foreground", state_color(current), NULL); } /** * Account settings tab */ -GtkWidget* create_account_list(GtkDialog * dialog UNUSED) +static GtkWidget* +create_account_list() { - - GtkWidget *table, *scrolledWindow, *buttonBox; - GtkCellRenderer *renderer; - GtkTreeView * treeView; - GtkTreeViewColumn *treeViewColumn; - GtkTreeSelection *treeSelection; - GtkRequisition requisition; - - selectedAccount = NULL; - - table = gtk_table_new(1, 2, FALSE/* homogeneous */); + GtkWidget *table = gtk_table_new(1, 2, FALSE /* homogeneous */); gtk_table_set_col_spacings(GTK_TABLE(table), 10); gtk_container_set_border_width(GTK_CONTAINER(table), 10); - scrolledWindow = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_SHADOW_IN); - gtk_table_attach(GTK_TABLE(table), scrolledWindow, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - accountStore = gtk_list_store_new(COLUMN_ACCOUNT_COUNT, - G_TYPE_STRING, // Name - G_TYPE_STRING, // Protocol - G_TYPE_STRING, // Status - G_TYPE_BOOLEAN, // Enabled / Disabled - G_TYPE_POINTER // Pointer to the Object - ); - - account_list_config_dialog_fill(); - - treeView = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(accountStore))); - treeSelection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeView)); - g_signal_connect(G_OBJECT(treeSelection), "changed", - G_CALLBACK(select_account_cb), - accountStore); - - renderer = gtk_cell_renderer_toggle_new(); - treeViewColumn = gtk_tree_view_column_new_with_attributes("Enabled", renderer, "active", COLUMN_ACCOUNT_ACTIVE , NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn); - g_signal_connect(G_OBJECT(renderer) , "toggled" , G_CALLBACK(enable_account_cb), (gpointer) treeView); - - // gtk_cell_renderer_toggle_set_activatable (renderer, FALSE); + GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_SHADOW_IN); + gtk_table_attach(GTK_TABLE(table), scrolled_window, 0, 1, 0, 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + + account_store = gtk_list_store_new(COLUMN_ACCOUNT_COUNT, + G_TYPE_STRING, // Name + G_TYPE_STRING, // Protocol + G_TYPE_STRING, // Status + G_TYPE_BOOLEAN, // Enabled / Disabled + G_TYPE_STRING // AccountID + ); + + account_store_fill(); + + GtkTreeView * tree_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(account_store))); + GtkTreeSelection *tree_selection = gtk_tree_view_get_selection(tree_view); + g_signal_connect(G_OBJECT(tree_selection), "changed", + G_CALLBACK(select_account_cb), NULL); + + GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new(); + GtkTreeViewColumn *tree_view_column = + gtk_tree_view_column_new_with_attributes("Enabled", renderer, "active", + COLUMN_ACCOUNT_ACTIVE , NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), tree_view_column); + g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(enable_account_cb), tree_view); renderer = gtk_cell_renderer_text_new(); - treeViewColumn = gtk_tree_view_column_new_with_attributes("Alias", - renderer, - "markup", COLUMN_ACCOUNT_ALIAS, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn); + tree_view_column = gtk_tree_view_column_new_with_attributes("Alias", + renderer, + "markup", + COLUMN_ACCOUNT_ALIAS, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), tree_view_column); // A double click on the account line opens the window to edit the account - g_signal_connect(G_OBJECT(treeView) , "row-activated" , G_CALLBACK(edit_account_cb) , NULL); - gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_ip_profile, NULL, NULL); + g_signal_connect(G_OBJECT(tree_view), "row-activated", G_CALLBACK(row_activated_cb), NULL); + gtk_tree_view_column_set_cell_data_func(tree_view_column, renderer, + highlight_ip_profile, NULL, NULL); renderer = gtk_cell_renderer_text_new(); - treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Protocol"), - renderer, - "markup", COLUMN_ACCOUNT_TYPE, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn); - gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_ip_profile, NULL, NULL); + tree_view_column = gtk_tree_view_column_new_with_attributes(_("Protocol"), + renderer, + "markup", + COLUMN_ACCOUNT_TYPE, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), tree_view_column); + gtk_tree_view_column_set_cell_data_func(tree_view_column, renderer, + highlight_ip_profile, NULL, NULL); renderer = gtk_cell_renderer_text_new(); - treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Status"), + tree_view_column = gtk_tree_view_column_new_with_attributes(_("Status"), renderer, - "markup", COLUMN_ACCOUNT_STATUS, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn); + "markup", COLUMN_ACCOUNT_STATUS, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), tree_view_column); // Highlight IP profile - gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_ip_profile, NULL, NULL); + gtk_tree_view_column_set_cell_data_func(tree_view_column, renderer, + highlight_ip_profile, NULL, NULL); // Highlight account registration state - gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_registration, NULL, NULL); + gtk_tree_view_column_set_cell_data_func(tree_view_column, renderer, + highlight_registration, NULL, + NULL); - g_object_unref(G_OBJECT(accountStore)); + g_object_unref(G_OBJECT(account_store)); - gtk_container_add(GTK_CONTAINER(scrolledWindow), GTK_WIDGET(treeView)); + gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(tree_view)); /* The buttons to press! */ - buttonBox = gtk_button_box_new(GTK_ORIENTATION_VERTICAL); - gtk_box_set_spacing(GTK_BOX(buttonBox), 10); - gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_START); - gtk_table_attach(GTK_TABLE(table), buttonBox, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - accountMoveUpButton = gtk_button_new_from_stock(GTK_STOCK_GO_UP); - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), FALSE); - gtk_box_pack_start(GTK_BOX(buttonBox), accountMoveUpButton, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(accountMoveUpButton), "clicked", G_CALLBACK(account_move_up_cb), treeView); - - accountMoveDownButton = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN); - gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), FALSE); - gtk_box_pack_start(GTK_BOX(buttonBox), accountMoveDownButton, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(accountMoveDownButton), "clicked", G_CALLBACK(account_move_down_cb), treeView); - - addButton = gtk_button_new_from_stock(GTK_STOCK_ADD); - g_signal_connect_swapped(G_OBJECT(addButton), "clicked", + GtkWidget *button_box = gtk_button_box_new(GTK_ORIENTATION_VERTICAL); + gtk_box_set_spacing(GTK_BOX(button_box), 10); + gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_START); + gtk_table_attach(GTK_TABLE(table), button_box, 1, 2, 0, 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + + move_up_button = gtk_button_new_from_stock(GTK_STOCK_GO_UP); + gtk_widget_set_sensitive(move_up_button, FALSE); + gtk_box_pack_start(GTK_BOX(button_box), move_up_button, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(move_up_button), "clicked", + G_CALLBACK(move_up_cb), tree_view); + + move_down_button = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN); + gtk_widget_set_sensitive(move_down_button, FALSE); + gtk_box_pack_start(GTK_BOX(button_box), move_down_button, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(move_down_button), "clicked", + G_CALLBACK(move_down_cb), tree_view); + + GtkWidget *add_button = gtk_button_new_from_stock(GTK_STOCK_ADD); + g_signal_connect_swapped(G_OBJECT(add_button), "clicked", G_CALLBACK(add_account_cb), NULL); - gtk_box_pack_start(GTK_BOX(buttonBox), addButton, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(button_box), add_button, FALSE, FALSE, 0); - editButton = gtk_button_new_from_stock(GTK_STOCK_EDIT); - gtk_widget_set_sensitive(GTK_WIDGET(editButton), FALSE); - g_signal_connect_swapped(G_OBJECT(editButton), "clicked", - G_CALLBACK(edit_account_cb), NULL); - gtk_box_pack_start(GTK_BOX(buttonBox), editButton, FALSE, FALSE, 0); + edit_button = gtk_button_new_from_stock(GTK_STOCK_EDIT); + gtk_widget_set_sensitive(edit_button, FALSE); + g_signal_connect(G_OBJECT(edit_button), "clicked", G_CALLBACK(edit_account_cb), tree_view); + gtk_box_pack_start(GTK_BOX(button_box), edit_button, FALSE, FALSE, 0); - deleteButton = gtk_button_new_from_stock(GTK_STOCK_REMOVE); - gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), FALSE); - g_signal_connect_swapped(G_OBJECT(deleteButton), "clicked", - G_CALLBACK(delete_account_cb), NULL); - gtk_box_pack_start(GTK_BOX(buttonBox), deleteButton, FALSE, FALSE, 0); + delete_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); + gtk_widget_set_sensitive(delete_button, FALSE); + g_signal_connect(G_OBJECT(delete_button), "clicked", + G_CALLBACK(delete_account_cb), tree_view); + gtk_box_pack_start(GTK_BOX(button_box), delete_button, FALSE, FALSE, 0); /* help and close buttons */ GtkWidget * buttonHbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL); - gtk_table_attach(GTK_TABLE(table), buttonHbox, 0, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 10); + gtk_table_attach(GTK_TABLE(table), buttonHbox, 0, 2, 1, 2, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 10); GtkWidget * helpButton = gtk_button_new_from_stock(GTK_STOCK_HELP); g_signal_connect_swapped(G_OBJECT(helpButton), "clicked", @@ -556,71 +553,115 @@ GtkWidget* create_account_list(GtkDialog * dialog UNUSED) gtk_box_pack_start(GTK_BOX(buttonHbox), helpButton, FALSE, FALSE, 0); GtkWidget * closeButton = gtk_button_new_from_stock(GTK_STOCK_CLOSE); - g_signal_connect_swapped(G_OBJECT(closeButton), "clicked", G_CALLBACK(close_dialog_cb), NULL); + g_signal_connect_swapped(G_OBJECT(closeButton), "clicked", + G_CALLBACK(close_dialog_cb), NULL); gtk_box_pack_start(GTK_BOX(buttonHbox), closeButton, FALSE, FALSE, 0); gtk_widget_show_all(table); - // account_list_config_dialog_fill(); - /* Resize the scrolledWindow for a better view */ - gtk_widget_get_preferred_size(GTK_WIDGET(treeView), NULL, &requisition); - gtk_widget_set_size_request(GTK_WIDGET(scrolledWindow), requisition.width + 20, requisition.height); + /* Resize the scrolled window for a better view */ + GtkRequisition requisition; + gtk_widget_get_preferred_size(GTK_WIDGET(tree_view), NULL, &requisition); + gtk_widget_set_size_request(scrolled_window, requisition.width + 20, + requisition.height); GtkRequisition requisitionButton; - gtk_widget_get_preferred_size(GTK_WIDGET(deleteButton), NULL, &requisitionButton); - gtk_widget_set_size_request(GTK_WIDGET(closeButton), requisitionButton.width, -1); - gtk_widget_set_size_request(GTK_WIDGET(helpButton), requisitionButton.width, -1); + gtk_widget_get_preferred_size(delete_button, NULL, &requisitionButton); + gtk_widget_set_size_request(closeButton, requisitionButton.width, -1); + gtk_widget_set_size_request(helpButton, requisitionButton.width, -1); gtk_widget_show_all(table); return table; } -void -show_account_list_config_dialog(void) +void update_account_list_status_bar(account_t *account) { - accountListDialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("Accounts"), - GTK_WINDOW(get_main_window()), - GTK_DIALOG_DESTROY_WITH_PARENT, - NULL, - NULL)); + if (!account || !account_list_status_bar) + return; + + /* Update status bar about current registration state */ + gtk_statusbar_pop(GTK_STATUSBAR(account_list_status_bar), + CONTEXT_ID_REGISTRATION); + + const gchar *state_name = account_state_name(account->state); + if (account->protocol_state_description != NULL && + account->protocol_state_code != 0) { + + gchar * response = g_strdup_printf(_("Server returned \"%s\" (%d)"), + account->protocol_state_description, + account->protocol_state_code); + gchar * message = g_strconcat(state_name, ". ", response, NULL); + gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar), + CONTEXT_ID_REGISTRATION, message); + + g_free(response); + g_free(message); + } else { + gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar), + CONTEXT_ID_REGISTRATION, state_name); + } + + GtkTreeModel *model = GTK_TREE_MODEL(account_store); + GtkTreeIter iter; + if (find_account_in_account_store(account->accountID, model, &iter)) + gtk_list_store_set(account_store, &iter, COLUMN_ACCOUNT_STATUS, state_name, -1); +} + +void show_account_list_config_dialog(void) +{ + account_list_dialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("Accounts"), + GTK_WINDOW(get_main_window()), + GTK_DIALOG_DESTROY_WITH_PARENT, NULL, + NULL)); /* Set window properties */ - gtk_container_set_border_width(GTK_CONTAINER(accountListDialog), 0); - gtk_window_set_resizable(GTK_WINDOW(accountListDialog), FALSE); + gtk_container_set_border_width(GTK_CONTAINER(account_list_dialog), 0); + gtk_window_set_resizable(GTK_WINDOW(account_list_dialog), FALSE); GtkWidget *accountFrame = gnome_main_section_new(_("Configured Accounts")); - gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(accountListDialog)), + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(account_list_dialog)), accountFrame, TRUE, TRUE, 0); gtk_widget_show(accountFrame); /* Accounts tab */ - GtkWidget *tab = create_account_list(accountListDialog); + GtkWidget *tab = create_account_list(); gtk_widget_show(tab); gtk_container_add(GTK_CONTAINER(accountFrame), tab); /* Status bar for the account list */ - status_bar = gtk_statusbar_new(); - gtk_widget_show (status_bar); - gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area(accountListDialog)), status_bar, TRUE, TRUE, 0); + account_list_status_bar = gtk_statusbar_new(); + gtk_widget_show(account_list_status_bar); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(account_list_dialog)), account_list_status_bar, TRUE, TRUE, 0); - int number_accounts = account_list_get_registered_accounts(); + const gint num_accounts = account_list_get_registered_accounts(); - if (number_accounts) { + if (num_accounts) { gchar * message = g_strdup_printf(n_("There is %d active account", "There are %d active accounts", - number_accounts), number_accounts); - gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, message); + num_accounts), num_accounts); + gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar), CONTEXT_ID_REGISTRATION, + message); g_free(message); - } else - gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, + } else { + gtk_statusbar_push(GTK_STATUSBAR(account_list_status_bar), CONTEXT_ID_REGISTRATION, _("You have no active account")); + } - gtk_dialog_run(accountListDialog); + gtk_dialog_run(account_list_dialog); status_bar_display_account(); - gtk_widget_destroy(GTK_WIDGET(accountListDialog)); - accountListDialog = NULL; + gtk_widget_destroy(GTK_WIDGET(account_list_dialog)); + + /* Invalidate static pointers */ + account_list_dialog = NULL; + account_list_status_bar = NULL; + edit_button = NULL; + delete_button = NULL; + move_down_button = NULL; + move_up_button = NULL; + account_store = NULL; + update_actions(); } diff --git a/gnome/src/config/accountlistconfigdialog.h b/gnome/src/config/accountlistconfigdialog.h index 94764a5f989af1dd8282200d7999c89651cdec68..bae376b6d92152cd13c6dc43fcb0dc3765a34cca 100644 --- a/gnome/src/config/accountlistconfigdialog.h +++ b/gnome/src/config/accountlistconfigdialog.h @@ -29,12 +29,12 @@ */ -#ifndef __SFL_ACCOUNTLISTDIALOG_H__ -#define __SFL_ACCOUNTLISTDIALOG_H__ +#ifndef ACCOUNTLISTDIALOG_H_ +#define ACCOUNTLISTDIALOG_H_ -#include <sflphone_const.h> +#include "accountlist.h" -void show_account_list_config_dialog (void); -void account_list_config_dialog_fill (void); +void show_account_list_config_dialog(void); +void update_account_list_status_bar(account_t *account); -#endif +#endif // ACCOUNTLISTDIALOG_H_ diff --git a/gnome/src/config/addressbook-config.c b/gnome/src/config/addressbook-config.c index fd12fc8672196ab13d9fcd1318ae7f60cf3c1e3b..3eb74d378f9db063988bbffe9c3dc1ff3959b0f2 100644 --- a/gnome/src/config/addressbook-config.c +++ b/gnome/src/config/addressbook-config.c @@ -444,14 +444,14 @@ addressbook_display(AddressBook_Config *settings, const gchar *field) { gboolean display; - if (utf8_case_cmp(field, ADDRESSBOOK_DISPLAY_CONTACT_PHOTO) == 0) - display = (settings->display_contact_photo == 1) ? TRUE : FALSE; - else if (utf8_case_cmp(field, ADDRESSBOOK_DISPLAY_PHONE_BUSINESS) == 0) - display = (settings->search_phone_business == 1) ? TRUE : FALSE; - else if (utf8_case_cmp(field, ADDRESSBOOK_DISPLAY_PHONE_HOME) == 0) - display = (settings->search_phone_home == 1) ? TRUE : FALSE; - else if (utf8_case_cmp(field, ADDRESSBOOK_DISPLAY_PHONE_MOBILE) == 0) - display = (settings->search_phone_mobile == 1) ? TRUE : FALSE; + if (utf8_case_equal(field, ADDRESSBOOK_DISPLAY_CONTACT_PHOTO)) + display = settings->display_contact_photo == 1; + else if (utf8_case_equal(field, ADDRESSBOOK_DISPLAY_PHONE_BUSINESS)) + display = settings->search_phone_business == 1; + else if (utf8_case_equal(field, ADDRESSBOOK_DISPLAY_PHONE_HOME)) + display = settings->search_phone_home == 1; + else if (utf8_case_equal(field, ADDRESSBOOK_DISPLAY_PHONE_MOBILE)) + display = settings->search_phone_mobile == 1; else display = FALSE; diff --git a/gnome/src/config/assistant.c b/gnome/src/config/assistant.c index 202767eb2494e390f4ed84f0c633d37945073300..bc74e9cf2c4122655ce2a14d17f8f1ebf06247a0 100644 --- a/gnome/src/config/assistant.c +++ b/gnome/src/config/assistant.c @@ -145,26 +145,25 @@ static void sip_apply_callback(void) } if (account_type == _SIP) { - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ALIAS), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->sip_alias)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ENABLED), g_strdup("true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_MAILBOX), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->sip_voicemail)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_TYPE), g_strdup("SIP")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_HOSTNAME), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->sip_server)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_PASSWORD), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->sip_password)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_USERNAME), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->sip_username)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_SIP_STUN_ENABLED), g_strdup((gchar *)(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiz->enable)) ? "true":"false"))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_SIP_STUN_SERVER), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->addr)))); + account_insert(current, ACCOUNT_ALIAS, gtk_entry_get_text(GTK_ENTRY(wiz->sip_alias))); + account_insert(current, ACCOUNT_ENABLED, "true"); + account_insert(current, ACCOUNT_MAILBOX, gtk_entry_get_text(GTK_ENTRY(wiz->sip_voicemail))); + account_insert(current, ACCOUNT_TYPE, "SIP"); + account_insert(current, ACCOUNT_HOSTNAME, gtk_entry_get_text(GTK_ENTRY(wiz->sip_server))); + account_insert(current, ACCOUNT_PASSWORD, gtk_entry_get_text(GTK_ENTRY(wiz->sip_password))); + account_insert(current, ACCOUNT_USERNAME, gtk_entry_get_text(GTK_ENTRY(wiz->sip_username))); + account_insert(current, ACCOUNT_SIP_STUN_ENABLED, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiz->enable)) ? "true" : "false"); + account_insert(current, ACCOUNT_SIP_STUN_SERVER, gtk_entry_get_text(GTK_ENTRY(wiz->addr))); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiz->zrtp_enable)) == TRUE) { - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_SRTP_ENABLED), g_strdup((gchar *) "true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_KEY_EXCHANGE), g_strdup((gchar *) ZRTP)); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ZRTP_DISPLAY_SAS), g_strdup((gchar *) "true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ZRTP_NOT_SUPP_WARNING), g_strdup((gchar *) "true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ZRTP_HELLO_HASH), g_strdup((gchar *) "true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_DISPLAY_SAS_ONCE), g_strdup((gchar *) "false")); + account_insert(current, ACCOUNT_SRTP_ENABLED, "true"); + account_insert(current, ACCOUNT_KEY_EXCHANGE, ZRTP); + account_insert(current, ACCOUNT_ZRTP_DISPLAY_SAS, "true"); + account_insert(current, ACCOUNT_ZRTP_NOT_SUPP_WARNING, "true"); + account_insert(current, ACCOUNT_ZRTP_HELLO_HASH, "true"); + account_insert(current, ACCOUNT_DISPLAY_SAS_ONCE, "false"); } - // Add default interface info gchar ** iface_list = NULL; iface_list = (gchar**) dbus_get_all_ip_interface_by_name(); @@ -174,9 +173,8 @@ static void sip_apply_callback(void) iface = iface_list; DEBUG("Selected interface %s", *iface); - g_hash_table_insert(current->properties, g_strdup(LOCAL_INTERFACE), g_strdup((gchar *) *iface)); - - g_hash_table_insert(current->properties, g_strdup(PUBLISHED_ADDRESS), g_strdup((gchar *) *iface)); + account_insert(current, LOCAL_INTERFACE, *iface); + account_insert(current, PUBLISHED_ADDRESS, *iface); dbus_add_account(current); getMessageSummary(gtk_entry_get_text(GTK_ENTRY(wiz->sip_alias)), @@ -196,20 +194,19 @@ static void sip_apply_callback(void) static void iax_apply_callback(void) { if (account_type == _IAX) { - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ALIAS), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->iax_alias)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_ENABLED), g_strdup("true")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_MAILBOX), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->iax_voicemail)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_TYPE), g_strdup("IAX")); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_USERNAME), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->iax_username)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_HOSTNAME), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->iax_server)))); - g_hash_table_insert(current->properties, g_strdup(ACCOUNT_PASSWORD), g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(wiz->iax_password)))); + account_insert(current, ACCOUNT_ALIAS, gtk_entry_get_text(GTK_ENTRY(wiz->iax_alias))); + account_insert(current, ACCOUNT_ENABLED, "true"); + account_insert(current, ACCOUNT_MAILBOX, gtk_entry_get_text(GTK_ENTRY(wiz->iax_voicemail))); + account_insert(current, ACCOUNT_TYPE, "IAX"); + account_insert(current, ACCOUNT_USERNAME, gtk_entry_get_text(GTK_ENTRY(wiz->iax_username))); + account_insert(current, ACCOUNT_HOSTNAME, gtk_entry_get_text(GTK_ENTRY(wiz->iax_server))); + account_insert(current, ACCOUNT_PASSWORD, gtk_entry_get_text(GTK_ENTRY(wiz->iax_password))); dbus_add_account(current); getMessageSummary(gtk_entry_get_text(GTK_ENTRY(wiz->iax_alias)), gtk_entry_get_text(GTK_ENTRY(wiz->iax_server)), gtk_entry_get_text(GTK_ENTRY(wiz->iax_username)), - FALSE - ) ; + FALSE); gtk_label_set_text(GTK_LABEL(wiz->label_summary), message); } @@ -228,17 +225,13 @@ void build_wizard(void) return ; wiz = (struct _wizard*) g_malloc(sizeof(struct _wizard)); - current = g_new0(account_t, 1); - current->properties = NULL; - current->properties = dbus_get_account_details(NULL); + current = create_default_account(); if (current->properties == NULL) { DEBUG("Failed to get default values. Creating from scratch"); current->properties = g_hash_table_new(NULL, g_str_equal); } - current->accountID = g_strdup("new"); - wiz->assistant = gtk_assistant_new(); gtk_window_set_title(GTK_WINDOW(wiz->assistant), _("SFLphone account creation wizard")); diff --git a/gnome/src/config/audioconf.c b/gnome/src/config/audioconf.c index 04c2a1e521ec6c572b2d223c86374a9d1e0071b7..759220b166a39891982a59d180a393805e672c7d 100644 --- a/gnome/src/config/audioconf.c +++ b/gnome/src/config/audioconf.c @@ -70,13 +70,14 @@ static void active_is_always_recording(void); /** * Fills the tree list with supported codecs */ -static void preferences_dialog_fill_codec_list(account_t *a) +static void +preferences_dialog_fill_codec_list(const account_t *account) { // Get model of view and clear it GtkListStore *codecStore = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(codecTreeView))); gtk_list_store_clear(codecStore); - GQueue *list = a ? a->acodecs : get_audio_codecs_list(); + GQueue *list = account ? account->acodecs : get_audio_codecs_list(); // Insert codecs for (size_t i = 0; i < list->length; ++i) { @@ -275,7 +276,7 @@ select_active_input_audio_device() void update_device_widget(gchar *pluginName) { - if (utf8_case_cmp(pluginName, "default") == 0) { + if (utf8_case_equal(pluginName, "default")) { gtk_widget_set_sensitive(output, FALSE); gtk_widget_set_sensitive(input, FALSE); gtk_widget_set_sensitive(ringtone, FALSE); @@ -318,7 +319,7 @@ select_active_output_audio_plugin() do { gtk_tree_model_get(model, &iter, 0, &pluginname, -1); - if (utf8_case_cmp(tmp, pluginname) == 0) { + if (utf8_case_equal(tmp, pluginname)) { // Set current iteration the active one gtk_combo_box_set_active_iter(GTK_COMBO_BOX(plugin), &iter); return; @@ -514,7 +515,7 @@ static void codec_move_down(GtkButton *button UNUSED, gpointer data) codec_move(FALSE, data); } -GtkWidget* audiocodecs_box(account_t *a) +GtkWidget* audiocodecs_box(const account_t *account) { GtkWidget *audiocodecs_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); gtk_container_set_border_width(GTK_CONTAINER(audiocodecs_hbox), 10); @@ -545,7 +546,8 @@ GtkWidget* audiocodecs_box(account_t *a) gtk_tree_view_append_column(GTK_TREE_VIEW(codecTreeView), treeViewColumn); // Toggle codec active property on clicked - g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(codec_active_toggled),(gpointer) a); + g_signal_connect(G_OBJECT(renderer), "toggled", + G_CALLBACK(codec_active_toggled), (gpointer) account); // Name column renderer = gtk_cell_renderer_text_new(); @@ -573,14 +575,16 @@ GtkWidget* audiocodecs_box(account_t *a) codecMoveUpButton = gtk_button_new_from_stock(GTK_STOCK_GO_UP); gtk_widget_set_sensitive(GTK_WIDGET(codecMoveUpButton), FALSE); gtk_box_pack_start(GTK_BOX(buttonBox), codecMoveUpButton, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(codecMoveUpButton), "clicked", G_CALLBACK(codec_move_up), a); + g_signal_connect(G_OBJECT(codecMoveUpButton), "clicked", + G_CALLBACK(codec_move_up), (gpointer) account); codecMoveDownButton = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN); gtk_widget_set_sensitive(GTK_WIDGET(codecMoveDownButton), FALSE); gtk_box_pack_start(GTK_BOX(buttonBox), codecMoveDownButton, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(codecMoveDownButton), "clicked", G_CALLBACK(codec_move_down), a); + g_signal_connect(G_OBJECT(codecMoveDownButton), "clicked", + G_CALLBACK(codec_move_down), (gpointer) account); - preferences_dialog_fill_codec_list(a); + preferences_dialog_fill_codec_list(account); return audiocodecs_hbox; } diff --git a/gnome/src/config/audioconf.h b/gnome/src/config/audioconf.h index 6f0b399f733a404964776239e22156bfd4f86058..c3f3e221d1ca9fb51eb143ecccec25c7b0c86a90 100644 --- a/gnome/src/config/audioconf.h +++ b/gnome/src/config/audioconf.h @@ -38,7 +38,7 @@ GtkWidget* create_audio_configuration (void); GtkWidget* api_box(); GtkWidget* alsa_box(); GtkWidget* pulse_box(); -GtkWidget* audiocodecs_box(); +GtkWidget* audiocodecs_box(const account_t *a); GtkWidget* ringtone_box(); gboolean get_api(); diff --git a/gnome/src/config/hooks-config.c b/gnome/src/config/hooks-config.c index 5a161344ac29d414e0b4fb593b12ed6600de1b29..2ff4dc500346fc4cf39a6248acbd2e68dbb8f821 100644 --- a/gnome/src/config/hooks-config.c +++ b/gnome/src/config/hooks-config.c @@ -157,7 +157,7 @@ GtkWidget* create_hooks_settings() gtk_table_attach(GTK_TABLE(table), info_bar, 0, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 10, 10); widg = gtk_check_button_new_with_mnemonic(_("Trigger on specific _SIP header")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), (utf8_case_cmp(_urlhook_config->sip_enabled, "true") ==0) ?TRUE:FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), utf8_case_equal(_urlhook_config->sip_enabled, "true")); g_signal_connect(G_OBJECT(widg) , "clicked" , G_CALLBACK(sip_enabled_cb), NULL); gtk_table_attach(GTK_TABLE(table), widg, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); @@ -166,7 +166,7 @@ GtkWidget* create_hooks_settings() gtk_table_attach(GTK_TABLE(table), field, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); widg = gtk_check_button_new_with_mnemonic(_("Trigger on _IAX2 URL")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), (utf8_case_cmp(_urlhook_config->iax2_enabled, "true") ==0) ?TRUE:FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), utf8_case_equal(_urlhook_config->iax2_enabled, "true")); g_signal_connect(G_OBJECT(widg) , "clicked" , G_CALLBACK(iax2_enabled_cb), NULL); gtk_table_attach(GTK_TABLE(table), widg, 0, 2, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); @@ -183,7 +183,7 @@ GtkWidget* create_hooks_settings() gtk_widget_show(frame); widg = gtk_check_button_new_with_mnemonic(_("_Prefix dialed numbers with")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), (utf8_case_cmp(_urlhook_config->phone_number_enabled, "true") ==0) ?TRUE:FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widg), utf8_case_equal(_urlhook_config->phone_number_enabled, "true")); g_signal_connect(G_OBJECT(widg) , "clicked" , G_CALLBACK(phone_number_enabled_cb), NULL); gtk_table_attach(GTK_TABLE(table), widg, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); diff --git a/gnome/src/config/tlsadvanceddialog.c b/gnome/src/config/tlsadvanceddialog.c index 232c3a8d8938483cc8080ebb03828d792cb5f1eb..7c77eba19ae67b3268fbc1f8b515fa0899b8a135 100644 --- a/gnome/src/config/tlsadvanceddialog.c +++ b/gnome/src/config/tlsadvanceddialog.c @@ -31,13 +31,26 @@ #include "tlsadvanceddialog.h" #include "str_utils.h" #include "sflphone_const.h" +#include "mainwindow.h" #include "utils.h" #include <dbus.h> #include <glib/gi18n.h> #include <gtk/gtk.h> #include <math.h> -void show_advanced_tls_options(GHashTable * properties) +static +const gchar *toggle_to_string(GtkWidget *toggle) +{ + return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)) ? "true" : "false"; +} + +static +const gchar *get_filename(GtkWidget *chooser) +{ + return gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser)); +} + +void show_advanced_tls_options(account_t *account) { GtkDialog *tlsDialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("Advanced options for TLS"), GTK_WINDOW(get_main_window()), @@ -72,7 +85,6 @@ void show_advanced_tls_options(GHashTable * properties) gtk_label_set_markup(GTK_LABEL(label), description); gtk_table_attach(GTK_TABLE(table), label, 0, 3, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gchar * account_id = NULL; gchar * tls_listener_port = NULL; gchar * tls_ca_list_file = NULL; gchar * tls_certificate_file = NULL; @@ -87,23 +99,20 @@ void show_advanced_tls_options(GHashTable * properties) gchar * negotiation_timeout_sec = NULL; gchar * negotiation_timeout_msec = NULL; - if (properties != NULL) { - - account_id = g_hash_table_lookup(properties, ACCOUNT_ID); - tls_listener_port = g_hash_table_lookup(properties, TLS_LISTENER_PORT); - tls_ca_list_file = g_hash_table_lookup(properties, TLS_CA_LIST_FILE); - tls_certificate_file = g_hash_table_lookup(properties, TLS_CERTIFICATE_FILE); - tls_private_key_file = g_hash_table_lookup(properties, TLS_PRIVATE_KEY_FILE); - tls_password = g_hash_table_lookup(properties, TLS_PASSWORD); - tls_method = g_hash_table_lookup(properties, TLS_METHOD); - tls_ciphers = g_hash_table_lookup(properties, TLS_CIPHERS); - tls_server_name = g_hash_table_lookup(properties, TLS_SERVER_NAME); - verify_server = g_hash_table_lookup(properties, TLS_VERIFY_SERVER); - verify_client = g_hash_table_lookup(properties, TLS_VERIFY_CLIENT); - require_client_certificate = g_hash_table_lookup(properties, TLS_REQUIRE_CLIENT_CERTIFICATE); - negotiation_timeout_sec = g_hash_table_lookup(properties, TLS_NEGOTIATION_TIMEOUT_SEC); - negotiation_timeout_msec = g_hash_table_lookup(properties, TLS_NEGOTIATION_TIMEOUT_MSEC); - + if (account->properties != NULL) { + tls_listener_port = account_lookup(account, TLS_LISTENER_PORT); + tls_ca_list_file = account_lookup(account, TLS_CA_LIST_FILE); + tls_certificate_file = account_lookup(account, TLS_CERTIFICATE_FILE); + tls_private_key_file = account_lookup(account, TLS_PRIVATE_KEY_FILE); + tls_password = account_lookup(account, TLS_PASSWORD); + tls_method = account_lookup(account, TLS_METHOD); + tls_ciphers = account_lookup(account, TLS_CIPHERS); + tls_server_name = account_lookup(account, TLS_SERVER_NAME); + verify_server = account_lookup(account, TLS_VERIFY_SERVER); + verify_client = account_lookup(account, TLS_VERIFY_CLIENT); + require_client_certificate = account_lookup(account, TLS_REQUIRE_CLIENT_CERTIFICATE); + negotiation_timeout_sec = account_lookup(account, TLS_NEGOTIATION_TIMEOUT_SEC); + negotiation_timeout_msec = account_lookup(account, TLS_NEGOTIATION_TIMEOUT_MSEC); } @@ -117,9 +126,8 @@ void show_advanced_tls_options(GHashTable * properties) gtk_spin_button_set_value(GTK_SPIN_BUTTON(tlsListenerPort), g_ascii_strtod(tls_listener_port, NULL)); gtk_box_pack_start(GTK_BOX(hbox), tlsListenerPort, TRUE, TRUE, 0); - if (g_strcmp0(account_id, IP2IP_PROFILE) != 0) { + if (!account_is_IP2IP(account)) gtk_widget_set_sensitive(tlsListenerPort, FALSE); - } label = gtk_label_new(_("Certificate of Authority list")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); @@ -127,13 +135,12 @@ void show_advanced_tls_options(GHashTable * properties) GtkWidget * caListFileChooser = gtk_file_chooser_button_new(_("Choose a CA list file (optional)"), GTK_FILE_CHOOSER_ACTION_OPEN); gtk_table_attach(GTK_TABLE(table), caListFileChooser, 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - if (!tls_ca_list_file || !*tls_ca_list_file) { - gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(caListFileChooser)); - } else { + if (tls_ca_list_file && *tls_ca_list_file) { GFile *file = g_file_new_for_path(tls_ca_list_file); gtk_file_chooser_set_file(GTK_FILE_CHOOSER(caListFileChooser), file, NULL); g_object_unref(file); + } else { + gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(caListFileChooser)); } label = gtk_label_new(_("Public endpoint certificate file")); @@ -251,71 +258,53 @@ void show_advanced_tls_options(GHashTable * properties) GtkWidget * verifyCertificateServer; verifyCertificateServer = gtk_check_button_new_with_mnemonic(_("Verify incoming certificates, as a server")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(verifyCertificateServer), - utf8_case_cmp(verify_server,"true") == 0); + utf8_case_equal(verify_server, "true")); gtk_table_attach(GTK_TABLE(table), verifyCertificateServer, 0, 1, 11, 12, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); GtkWidget * verifyCertificateClient; verifyCertificateClient = gtk_check_button_new_with_mnemonic(_("Verify certificates from answer, as a client")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(verifyCertificateClient), - utf8_case_cmp(verify_client,"true") == 0); + utf8_case_equal(verify_client, "true")); gtk_table_attach(GTK_TABLE(table), verifyCertificateClient, 0, 1, 12, 13, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); GtkWidget * requireCertificate; requireCertificate = gtk_check_button_new_with_mnemonic(_("Require certificate for incoming tls connections")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(requireCertificate), - utf8_case_cmp(require_client_certificate,"true") == 0); + utf8_case_equal(require_client_certificate,"true")); gtk_table_attach(GTK_TABLE(table), requireCertificate, 0, 1, 13, 14, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show_all(ret); if (gtk_dialog_run(GTK_DIALOG(tlsDialog)) == GTK_RESPONSE_ACCEPT) { - g_hash_table_replace(properties, - g_strdup(TLS_LISTENER_PORT), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(tlsListenerPort)))); - g_hash_table_replace(properties, - g_strdup(TLS_CA_LIST_FILE), g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(caListFileChooser)))); + account_replace(account, TLS_LISTENER_PORT, + gtk_entry_get_text(GTK_ENTRY(tlsListenerPort))); + account_replace(account, TLS_CA_LIST_FILE, get_filename(caListFileChooser)); - g_hash_table_replace(properties, - g_strdup(TLS_CERTIFICATE_FILE), g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(certificateFileChooser)))); + account_replace(account, TLS_CERTIFICATE_FILE, + get_filename(certificateFileChooser)); - g_hash_table_replace(properties, - g_strdup(TLS_PRIVATE_KEY_FILE), g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(privateKeyFileChooser)))); + account_replace(account, TLS_PRIVATE_KEY_FILE, + get_filename(privateKeyFileChooser)); - g_hash_table_replace(properties, - g_strdup(TLS_PASSWORD), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(privateKeyPasswordEntry)))); + account_replace(account, TLS_PASSWORD, gtk_entry_get_text(GTK_ENTRY(privateKeyPasswordEntry))); - g_hash_table_replace(properties, - g_strdup(TLS_METHOD), - g_strdup((gchar *) gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(tlsProtocolMethodCombo)))); + gchar *tls_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(tlsProtocolMethodCombo)); + account_replace(account, TLS_METHOD, tls_text); + g_free(tls_text); - g_hash_table_replace(properties, - g_strdup(TLS_CIPHERS), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(cipherListEntry)))); + account_replace(account, TLS_CIPHERS, gtk_entry_get_text(GTK_ENTRY(cipherListEntry))); - g_hash_table_replace(properties, - g_strdup(TLS_SERVER_NAME), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(serverNameInstance)))); + account_replace(account, TLS_SERVER_NAME, gtk_entry_get_text(GTK_ENTRY(serverNameInstance))); - g_hash_table_replace(properties, - g_strdup(TLS_VERIFY_SERVER), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(verifyCertificateServer)) ? "true": "false")); + account_replace(account, TLS_VERIFY_SERVER, toggle_to_string(verifyCertificateServer)); - g_hash_table_replace(properties, - g_strdup(TLS_VERIFY_CLIENT), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(verifyCertificateClient)) ? "true": "false")); + account_replace(account, TLS_VERIFY_CLIENT, toggle_to_string(verifyCertificateClient)); - g_hash_table_replace(properties, - g_strdup(TLS_REQUIRE_CLIENT_CERTIFICATE), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(requireCertificate)) ? "true": "false")); + account_replace(account, TLS_REQUIRE_CLIENT_CERTIFICATE, toggle_to_string(requireCertificate)); - g_hash_table_replace(properties, - g_strdup(TLS_NEGOTIATION_TIMEOUT_SEC), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(tlsTimeOutSec)))); + account_replace(account, TLS_NEGOTIATION_TIMEOUT_SEC, gtk_entry_get_text(GTK_ENTRY(tlsTimeOutSec))); - g_hash_table_replace(properties, - g_strdup(TLS_NEGOTIATION_TIMEOUT_MSEC), - g_strdup((gchar *) gtk_entry_get_text(GTK_ENTRY(tlsTimeOutMSec)))); + account_replace(account, TLS_NEGOTIATION_TIMEOUT_MSEC, gtk_entry_get_text(GTK_ENTRY(tlsTimeOutMSec))); } gtk_widget_destroy(GTK_WIDGET(tlsDialog)); diff --git a/gnome/src/config/tlsadvanceddialog.h b/gnome/src/config/tlsadvanceddialog.h index 35d45d7eee4787c0b0d90a48e2704696d36b5cea..73a40ea6da7838d77ab680cf82019552eab7bc8f 100644 --- a/gnome/src/config/tlsadvanceddialog.h +++ b/gnome/src/config/tlsadvanceddialog.h @@ -28,19 +28,16 @@ * as that of the covered work. */ -#ifndef __SFL_TLS_ADVANCED_DIALOG__ -#define __SFL_TLS_ADVANCED_DIALOG__ +#ifndef TLS_ADVANCED_DIALOG_ +#define TLS_ADVANCED_DIALOG_ /** @file tlsadvanceddialog.h * @brief Display the advanced options window for tls */ -#include <glib.h> -#include <mainwindow.h> - +#include "accountlist.h" /** * Display the advanced options window for zrtp */ - -void show_advanced_tls_options (GHashTable * properties); +void show_advanced_tls_options(account_t *account); #endif diff --git a/gnome/src/config/zrtpadvanceddialog.c b/gnome/src/config/zrtpadvanceddialog.c index efb80d976356707b01d34d83fe143c9a1792b761..8b1090655239eb32a19fac11c086d45babc3a6ad 100644 --- a/gnome/src/config/zrtpadvanceddialog.c +++ b/gnome/src/config/zrtpadvanceddialog.c @@ -31,22 +31,23 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> #include "str_utils.h" -#include <zrtpadvanceddialog.h> +#include "mainwindow.h" +#include "zrtpadvanceddialog.h" #include "sflphone_const.h" #include "utils.h" -void show_advanced_zrtp_options(GHashTable * properties) +void show_advanced_zrtp_options(account_t *account) { gboolean curSasConfirm = TRUE; gboolean curHelloEnabled = TRUE; gboolean curZrtpNotSuppOther = TRUE; gboolean curDisplaySasOnce = FALSE; - if (properties != NULL) { - curHelloEnabled = !utf8_case_cmp(g_hash_table_lookup(properties, ACCOUNT_ZRTP_HELLO_HASH), "true"); - curSasConfirm = !utf8_case_cmp(g_hash_table_lookup(properties, ACCOUNT_ZRTP_DISPLAY_SAS), "true"); - curZrtpNotSuppOther = !utf8_case_cmp(g_hash_table_lookup(properties, ACCOUNT_ZRTP_NOT_SUPP_WARNING), "true"); - curDisplaySasOnce = !utf8_case_cmp(g_hash_table_lookup(properties, ACCOUNT_DISPLAY_SAS_ONCE), "true"); + if (account != NULL) { + curHelloEnabled = utf8_case_equal(account_lookup(account, ACCOUNT_ZRTP_HELLO_HASH), "true"); + curSasConfirm = utf8_case_equal(account_lookup(account, ACCOUNT_ZRTP_DISPLAY_SAS), "true"); + curZrtpNotSuppOther = utf8_case_equal(account_lookup(account, ACCOUNT_ZRTP_NOT_SUPP_WARNING), "true"); + curDisplaySasOnce = utf8_case_equal(account_lookup(account, ACCOUNT_DISPLAY_SAS_ONCE), "true"); } GtkDialog *securityDialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("ZRTP Options"), @@ -56,13 +57,11 @@ void show_advanced_zrtp_options(GHashTable * properties) GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL) - ); + NULL)); gtk_window_set_resizable(GTK_WINDOW(securityDialog), FALSE); gtk_container_set_border_width(GTK_CONTAINER(securityDialog), 0); - - GtkWidget *tableZrtp = gtk_table_new(4, 2 , FALSE/* homogeneous */); + GtkWidget *tableZrtp = gtk_table_new(4, 2, FALSE /* homogeneous */); gtk_table_set_row_spacings(GTK_TABLE(tableZrtp), 10); gtk_table_set_col_spacings(GTK_TABLE(tableZrtp), 10); gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(securityDialog)), tableZrtp, FALSE, FALSE, 0); @@ -71,70 +70,63 @@ void show_advanced_zrtp_options(GHashTable * properties) GtkWidget *enableHelloHash = gtk_check_button_new_with_mnemonic(_("Send Hello Hash in S_DP")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableHelloHash), curHelloEnabled); gtk_table_attach(GTK_TABLE(tableZrtp), enableHelloHash, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(enableHelloHash) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(enableHelloHash), TRUE); GtkWidget *enableSASConfirm = gtk_check_button_new_with_mnemonic(_("Ask User to Confirm SAS")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableSASConfirm), curSasConfirm); gtk_table_attach(GTK_TABLE(tableZrtp), enableSASConfirm, 0, 1, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(enableSASConfirm) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(enableSASConfirm), TRUE); GtkWidget *enableZrtpNotSuppOther = gtk_check_button_new_with_mnemonic(_("_Warn if ZRTP not supported")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableZrtpNotSuppOther), curZrtpNotSuppOther); gtk_table_attach(GTK_TABLE(tableZrtp), enableZrtpNotSuppOther, 0, 1, 4, 5, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(enableZrtpNotSuppOther) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(enableZrtpNotSuppOther), TRUE); GtkWidget *displaySasOnce = gtk_check_button_new_with_mnemonic(_("Display SAS once for hold events")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displaySasOnce), curDisplaySasOnce); gtk_table_attach(GTK_TABLE(tableZrtp), displaySasOnce, 0, 1, 5, 6, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(displaySasOnce) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(displaySasOnce), TRUE); gtk_widget_show_all(tableZrtp); gtk_container_set_border_width(GTK_CONTAINER(tableZrtp), 10); if (gtk_dialog_run(GTK_DIALOG(securityDialog)) == GTK_RESPONSE_ACCEPT) { - g_hash_table_replace(properties, - g_strdup(ACCOUNT_ZRTP_DISPLAY_SAS), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableSASConfirm)) ? "true": "false")); + account_replace(account, ACCOUNT_ZRTP_DISPLAY_SAS, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableSASConfirm)) ? "true": "false"); - g_hash_table_replace(properties, - g_strdup(ACCOUNT_DISPLAY_SAS_ONCE), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(displaySasOnce)) ? "true": "false")); + account_replace(account, ACCOUNT_DISPLAY_SAS_ONCE, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(displaySasOnce)) ? "true": "false"); - g_hash_table_replace(properties, - g_strdup(ACCOUNT_ZRTP_HELLO_HASH), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableHelloHash)) ? "true": "false")); + account_replace(account, ACCOUNT_ZRTP_HELLO_HASH, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableHelloHash)) ? "true": "false"); - g_hash_table_replace(properties, - g_strdup(ACCOUNT_ZRTP_NOT_SUPP_WARNING), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableZrtpNotSuppOther)) ? "true": "false")); + account_replace(account, ACCOUNT_ZRTP_NOT_SUPP_WARNING, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableZrtpNotSuppOther)) ? "true": "false"); } gtk_widget_destroy(GTK_WIDGET(securityDialog)); } -void show_advanced_sdes_options(GHashTable * properties) +void show_advanced_sdes_options(account_t *account) { gboolean rtpFallback = FALSE; - if (properties != NULL) { - rtpFallback = !utf8_case_cmp(g_hash_table_lookup(properties, ACCOUNT_SRTP_RTP_FALLBACK), "true"); - } + if (account != NULL) + rtpFallback = utf8_case_equal(account_lookup(account, ACCOUNT_SRTP_RTP_FALLBACK), "true"); GtkDialog *securityDialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("SDES Options"), GTK_WINDOW(get_main_window()), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, - GTK_RESPONSE_ACCEPT, - NULL)); + GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, + GTK_RESPONSE_ACCEPT, NULL)); gtk_window_set_resizable(GTK_WINDOW(securityDialog), FALSE); gtk_container_set_border_width(GTK_CONTAINER(securityDialog), 0); - GtkWidget *sdesTable = gtk_table_new(1, 2 , FALSE/* homogeneous */); + GtkWidget *sdesTable = gtk_table_new(1, 2, FALSE /* homogeneous */); gtk_table_set_row_spacings(GTK_TABLE(sdesTable), 10); gtk_table_set_col_spacings(GTK_TABLE(sdesTable), 10); gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(securityDialog)), sdesTable, FALSE, FALSE, 0); @@ -143,16 +135,15 @@ void show_advanced_sdes_options(GHashTable * properties) GtkWidget *enableRtpFallback = gtk_check_button_new_with_mnemonic(_("Fallback on RTP on SDES failure")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableRtpFallback), rtpFallback); gtk_table_attach(GTK_TABLE(sdesTable), enableRtpFallback, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_set_sensitive(GTK_WIDGET(enableRtpFallback) , TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(enableRtpFallback), TRUE); gtk_widget_show_all(sdesTable); gtk_container_set_border_width(GTK_CONTAINER(sdesTable), 10); if (gtk_dialog_run(GTK_DIALOG(securityDialog)) == GTK_RESPONSE_ACCEPT) { - g_hash_table_replace(properties, - g_strdup(ACCOUNT_SRTP_RTP_FALLBACK), - g_strdup(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableRtpFallback)) ? "true": "false")); + account_replace(account, ACCOUNT_SRTP_RTP_FALLBACK, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enableRtpFallback)) ? "true": "false"); } gtk_widget_destroy(GTK_WIDGET(securityDialog)); diff --git a/gnome/src/config/zrtpadvanceddialog.h b/gnome/src/config/zrtpadvanceddialog.h index 0a98ddb96089001c66f0df3cdf15e3b20de00fb0..ddc09114beb8d4fbb2455139c981618bf4e324af 100644 --- a/gnome/src/config/zrtpadvanceddialog.h +++ b/gnome/src/config/zrtpadvanceddialog.h @@ -34,14 +34,13 @@ * @brief Display the advanced options window for zrtp */ -#include <glib.h> -#include <mainwindow.h> +#include "accountlist.h" /** * Display the advanced options window for zrtp */ -void show_advanced_zrtp_options (GHashTable * properties); +void show_advanced_zrtp_options (account_t *account); -void show_advanced_sdes_options (GHashTable * properties); +void show_advanced_sdes_options (account_t *account); #endif diff --git a/gnome/src/contacts/calltab.c b/gnome/src/contacts/calltab.c index 7ff8c1ccc55d40b487c31cfbadb6c90db0458201..af12e642742b7216ac5d10706cd2a0c022e2d53f 100644 --- a/gnome/src/contacts/calltab.c +++ b/gnome/src/contacts/calltab.c @@ -98,9 +98,9 @@ calltab_create_searchbar(calltab_t* tab) { g_assert(tab); - if (utf8_case_cmp(tab->_name, HISTORY) == 0) + if (utf8_case_equal(tab->_name, HISTORY)) tab->searchbar = history_searchbar_new(); - else if (utf8_case_cmp(tab->_name, CONTACTS) == 0) + else if (utf8_case_equal(tab->_name, CONTACTS)) tab->searchbar = contacts_searchbar_new(); else ERROR("Current calls tab does not need a searchbar\n"); diff --git a/gnome/src/contacts/calltree.c b/gnome/src/contacts/calltree.c index 2669e56ea5ec2bf8bf675511276dbd1f2511f546..80800010eed9acec1bce652846419353bebaef6a 100644 --- a/gnome/src/contacts/calltree.c +++ b/gnome/src/contacts/calltree.c @@ -292,7 +292,7 @@ row_single_click(GtkTreeView *tree_view UNUSED, void * data UNUSED) case SRTP_STATE_ZRTP_SAS_UNCONFIRMED: selectedCall->_srtp_state = SRTP_STATE_ZRTP_SAS_CONFIRMED; - if (utf8_case_cmp(displaySasOnce, "true") == 0) + if (utf8_case_equal(displaySasOnce, "true")) selectedCall->_zrtp_confirmed = TRUE; dbus_confirm_sas(selectedCall); @@ -668,25 +668,21 @@ calltree_update_call_recursive(calltab_t* tab, callable_obj_t * c, GtkTreeIter * gchar* srtp_enabled = NULL; gboolean display_sas = TRUE; - account_t* account_details=NULL; + account_t* account = NULL; int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), parent); if (c) { - account_details = account_list_get_by_id(c->_accountID); - - if (account_details != NULL) { - srtp_enabled = g_hash_table_lookup(account_details->properties, ACCOUNT_SRTP_ENABLED); + account = account_list_get_by_id(c->_accountID); - if (utf8_case_cmp(g_hash_table_lookup(account_details->properties, ACCOUNT_ZRTP_DISPLAY_SAS),"false") == 0) - display_sas = FALSE; + if (account != NULL) { + srtp_enabled = account_lookup(account, ACCOUNT_SRTP_ENABLED); + display_sas = utf8_case_equal(account_lookup(account, ACCOUNT_ZRTP_DISPLAY_SAS), "true"); } else { GHashTable * properties = sflphone_get_ip2ip_properties(); if (properties != NULL) { srtp_enabled = g_hash_table_lookup(properties, ACCOUNT_SRTP_ENABLED); - - if (utf8_case_cmp(g_hash_table_lookup(properties, ACCOUNT_ZRTP_DISPLAY_SAS),"false") == 0) - display_sas = FALSE; + display_sas = utf8_case_equal(g_hash_table_lookup(properties, ACCOUNT_ZRTP_DISPLAY_SAS), "true"); } } } @@ -771,12 +767,12 @@ calltree_update_call_recursive(calltab_t* tab, callable_obj_t * c, GtkTreeIter * pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_certified.svg", NULL); break; case SRTP_STATE_UNLOCKED: - if (utf8_case_cmp(srtp_enabled,"true") == 0) + if (utf8_case_equal(srtp_enabled, "true")) pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL); break; default: WARN("Update calltree srtp state #%d- Should not happen!", c->_srtp_state); - if (utf8_case_cmp(srtp_enabled, "true") == 0) + if (utf8_case_equal(srtp_enabled, "true")) pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL); } @@ -884,7 +880,7 @@ void calltree_add_call(calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent) WARN("Update calltree add - Should not happen!"); } - if (srtp_enabled && utf8_case_cmp(srtp_enabled, "true") == 0) + if (srtp_enabled && utf8_case_equal(srtp_enabled, "true")) pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/secure_off.svg", NULL); } else if (tab == contacts_tab) @@ -1045,7 +1041,7 @@ void calltree_add_conference_to_current_calls(conference_obj_t* conf) else srtp_enabled = g_hash_table_lookup(account_details->properties, ACCOUNT_SRTP_ENABLED); - if (utf8_case_cmp(srtp_enabled, "true") == 0) { + if (utf8_case_equal(srtp_enabled, "true")) { DEBUG("Calltree: SRTP enabled for participant %s", call_id); conf->_conf_srtp_enabled = TRUE; break; diff --git a/gnome/src/dbus/configurationmanager-introspec.xml b/gnome/src/dbus/configurationmanager-introspec.xml index 19ded470d6556d8a549c7fbcc625f7f7c07baeae..2021a4b3e54216fd0b7c272020f332ae8e97e66d 100644 --- a/gnome/src/dbus/configurationmanager-introspec.xml +++ b/gnome/src/dbus/configurationmanager-introspec.xml @@ -449,6 +449,21 @@ <signal name="accountsChanged" tp:name-for-bindings="accountsChanged"> </signal> + <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged"> + <arg type="s" name="accountID"/> + <arg type="i" name="registration_state"/> + </signal> + + <signal name="stunStatusFailure" tp:name-for_bindings="stunStatusFailure"> + <arg type="s" name="reason"> + </arg> + </signal> + + <signal name="stunStatusSuccess" tp:name-for_bindings="stunStatusSuccess"> + <arg type="s" name="message"> + </arg> + </signal> + <signal name="errorAlert" tp:name-for-bindings="errorAlert"> <arg type="i" name="code"> </arg> diff --git a/gnome/src/dbus/dbus.c b/gnome/src/dbus/dbus.c index 33af8b7c5e813d1a679b93adb85d22e31a68787f..6f96d63ea3ac25e1deba37ed9614be6f112fa02b 100644 --- a/gnome/src/dbus/dbus.c +++ b/gnome/src/dbus/dbus.c @@ -45,12 +45,12 @@ #endif #include "instance-glue.h" #include "preferencesdialog.h" -#include "accountlistconfigdialog.h" #include "mainwindow.h" #include "marshaller.h" #include "sliders.h" #include "statusicon.h" #include "assistant.h" +#include "accountlistconfigdialog.h" #include "dbus.h" #include "actions.h" @@ -251,7 +251,7 @@ process_nonexisting_call_state_change(const gchar *callID, const gchar *state) GHashTable *call_details = dbus_get_call_details(callID); callable_obj_t *new_call = create_new_call_from_details(callID, call_details); - if (utf8_case_cmp(g_hash_table_lookup(call_details, "CALL_TYPE"), INCOMING_STRING) == 0) + if (utf8_case_equal(g_hash_table_lookup(call_details, "CALL_TYPE"), INCOMING_STRING)) new_call->_history_state = g_strdup(INCOMING_STRING); else new_call->_history_state = g_strdup(OUTGOING_STRING); @@ -431,16 +431,39 @@ record_playback_stopped_cb(DBusGProxy *proxy UNUSED, const gchar *filepath) update_actions(); } +static void +registration_state_changed_cb(DBusGProxy *proxy UNUSED, const gchar *accountID, + guint state, void *foo UNUSED) +{ + DEBUG("DBus: Registration state changed to %s for account %s", + account_state_name(state), accountID); + account_t *acc = account_list_get_by_id(accountID); + if (acc) { + acc->state = state; + update_account_list_status_bar(acc); + } +} + static void accounts_changed_cb(DBusGProxy *proxy UNUSED, void *foo UNUSED) { sflphone_fill_account_list(); sflphone_fill_ip2ip_profile(); - account_list_config_dialog_fill(); status_bar_display_account(); statusicon_set_tooltip(); } +static void +stun_status_failure_cb(DBusGProxy *proxy UNUSED, const gchar *reason, void *foo UNUSED) +{ + ERROR("Error: Stun status failure: %s failed", reason); +} + +static void +stun_status_success_cb(DBusGProxy *proxy UNUSED, const gchar *message UNUSED, void *foo UNUSED) +{ +} + static void transfer_succeeded_cb(DBusGProxy *proxy UNUSED, void *foo UNUSED) { @@ -622,43 +645,98 @@ gboolean dbus_connect_session_manager(DBusGConnection *connection) gboolean dbus_connect(GError **error) { + const char *dbus_message_bus_name = "org.sflphone.SFLphone"; + const char *dbus_object_instance = "/org/sflphone/SFLphone/Instance"; + const char *dbus_interface = "org.sflphone.SFLphone.Instance"; + const char *callmanager_object_instance = "/org/sflphone/SFLphone/CallManager"; + const char *callmanager_interface = "org.sflphone.SFLphone.CallManager"; + const char *configurationmanager_object_instance = "/org/sflphone/SFLphone/ConfigurationManager"; + const char *configurationmanager_interface = "org.sflphone.SFLphone.ConfigurationManager"; + g_type_init(); DBusGConnection *connection = dbus_g_bus_get(DBUS_BUS_SESSION, error); - if (connection == NULL) { ERROR("DBUS: Error, could not establish connection with session bus"); return FALSE; } /* Create a proxy object for the "bus driver" (name "org.freedesktop.DBus") */ + DEBUG("Connect to message bus: %s", dbus_message_bus_name); + DEBUG(" object instance: %s", dbus_object_instance); + DEBUG(" dbus interface: %s", dbus_interface); - instance_proxy = dbus_g_proxy_new_for_name(connection, - "org.sflphone.SFLphone", "/org/sflphone/SFLphone/Instance", - "org.sflphone.SFLphone.Instance"); - + instance_proxy = dbus_g_proxy_new_for_name(connection, dbus_message_bus_name, dbus_object_instance, dbus_interface); if (instance_proxy == NULL) { - ERROR("Failed to get proxy to Instance"); + ERROR("Error: Failed to connect to %s", dbus_message_bus_name); return FALSE; } - DEBUG("DBus connected to Instance"); + DEBUG("Connect to object instance: %s", callmanager_object_instance); + DEBUG(" dbus interface: %s", callmanager_interface); - call_proxy = dbus_g_proxy_new_for_name(connection, "org.sflphone.SFLphone", - "/org/sflphone/SFLphone/CallManager", - "org.sflphone.SFLphone.CallManager"); - g_assert(call_proxy != NULL); + call_proxy = dbus_g_proxy_new_for_name(connection, dbus_message_bus_name, callmanager_object_instance, callmanager_interface); + if (call_proxy == NULL) { + ERROR("Error: Failed to connect to %s", callmanager_object_instance); + return FALSE; + } - DEBUG("DBus connected to CallManager"); - /* STRING STRING STRING Marshaller */ - /* Incoming call */ + config_proxy = dbus_g_proxy_new_for_name(connection, dbus_message_bus_name, configurationmanager_object_instance, configurationmanager_interface); + if (config_proxy == NULL) { + ERROR("Error: Failed to connect to %s", configurationmanager_object_instance); + return FALSE; + } + + /* Register INT Marshaller */ + dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__INT, + G_TYPE_NONE, G_TYPE_INT, G_TYPE_INVALID); + + /* Register STRING STRING STRING Marshaller */ dbus_g_object_register_marshaller( g_cclosure_user_marshal_VOID__STRING_STRING_STRING, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); + + /* Register STRING STRING INT Marshaller */ + dbus_g_object_register_marshaller( + g_cclosure_user_marshal_VOID__STRING_STRING_INT, G_TYPE_NONE, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); + + /* Register STRING STRING Marshaller */ + dbus_g_object_register_marshaller( + g_cclosure_user_marshal_VOID__STRING_STRING, G_TYPE_NONE, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_INVALID); + + /* Register STRING INT Marshaller */ + dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING_INT, + G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); + + /* Register STRING DOUBLE Marshaller */ + dbus_g_object_register_marshaller( + g_cclosure_user_marshal_VOID__STRING_DOUBLE, G_TYPE_NONE, G_TYPE_STRING, + G_TYPE_DOUBLE, G_TYPE_INVALID); + + /* Register STRING Marshaller */ + dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING, + G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID); + + /* Register STRING STRING BOOL Marshaller */ + dbus_g_object_register_marshaller( + g_cclosure_user_marshal_VOID__STRING_STRING_BOOL, G_TYPE_NONE, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID); + + /* Register STRING Marshaller */ + dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING, + G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID); + + + DEBUG("Adding callmanager Dbus signals"); + + /* Incoming call */ dbus_g_proxy_add_signal(call_proxy, "newCallCreated", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "newCallCreated", G_CALLBACK(new_call_created_cb), NULL, NULL); + dbus_g_proxy_add_signal(call_proxy, "incomingCall", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "incomingCall", @@ -669,30 +747,26 @@ gboolean dbus_connect(GError **error) dbus_g_proxy_connect_signal(call_proxy, "zrtpNegotiationFailed", G_CALLBACK(zrtp_negotiation_failed_cb), NULL, NULL); - /* Register a marshaller for STRING,STRING */ - dbus_g_object_register_marshaller( - g_cclosure_user_marshal_VOID__STRING_STRING, G_TYPE_NONE, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "callStateChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "callStateChanged", G_CALLBACK(call_state_cb), NULL, NULL); - dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING_INT, - G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "voiceMailNotify", G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "voiceMailNotify", G_CALLBACK(voice_mail_cb), NULL, NULL); + dbus_g_proxy_add_signal(config_proxy, "registrationStateChanged", G_TYPE_STRING, + G_TYPE_INT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(config_proxy, "registrationStateChanged", + G_CALLBACK(registration_state_changed_cb), NULL, NULL); + dbus_g_proxy_add_signal(call_proxy, "incomingMessage", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "incomingMessage", G_CALLBACK(incoming_message_cb), NULL, NULL); - dbus_g_object_register_marshaller( - g_cclosure_user_marshal_VOID__STRING_DOUBLE, G_TYPE_NONE, G_TYPE_STRING, - G_TYPE_DOUBLE, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "volumeChanged", G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "volumeChanged", @@ -707,9 +781,6 @@ gboolean dbus_connect(GError **error) G_CALLBACK(transfer_failed_cb), NULL, NULL); /* Conference related callback */ - - dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING, - G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "conferenceChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "conferenceChanged", @@ -730,12 +801,12 @@ gboolean dbus_connect(GError **error) G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "recordPlaybackFilepath", G_CALLBACK(record_playback_filepath_cb), NULL, NULL); + dbus_g_proxy_add_signal(call_proxy, "recordPlaybackStopped", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "recordPlaybackStopped", G_CALLBACK(record_playback_stopped_cb), NULL, NULL); /* Security related callbacks */ - dbus_g_proxy_add_signal(call_proxy, "secureSdesOn", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "secureSdesOn", @@ -746,10 +817,6 @@ gboolean dbus_connect(GError **error) dbus_g_proxy_connect_signal(call_proxy, "secureSdesOff", G_CALLBACK(secure_sdes_off_cb), NULL, NULL); - /* Register a marshaller for STRING,STRING,BOOL */ - dbus_g_object_register_marshaller( - g_cclosure_user_marshal_VOID__STRING_STRING_BOOL, G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "showSAS", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "showSAS", @@ -760,48 +827,43 @@ gboolean dbus_connect(GError **error) dbus_g_proxy_connect_signal(call_proxy, "secureZrtpOn", G_CALLBACK(secure_zrtp_on_cb), NULL, NULL); - /* Register a marshaller for STRING*/ - dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING, - G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_add_signal(call_proxy, "secureZrtpOff", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "secureZrtpOff", G_CALLBACK(secure_zrtp_off_cb), NULL, NULL); + dbus_g_proxy_add_signal(call_proxy, "zrtpNotSuppOther", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "zrtpNotSuppOther", G_CALLBACK(zrtp_not_supported_cb), NULL, NULL); + dbus_g_proxy_add_signal(call_proxy, "confirmGoClear", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "confirmGoClear", G_CALLBACK(confirm_go_clear_cb), NULL, NULL); - /* VOID STRING STRING INT */ - dbus_g_object_register_marshaller( - g_cclosure_user_marshal_VOID__STRING_STRING_INT, G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); - dbus_g_proxy_add_signal(call_proxy, "sipCallStateChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID); dbus_g_proxy_connect_signal(call_proxy, "sipCallStateChanged", G_CALLBACK(sip_call_state_cb), NULL, NULL); - config_proxy = dbus_g_proxy_new_for_name(connection, - "org.sflphone.SFLphone", - "/org/sflphone/SFLphone/ConfigurationManager", - "org.sflphone.SFLphone.ConfigurationManager"); - g_assert(config_proxy != NULL); - DEBUG("DBus connected to ConfigurationManager"); + DEBUG("Adding configurationmanager Dbus signals"); + dbus_g_proxy_add_signal(config_proxy, "accountsChanged", G_TYPE_INVALID); dbus_g_proxy_connect_signal(config_proxy, "accountsChanged", G_CALLBACK(accounts_changed_cb), NULL, NULL); - dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__INT, - G_TYPE_NONE, G_TYPE_INT, G_TYPE_INVALID); - dbus_g_proxy_add_signal(config_proxy, "errorAlert", G_TYPE_INT, - G_TYPE_INVALID); + dbus_g_proxy_add_signal(config_proxy, "stunStatusFailure", G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(config_proxy, "stunStatusFailure", + G_CALLBACK(stun_status_failure_cb), NULL, NULL); + + dbus_g_proxy_add_signal(config_proxy, "stunStatusSuccess", G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(config_proxy, "stunStatusSuccess", + G_CALLBACK(stun_status_success_cb), NULL, NULL); + + dbus_g_proxy_add_signal(config_proxy, "errorAlert", G_TYPE_INT, G_TYPE_INVALID); dbus_g_proxy_connect_signal(config_proxy, "errorAlert", G_CALLBACK(error_alert), NULL, NULL); @@ -1084,11 +1146,12 @@ dbus_remove_account(const gchar *accountID) { GError *error = NULL; org_sflphone_SFLphone_ConfigurationManager_remove_account(config_proxy, accountID, &error); + account_list_remove(accountID); check_error(error); } void -dbus_set_account_details(account_t *a) +dbus_set_account_details(const account_t *a) { g_assert(a); GError *error = NULL; @@ -1101,8 +1164,11 @@ void dbus_add_account(account_t *a) { g_assert(a); - GError *error = NULL; + g_assert(a->accountID); + g_assert(a->properties); g_free(a->accountID); + GError *error = NULL; + a->accountID = NULL; org_sflphone_SFLphone_ConfigurationManager_add_account(config_proxy, a->properties, &a->accountID, &error); check_error(error); diff --git a/gnome/src/dbus/dbus.h b/gnome/src/dbus/dbus.h index 690fe36cbc74c86f9d7c0bc7cb1477183b056801..b8c2cfc5d4bf8deeb5411a6aeb9453186b82cafa 100644 --- a/gnome/src/dbus/dbus.h +++ b/gnome/src/dbus/dbus.h @@ -123,7 +123,7 @@ GHashTable *dbus_get_account_details(const gchar *accountID); * ConfigurationManager - Set the details of a specific account * @param a The account to update */ -void dbus_set_account_details(account_t *a); +void dbus_set_account_details(const account_t *a); /** * ConfigurationManager - Set the additional credential information diff --git a/gnome/src/logger.h b/gnome/src/logger.h index f196360da9f686cc04d00de4e4cd0bd9b3c9b4e9..330503be82bd3be8a2dca855d7ee087498c5c431 100644 --- a/gnome/src/logger.h +++ b/gnome/src/logger.h @@ -28,8 +28,8 @@ * as that of the covered work. */ -#ifndef __LOGGER_H -#define __LOGGER_H +#ifndef LOGGER_H_ +#define LOGGER_H_ void internal_log (const int level, const char* format, ...); void set_log_level (const int level); @@ -44,4 +44,8 @@ void set_log_level (const int level); #define INFO(...) internal_log(LOG_INFO, __VA_ARGS__) #define DEBUG(...) internal_log(LOG_DEBUG, __VA_ARGS__) -#endif +/* Prints an error message and returns if the pointer A is NULL */ +#define RETURN_IF_NULL(A, M, ...) \ + if (!(A)) { ERROR(M, ##__VA_ARGS__); return; } + +#endif // LOGGER_H_ diff --git a/gnome/src/main.c b/gnome/src/main.c index ba8899c93a4a4f5a74324f2e51e70050b09858cb..2be022a769c2501ec8bff65f643d68ce7a58f07b 100644 --- a/gnome/src/main.c +++ b/gnome/src/main.c @@ -66,7 +66,7 @@ main(int argc, char *argv[]) gtk_init(&argc, &argv); g_print("%s %s\n", PACKAGE, VERSION); - g_print("\nCopyright (c) 2005 - 2011 Savoir-faire Linux Inc.\n\n"); + g_print("\nCopyright (c) 2005 - 2012 Savoir-faire Linux Inc.\n\n"); g_print("This is free software. You may redistribute copies of it under the terms of\n" \ "the GNU General Public License Version 3 <http://www.gnu.org/licenses/gpl.html>.\n" \ "There is NO WARRANTY, to the extent permitted by law.\n\n" \ @@ -113,7 +113,6 @@ main(int argc, char *argv[]) set_minimized(TRUE); } - status_bar_display_account(); sflphone_fill_history(); diff --git a/gnome/src/mainwindow.c b/gnome/src/mainwindow.c index ce8d3b8140d6807af5bccca9f8029777eec3279b..9b079d739650c89ed326e95d7d4b9303b3af8ed1 100644 --- a/gnome/src/mainwindow.c +++ b/gnome/src/mainwindow.c @@ -402,22 +402,22 @@ main_window_zrtp_not_supported(callable_obj_t * c) { gchar* warning_enabled = ""; - account_t *account_details = account_list_get_by_id(c->_accountID); + account_t *account = account_list_get_by_id(c->_accountID); - if (account_details != NULL) { - warning_enabled = g_hash_table_lookup(account_details->properties, - ACCOUNT_ZRTP_NOT_SUPP_WARNING); + if (account != NULL) { + warning_enabled = account_lookup(account, + ACCOUNT_ZRTP_NOT_SUPP_WARNING); DEBUG("Warning Enabled %s", warning_enabled); } else { DEBUG("Account is null callID %s", c->_callID); GHashTable * properties = sflphone_get_ip2ip_properties(); if (properties) - warning_enabled = g_hash_table_lookup (properties, - ACCOUNT_ZRTP_NOT_SUPP_WARNING); + warning_enabled = g_hash_table_lookup(properties, + ACCOUNT_ZRTP_NOT_SUPP_WARNING); } - if (utf8_case_cmp(warning_enabled, "true") == 0) { + if (utf8_case_equal(warning_enabled, "true")) { PidginMiniDialog *mini_dialog; gchar *desc = g_markup_printf_escaped( _("ZRTP is not supported by peer %s\n"), c->_peer_number); diff --git a/gnome/src/sflnotify.c b/gnome/src/sflnotify.c index 773946eb06d8efb8277905de9b364bacad6cbbc4..7f8c19a9c1d0644b89ae61153a8840b70a2199f0 100644 --- a/gnome/src/sflnotify.c +++ b/gnome/src/sflnotify.c @@ -90,7 +90,7 @@ notify_incoming_message(const gchar *callID, const gchar *msg) create_new_gnome_notification(title, (gchar *)msg, NOTIFY_URGENCY_CRITICAL, - (utf8_case_cmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } @@ -113,7 +113,7 @@ notify_incoming_call(callable_obj_t* c) create_new_gnome_notification(title, callerid, NOTIFY_URGENCY_CRITICAL, - (utf8_case_cmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } @@ -185,7 +185,7 @@ notify_secure_on(callable_obj_t* c) create_new_gnome_notification(title, callerid, NOTIFY_URGENCY_CRITICAL, - (utf8_case_cmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } @@ -198,7 +198,7 @@ notify_zrtp_not_supported(callable_obj_t* c) create_new_gnome_notification(title, callerid, NOTIFY_URGENCY_CRITICAL, - (utf8_case_cmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } @@ -211,7 +211,7 @@ notify_zrtp_negotiation_failed(callable_obj_t* c) create_new_gnome_notification(title, callerid, NOTIFY_URGENCY_CRITICAL, - (utf8_case_cmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } @@ -224,6 +224,6 @@ notify_secure_off(callable_obj_t* c) create_new_gnome_notification(title, callerid, NOTIFY_URGENCY_CRITICAL, - (utf8_case_cmp(__TIMEOUT_MODE, "default") == 0) ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); + utf8_case_equal(__TIMEOUT_MODE, "default") ? __TIMEOUT_TIME : NOTIFY_EXPIRES_NEVER); #endif } diff --git a/gnome/src/sflphone_const.h b/gnome/src/sflphone_const.h index e642e0ae8ee5eb102e6bb803e38cd78a09f3e8b7..62e2887a86e6617a32b38504ecf61dcfdcc47ee0 100644 --- a/gnome/src/sflphone_const.h +++ b/gnome/src/sflphone_const.h @@ -48,24 +48,19 @@ #define CONTACTS "contacts" /** Locale */ -//#define _(STRING) gettext( STRING ) -//#define N_(STRING) (STRING) #define c_(COMMENT,STRING) gettext(STRING) #define n_(SING,PLUR,COUNT) ngettext(SING,PLUR,COUNT) -#define IP2IP "IP2IP" - #define IP2IP_PROFILE "IP2IP" #define ACCOUNT_ID "Account.id" #define ACCOUNT_TYPE "Account.type" -#define ACCOUNT_ALIAS "Account.alias" -#define ACCOUNT_ENABLED "Account.enable" -#define ACCOUNT_MAILBOX "Account.mailbox" -#define ACCOUNT_USERAGENT "Account.useragent" -#define ACCOUNT_RESOLVE_ONCE "Account.resolveOnce" +#define ACCOUNT_ALIAS "Account.alias" +#define ACCOUNT_ENABLED "Account.enable" +#define ACCOUNT_MAILBOX "Account.mailbox" +#define ACCOUNT_USERAGENT "Account.useragent" #define ACCOUNT_REGISTRATION_EXPIRE "Account.registrationExpire" -#define ACCOUNT_SIP_STUN_SERVER "STUN.server" +#define ACCOUNT_SIP_STUN_SERVER "STUN.server" #define ACCOUNT_SIP_STUN_ENABLED "STUN.enable" #define ACCOUNT_DTMF_TYPE "Account.dtmfType" #define ACCOUNT_HOSTNAME "Account.hostname" @@ -84,45 +79,45 @@ #define ZRTP "zrtp" #define SDES "sdes" -#define CONFIG_RINGTONE_PATH "Account.ringtonePath" -#define CONFIG_RINGTONE_ENABLED "Account.ringtoneEnabled" - -#define TLS_LISTENER_PORT "TLS.listenerPort" -#define TLS_ENABLE "TLS.enable" -#define TLS_PORT "TLS.port" -#define TLS_CA_LIST_FILE "TLS.certificateListFile" -#define TLS_CERTIFICATE_FILE "TLS.certificateFile" -#define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" -#define TLS_PASSWORD "TLS.password" -#define TLS_METHOD "TLS.method" -#define TLS_CIPHERS "TLS.ciphers" -#define TLS_SERVER_NAME "TLS.serverName" -#define TLS_VERIFY_SERVER "TLS.verifyServer" -#define TLS_VERIFY_CLIENT "TLS.verifyClient" -#define TLS_REQUIRE_CLIENT_CERTIFICATE "TLS.requireClientCertificate" -#define TLS_NEGOTIATION_TIMEOUT_SEC "TLS.negotiationTimeoutSec" -#define TLS_NEGOTIATION_TIMEOUT_MSEC "TLS.negotiationTimemoutMsec" - -#define LOCAL_INTERFACE "Account.localInterface" -#define PUBLISHED_SAMEAS_LOCAL "Account.publishedSameAsLocal" -#define LOCAL_PORT "Account.localPort" -#define PUBLISHED_PORT "Account.publishedPort" -#define PUBLISHED_ADDRESS "Account.publishedAddress" - -#define REGISTRATION_STATUS "Registration.Status" -#define REGISTRATION_STATE_CODE "Registration.code" -#define REGISTRATION_STATE_DESCRIPTION "Registration.description" - -#define SHORTCUT_PICKUP "pickUp" -#define SHORTCUT_HANGUP "hangUp" -#define SHORTCUT_POPUP "popupWindow" -#define SHORTCUT_TOGGLEPICKUPHANGUP "togglePickupHangup" -#define SHORTCUT_TOGGLEHOLD "toggleHold" +#define CONFIG_RINGTONE_PATH "Account.ringtonePath" +#define CONFIG_RINGTONE_ENABLED "Account.ringtoneEnabled" + +#define TLS_LISTENER_PORT "TLS.listenerPort" +#define TLS_ENABLE "TLS.enable" +#define TLS_PORT "TLS.port" +#define TLS_CA_LIST_FILE "TLS.certificateListFile" +#define TLS_CERTIFICATE_FILE "TLS.certificateFile" +#define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" +#define TLS_PASSWORD "TLS.password" +#define TLS_METHOD "TLS.method" +#define TLS_CIPHERS "TLS.ciphers" +#define TLS_SERVER_NAME "TLS.serverName" +#define TLS_VERIFY_SERVER "TLS.verifyServer" +#define TLS_VERIFY_CLIENT "TLS.verifyClient" +#define TLS_REQUIRE_CLIENT_CERTIFICATE "TLS.requireClientCertificate" +#define TLS_NEGOTIATION_TIMEOUT_SEC "TLS.negotiationTimeoutSec" +#define TLS_NEGOTIATION_TIMEOUT_MSEC "TLS.negotiationTimemoutMsec" + +#define LOCAL_INTERFACE "Account.localInterface" +#define PUBLISHED_SAMEAS_LOCAL "Account.publishedSameAsLocal" +#define LOCAL_PORT "Account.localPort" +#define PUBLISHED_PORT "Account.publishedPort" +#define PUBLISHED_ADDRESS "Account.publishedAddress" + +#define REGISTRATION_STATUS "Registration.Status" +#define REGISTRATION_STATE_CODE "Registration.code" +#define REGISTRATION_STATE_DESCRIPTION "Registration.description" + +#define SHORTCUT_PICKUP "pickUp" +#define SHORTCUT_HANGUP "hangUp" +#define SHORTCUT_POPUP "popupWindow" +#define SHORTCUT_TOGGLEPICKUPHANGUP "togglePickupHangup" +#define SHORTCUT_TOGGLEHOLD "toggleHold" /** Error while opening capture device */ -#define ALSA_CAPTURE_DEVICE 0x0001 +#define ALSA_CAPTURE_DEVICE 0x0001 /** Error while opening playback device */ -#define ALSA_PLAYBACK_DEVICE 0x0010 +#define ALSA_PLAYBACK_DEVICE 0x0010 /** Error pulseaudio */ #define PULSEAUDIO_NOT_RUNNING 0x0100 /** Error codecs not loaded */ @@ -136,11 +131,11 @@ /** Tone to play when voice mails */ #define TONE_WITH_MESSAGE 1 /** Tells if the main window is reduced to the system tray or not */ -#define MINIMIZED TRUE +#define MINIMIZED TRUE /** Behaviour of the main window on incoming calls */ #define __POPUP_WINDOW (eel_gconf_get_integer (POPUP_ON_CALL)) /** Show/Hide the volume controls */ -#define SHOW_VOLUME (eel_gconf_get_integer (SHOW_VOLUME_CONTROLS) && must_show_alsa_conf()) +#define SHOW_VOLUME (eel_gconf_get_integer (SHOW_VOLUME_CONTROLS) && must_show_alsa_conf()) /** DTMF type */ #define OVERRTP "overrtp" @@ -154,7 +149,7 @@ /** Messages ID for the status bar - Incoming calls */ #define __MSG_INCOMING_CALL 0 /** Messages ID for the status bar - Calling */ -#define __MSG_CALLING 1 +#define __MSG_CALLING 1 /** Messages ID for the status bar - Voice mails notification */ #define __MSG_VOICE_MAILS 2 /** Messages ID for the status bar - Current account */ diff --git a/gnome/src/str_utils.c b/gnome/src/str_utils.c index 9e395c1efb74a5e8324059e3424b34ce51a0a456..2bbff79e159340e71fd2f65e888802d2d6cc8167 100644 --- a/gnome/src/str_utils.c +++ b/gnome/src/str_utils.c @@ -39,3 +39,14 @@ gint utf8_case_cmp(const gchar *a, const gchar *b) g_free(r); return result; } + +gboolean utf8_case_equal(const gchar *a, const gchar *b) +{ + if (a == NULL) { + if (b == NULL) + return TRUE; + else + return FALSE; + } else + return utf8_case_cmp(a, b) == 0; +} diff --git a/gnome/src/str_utils.h b/gnome/src/str_utils.h index b2b4bddb56655337552f51e17ce454fff7ea2245..bc9f7cc2780bc1e6f2410f699c3fe8e5d5c9e217 100644 --- a/gnome/src/str_utils.h +++ b/gnome/src/str_utils.h @@ -33,6 +33,10 @@ #include <glib.h> +/* Case independent, local independent string comparison test */ gint utf8_case_cmp(const gchar *a, const gchar *b); +/* Case independent, local independent string equality test, NULL-safe */ +gint utf8_case_equal(const gchar *a, const gchar *b); + #endif /* STR_UTILS_H_ */ diff --git a/gnome/src/uimanager.c b/gnome/src/uimanager.c index 04ee1f5d369b77f8a771135306f4805cad15da72..b2b16d5d2ef0b42687a0e2d0130a300161348942 100644 --- a/gnome/src/uimanager.c +++ b/gnome/src/uimanager.c @@ -67,29 +67,33 @@ void show_edit_number(callable_obj_t *call); static GtkWidget *toolbar_; -static guint transferButtonConnId_; // The button toggled signal connection ID -static guint recordButtonConnId_; // The button toggled signal connection ID +// store the signal ID in case we need to +// intercept this signal +static guint transferButtonConnId_; +static guint recordButtonConnId_; static GtkAction * pickUpAction_; -static GtkWidget * pickUpWidget_; static GtkAction * newCallAction_; -static GtkWidget * newCallWidget_; static GtkAction * hangUpAction_; +static GtkAction * copyAction_; +static GtkAction * pasteAction_; +static GtkAction * recordAction_; +static GtkAction * muteAction_; +static GtkAction * voicemailAction_; +static GtkAction * imAction_; + +static GtkWidget * pickUpWidget_; +static GtkWidget * newCallWidget_; static GtkWidget * hangUpWidget_; static GtkWidget * holdMenu_; static GtkWidget * holdToolbar_; static GtkWidget * offHoldToolbar_; static GtkWidget * transferToolbar_; -static GtkAction * copyAction_; -static GtkAction * pasteAction_; -static GtkAction * recordAction_; -static GtkAction * muteAction_; static GtkWidget * recordWidget_; static GtkWidget * muteWidget_; -static GtkAction * voicemailAction_; static GtkWidget * voicemailToolbar_; static GtkWidget * imToolbar_; -static GtkAction * imAction_; + static GtkWidget * playRecordWidget_; static GtkWidget * stopRecordWidget_; @@ -130,69 +134,332 @@ call_mute(void) sflphone_mute_call(); } + +static void +update_toolbar_for_call(callable_obj_t *selectedCall, gboolean instant_messaging_enabled) { + int pos = 0; + + DEBUG("UIManager: Update actions for call %s", selectedCall->_callID); + + if(selectedCall == NULL) { + ERROR("Selected call is NULL while updating toolbar"); + return; + } + + // update icon in systray + show_status_hangup_icon(); + + gtk_action_set_sensitive(copyAction_, TRUE); + + switch (selectedCall->_state) { + case CALL_STATE_INCOMING: + { + DEBUG("UIManager: Call State Incoming"); + // Make the button toolbar clickable + gtk_action_set_sensitive(pickUpAction_, TRUE); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + // Replace the dial button with the hangup button + g_object_ref(newCallWidget_); + remove_from_toolbar(newCallWidget_); + pos = 0; + add_to_toolbar(toolbar_, pickUpWidget_, pos++); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + break; + } + case CALL_STATE_HOLD: + { + DEBUG("UIManager: Call State Hold"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(offHoldToolbar_, TRUE); + gtk_widget_set_sensitive(newCallWidget_, TRUE); + + // Replace the hold button with the off-hold button + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, offHoldToolbar_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos++); + } + + break; + } + case CALL_STATE_RINGING: + { + DEBUG("UIManager: Call State Ringing"); + gtk_action_set_sensitive(pickUpAction_, TRUE); + gtk_action_set_sensitive(hangUpAction_, TRUE); + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + break; + } + case CALL_STATE_DIALING: + { + DEBUG("UIManager: Call State Dialing"); + gtk_action_set_sensitive(pickUpAction_, TRUE); + + if (active_calltree_tab == current_calls_tab) + gtk_action_set_sensitive(hangUpAction_, TRUE); + + g_object_ref(newCallWidget_); + remove_from_toolbar(newCallWidget_); + pos = 0; + add_to_toolbar(toolbar_, pickUpWidget_, pos++); + + if (active_calltree_tab == current_calls_tab) + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + else if (active_calltree_tab == history_tab) { + if (is_non_empty(selectedCall->_recordfile)) { + if (selectedCall->_record_is_playing) + add_to_toolbar(toolbar_, stopRecordWidget_, pos++); + else + add_to_toolbar(toolbar_, playRecordWidget_, pos++); + } + } + break; + } + case CALL_STATE_CURRENT: + { + DEBUG("UIManager: Call State Current"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(muteWidget_, TRUE); + if (instant_messaging_enabled) + gtk_action_set_sensitive(imAction_, TRUE); + + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, transferToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + if (instant_messaging_enabled) { + add_to_toolbar(toolbar_, imToolbar_, pos++); + + g_signal_handler_block(transferToolbar_, transferButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); + g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); + g_signal_handler_block(recordWidget_, recordButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), FALSE); + g_signal_handler_unblock(recordWidget_, recordButtonConnId_); + break; + } + + case CALL_STATE_RECORD: + { + DEBUG("UIManager: Call State Record"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(muteWidget_, TRUE); + if (instant_messaging_enabled) + gtk_action_set_sensitive(imAction_, TRUE); + + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, transferToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + add_to_toolbar(toolbar_, muteWidget_, pos++); + if (instant_messaging_enabled) + add_to_toolbar(toolbar_, imToolbar_, pos++); + + g_signal_handler_block(transferToolbar_, transferButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); + g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); + g_signal_handler_block(recordWidget_, recordButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), TRUE); + g_signal_handler_unblock(recordWidget_, recordButtonConnId_); + break; + } + case CALL_STATE_BUSY: + case CALL_STATE_FAILURE: + { + pos = 1; + DEBUG("UIManager: Call State Busy/Failure"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + break; + } + case CALL_STATE_TRANSFER: + { + pos = 1; + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_action_set_sensitive(muteAction_, TRUE); + gtk_widget_set_sensitive(holdMenu_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(transferToolbar_, TRUE); + gtk_widget_set_sensitive(muteWidget_, TRUE); + + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, transferToolbar_, pos++); + g_signal_handler_block(transferToolbar_, transferButtonConnId_); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE); + g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); + add_to_toolbar(toolbar_, muteWidget_, pos++); + break; + } + default: + ERROR("UIMAnager: Error: Unknown state in action update!"); + break; + } + } +} + +static void +update_toolbar_for_conference(conference_obj_t * selectedConf, gboolean instant_messaging_enabled) { + int pos = 0; + + DEBUG("UIManager: Update actions for conference"); + + // update icon in systray + show_status_hangup_icon(); + + switch (selectedConf->_state) { + + case CONFERENCE_STATE_ACTIVE_ATTACHED: + case CONFERENCE_STATE_ACTIVE_DETACHED: + DEBUG("UIManager: Conference State Active"); + + if (active_calltree_tab == current_calls_tab) { + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + pos = 1; + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos); + } + } else if (active_calltree_tab == history_tab) { + if (is_non_empty(selectedConf->_recordfile)) { + pos = 2; + if (selectedConf->_record_is_playing) + add_to_toolbar(toolbar_, stopRecordWidget_, pos); + else + add_to_toolbar(toolbar_, playRecordWidget_, pos); + } + } + + break; + case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD: + case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: { + pos = 1; + DEBUG("UIManager: Conference State Record"); + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(holdToolbar_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, holdToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos); + } + + break; + } + case CONFERENCE_STATE_HOLD: + case CONFERENCE_STATE_HOLD_RECORD: { + DEBUG("UIManager: Conference State Hold"); + pos = 1; + gtk_action_set_sensitive(hangUpAction_, TRUE); + gtk_widget_set_sensitive(offHoldToolbar_, TRUE); + gtk_action_set_sensitive(recordAction_, TRUE); + add_to_toolbar(toolbar_, hangUpWidget_, pos++); + add_to_toolbar(toolbar_, offHoldToolbar_, pos++); + add_to_toolbar(toolbar_, recordWidget_, pos++); + + if (instant_messaging_enabled) { + gtk_action_set_sensitive(imAction_, TRUE); + add_to_toolbar(toolbar_, imToolbar_, pos); + } + + break; + } + default: + WARN("UIManager: Error: Should not happen in action update!"); + break; + } + +} + void update_actions() { - int pos = 0; - gtk_action_set_sensitive(newCallAction_, TRUE); gtk_action_set_sensitive(pickUpAction_, FALSE); gtk_action_set_sensitive(hangUpAction_, FALSE); + gtk_action_set_sensitive(recordAction_, FALSE); + gtk_action_set_sensitive(muteAction_, FALSE); + gtk_action_set_sensitive(copyAction_, FALSE); gtk_action_set_sensitive(imAction_, FALSE); + gtk_widget_set_sensitive(holdMenu_, FALSE); + gtk_widget_set_sensitive(holdToolbar_, FALSE); + gtk_widget_set_sensitive(offHoldToolbar_, FALSE); + gtk_widget_set_sensitive(recordWidget_, FALSE); + gtk_widget_set_sensitive(muteWidget_, FALSE); + gtk_widget_set_sensitive(historyButton_, FALSE); + + // Increment the reference counter g_object_ref(hangUpWidget_); g_object_ref(recordWidget_); g_object_ref(muteWidget_); g_object_ref(holdToolbar_); g_object_ref(offHoldToolbar_); - - if (addrbook) - g_object_ref(contactButton_); - g_object_ref(historyButton_); g_object_ref(transferToolbar_); g_object_ref(voicemailToolbar_); g_object_ref(imToolbar_); + if (addrbook) + g_object_ref(contactButton_); + + // Make sure the toolbar is reinitialized + // Widget will be added according to the state + // of the selected call remove_from_toolbar(hangUpWidget_); remove_from_toolbar(recordWidget_); remove_from_toolbar(muteWidget_); remove_from_toolbar(transferToolbar_); remove_from_toolbar(historyButton_); - - if (addrbook) - remove_from_toolbar(contactButton_); - remove_from_toolbar(voicemailToolbar_); remove_from_toolbar(imToolbar_); - - gtk_widget_set_sensitive(holdMenu_, FALSE); - gtk_widget_set_sensitive(holdToolbar_, FALSE); - gtk_widget_set_sensitive(offHoldToolbar_, FALSE); - gtk_action_set_sensitive(recordAction_, FALSE); - gtk_action_set_sensitive(muteAction_, FALSE); - gtk_widget_set_sensitive(recordWidget_, FALSE); - gtk_widget_set_sensitive(muteWidget_, FALSE); - gtk_action_set_sensitive(copyAction_, FALSE); - - if (addrbook) - gtk_widget_set_sensitive(contactButton_, FALSE); - - gtk_widget_set_sensitive(historyButton_, FALSE); - - if (addrbook) - gtk_widget_set_tooltip_text(contactButton_, _("No address book selected")); - remove_from_toolbar(holdToolbar_); remove_from_toolbar(offHoldToolbar_); remove_from_toolbar(newCallWidget_); remove_from_toolbar(pickUpWidget_); - - add_to_toolbar(toolbar_, newCallWidget_, 0); - remove_from_toolbar(playRecordWidget_); remove_from_toolbar(stopRecordWidget_); + if (addrbook) { + remove_from_toolbar(contactButton_); + gtk_widget_set_sensitive(contactButton_, FALSE); + gtk_widget_set_tooltip_text(contactButton_, _("No address book selected")); + } + + // New call widget always present + add_to_toolbar(toolbar_, newCallWidget_, 0); + + // Add the history button and set it to sensitive if enabled if (eel_gconf_get_integer(HISTORY_ENABLED)) { add_to_toolbar(toolbar_, historyButton_, -1); gtk_widget_set_sensitive(historyButton_, TRUE); @@ -200,9 +467,7 @@ update_actions() GtkToolItem *separator = gtk_separator_tool_item_new(); gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), separator, -1); - // add mute button - add_to_toolbar(toolbar_, muteWidget_, -1); - gtk_action_set_sensitive(muteAction_, TRUE); + // If addressbook support has been enabled and all addressbooks are loaded, display the icon if (addrbook && addrbook->is_ready() && addressbook_config_load_parameters()->enable) { @@ -224,242 +489,9 @@ update_actions() instant_messaging_enabled = eel_gconf_get_integer(INSTANT_MESSAGING_ENABLED); if (selectedCall) { - DEBUG("UIManager: Update actions for call %s", selectedCall->_callID); - - // update icon in systray - show_status_hangup_icon(); - - gtk_action_set_sensitive(copyAction_, TRUE); - - switch (selectedCall->_state) { - case CALL_STATE_INCOMING: - { - DEBUG("UIManager: Call State Incoming"); - // Make the button toolbar clickable - gtk_action_set_sensitive(pickUpAction_, TRUE); - gtk_action_set_sensitive(hangUpAction_, TRUE); - // Replace the dial button with the hangup button - g_object_ref(newCallWidget_); - remove_from_toolbar(newCallWidget_); - pos = 0; - add_to_toolbar(toolbar_, pickUpWidget_, pos++); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - break; - } - case CALL_STATE_HOLD: - { - DEBUG("UIManager: Call State Hold"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(offHoldToolbar_, TRUE); - gtk_widget_set_sensitive(newCallWidget_, TRUE); - - // Replace the hold button with the off-hold button - pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, offHoldToolbar_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos++); - } - - break; - } - case CALL_STATE_RINGING: - { - DEBUG("UIManager: Call State Ringing"); - gtk_action_set_sensitive(pickUpAction_, TRUE); - gtk_action_set_sensitive(hangUpAction_, TRUE); - pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - break; - } - case CALL_STATE_DIALING: - { - DEBUG("UIManager: Call State Dialing"); - gtk_action_set_sensitive(pickUpAction_, TRUE); - - if (active_calltree_tab == current_calls_tab) - gtk_action_set_sensitive(hangUpAction_, TRUE); - - g_object_ref(newCallWidget_); - remove_from_toolbar(newCallWidget_); - pos = 0; - add_to_toolbar(toolbar_, pickUpWidget_, pos++); - - if (active_calltree_tab == current_calls_tab) - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - else if (active_calltree_tab == history_tab) { - if (is_non_empty(selectedCall->_recordfile)) { - if (selectedCall->_record_is_playing) - add_to_toolbar(toolbar_, stopRecordWidget_, pos++); - else - add_to_toolbar(toolbar_, playRecordWidget_, pos++); - } - } - break; - } - case CALL_STATE_CURRENT: - { - DEBUG("UIManager: Call State Current"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_widget_set_sensitive(transferToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, transferToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - g_signal_handler_block(transferToolbar_, transferButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); - g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); - g_signal_handler_block(recordWidget_, recordButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), FALSE); - g_signal_handler_unblock(recordWidget_, recordButtonConnId_); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos++); - } - - break; - } - - case CALL_STATE_RECORD: - { - DEBUG("UIManager: Call State Record"); - pos = 1; - gtk_action_set_sensitive(hangUpAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_widget_set_sensitive(transferToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, transferToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - g_signal_handler_block(transferToolbar_, transferButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE); - g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); - g_signal_handler_block(recordWidget_, recordButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), TRUE); - g_signal_handler_unblock(recordWidget_, recordButtonConnId_); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos++); - } - - break; - } - case CALL_STATE_BUSY: - case CALL_STATE_FAILURE: - { - pos = 1; - DEBUG("UIManager: Call State Busy/Failure"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - break; - } - case CALL_STATE_TRANSFER: - { - pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, transferToolbar_, pos++); - g_signal_handler_block(transferToolbar_, transferButtonConnId_); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE); - g_signal_handler_unblock(transferToolbar_, transferButtonConnId_); - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdMenu_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_widget_set_sensitive(transferToolbar_, TRUE); - break; - } - default: - ERROR("UIMAnager: Error: Unknown state in action update!"); - break; - } - + update_toolbar_for_call(selectedCall, instant_messaging_enabled); } else if (selectedConf) { - - DEBUG("UIManager: Update actions for conference"); - - // update icon in systray - show_status_hangup_icon(); - - switch (selectedConf->_state) { - - case CONFERENCE_STATE_ACTIVE_ATTACHED: - case CONFERENCE_STATE_ACTIVE_DETACHED: - DEBUG("UIManager: Conference State Active"); - - if (active_calltree_tab == current_calls_tab) { - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - pos = 1; - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - } else if (active_calltree_tab == history_tab) { - if (is_non_empty(selectedConf->_recordfile)) { - pos = 2; - if (selectedConf->_record_is_playing) - add_to_toolbar(toolbar_, stopRecordWidget_, pos); - else - add_to_toolbar(toolbar_, playRecordWidget_, pos); - } - } - - break; - case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD: - case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: { - pos = 1; - DEBUG("UIManager: Conference State Record"); - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(holdToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, holdToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - - break; - } - case CONFERENCE_STATE_HOLD: - case CONFERENCE_STATE_HOLD_RECORD: { - DEBUG("UIManager: Conference State Hold"); - pos = 1; - gtk_action_set_sensitive(hangUpAction_, TRUE); - gtk_widget_set_sensitive(offHoldToolbar_, TRUE); - gtk_action_set_sensitive(recordAction_, TRUE); - add_to_toolbar(toolbar_, hangUpWidget_, pos++); - add_to_toolbar(toolbar_, offHoldToolbar_, pos++); - add_to_toolbar(toolbar_, recordWidget_, pos++); - - if (instant_messaging_enabled) { - gtk_action_set_sensitive(imAction_, TRUE); - add_to_toolbar(toolbar_, imToolbar_, pos); - } - - break; - } - default: - WARN("UIManager: Error: Should not happen in action update!"); - break; - } + update_toolbar_for_conference(selectedConf, instant_messaging_enabled); } else { // update icon in systray hide_status_hangup_icon(); @@ -554,7 +586,7 @@ help_about(void * foo UNUSED) "artists", artists, "authors", authors, "comments", _("SFLphone is a VoIP client compatible with SIP and IAX2 protocols."), - "copyright", "Copyright © 2004-2011 Savoir-faire Linux Inc.", + "copyright", "Copyright © 2004-2012 Savoir-faire Linux Inc.", "name", PACKAGE, "title", _("About SFLphone"), "version", VERSION, @@ -1237,8 +1269,8 @@ add_registered_accounts_to_menu(GtkWidget *menu) account_t *acc = account_list_get_nth(i); // Display only the registered accounts - if (utf8_case_cmp(account_state_name(acc->state), account_state_name( - ACCOUNT_STATE_REGISTERED)) == 0) { + if (utf8_case_equal(account_state_name(acc->state), + account_state_name(ACCOUNT_STATE_REGISTERED))) { gchar *alias = g_strconcat(g_hash_table_lookup(acc->properties, ACCOUNT_ALIAS), " - ", g_hash_table_lookup(acc->properties, ACCOUNT_TYPE), @@ -1251,7 +1283,7 @@ add_registered_accounts_to_menu(GtkWidget *menu) if (current) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_items), - utf8_case_cmp(acc->accountID, current->accountID) == 0); + utf8_case_equal(acc->accountID, current->accountID)); } g_signal_connect(G_OBJECT(menu_items), "activate", diff --git a/gnome/tests/Makefile.am b/gnome/tests/Makefile.am index 5b4953a729dad59212e6509ce6c00f6ea98b9f97..fea639c290dfd9cdddec7fdbb41616191884dce3 100644 --- a/gnome/tests/Makefile.am +++ b/gnome/tests/Makefile.am @@ -3,9 +3,11 @@ include ../globals.mak TESTS = check_global check_contacts check_config check_dbus check_PROGRAMS = check_global check_contacts check_config check_dbus -SFLPHONE_LIBS = $(top_builddir)/src/contacts/libcontacts.la \ - $(top_builddir)/src/dbus/libdbus.la \ - $(top_builddir)/src/config/libconfig.la +SFLPHONE_LIBS= $(top_builddir)/src/contacts/libcontacts.la \ + $(top_builddir)/src/config/libconfig.la \ + $(top_builddir)/src/dbus/libdbus.la \ + $(top_builddir)/src/widget/libwidget.la \ + $(top_builddir)/src/icons/libicons.la check_global_SOURCES = check_global.c $(top_srcdir)/src/accountlist.c $(top_srcdir)/src/logger.c $(top_srcdir)/src/str_utils.c check_global_CFLAGS = @CHECK_CFLAGS@ @GTK_CFLAGS@ @GLIB_CFLAGS@ @DBUSGLIB_CFLAGS@ @GCONF_CFLAGS@ diff --git a/gnome/tests/check_global.c b/gnome/tests/check_global.c index d1e6eb37692073e024b2142459984ef361f179cc..09ead1053e987e9b6ffc3d24b8d3d4d96ad9e56d 100644 --- a/gnome/tests/check_global.c +++ b/gnome/tests/check_global.c @@ -48,15 +48,15 @@ account_t* create_test_account(gchar *alias) test->properties = g_hash_table_new(NULL, g_str_equal); // Populate the properties - g_hash_table_replace(test->properties, ACCOUNT_ENABLED, "1"); - g_hash_table_replace(test->properties, ACCOUNT_ALIAS, alias); - g_hash_table_replace(test->properties, ACCOUNT_TYPE, "SIP"); - g_hash_table_replace(test->properties, ACCOUNT_HOSTNAME, "sflphone.org"); - g_hash_table_replace(test->properties, ACCOUNT_USERNAME, "1260"); - g_hash_table_replace(test->properties, ACCOUNT_PASSWORD, "NIPAgmLo"); - g_hash_table_replace(test->properties, ACCOUNT_MAILBOX, ""); - g_hash_table_replace(test->properties, ACCOUNT_SIP_STUN_SERVER, ""); - g_hash_table_replace(test->properties, ACCOUNT_SIP_STUN_ENABLED, "0"); + account_replace(test, ACCOUNT_ENABLED, "1"); + account_replace(test, ACCOUNT_ALIAS, alias); + account_replace(test, ACCOUNT_TYPE, "SIP"); + account_replace(test, ACCOUNT_HOSTNAME, "sflphone.org"); + account_replace(test, ACCOUNT_USERNAME, "1260"); + account_replace(test, ACCOUNT_PASSWORD, "NIPAgmLo"); + account_replace(test, ACCOUNT_MAILBOX, ""); + account_replace(test, ACCOUNT_SIP_STUN_SERVER, ""); + account_replace(test, ACCOUNT_SIP_STUN_ENABLED, "0"); return test; } @@ -79,7 +79,7 @@ START_TEST(test_ordered_list) account_list_init(); account_list_add(test); account_list_add(test); - fail_unless(utf8_case_cmp(account_list_get_ordered_list(), list) == 0, "ERROR - BAD ACCOUNT LIST SERIALIZING"); + fail_unless(utf8_case_equal(account_list_get_ordered_list(), list), "ERROR - BAD ACCOUNT LIST SERIALIZING"); g_free(list); } END_TEST @@ -92,7 +92,7 @@ START_TEST(test_get_by_id) account_list_init(); account_list_add(test); tmp = account_list_get_by_id(test->accountID); - fail_unless(utf8_case_cmp(tmp->accountID, test->accountID) == 0, "ERROR - ACCOUNTLIST_GET_BY_ID"); + fail_unless(utf8_case_equal(tmp->accountID, test->accountID), "ERROR - ACCOUNTLIST_GET_BY_ID"); } END_TEST @@ -110,8 +110,8 @@ START_TEST(test_get_current_account) // The current account must be the first we add if (current) { - fail_unless(utf8_case_cmp(g_hash_table_lookup(current->properties, ACCOUNT_ALIAS) , - g_hash_table_lookup(test->properties, ACCOUNT_ALIAS)) == 0, + fail_unless(utf8_case_equal(account_lookup(current, ACCOUNT_ALIAS), + account_lookup(test, ACCOUNT_ALIAS)), "ERROR - BAD CURRENT ACCOUNT"); } @@ -122,8 +122,8 @@ START_TEST(test_get_current_account) // The current account must be the first we add if (current) { - fail_unless(utf8_case_cmp(g_hash_table_lookup(current->properties, ACCOUNT_ALIAS) , - g_hash_table_lookup(test2->properties, ACCOUNT_ALIAS)) == 0, + fail_unless(utf8_case_equal(account_lookup(current, ACCOUNT_ALIAS), + account_lookup(test2, ACCOUNT_ALIAS)), "ERROR - BAD CURRENT ACCOUNT"); } }