- format source code (indentation 4 space

This commit is contained in:
Dmytro Bogovych 2024-11-05 11:41:56 +03:00
parent 7c346fbe9b
commit 10ec751e43
15 changed files with 2383 additions and 2381 deletions

View File

@ -15,181 +15,181 @@
AudioManager::AudioManager() AudioManager::AudioManager()
:mTerminal(nullptr), mAudioMonitoring(nullptr) :mTerminal(nullptr), mAudioMonitoring(nullptr)
{ {
mPlayer.setDelegate(this); mPlayer.setDelegate(this);
} }
AudioManager::~AudioManager() AudioManager::~AudioManager()
{ {
// stop(); // stop();
} }
AudioManager& AudioManager::instance() AudioManager& AudioManager::instance()
{ {
static std::shared_ptr<AudioManager> GAudioManager; static std::shared_ptr<AudioManager> GAudioManager;
if (!GAudioManager) if (!GAudioManager)
GAudioManager = std::make_shared<AudioManager>(); GAudioManager = std::make_shared<AudioManager>();
return *GAudioManager; return *GAudioManager;
} }
void AudioManager::setTerminal(MT::Terminal* terminal) void AudioManager::setTerminal(MT::Terminal* terminal)
{ {
mTerminal = terminal; mTerminal = terminal;
} }
MT::Terminal* AudioManager::terminal() MT::Terminal* AudioManager::terminal()
{ {
return mTerminal; return mTerminal;
} }
void AudioManager::setAudioMonitoring(Audio::DataConnection* monitoring) void AudioManager::setAudioMonitoring(Audio::DataConnection* monitoring)
{ {
mAudioMonitoring = monitoring; mAudioMonitoring = monitoring;
} }
Audio::DataConnection* AudioManager::audioMonitoring() Audio::DataConnection* AudioManager::audioMonitoring()
{ {
return mAudioMonitoring; return mAudioMonitoring;
} }
#define LOCK_MANAGER std::unique_lock<std::mutex> l(mGuard) #define LOCK_MANAGER std::unique_lock<std::mutex> l(mGuard)
void AudioManager::start(int usageId) void AudioManager::start(int usageId)
{ {
assert(mTerminal); assert(mTerminal);
LOCK_MANAGER; LOCK_MANAGER;
ICELogInfo(<< "Start main audio with usage id " << usageId);
if (mUsage.obtain(usageId) > 1) ICELogInfo(<< "Start main audio with usage id " << usageId);
return;
if (Audio::OsEngine::instance()) if (mUsage.obtain(usageId) > 1)
Audio::OsEngine::instance()->open(); return;
if (!mAudioInput || !mAudioOutput) if (Audio::OsEngine::instance())
{ Audio::OsEngine::instance()->open();
// Disable AEC for now - because PVQA conflicts with speex AEC.
std::shared_ptr<Audio::Enumerator> enumerator(Audio::Enumerator::make(usageId == atNull));
if (!mTerminal->audio())
{
auto audio = std::make_shared<Audio::DevicePair>();
audio->setAgc(true);
audio->setAec(false);
audio->setMonitoring(mAudioMonitoring);
mTerminal->setAudio(audio); if (!mAudioInput || !mAudioOutput)
} {
// Disable AEC for now - because PVQA conflicts with speex AEC.
std::shared_ptr<Audio::Enumerator> enumerator(Audio::Enumerator::make(usageId == atNull));
if (!mTerminal->audio())
{
auto audio = std::make_shared<Audio::DevicePair>();
audio->setAgc(true);
audio->setAec(false);
audio->setMonitoring(mAudioMonitoring);
if (!mAudioInput) mTerminal->setAudio(audio);
{ }
enumerator->open(Audio::myMicrophone);
int inputIndex = enumerator->indexOfDefaultDevice();
// Construct and set to terminal's audio pair input device if (!mAudioInput)
if (usageId != atNull) {
mAudioInput = Audio::PInputDevice(Audio::InputDevice::make(enumerator->idAt(inputIndex))); enumerator->open(Audio::myMicrophone);
else int inputIndex = enumerator->indexOfDefaultDevice();
mAudioInput = Audio::PInputDevice(new Audio::NullInputDevice());
mTerminal->audio()->setInput(mAudioInput); // Construct and set to terminal's audio pair input device
} if (usageId != atNull)
mAudioInput = Audio::PInputDevice(Audio::InputDevice::make(enumerator->idAt(inputIndex)));
else
mAudioInput = Audio::PInputDevice(new Audio::NullInputDevice());
if (!mAudioOutput) mTerminal->audio()->setInput(mAudioInput);
{ }
Audio::Enumerator *enumerator = Audio::Enumerator::make(usageId == atNull);
enumerator->open(Audio::mySpeaker);
int outputIndex = enumerator->indexOfDefaultDevice();
// Construct and set terminal's audio pair output device if (!mAudioOutput)
if (usageId != atNull) {
{ Audio::Enumerator *enumerator = Audio::Enumerator::make(usageId == atNull);
if (outputIndex >= enumerator->count()) enumerator->open(Audio::mySpeaker);
outputIndex = 0; int outputIndex = enumerator->indexOfDefaultDevice();
mAudioOutput = Audio::POutputDevice( // Construct and set terminal's audio pair output device
Audio::OutputDevice::make(enumerator->idAt(outputIndex))); if (usageId != atNull)
} {
else if (outputIndex >= enumerator->count())
mAudioOutput = Audio::POutputDevice(new Audio::NullOutputDevice()); outputIndex = 0;
mTerminal->audio()->setOutput(mAudioOutput); mAudioOutput = Audio::POutputDevice(
} Audio::OutputDevice::make(enumerator->idAt(outputIndex)));
} }
else
mAudioOutput = Audio::POutputDevice(new Audio::NullOutputDevice());
// Open audio mTerminal->audio()->setOutput(mAudioOutput);
if (mAudioInput) }
mAudioInput->open(); }
if (mAudioOutput)
mAudioOutput->open(); // Open audio
if (mAudioInput)
mAudioInput->open();
if (mAudioOutput)
mAudioOutput->open();
} }
void AudioManager::close() void AudioManager::close()
{ {
mUsage.clear(); mUsage.clear();
if (mAudioInput) if (mAudioInput)
{ {
mAudioInput->close(); mAudioInput->close();
mAudioInput.reset(); mAudioInput.reset();
} }
if (mAudioOutput) if (mAudioOutput)
{ {
mAudioOutput->close(); mAudioOutput->close();
mAudioOutput.reset(); mAudioOutput.reset();
} }
mPlayer.setOutput(Audio::POutputDevice()); mPlayer.setOutput(Audio::POutputDevice());
} }
void AudioManager::stop(int usageId) void AudioManager::stop(int usageId)
{ {
LOCK_MANAGER; LOCK_MANAGER;
ICELogInfo( << "Stop main audio with usage id " << usageId);
if (mTerminal)
{
if (mTerminal->audio())
mTerminal->audio()->player().release(usageId);
}
if (!mUsage.release(usageId)) ICELogInfo( << "Stop main audio with usage id " << usageId);
{ if (mTerminal)
close(); {
if (mTerminal->audio())
mTerminal->audio()->player().release(usageId);
}
// Reset device pair on terminal side if (!mUsage.release(usageId))
mTerminal->setAudio(Audio::PDevicePair()); {
close();
if (Audio::OsEngine::instance()) // Reset device pair on terminal side
Audio::OsEngine::instance()->close(); mTerminal->setAudio(Audio::PDevicePair());
}
if (Audio::OsEngine::instance())
Audio::OsEngine::instance()->close();
}
} }
void AudioManager::startPlayFile(int usageId, const std::string& path, AudioTarget target, LoopMode lm, int timelimit) void AudioManager::startPlayFile(int usageId, const std::string& path, AudioTarget target, LoopMode lm, int timelimit)
{ {
// Check if file exists // Check if file exists
Audio::PWavFileReader r = std::make_shared<Audio::WavFileReader>(); Audio::PWavFileReader r = std::make_shared<Audio::WavFileReader>();
#ifdef TARGET_WIN #ifdef TARGET_WIN
r->open(StringHelper::makeTstring(path)); r->open(StringHelper::makeTstring(path));
#else #else
r->open(path); r->open(path);
#endif #endif
if (!r->isOpened()) if (!r->isOpened())
{ {
ICELogError(<< "Cannot open file to play"); ICELogError(<< "Cannot open file to play");
return; return;
} }
// Delegate processing to existing audio device pair manager // Delegate processing to existing audio device pair manager
mTerminal->audio()->player().add(usageId, r, lm == lmLoopAudio, timelimit); mTerminal->audio()->player().add(usageId, r, lm == lmLoopAudio, timelimit);
start(usageId); start(usageId);
} }
void AudioManager::stopPlayFile(int usageId) void AudioManager::stopPlayFile(int usageId)
{ {
stop(usageId); stop(usageId);
mPlayer.release(usageId); mPlayer.release(usageId);
} }
void AudioManager::onFilePlayed(Audio::Player::PlaylistItem& item) void AudioManager::onFilePlayed(Audio::Player::PlaylistItem& item)
@ -198,9 +198,9 @@ void AudioManager::onFilePlayed(Audio::Player::PlaylistItem& item)
void AudioManager::process() void AudioManager::process()
{ {
mPlayer.releasePlayed(); mPlayer.releasePlayed();
std::vector<int> ids; std::vector<int> ids;
mTerminal->audio()->player().retrieveUsageIds(ids); mTerminal->audio()->player().retrieveUsageIds(ids);
for (unsigned i=0; i<ids.size(); i++) for (unsigned i=0; i<ids.size(); i++)
stop(ids[i]); stop(ids[i]);
} }

View File

@ -14,19 +14,19 @@
enum enum
{ {
AudioPrefix_Ring = 1, AudioPrefix_Ring = 1,
AudioPrefix_Zero, AudioPrefix_Zero,
AudioPrefix_One, AudioPrefix_One,
AudioPrefix_Two, AudioPrefix_Two,
AudioPrefix_Three, AudioPrefix_Three,
AudioPrefix_Four, AudioPrefix_Four,
AudioPrefix_Five, AudioPrefix_Five,
AudioPrefix_Six, AudioPrefix_Six,
AudioPrefix_Seven, AudioPrefix_Seven,
AudioPrefix_Eight, AudioPrefix_Eight,
AudioPrefix_Nine, AudioPrefix_Nine,
AudioPrefix_Asterisk, AudioPrefix_Asterisk,
AudioPrefix_Diez AudioPrefix_Diez
}; };
#define AudioSessionCoeff 64 #define AudioSessionCoeff 64
@ -34,56 +34,56 @@ enum
class AudioManager: public Audio::Player::EndOfAudioDelegate class AudioManager: public Audio::Player::EndOfAudioDelegate
{ {
public: public:
AudioManager(); AudioManager();
virtual ~AudioManager(); virtual ~AudioManager();
static AudioManager& instance();
// Enforces to close audio devices. Used to shutdown AudioManager on exit from application
void close();
// Terminal and settings must be available for AudioManager static AudioManager& instance();
void setTerminal(MT::Terminal* terminal);
MT::Terminal* terminal();
void setAudioMonitoring(Audio::DataConnection* monitoring); // Enforces to close audio devices. Used to shutdown AudioManager on exit from application
Audio::DataConnection* audioMonitoring(); void close();
// Start/stop methods relies on usage counter; only first start and last stop opens/closes devices actually // Terminal and settings must be available for AudioManager
void start(int usageId); void setTerminal(MT::Terminal* terminal);
void stop(int usageId); MT::Terminal* terminal();
enum AudioTarget
{
atNull,
atReceiver,
atRinger
};
enum LoopMode void setAudioMonitoring(Audio::DataConnection* monitoring);
{ Audio::DataConnection* audioMonitoring();
lmLoopAudio,
lmNoloop
};
void startPlayFile(int usageId, const std::string& path, AudioTarget target, LoopMode lm, int timelimit = 0); // Start/stop methods relies on usage counter; only first start and last stop opens/closes devices actually
void stopPlayFile(int usageId); void start(int usageId);
void stop(int usageId);
void onFilePlayed(Audio::Player::PlaylistItem& item); enum AudioTarget
{
// Must be called from main loop to release used audio devices atNull,
void process(); atReceiver,
atRinger
};
enum LoopMode
{
lmLoopAudio,
lmNoloop
};
void startPlayFile(int usageId, const std::string& path, AudioTarget target, LoopMode lm, int timelimit = 0);
void stopPlayFile(int usageId);
void onFilePlayed(Audio::Player::PlaylistItem& item);
// Must be called from main loop to release used audio devices
void process();
protected: protected:
Audio::PInputDevice mAudioInput; Audio::PInputDevice mAudioInput;
Audio::POutputDevice mAudioOutput; Audio::POutputDevice mAudioOutput;
Audio::Player mPlayer; Audio::Player mPlayer;
MT::Terminal* mTerminal; MT::Terminal* mTerminal;
Audio::DataConnection* mAudioMonitoring; Audio::DataConnection* mAudioMonitoring;
std::map<int, int> UsageMap; std::map<int, int> UsageMap;
UsageCounter mUsage; UsageCounter mUsage;
std::mutex mGuard; std::mutex mGuard;
}; };
#endif #endif

View File

@ -682,34 +682,34 @@ void AgentImpl::processUseStreamForSession(JsonCpp::Value& request, JsonCpp::Val
} }
} }
else else
if (actionText == "write") if (actionText == "write")
{
if (path.empty())
{ {
if (path.empty()) // Turn off recording from the stream
{ prov->writeFile(Audio::PWavFileWriter(), direction);
// Turn off recording from the stream answer["status"] = Status_Ok;
prov->writeFile(Audio::PWavFileWriter(), direction);
answer["status"] = Status_Ok;
}
else
{
Audio::PWavFileWriter writer = std::make_shared<Audio::WavFileWriter>();
if (!writer->open(strx::makeTstring(path), AUDIO_SAMPLERATE, AUDIO_CHANNELS))
answer["status"] = Status_FailedToOpenFile;
else
{
prov->writeFile(writer, direction);
answer["status"] = Status_Ok;
}
}
} }
else else
if (actionText == "mirror") {
Audio::PWavFileWriter writer = std::make_shared<Audio::WavFileWriter>();
if (!writer->open(strx::makeTstring(path), AUDIO_SAMPLERATE, AUDIO_CHANNELS))
answer["status"] = Status_FailedToOpenFile;
else
{ {
prov->setupMirror(request["enable"].asBool()); prov->writeFile(writer, direction);
answer["status"] = Status_Ok; answer["status"] = Status_Ok;
} }
else }
answer["status"] = Status_AccountNotFound; }
else
if (actionText == "mirror")
{
prov->setupMirror(request["enable"].asBool());
answer["status"] = Status_Ok;
}
else
answer["status"] = Status_AccountNotFound;
} }
else else
answer["status"] = Status_NoMediaAction; answer["status"] = Status_NoMediaAction;

View File

@ -66,10 +66,10 @@ std::string WavFileReader::readChunk()
if (result == "fact") if (result == "fact")
fread(&mDataLength, 4, 1, mHandle); fread(&mDataLength, 4, 1, mHandle);
else else
if (result != "data") if (result != "data")
fseek(mHandle, size, SEEK_CUR); fseek(mHandle, size, SEEK_CUR);
else else
mDataLength = size; mDataLength = size;
return result; return result;
} }

View File

@ -17,23 +17,23 @@
namespace Audio namespace Audio
{ {
class WavFileReader class WavFileReader
{ {
protected: protected:
FILE* mHandle; FILE* mHandle;
uint16_t mChannels; uint16_t mChannels;
uint16_t mBits; uint16_t mBits;
int mSamplerate; int mSamplerate;
std::tstring mFileName; std::tstring mFileName;
mutable std::recursive_mutex mutable std::recursive_mutex
mFileMtx; mFileMtx;
size_t mDataOffset; size_t mDataOffset;
size_t mDataLength; size_t mDataLength;
Resampler mResampler; Resampler mResampler;
unsigned mLastError; unsigned mLastError;
std::string readChunk(); std::string readChunk();
public: public:
WavFileReader(); WavFileReader();
~WavFileReader(); ~WavFileReader();
@ -56,24 +56,24 @@ namespace Audio
size_t size() const; size_t size() const;
unsigned lastError() const; unsigned lastError() const;
}; };
typedef std::shared_ptr<WavFileReader> PWavFileReader; typedef std::shared_ptr<WavFileReader> PWavFileReader;
class WavFileWriter class WavFileWriter
{ {
protected: protected:
FILE* mHandle; /// Handle of audio file. FILE* mHandle; /// Handle of audio file.
std::tstring mFileName; /// Path to requested audio file. std::tstring mFileName; /// Path to requested audio file.
std::recursive_mutex mFileMtx; /// Mutex to protect this instance. std::recursive_mutex mFileMtx; /// Mutex to protect this instance.
size_t mWritten; /// Amount of written data (in bytes) size_t mWritten; /// Amount of written data (in bytes)
size_t mLengthOffset; /// Position of length field. size_t mLengthOffset; /// Position of length field.
int mRate, int mRate,
mChannels; mChannels;
void checkWriteResult(int result); void checkWriteResult(int result);
public: public:
WavFileWriter(); WavFileWriter();
~WavFileWriter(); ~WavFileWriter();
@ -82,9 +82,9 @@ namespace Audio
bool isOpened(); bool isOpened();
size_t write(const void* buffer, size_t bytes); size_t write(const void* buffer, size_t bytes);
std::tstring filename(); std::tstring filename();
}; };
typedef std::shared_ptr<WavFileWriter> PWavFileWriter; typedef std::shared_ptr<WavFileWriter> PWavFileWriter;
} }

File diff suppressed because it is too large Load Diff

View File

@ -24,118 +24,118 @@ class Session;
class Account: public resip::DnsResultSink class Account: public resip::DnsResultSink
{ {
friend class UserAgent; friend class UserAgent;
friend class NATDecorator; friend class NATDecorator;
public: public:
Account(PVariantMap config, UserAgent& agent); Account(PVariantMap config, UserAgent& agent);
~Account(); ~Account();
void start(); void start();
void stop(); void stop();
void refresh(); void refresh();
bool active(); bool active();
int id() const; int id() const;
enum class RegistrationState enum class RegistrationState
{ {
None, None,
Registering, Registering,
Reregistering, Reregistering,
Registered, Registered,
Unregistering Unregistering
}; };
RegistrationState registrationState(); RegistrationState registrationState();
/* Publishes new presence information */ /* Publishes new presence information */
void publishPresence(bool online, const std::string& content, int seconds = 600); void publishPresence(bool online, const std::string& content, int seconds = 600);
/* Stops publishing of presence */ /* Stops publishing of presence */
void stopPublish(); void stopPublish();
/* Starts observing on specified target / package */ /* Starts observing on specified target / package */
PClientObserver observe(const std::string& target, const std::string& package, void* tag); PClientObserver observe(const std::string& target, const std::string& package, void* tag);
/* Queues message to peer with specified mime type. Returns ID of message. */ /* Queues message to peer with specified mime type. Returns ID of message. */
int sendMsg(const std::string& peer, const void* ptr, unsigned length, const std::string& mime, void* tag); int sendMsg(const std::string& peer, const void* ptr, unsigned length, const std::string& mime, void* tag);
/* Returns name of account - <sip:user@domain> */ /* Returns name of account - <sip:user@domain> */
std::string name(); std::string name();
/* Updates account with configuration */ /* Updates account with configuration */
void setup(VariantMap& config); void setup(VariantMap& config);
/* Returns corresponding resiprocate profile */ /* Returns corresponding resiprocate profile */
std::shared_ptr<resip::UserProfile> getUserProfile() const { return mProfile; } std::shared_ptr<resip::UserProfile> getUserProfile() const { return mProfile; }
typedef std::map<std::string, std::string> UserInfo; typedef std::map<std::string, std::string> UserInfo;
void setUserInfo(const UserInfo& info); void setUserInfo(const UserInfo& info);
UserInfo getUserInfo() const; UserInfo getUserInfo() const;
protected: protected:
PVariantMap mConfig; PVariantMap mConfig;
// Registration // Registration
ResipSession* mRegistration; ResipSession* mRegistration;
resip::ClientRegistrationHandle mRegistrationHandle; resip::ClientRegistrationHandle mRegistrationHandle;
resip::ClientPublicationHandle mPublication; resip::ClientPublicationHandle mPublication;
resip::TransportType mUsedTransport; resip::TransportType mUsedTransport;
RegistrationState mRegistrationState; RegistrationState mRegistrationState;
ice::NetworkAddress mExternalAddress; ice::NetworkAddress mExternalAddress;
std::shared_ptr<resip::UserProfile> mProfile; std::shared_ptr<resip::UserProfile> mProfile;
UserAgent& mAgent; UserAgent& mAgent;
bool mPresenceOnline; bool mPresenceOnline;
std::string mPresenceContent; std::string mPresenceContent;
// Timer to refresh STUN server IP // Timer to refresh STUN server IP
ice::ICEScheduleTimer mRefreshStunServerIpTimer; ice::ICEScheduleTimer mRefreshStunServerIpTimer;
// Cached auth // Cached auth
resip::Auth mCachedAuth; resip::Auth mCachedAuth;
// Id of account // Id of account
int mId; int mId;
// User info about current state // User info about current state
UserInfo mUserInfo; UserInfo mUserInfo;
// List of client subscriptions sent from this account // List of client subscriptions sent from this account
typedef std::set<PClientObserver> ClientObserverSet; typedef std::set<PClientObserver> ClientObserverSet;
ClientObserverSet mClientObserverSet; ClientObserverSet mClientObserverSet;
void process(); void process();
// Method queries new stun server ip from dns (if stun server is specified as dns name) // Method queries new stun server ip from dns (if stun server is specified as dns name)
void queryStunServerIp(); void queryStunServerIp();
bool isResponsibleFor(const resip::NameAddr& addr); bool isResponsibleFor(const resip::NameAddr& addr);
enum class SecureScheme enum class SecureScheme
{ {
SipsAndTls, SipsAndTls,
SipsOnly, SipsOnly,
TlsOnly, TlsOnly,
Nothing Nothing
}; };
resip::NameAddr contact(SecureScheme ss = SecureScheme::SipsOnly); resip::NameAddr contact(SecureScheme ss = SecureScheme::SipsOnly);
// This method prepares configuration, creates ice stack and sets ownership to session // This method prepares configuration, creates ice stack and sets ownership to session
void prepareIceStack(Session* session, ice::AgentRole role); void prepareIceStack(Session* session, ice::AgentRole role);
void onSuccess(resip::ClientRegistrationHandle h, const resip::SipMessage& response); void onSuccess(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
void onRemoved(resip::ClientRegistrationHandle h, const resip::SipMessage& response); void onRemoved(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
void onFailure(resip::ClientRegistrationHandle, const resip::SipMessage& response); void onFailure(resip::ClientRegistrationHandle, const resip::SipMessage& response);
#pragma region DnsResultSink implementation #pragma region DnsResultSink implementation
void onDnsResult(const resip::DNSResult<resip::DnsHostRecord>&); void onDnsResult(const resip::DNSResult<resip::DnsHostRecord>&);
void onDnsResult(const resip::DNSResult<resip::DnsAAAARecord>&); void onDnsResult(const resip::DNSResult<resip::DnsAAAARecord>&);
void onDnsResult(const resip::DNSResult<resip::DnsSrvRecord>&); void onDnsResult(const resip::DNSResult<resip::DnsSrvRecord>&);
void onDnsResult(const resip::DNSResult<resip::DnsNaptrRecord>&); void onDnsResult(const resip::DNSResult<resip::DnsNaptrRecord>&);
void onDnsResult(const resip::DNSResult<resip::DnsCnameRecord>&); void onDnsResult(const resip::DNSResult<resip::DnsCnameRecord>&);
#pragma endregion #pragma endregion
static int generateId(); static int generateId();
static std::atomic_int IdGenerator; static std::atomic_int IdGenerator;
}; };
typedef std::shared_ptr<Account> PAccount; typedef std::shared_ptr<Account> PAccount;

View File

@ -8,67 +8,67 @@
bool DataProvider::isSupported(const char* name) bool DataProvider::isSupported(const char* name)
{ {
return !strcmp(name, "audio"); return !strcmp(name, "audio");
//return (!strcmp(name, "screen") || !strcmp(name, "data") || !strcmp(name, "audio") || !strcmp(name, "video")); //return (!strcmp(name, "screen") || !strcmp(name, "data") || !strcmp(name, "audio") || !strcmp(name, "video"));
} }
void DataProvider::pause() void DataProvider::pause()
{ {
/*if (state() & STATE_SIPRECV) /*if (state() & STATE_SIPRECV)
setState( state() & ~STATE_SIPRECV );*/ setState( state() & ~STATE_SIPRECV );*/
// Stop receive RTP stream // Stop receive RTP stream
if (state() & (int)StreamState::Receiving) if (state() & (int)StreamState::Receiving)
setState( state() & ~(int)StreamState::Receiving ); setState( state() & ~(int)StreamState::Receiving );
mActive = mfPaused; mActive = mfPaused;
} }
void DataProvider::resume() void DataProvider::resume()
{ {
// Tell remote peer about resumed receiving in SDP // Tell remote peer about resumed receiving in SDP
//setState( state() | STATE_SIPRECV ); //setState( state() | STATE_SIPRECV );
// Start receive RTP stream // Start receive RTP stream
setState( state() | (int)StreamState::Receiving ); setState( state() | (int)StreamState::Receiving );
mActive = mfActive; mActive = mfActive;
} }
bool DataProvider::processSdpOffer(const resip::SdpContents::Session::Medium& media, SdpDirection sdpDirection) bool DataProvider::processSdpOffer(const resip::SdpContents::Session::Medium& media, SdpDirection sdpDirection)
{ {
// Process paused and inactive calls // Process paused and inactive calls
if (media.exists("sendonly")) if (media.exists("sendonly"))
{
mRemoteState = msSendonly;
setState(state() & ~(int)StreamState::Sending);
}
else
if (media.exists("recvonly"))
{
mRemoteState = msRecvonly;
setState(state() & ~(int)StreamState::Receiving);
}
else
if (media.exists("inactive"))
{
mRemoteState = msInactive;
setState(state() & ~((int)StreamState::Sending | (int)StreamState::Receiving) );
}
else
{
mRemoteState = msSendRecv;
switch (mActive)
{ {
case mfActive: mRemoteState = msSendonly;
setState(state() | (int)StreamState::Sending | (int)StreamState::Receiving); setState(state() & ~(int)StreamState::Sending);
break;
case mfPaused:
setState(state() | (int)StreamState::Sending );
break;
} }
} else
return true; if (media.exists("recvonly"))
{
mRemoteState = msRecvonly;
setState(state() & ~(int)StreamState::Receiving);
}
else
if (media.exists("inactive"))
{
mRemoteState = msInactive;
setState(state() & ~((int)StreamState::Sending | (int)StreamState::Receiving) );
}
else
{
mRemoteState = msSendRecv;
switch (mActive)
{
case mfActive:
setState(state() | (int)StreamState::Sending | (int)StreamState::Receiving);
break;
case mfPaused:
setState(state() | (int)StreamState::Sending );
break;
}
}
return true;
} }

View File

@ -19,70 +19,70 @@
class DataProvider class DataProvider
{ {
public: public:
enum MediaFlow enum MediaFlow
{ {
mfActive, mfActive,
mfPaused mfPaused
}; };
enum MediaState
{
msSendRecv,
msSendonly,
msRecvonly,
msInactive
};
static bool isSupported(const char* name); enum MediaState
{
msSendRecv,
msSendonly,
msRecvonly,
msInactive
};
// Returns provider RTP name static bool isSupported(const char* name);
virtual std::string streamName() = 0;
// Returns provider RTP profile name
virtual std::string streamProfile() = 0;
// Sets destination IP address
virtual void setDestinationAddress(const RtpPair<InternetAddress>& addr) = 0;
// Processes incoming data // Returns provider RTP name
virtual void processData(const PDatagramSocket& s, const void* dataBuffer, int dataSize, InternetAddress& address) = 0; virtual std::string streamName() = 0;
// This method is called by user agent to send ICE packet from mediasocket // Returns provider RTP profile name
virtual void sendData(const PDatagramSocket& s, InternetAddress& destination, const void* dataBuffer, unsigned int datasize) = 0; virtual std::string streamProfile() = 0;
// Updates SDP offer
virtual void updateSdpOffer(resip::SdpContents::Session::Medium& sdp, SdpDirection direction) = 0;
// Called by user agent when session is deleted. Comes after sessionTerminated(). // Sets destination IP address
virtual void sessionDeleted() = 0; virtual void setDestinationAddress(const RtpPair<InternetAddress>& addr) = 0;
// Called by user agent when session is terminated. // Processes incoming data
virtual void sessionTerminated() = 0; virtual void processData(const PDatagramSocket& s, const void* dataBuffer, int dataSize, InternetAddress& address) = 0;
// Called by user agent when session is started. // This method is called by user agent to send ICE packet from mediasocket
virtual void sessionEstablished(int conntype) = 0; virtual void sendData(const PDatagramSocket& s, InternetAddress& destination, const void* dataBuffer, unsigned int datasize) = 0;
// Called by user agent to save media socket for this provider // Updates SDP offer
virtual void setSocket(const RtpPair<PDatagramSocket>& p4, const RtpPair<PDatagramSocket>& p6) = 0; virtual void updateSdpOffer(resip::SdpContents::Session::Medium& sdp, SdpDirection direction) = 0;
// Called by user agent to get media socket for this provider
virtual RtpPair<PDatagramSocket>& socket(int family) = 0;
// Called by user agent to process media stream description from remote peer. // Called by user agent when session is deleted. Comes after sessionTerminated().
// Returns true if description is processed succesfully. Otherwise method returns false. virtual void sessionDeleted() = 0;
virtual bool processSdpOffer(const resip::SdpContents::Session::Medium& media, SdpDirection sdpDirection) = 0;
virtual unsigned state() = 0;
virtual void setState(unsigned state) = 0;
virtual void pause();
virtual void resume();
virtual MT::Statistics getStatistics() = 0; // Called by user agent when session is terminated.
virtual void sessionTerminated() = 0;
// Called by user agent when session is started.
virtual void sessionEstablished(int conntype) = 0;
// Called by user agent to save media socket for this provider
virtual void setSocket(const RtpPair<PDatagramSocket>& p4, const RtpPair<PDatagramSocket>& p6) = 0;
// Called by user agent to get media socket for this provider
virtual RtpPair<PDatagramSocket>& socket(int family) = 0;
// Called by user agent to process media stream description from remote peer.
// Returns true if description is processed succesfully. Otherwise method returns false.
virtual bool processSdpOffer(const resip::SdpContents::Session::Medium& media, SdpDirection sdpDirection) = 0;
virtual unsigned state() = 0;
virtual void setState(unsigned state) = 0;
virtual void pause();
virtual void resume();
virtual MT::Statistics getStatistics() = 0;
protected: protected:
MediaFlow mActive; MediaFlow mActive;
MediaState mRemoteState; MediaState mRemoteState;
}; };
typedef std::shared_ptr<DataProvider> PDataProvider; typedef std::shared_ptr<DataProvider> PDataProvider;

File diff suppressed because it is too large Load Diff

View File

@ -70,52 +70,52 @@ enum
enum enum
{ {
CONFIG_IPV4 = 0, // Use IP4 CONFIG_IPV4 = 0, // Use IP4
CONFIG_IPV6, // Use IP6. CONFIG_IPV6, // Use IP6.
CONFIG_USERNAME, // Username. String value. CONFIG_USERNAME, // Username. String value.
CONFIG_DOMAIN, // Domain. String value. CONFIG_DOMAIN, // Domain. String value.
CONFIG_PASSWORD, // Password. String value. CONFIG_PASSWORD, // Password. String value.
CONFIG_RINSTANCE, // Determines if SIP rinstance field has to be used during registration. Boolean value. CONFIG_RINSTANCE, // Determines if SIP rinstance field has to be used during registration. Boolean value.
CONFIG_INSTANCE_ID, // Instance id. It is alternative option to rinstance. CONFIG_INSTANCE_ID, // Instance id. It is alternative option to rinstance.
CONFIG_DISPLAYNAME, // Optional user display name. String value. CONFIG_DISPLAYNAME, // Optional user display name. String value.
CONFIG_DOMAINPORT, // Optional domain port number. Integer value. CONFIG_DOMAINPORT, // Optional domain port number. Integer value.
CONFIG_REGISTERDURATION, // Wanted duration for registration. Integer value. It is MANDATORY value. CONFIG_REGISTERDURATION, // Wanted duration for registration. Integer value. It is MANDATORY value.
CONFIG_RPORT, // Use SIP rport field. Recommended to set it to true. Boolean value. CONFIG_RPORT, // Use SIP rport field. Recommended to set it to true. Boolean value.
CONFIG_KEEPALIVETIME, // Interval between UDP keep-alive messages. Boolean value. CONFIG_KEEPALIVETIME, // Interval between UDP keep-alive messages. Boolean value.
CONFIG_RELAY, // Sets if TURN server must be used instead of STUN. Boolean value. CONFIG_RELAY, // Sets if TURN server must be used instead of STUN. Boolean value.
CONFIG_ICETIMEOUT, // Optional timeout for ICE connectivity checks and candidate gathering. Integer value. CONFIG_ICETIMEOUT, // Optional timeout for ICE connectivity checks and candidate gathering. Integer value.
CONFIG_ICEUSERNAME, // Optional username for TURN server. String value. CONFIG_ICEUSERNAME, // Optional username for TURN server. String value.
CONFIG_ICEPASSWORD, // Optional password for TURN server. String value. CONFIG_ICEPASSWORD, // Optional password for TURN server. String value.
CONFIG_SIPS, // Marks if account credentials are sips: scheme. Boolean value. CONFIG_SIPS, // Marks if account credentials are sips: scheme. Boolean value.
CONFIG_STUNSERVER_IP, // Optional IP address of STUN/TURN server. String value. It is better to use CONFIG_STUNSERVER_NAME. CONFIG_STUNSERVER_IP, // Optional IP address of STUN/TURN server. String value. It is better to use CONFIG_STUNSERVER_NAME.
CONFIG_STUNSERVER_NAME, // Host name of STUN/TURN server. stun.xten.com for example. String value. CONFIG_STUNSERVER_NAME, // Host name of STUN/TURN server. stun.xten.com for example. String value.
CONFIG_STUNSERVER_PORT, // Port number of STUN/TURN server. Integer value. CONFIG_STUNSERVER_PORT, // Port number of STUN/TURN server. Integer value.
CONFIG_USERAGENT, // Name of user agent in SIP headers. String value. CONFIG_USERAGENT, // Name of user agent in SIP headers. String value.
CONFIG_ICEREQUIRED, // ICE MUST be present in remote peer offers and answers. Boolean value. CONFIG_ICEREQUIRED, // ICE MUST be present in remote peer offers and answers. Boolean value.
CONFIG_TRANSPORT, // 0 - all transports, 1 - UDP, 2 - TCP, 3 - TLS, CONFIG_TRANSPORT, // 0 - all transports, 1 - UDP, 2 - TCP, 3 - TLS,
CONFIG_SUBSCRIPTION_TIME, // Subscription time (in seconds) CONFIG_SUBSCRIPTION_TIME, // Subscription time (in seconds)
CONFIG_SUBSCRIPTION_REFRESHTIME, // Refresh interval for subscriptions CONFIG_SUBSCRIPTION_REFRESHTIME, // Refresh interval for subscriptions
CONFIG_DNS_CACHE_TIME, // DNS cache time; default is 86400 seconds CONFIG_DNS_CACHE_TIME, // DNS cache time; default is 86400 seconds
CONFIG_PRESENCE_ID, // Tuple ID used in presence publishing; determines source device CONFIG_PRESENCE_ID, // Tuple ID used in presence publishing; determines source device
CONFIG_ROOTCERT, // Additional root cert in PEM format; string. CONFIG_ROOTCERT, // Additional root cert in PEM format; string.
CONFIG_CACHECREDENTIALS, // Attempt to cache credentials that comes in response from PBX. Use them when possible to reduce number of steps of SIP transaction CONFIG_CACHECREDENTIALS, // Attempt to cache credentials that comes in response from PBX. Use them when possible to reduce number of steps of SIP transaction
CONFIG_RTCP_ATTR, // Use "rtcp" attribute in sdp. Default value is true. CONFIG_RTCP_ATTR, // Use "rtcp" attribute in sdp. Default value is true.
CONFIG_MULTIPLEXING, // Do rtp/rtcp multiplexing CONFIG_MULTIPLEXING, // Do rtp/rtcp multiplexing
CONFIG_DEFERRELAYED, // Defer relayed media path CONFIG_DEFERRELAYED, // Defer relayed media path
CONFIG_PROXY, // Proxy host name or IP address CONFIG_PROXY, // Proxy host name or IP address
CONFIG_PROXYPORT, // Proxy port number CONFIG_PROXYPORT, // Proxy port number
CONFIG_CODEC_PRIORITY, // Another VariantMap with codec priorities, CONFIG_CODEC_PRIORITY, // Another VariantMap with codec priorities,
CONFIG_ACCOUNT, // VariantMap with account configuration CONFIG_ACCOUNT, // VariantMap with account configuration
CONFIG_EXTERNALIP, // Use external/public IP in outgoing requests CONFIG_EXTERNALIP, // Use external/public IP in outgoing requests
CONFIG_OWN_DNS, // Use predefined DNS servers CONFIG_OWN_DNS, // Use predefined DNS servers
CONFIG_REGID // reg-id value from RFC5626 CONFIG_REGID // reg-id value from RFC5626
}; };
// Conntype parameter for OnSessionEstablished event // Conntype parameter for OnSessionEstablished event
enum enum
{ {
EV_SIP = 1, EV_SIP = 1,
EV_ICE = 2 EV_ICE = 2
}; };
class UserAgent; class UserAgent;
@ -124,7 +124,7 @@ class UserAgent;
class SIPAction class SIPAction
{ {
public: public:
virtual void Run(UserAgent& ua) = 0; virtual void Run(UserAgent& ua) = 0;
}; };
typedef std::vector<SIPAction*> SIPActionVector; typedef std::vector<SIPAction*> SIPActionVector;
@ -132,15 +132,15 @@ typedef std::vector<SIPAction*> SIPActionVector;
// Session termination reason // Session termination reason
enum enum
{ {
Error, Error,
Timeout, Timeout,
Replaced, Replaced,
LocalBye, LocalBye,
RemoteBye, RemoteBye,
LocalCancel, LocalCancel,
RemoteCancel, RemoteCancel,
Rejected, //Only as UAS, UAC has distinct onFailure callback Rejected, //Only as UAS, UAC has distinct onFailure callback
Referred Referred
}; };
class UserAgent: public resip::ClientRegistrationHandler, class UserAgent: public resip::ClientRegistrationHandler,
@ -153,238 +153,238 @@ class UserAgent: public resip::ClientRegistrationHandler,
public resip::ClientPagerMessageHandler, public resip::ClientPagerMessageHandler,
public resip::ServerPagerMessageHandler, public resip::ServerPagerMessageHandler,
public resip::ClientPublicationHandler public resip::ClientPublicationHandler
//public resip::InternalTransport::TransportLogger //public resip::InternalTransport::TransportLogger
{ {
friend class Account; friend class Account;
friend class Session; friend class Session;
friend class ResipSession; friend class ResipSession;
friend class NATDecorator; friend class NATDecorator;
friend class WatcherQueue; friend class WatcherQueue;
public: public:
/* Compares two sip addresses. Returns true if they represent the same entity - user and domain are the same. Otherwise returns false. */ /* Compares two sip addresses. Returns true if they represent the same entity - user and domain are the same. Otherwise returns false. */
static bool compareSipAddresses(const std::string& sip1, const std::string& sip2); static bool compareSipAddresses(const std::string& sip1, const std::string& sip2);
static std::string formatSipAddress(const std::string& sip); static std::string formatSipAddress(const std::string& sip);
static bool isSipAddressValid(const std::string& sip); static bool isSipAddressValid(const std::string& sip);
struct SipAddress struct SipAddress
{ {
bool mValid; bool mValid;
std::string mScheme; std::string mScheme;
std::string mUsername; std::string mUsername;
std::string mDomain; std::string mDomain;
std::string mDisplayname; std::string mDisplayname;
}; };
static SipAddress parseSipAddress(const std::string& sip); static SipAddress parseSipAddress(const std::string& sip);
UserAgent(); UserAgent();
virtual ~UserAgent(); virtual ~UserAgent();
/* Brings user agent online. Basically it creates a signalling socket(s). /* Brings user agent online. Basically it creates a signalling socket(s).
This is asynchronous method. */ This is asynchronous method. */
void start(); void start();
/* Shutdowns user agent. It closes all sessions, tries to unregister from server and disconnects from it. /* Shutdowns user agent. It closes all sessions, tries to unregister from server and disconnects from it.
This is asynchronous method. onStop() event will be called later */ This is asynchronous method. onStop() event will be called later */
void shutdown(); void shutdown();
/* Emergency stop. Please always call shutdown() before this. Kills registration, sessions & presence - everything. onStop() is called in context of this method. */
void stop();
/* Checks if user agent is active (started). */ /* Emergency stop. Please always call shutdown() before this. Kills registration, sessions & presence - everything. onStop() is called in context of this method. */
bool active(); void stop();
/* Used to refresh existing registration(s), publication, subscriptions. */
void refresh();
/* Runs sip & ice stacks. Event handlers are called in its context. */ /* Checks if user agent is active (started). */
void process(); bool active();
/* Adds root cert in PEM format. Usable after start() call. */
void addRootCert(const ByteBuffer& data);
PAccount createAccount(PVariantMap config); /* Used to refresh existing registration(s), publication, subscriptions. */
void deleteAccount(PAccount account); void refresh();
/* Creates session. Returns session ID. */ /* Runs sip & ice stacks. Event handlers are called in its context. */
PSession createSession(PAccount account); void process();
// Must be called when IP interface list is changed
void updateInterfaceList();
// Called on new incoming session; providers shoukld /* Adds root cert in PEM format. Usable after start() call. */
virtual PDataProvider onProviderNeeded(const std::string& name) = 0; void addRootCert(const ByteBuffer& data);
// Called on new session offer PAccount createAccount(PVariantMap config);
virtual void onNewSession(PSession s) = 0; void deleteAccount(PAccount account);
// Called when session is terminated
virtual void onSessionTerminated(PSession s, int responsecode, int reason) = 0;
// Called when session is established ok i.e. after all ICE signalling is finished
// Conntype is type of establish event - EV_SIP or EV_ICE
virtual void onSessionEstablished(PSession s, int conntype, const RtpPair<InternetAddress>& p) = 0;
// Called when client session gets /* Creates session. Returns session ID. */
virtual void onSessionProvisional(PSession s, int code) = 0; PSession createSession(PAccount account);
// Called when user agent started // Must be called when IP interface list is changed
virtual void onStart(int errorcode) = 0; void updateInterfaceList();
// Called when user agent stopped
virtual void onStop() = 0;
// Called when account registered // Called on new incoming session; providers shoukld
virtual void onAccountStart(PAccount account) = 0; virtual PDataProvider onProviderNeeded(const std::string& name) = 0;
// Called when account removed or failed (non zero error code) // Called on new session offer
virtual void onAccountStop(PAccount account, int error) = 0; virtual void onNewSession(PSession s) = 0;
// Called when connectivity checks failed. // Called when session is terminated
virtual void onConnectivityFailed(PSession s) = 0; virtual void onSessionTerminated(PSession s, int responsecode, int reason) = 0;
// Called when new candidate is gathered // Called when session is established ok i.e. after all ICE signalling is finished
virtual void onCandidateGathered(PSession s, const char* address); // Conntype is type of establish event - EV_SIP or EV_ICE
virtual void onSessionEstablished(PSession s, int conntype, const RtpPair<InternetAddress>& p) = 0;
// Called when network change detected
virtual void onNetworkChange(PSession s) = 0;
// Called when all candidates are gathered // Called when client session gets
virtual void onGathered(PSession s); virtual void onSessionProvisional(PSession s, int code) = 0;
// Called when new connectivity check is finished // Called when user agent started
virtual void onCheckFinished(PSession s, const char* description); virtual void onStart(int errorcode) = 0;
// Called when log message must be recorded
virtual void onLog(const char* msg);
// Called when problem with SIP connection(s) detected
virtual void onSipConnectionFailed() = 0;
// Subscribe/publish presence methods // Called when user agent stopped
virtual void onPublicationSuccess(PAccount acc); virtual void onStop() = 0;
virtual void onPublicationTerminated(PAccount acc, int code);
virtual void onClientObserverStart(PClientObserver observer);
virtual void onServerObserverStart(PServerObserver observer);
virtual void onClientObserverStop(PClientObserver observer, int code);
virtual void onServerObserverStop(PServerObserver observer, int code);
virtual void onPresenceUpdate(PClientObserver observer, const std::string& peer, bool online, const std::string& content); // Called when account registered
virtual void onMessageArrived(PAccount account, const std::string& peer, const void* ptr, unsigned length); virtual void onAccountStart(PAccount account) = 0;
virtual void onMessageFailed(PAccount account, int id, const std::string& peer, int code, void* tag);
virtual void onMessageSent(PAccount account, int id, const std::string& peer, void* tag); // Called when account removed or failed (non zero error code)
virtual void onAccountStop(PAccount account, int error) = 0;
// Configuration methods
VariantMap& config(); // Called when connectivity checks failed.
virtual void onConnectivityFailed(PSession s) = 0;
// Called when new candidate is gathered
virtual void onCandidateGathered(PSession s, const char* address);
// Called when network change detected
virtual void onNetworkChange(PSession s) = 0;
// Called when all candidates are gathered
virtual void onGathered(PSession s);
// Called when new connectivity check is finished
virtual void onCheckFinished(PSession s, const char* description);
// Called when log message must be recorded
virtual void onLog(const char* msg);
// Called when problem with SIP connection(s) detected
virtual void onSipConnectionFailed() = 0;
// Subscribe/publish presence methods
virtual void onPublicationSuccess(PAccount acc);
virtual void onPublicationTerminated(PAccount acc, int code);
virtual void onClientObserverStart(PClientObserver observer);
virtual void onServerObserverStart(PServerObserver observer);
virtual void onClientObserverStop(PClientObserver observer, int code);
virtual void onServerObserverStop(PServerObserver observer, int code);
virtual void onPresenceUpdate(PClientObserver observer, const std::string& peer, bool online, const std::string& content);
virtual void onMessageArrived(PAccount account, const std::string& peer, const void* ptr, unsigned length);
virtual void onMessageFailed(PAccount account, int id, const std::string& peer, int code, void* tag);
virtual void onMessageSent(PAccount account, int id, const std::string& peer, void* tag);
// Configuration methods
VariantMap& config();
public: public:
// InviteSessionHandler implementation // InviteSessionHandler implementation
#pragma region InviteSessionHandler implementation #pragma region InviteSessionHandler implementation
/// called when an initial INVITE or the intial response to an outoing invite /// called when an initial INVITE or the intial response to an outoing invite
virtual void onNewSession(resip::ClientInviteSessionHandle, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg) override; virtual void onNewSession(resip::ClientInviteSessionHandle, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg) override;
virtual void onNewSession(resip::ServerInviteSessionHandle, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg) override; virtual void onNewSession(resip::ServerInviteSessionHandle, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg) override;
/// Received a failure response from UAS /// Received a failure response from UAS
virtual void onFailure(resip::ClientInviteSessionHandle, const resip::SipMessage& msg) override; virtual void onFailure(resip::ClientInviteSessionHandle, const resip::SipMessage& msg) override;
/// called when an in-dialog provisional response is received that contains an SDP body
virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&, const resip::SdpContents&) override;
/// called when dialog enters the Early state - typically after getting 18x /// called when an in-dialog provisional response is received that contains an SDP body
virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage&) override; virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&, const resip::SdpContents&) override;
/// called when a dialog initiated as a UAC enters the connected state /// called when dialog enters the Early state - typically after getting 18x
virtual void onConnected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg) override; virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage&) override;
/// called when a dialog initiated as a UAS enters the connected state /// called when a dialog initiated as a UAC enters the connected state
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg) override; virtual void onConnected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg) override;
virtual void onTerminated(resip::InviteSessionHandle, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* related=0) override; /// called when a dialog initiated as a UAS enters the connected state
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// called when a fork that was created through a 1xx never receives a 2xx virtual void onTerminated(resip::InviteSessionHandle, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* related=0) override;
/// because another fork answered and this fork was canceled by a proxy.
virtual void onForkDestroyed(resip::ClientInviteSessionHandle) override;
/// called when a 3xx with valid targets is encountered in an early dialog /// called when a fork that was created through a 1xx never receives a 2xx
/// This is different then getting a 3xx in onTerminated, as another /// because another fork answered and this fork was canceled by a proxy.
/// request will be attempted, so the DialogSet will not be destroyed. virtual void onForkDestroyed(resip::ClientInviteSessionHandle) override;
/// Basically an onTermintated that conveys more information.
/// checking for 3xx respones in onTerminated will not work as there may
/// be no valid targets.
virtual void onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg) override;
/// called when an SDP answer is received - has nothing to do with user /// called when a 3xx with valid targets is encountered in an early dialog
/// answering the call /// This is different then getting a 3xx in onTerminated, as another
virtual void onAnswer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&) override; /// request will be attempted, so the DialogSet will not be destroyed.
/// Basically an onTermintated that conveys more information.
/// checking for 3xx respones in onTerminated will not work as there may
/// be no valid targets.
virtual void onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg) override;
/// called when an SDP offer is received - must send an answer soon after this /// called when an SDP answer is received - has nothing to do with user
virtual void onOffer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&) override; /// answering the call
virtual void onAnswer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&) override;
/// called when an Invite w/out SDP is sent, or any other context which /// called when an SDP offer is received - must send an answer soon after this
/// requires an SDP offer from the user virtual void onOffer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&) override;
virtual void onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// called if an offer in a UPDATE or re-INVITE was rejected - not real
/// useful. A SipMessage is provided if one is available
virtual void onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg) override;
/// called when INFO message is received
virtual void onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// called when response to INFO message is received /// called when an Invite w/out SDP is sent, or any other context which
virtual void onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg) override; /// requires an SDP offer from the user
virtual void onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg) override; virtual void onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// called when MESSAGE message is received /// called if an offer in a UPDATE or re-INVITE was rejected - not real
virtual void onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg) override; /// useful. A SipMessage is provided if one is available
virtual void onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg) override;
/// called when response to MESSAGE message is received /// called when INFO message is received
virtual void onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg) override; virtual void onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
virtual void onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// called when an REFER message is received. The refer is accepted or /// called when response to INFO message is received
/// rejected using the server subscription. If the offer is accepted, virtual void onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// DialogUsageManager::makeInviteSessionFromRefer can be used to create an virtual void onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// InviteSession that will send notify messages using the ServerSubscription
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg) override;
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg) override; /// called when MESSAGE message is received
virtual void onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// called when an REFER message receives a failure response /// called when response to MESSAGE message is received
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg) override; virtual void onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
virtual void onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// called when an REFER message receives an accepted response /// called when an REFER message is received. The refer is accepted or
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg) override; /// rejected using the server subscription. If the offer is accepted,
/// DialogUsageManager::makeInviteSessionFromRefer can be used to create an
/// InviteSession that will send notify messages using the ServerSubscription
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg) override;
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// called when an REFER message receives a failure response
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
/// called when an REFER message receives an accepted response
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg) override;
#pragma endregion #pragma endregion
// ClientRegistrationHandler implementation // ClientRegistrationHandler implementation
#pragma region ClientRegistrationHandler implementation #pragma region ClientRegistrationHandler implementation
/// Called when registraion succeeds or each time it is sucessfully /// Called when registraion succeeds or each time it is sucessfully
/// refreshed. /// refreshed.
void onSuccess(resip::ClientRegistrationHandle, const resip::SipMessage& response) override; void onSuccess(resip::ClientRegistrationHandle, const resip::SipMessage& response) override;
// Called when all of my bindings have been removed // Called when all of my bindings have been removed
void onRemoved(resip::ClientRegistrationHandle, const resip::SipMessage& response) override; void onRemoved(resip::ClientRegistrationHandle, const resip::SipMessage& response) override;
/// call on Retry-After failure. /// call on Retry-After failure.
/// return values: -1 = fail, 0 = retry immediately, N = retry in N seconds /// return values: -1 = fail, 0 = retry immediately, N = retry in N seconds
int onRequestRetry(resip::ClientRegistrationHandle, int retrySeconds, const resip::SipMessage& response) override; int onRequestRetry(resip::ClientRegistrationHandle, int retrySeconds, const resip::SipMessage& response) override;
/// Called if registration fails, usage will be destroyed (unless a /// Called if registration fails, usage will be destroyed (unless a
/// Registration retry interval is enabled in the Profile) /// Registration retry interval is enabled in the Profile)
void onFailure(resip::ClientRegistrationHandle, const resip::SipMessage& response) override; void onFailure(resip::ClientRegistrationHandle, const resip::SipMessage& response) override;
#pragma endregion #pragma endregion
#pragma region ExternalLogger implementation #pragma region ExternalLogger implementation
/** return true to also do default logging, false to suppress default logging. */ /** return true to also do default logging, false to suppress default logging. */
virtual bool operator()(resip::Log::Level level, virtual bool operator()(resip::Log::Level level,
const resip::Subsystem& subsystem, const resip::Subsystem& subsystem,
const resip::Data& appName, const resip::Data& appName,
const char* file, const char* file,
int line, int line,
const resip::Data& message, const resip::Data& message,
const resip::Data& messageWithHeaders, const resip::Data& messageWithHeaders,
const resip::Data& instanceName) override; const resip::Data& instanceName) override;
#pragma endregion #pragma endregion
#pragma region DnsResultSink implementation #pragma region DnsResultSink implementation
@ -402,92 +402,92 @@ public:
#pragma endregion #pragma endregion
#pragma region ClientPublicationHandler #pragma region ClientPublicationHandler
void onSuccess(resip::ClientPublicationHandle, const resip::SipMessage& status) override; void onSuccess(resip::ClientPublicationHandle, const resip::SipMessage& status) override;
void onRemove(resip::ClientPublicationHandle, const resip::SipMessage& status) override; void onRemove(resip::ClientPublicationHandle, const resip::SipMessage& status) override;
void onFailure(resip::ClientPublicationHandle, const resip::SipMessage& status) override; void onFailure(resip::ClientPublicationHandle, const resip::SipMessage& status) override;
int onRequestRetry(resip::ClientPublicationHandle, int retrySeconds, const resip::SipMessage& status) override; int onRequestRetry(resip::ClientPublicationHandle, int retrySeconds, const resip::SipMessage& status) override;
#pragma endregion #pragma endregion
#pragma region SubscriptionHandler #pragma region SubscriptionHandler
void onUpdate(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify); void onUpdate(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify);
void onUpdatePending(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder) override; void onUpdatePending(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder) override;
void onUpdateActive(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder) override; void onUpdateActive(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder) override;
//unknown Subscription-State value
void onUpdateExtension(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder) override;
int onRequestRetry(resip::ClientSubscriptionHandle, int retrySeconds, const resip::SipMessage& notify) override;
//subscription can be ended through a notify or a failure response.
void onTerminated(resip::ClientSubscriptionHandle, const resip::SipMessage* msg) override;
//not sure if this has any value.
void onNewSubscription(resip::ClientSubscriptionHandle, const resip::SipMessage& notify) override;
/// called to allow app to adorn a message. //unknown Subscription-State value
void onReadyToSend(resip::ClientSubscriptionHandle, resip::SipMessage& msg) override; void onUpdateExtension(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder) override;
void onNotifyNotReceived(resip::ClientSubscriptionHandle) override; int onRequestRetry(resip::ClientSubscriptionHandle, int retrySeconds, const resip::SipMessage& notify) override;
/// Called when a TCP or TLS flow to the server has terminated. This can be caused by socket //subscription can be ended through a notify or a failure response.
/// errors, or missing CRLF keep alives pong responses from the server. void onTerminated(resip::ClientSubscriptionHandle, const resip::SipMessage* msg) override;
// Called only if clientOutbound is enabled on the UserProfile and the first hop server //not sure if this has any value.
/// supports RFC5626 (outbound). void onNewSubscription(resip::ClientSubscriptionHandle, const resip::SipMessage& notify) override;
/// Default implementation is to re-form the subscription using a new flow
void onFlowTerminated(resip::ClientSubscriptionHandle) override; /// called to allow app to adorn a message.
void onNewSubscription(resip::ServerSubscriptionHandle, const resip::SipMessage& sub) override; void onReadyToSend(resip::ClientSubscriptionHandle, resip::SipMessage& msg) override;
void onTerminated(resip::ServerSubscriptionHandle) override; void onNotifyNotReceived(resip::ClientSubscriptionHandle) override;
/// Called when a TCP or TLS flow to the server has terminated. This can be caused by socket
/// errors, or missing CRLF keep alives pong responses from the server.
// Called only if clientOutbound is enabled on the UserProfile and the first hop server
/// supports RFC5626 (outbound).
/// Default implementation is to re-form the subscription using a new flow
void onFlowTerminated(resip::ClientSubscriptionHandle) override;
void onNewSubscription(resip::ServerSubscriptionHandle, const resip::SipMessage& sub) override;
void onTerminated(resip::ServerSubscriptionHandle) override;
#pragma endregion #pragma endregion
#pragma region PagerHandler #pragma region PagerHandler
void onSuccess(resip::ClientPagerMessageHandle, const resip::SipMessage& status) override; void onSuccess(resip::ClientPagerMessageHandle, const resip::SipMessage& status) override;
void onFailure(resip::ClientPagerMessageHandle, const resip::SipMessage& status, std::unique_ptr<resip::Contents> contents) override; void onFailure(resip::ClientPagerMessageHandle, const resip::SipMessage& status, std::unique_ptr<resip::Contents> contents) override;
void onMessageArrived(resip::ServerPagerMessageHandle, const resip::SipMessage& message) override; void onMessageArrived(resip::ServerPagerMessageHandle, const resip::SipMessage& message) override;
#pragma endregion #pragma endregion
void onDumCanBeDeleted() override; void onDumCanBeDeleted() override;
protected: protected:
// Mutex to protect this instance // Mutex to protect this instance
Mutex mGuard; Mutex mGuard;
// Smart pointer to resiprocate's master profile instance. The stack configuration holds here. // Smart pointer to resiprocate's master profile instance. The stack configuration holds here.
std::shared_ptr<resip::MasterProfile> mProfile; std::shared_ptr<resip::MasterProfile> mProfile;
// Resiprocate's SIP stack object pointer
resip::SipStack* mStack;
// Resiprocate's dialog usage manager object pointer
resip::DialogUsageManager* mDum;
// List of available transports. They are owned by SipStack - so there is no need to delete instances in UserAgent.
std::vector<resip::InternalTransport*> mTransportList;
typedef std::map<int, PSession> SessionMap; // Resiprocate's SIP stack object pointer
resip::SipStack* mStack;
// Session's map
SessionMap mSessionMap;
// Used configuration // Resiprocate's dialog usage manager object pointer
VariantMap mConfig; resip::DialogUsageManager* mDum;
// Action vector // List of available transports. They are owned by SipStack - so there is no need to delete instances in UserAgent.
SIPActionVector mActionVector; std::vector<resip::InternalTransport*> mTransportList;
typedef std::map<int, PClientObserver> ClientObserverMap;
ClientObserverMap mClientObserverMap;
typedef std::map<int, PServerObserver> ServerObserverMap; typedef std::map<int, PSession> SessionMap;
ServerObserverMap mServerObserverMap;
typedef std::set<PAccount> AccountSet;
AccountSet mAccountSet;
// Constructs and sends INVITE to remote peer. Remote peer address is stored inside session object. // Session's map
void sendOffer(Session* session); SessionMap mSessionMap;
void internalStopSession(Session& session);
void processWatchingList();
bool handleMultipartRelatedNotify(const resip::SipMessage& notify);
PSession getUserSession(int sessionId); // Used configuration
PAccount getAccount(const resip::NameAddr& myAddr); VariantMap mConfig;
PAccount getAccount(Account* account);
PAccount getAccount(int sessionId); // Action vector
SIPActionVector mActionVector;
typedef std::map<int, PClientObserver> ClientObserverMap;
ClientObserverMap mClientObserverMap;
typedef std::map<int, PServerObserver> ServerObserverMap;
ServerObserverMap mServerObserverMap;
typedef std::set<PAccount> AccountSet;
AccountSet mAccountSet;
// Constructs and sends INVITE to remote peer. Remote peer address is stored inside session object.
void sendOffer(Session* session);
void internalStopSession(Session& session);
void processWatchingList();
bool handleMultipartRelatedNotify(const resip::SipMessage& notify);
PSession getUserSession(int sessionId);
PAccount getAccount(const resip::NameAddr& myAddr);
PAccount getAccount(Account* account);
PAccount getAccount(int sessionId);
}; };
#endif #endif

View File

@ -2,7 +2,7 @@
#include "EP_Engine.h" #include "EP_Engine.h"
WatcherQueue::WatcherQueue(UserAgent& ua) WatcherQueue::WatcherQueue(UserAgent& ua)
:mActiveId(0), mAgent(ua) :mActiveId(0), mAgent(ua)
{} {}
WatcherQueue::~WatcherQueue() WatcherQueue::~WatcherQueue()
@ -10,173 +10,173 @@ WatcherQueue::~WatcherQueue()
int WatcherQueue::add(std::string peer, std::string package, void* tag) int WatcherQueue::add(std::string peer, std::string package, void* tag)
{ {
ice::Lock l(mGuard); ice::Lock l(mGuard);
// Check if queue has similar item // Check if queue has similar item
for (unsigned i=0; i<mItemList.size(); i++) for (unsigned i=0; i<mItemList.size(); i++)
{ {
Item& item = mItemList[i]; Item& item = mItemList[i];
if (item.mTarget == peer && item.mPackage == package && if (item.mTarget == peer && item.mPackage == package &&
item.mState != Item::State_Deleting) item.mState != Item::State_Deleting)
return item.mId; return item.mId;
} }
Item item; Item item;
item.mTarget = peer; item.mTarget = peer;
item.mPackage = package; item.mPackage = package;
item.mTag = tag; item.mTag = tag;
item.mState = Item::State_ScheduledToAdd; item.mState = Item::State_ScheduledToAdd;
item.mSession = new ResipSession(*mAgent.mDum); item.mSession = new ResipSession(*mAgent.mDum);
item.mSession->setUa(&mAgent); item.mSession->setUa(&mAgent);
item.mSession->setType(ResipSession::Type_Subscription); item.mSession->setType(ResipSession::Type_Subscription);
item.mSession->setTag(tag); item.mSession->setTag(tag);
item.mId = item.mSession->sessionId(); item.mId = item.mSession->sessionId();
item.mSession->setRemoteAddress(peer); item.mSession->setRemoteAddress(peer);
item.mTag = tag; item.mTag = tag;
mItemList.push_back(item); mItemList.push_back(item);
process(); process();
return item.mId; return item.mId;
} }
void WatcherQueue::remove(int id) void WatcherQueue::remove(int id)
{ {
ice::Lock l(mGuard); ice::Lock l(mGuard);
// Check if queue has similar item // Check if queue has similar item
for (unsigned i=0; i<mItemList.size(); i++) for (unsigned i=0; i<mItemList.size(); i++)
{
Item& item = mItemList[i];
if (item.mId == id && !id)
{ {
if (item.mState != Item::State_Deleting) Item& item = mItemList[i];
item.mState = Item::State_ScheduledToDelete; if (item.mId == id && !id)
{
if (item.mState != Item::State_Deleting)
item.mState = Item::State_ScheduledToDelete;
}
} }
} process();
process();
} }
void WatcherQueue::refresh(int id) void WatcherQueue::refresh(int id)
{ {
ice::Lock l(mGuard); ice::Lock l(mGuard);
// Check if queue has similar item // Check if queue has similar item
for (unsigned i=0; i<mItemList.size(); i++) for (unsigned i=0; i<mItemList.size(); i++)
{
Item& item = mItemList[i];
if (item.mId == id && !id)
{ {
if (item.mState == Item::State_ScheduledToDelete || item.mState == Item::State_Active) Item& item = mItemList[i];
item.mState = Item::State_ScheduledToRefresh; if (item.mId == id && !id)
{
if (item.mState == Item::State_ScheduledToDelete || item.mState == Item::State_Active)
item.mState = Item::State_ScheduledToRefresh;
}
} }
} process();
process();
} }
void WatcherQueue::process() void WatcherQueue::process()
{ {
while (!mActiveId) while (!mActiveId)
{
// Find next item to process
ItemList::iterator i = mItemList.begin();
for (;i != mItemList.end() && !i->scheduled(); i++)
;
if (i == mItemList.end())
return;
std::shared_ptr<resip::SipMessage> msg;
int expires = DEFAULT_SUBSCRIPTION_TIME, refresh = DEFAULT_SUBSCRIPTION_REFRESHTIME;
switch (i->mState)
{ {
case Item::State_ScheduledToAdd: // Find next item to process
if (mAgent.mConfig.exists(CONFIG_SUBSCRIPTION_TIME)) ItemList::iterator i = mItemList.begin();
expires = mAgent.mConfig[CONFIG_SUBSCRIPTION_TIME].asInt(); for (;i != mItemList.end() && !i->scheduled(); i++)
if (mAgent.mConfig.exists(CONFIG_SUBSCRIPTION_REFRESHTIME)) ;
refresh = mAgent.mConfig[CONFIG_SUBSCRIPTION_REFRESHTIME].asInt(); if (i == mItemList.end())
return;
msg = mAgent.mDum->makeSubscription(resip::NameAddr(resip::Data(i->mTarget)), resip::Data(i->mPackage), std::shared_ptr<resip::SipMessage> msg;
expires, refresh, i->mSession); int expires = DEFAULT_SUBSCRIPTION_TIME, refresh = DEFAULT_SUBSCRIPTION_REFRESHTIME;
msg->header(resip::h_Accepts) = mAgent.mDum->getMasterProfile()->getSupportedMimeTypes(resip::NOTIFY);
mActiveId = i->mId;
i->mState = Item::State_Adding;
mAgent.mDum->send(msg);
break;
case Item::State_ScheduledToDelete: switch (i->mState)
i->mSession->runTerminatedEvent(ResipSession::Type_Subscription, 0, 0); {
if (i->mHandle.isValid()) case Item::State_ScheduledToAdd:
{ if (mAgent.mConfig.exists(CONFIG_SUBSCRIPTION_TIME))
mActiveId = i->mId; expires = mAgent.mConfig[CONFIG_SUBSCRIPTION_TIME].asInt();
i->mHandle->end(); if (mAgent.mConfig.exists(CONFIG_SUBSCRIPTION_REFRESHTIME))
i->mState = Item::State_Deleting; refresh = mAgent.mConfig[CONFIG_SUBSCRIPTION_REFRESHTIME].asInt();
break;
}
else
mItemList.erase(i);
break;
case Item::State_ScheduledToRefresh: msg = mAgent.mDum->makeSubscription(resip::NameAddr(resip::Data(i->mTarget)), resip::Data(i->mPackage),
if (i->mHandle.isValid()) expires, refresh, i->mSession);
{ msg->header(resip::h_Accepts) = mAgent.mDum->getMasterProfile()->getSupportedMimeTypes(resip::NOTIFY);
mActiveId = i->mId; mActiveId = i->mId;
i->mState = Item::State_Refreshing; i->mState = Item::State_Adding;
i->mHandle->requestRefresh(); mAgent.mDum->send(msg);
} break;
else
mItemList.erase(i);
break;
default: case Item::State_ScheduledToDelete:
break; i->mSession->runTerminatedEvent(ResipSession::Type_Subscription, 0, 0);
if (i->mHandle.isValid())
{
mActiveId = i->mId;
i->mHandle->end();
i->mState = Item::State_Deleting;
break;
}
else
mItemList.erase(i);
break;
case Item::State_ScheduledToRefresh:
if (i->mHandle.isValid())
{
mActiveId = i->mId;
i->mState = Item::State_Refreshing;
i->mHandle->requestRefresh();
}
else
mItemList.erase(i);
break;
default:
break;
}
} }
}
} }
void WatcherQueue::onTerminated(int id, int code) void WatcherQueue::onTerminated(int id, int code)
{ {
ice::Lock l(mGuard); ice::Lock l(mGuard);
ItemList::iterator i = findById(id); ItemList::iterator i = findById(id);
if (i != mItemList.end()) if (i != mItemList.end())
{ {
if (i->mSession) if (i->mSession)
i->mSession->runTerminatedEvent(ResipSession::Type_Subscription, code, 0); i->mSession->runTerminatedEvent(ResipSession::Type_Subscription, code, 0);
mItemList.erase(i); mItemList.erase(i);
if (i->mId == mActiveId) if (i->mId == mActiveId)
mActiveId = 0; mActiveId = 0;
} }
process(); process();
} }
void WatcherQueue::onEstablished(int id, int code) void WatcherQueue::onEstablished(int id, int code)
{ {
ice::Lock l(mGuard); ice::Lock l(mGuard);
ItemList::iterator i = findById(id); ItemList::iterator i = findById(id);
if (i != mItemList.end()) if (i != mItemList.end())
{ {
i->mState = Item::State_Active; i->mState = Item::State_Active;
if (i->mId == mActiveId) if (i->mId == mActiveId)
mActiveId = 0; mActiveId = 0;
} }
process(); process();
} }
WatcherQueue::ItemList::iterator WatcherQueue::findById(int id) WatcherQueue::ItemList::iterator WatcherQueue::findById(int id)
{ {
for (ItemList::iterator i=mItemList.begin(); i != mItemList.end(); i++) for (ItemList::iterator i=mItemList.begin(); i != mItemList.end(); i++)
if (i->mId == id) if (i->mId == id)
return i; return i;
return mItemList.end(); return mItemList.end();
} }
void WatcherQueue::clear() void WatcherQueue::clear()
{ {
ice::Lock l(mGuard); ice::Lock l(mGuard);
for (ItemList::iterator i=mItemList.begin(); i != mItemList.end(); i++) for (ItemList::iterator i=mItemList.begin(); i != mItemList.end(); i++)
{ {
if (i->mHandle.isValid()) if (i->mHandle.isValid())
i->mHandle->end(); i->mHandle->end();
} }
mItemList.clear(); mItemList.clear();
} }

View File

@ -13,57 +13,57 @@ class UserAgent;
class WatcherQueue class WatcherQueue
{ {
public: public:
struct Item struct Item
{
enum State
{ {
State_None, enum State
State_Active, {
State_ScheduledToAdd, State_None,
State_Adding, State_Active,
State_ScheduledToRefresh, State_ScheduledToAdd,
State_Refreshing, State_Adding,
State_ScheduledToDelete, State_ScheduledToRefresh,
State_Deleting State_Refreshing,
State_ScheduledToDelete,
State_Deleting
};
resip::ClientSubscriptionHandle mHandle; // Subscription handle
ResipSession* mSession;
State mState;
std::string mTarget; // Target's address
std::string mPackage; // Event package
void* mTag; // User tag
int mId;
Item()
:mSession(NULL), mState(State_None), mTag(NULL), mId(0)
{}
bool scheduled()
{
return mState == State_ScheduledToAdd || mState == State_ScheduledToDelete || mState == State_ScheduledToRefresh;
}
}; };
WatcherQueue(UserAgent& agent);
~WatcherQueue();
resip::ClientSubscriptionHandle mHandle; // Subscription handle int add(std::string peer, std::string package, void* tag);
ResipSession* mSession; void remove(int id);
State mState; void refresh(int id);
std::string mTarget; // Target's address void clear();
std::string mPackage; // Event package
void* mTag; // User tag
int mId;
Item() void onTerminated(int id, int code);
:mSession(NULL), mState(State_None), mTag(NULL), mId(0) void onEstablished(int id, int code);
{}
bool scheduled()
{
return mState == State_ScheduledToAdd || mState == State_ScheduledToDelete || mState == State_ScheduledToRefresh;
}
};
WatcherQueue(UserAgent& agent);
~WatcherQueue();
int add(std::string peer, std::string package, void* tag);
void remove(int id);
void refresh(int id);
void clear();
void onTerminated(int id, int code);
void onEstablished(int id, int code);
protected: protected:
typedef std::vector<Item> ItemList; typedef std::vector<Item> ItemList;
ItemList mItemList; ItemList mItemList;
ice::Mutex mGuard; ice::Mutex mGuard;
UserAgent& mAgent; UserAgent& mAgent;
int mActiveId; int mActiveId;
void process(); void process();
ItemList::iterator findById(int id); ItemList::iterator findById(int id);
}; };
#endif #endif

View File

@ -19,88 +19,88 @@ ClientObserver::~ClientObserver()
void ClientObserver::refresh() void ClientObserver::refresh()
{ {
if (mHandle.isValid()) if (mHandle.isValid())
mHandle->requestRefresh(); mHandle->requestRefresh();
} }
void ClientObserver::stop() void ClientObserver::stop()
{ {
if (mHandle.isValid()) if (mHandle.isValid())
mHandle->end(); mHandle->end();
else else
if (mSession) if (mSession)
{ {
mSession->runTerminatedEvent(ResipSession::Type_Subscription); mSession->runTerminatedEvent(ResipSession::Type_Subscription);
if (mSession) if (mSession)
mSession->end(); mSession->end();
} }
mSession = NULL; mSession = NULL;
} }
std::string ClientObserver::peer() std::string ClientObserver::peer()
{ {
return mPeer; return mPeer;
} }
ServerObserver::ServerObserver() ServerObserver::ServerObserver()
:mState(State_Incoming) :mState(State_Incoming)
{ {
} }
ServerObserver::~ServerObserver() ServerObserver::~ServerObserver()
{ {
stop(); stop();
} }
std::string ServerObserver::peer() const std::string ServerObserver::peer() const
{ {
return mPeer; return mPeer;
} }
std::string ServerObserver::package() const std::string ServerObserver::package() const
{ {
return mPackage; return mPackage;
} }
void ServerObserver::update(std::string simpleId, bool online, std::string msg) void ServerObserver::update(std::string simpleId, bool online, std::string msg)
{ {
if (mState != State_Active) if (mState != State_Active)
return; return;
resip::Pidf p; resip::Pidf p;
p.setEntity(mContact); p.setEntity(mContact);
p.setSimpleId(resip::Data(simpleId)); p.setSimpleId(resip::Data(simpleId));
p.setSimpleStatus(online, resip::Data(msg)); p.setSimpleStatus(online, resip::Data(msg));
if (mHandle.isValid()) if (mHandle.isValid())
mHandle->send(mHandle->update(&p)); mHandle->send(mHandle->update(&p));
} }
void ServerObserver::accept() void ServerObserver::accept()
{ {
if (mHandle.isValid() && mState == State_Incoming) if (mHandle.isValid() && mState == State_Incoming)
{ {
mState = State_Active; mState = State_Active;
mHandle->accept(); mHandle->accept();
} }
} }
void ServerObserver::stop() void ServerObserver::stop()
{ {
if (!mHandle.isValid()) if (!mHandle.isValid())
return; return;
switch (mState) switch (mState)
{ {
case State_Incoming: case State_Incoming:
mHandle->reject(404); mHandle->reject(404);
break; break;
case State_Active: case State_Active:
mHandle->end(); mHandle->end();
break; break;
default: default:
break; break;
} }
mState = State_Closed; mState = State_Closed;
} }

View File

@ -21,51 +21,51 @@ class ResipSession;
class ClientObserver class ClientObserver
{ {
friend class Account; friend class Account;
friend class UserAgent; friend class UserAgent;
public: public:
ClientObserver(); ClientObserver();
~ClientObserver(); ~ClientObserver();
void refresh(); void refresh();
void stop(); void stop();
std::string peer(); std::string peer();
protected: protected:
resip::ClientSubscriptionHandle mHandle; resip::ClientSubscriptionHandle mHandle;
ResipSession* mSession; ResipSession* mSession;
int mSessionId; int mSessionId;
std::string mPeer; std::string mPeer;
}; };
typedef std::shared_ptr<ClientObserver> PClientObserver; typedef std::shared_ptr<ClientObserver> PClientObserver;
class ServerObserver class ServerObserver
{ {
friend class UserAgent; friend class UserAgent;
public: public:
ServerObserver(); ServerObserver();
~ServerObserver(); ~ServerObserver();
std::string peer() const; std::string peer() const;
std::string package() const; std::string package() const;
void accept(); void accept();
void update(std::string simpleId, bool online, std::string msg); void update(std::string simpleId, bool online, std::string msg);
void stop(); void stop();
protected: protected:
enum State enum State
{ {
State_Incoming, State_Incoming,
State_Active, State_Active,
State_Closed State_Closed
}; };
State mState; State mState;
resip::ServerSubscriptionHandle mHandle; resip::ServerSubscriptionHandle mHandle;
std::string mPeer, mPackage; std::string mPeer, mPackage;
resip::Uri mContact; resip::Uri mContact;
int mSessionId; int mSessionId;
}; };
typedef std::shared_ptr<ServerObserver> PServerObserver; typedef std::shared_ptr<ServerObserver> PServerObserver;