- format source code (indentation 4 space
This commit is contained in:
parent
7c346fbe9b
commit
10ec751e43
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue