From 9d4da88e9fee2ecf8fc6b13dd01152a6aa7b96a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20S=C5=82omkowski?= Date: Mon, 9 Nov 2015 00:51:51 +0100 Subject: [PATCH] Add SIP URI validator. --- CMakeLists.txt | 4 +- IncomingConnectionValidator.cpp | 11 +++ IncomingConnectionValidator.hpp | 19 +++++ PjsuaCommunicator.cpp | 145 +++++++++++++++++++------------- PjsuaCommunicator.hpp | 5 +- config.ini.example | 1 + main.cpp | 10 ++- 7 files changed, 133 insertions(+), 62 deletions(-) create mode 100644 IncomingConnectionValidator.cpp create mode 100644 IncomingConnectionValidator.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f14680d..f0421b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,9 @@ set(SOURCE_FILES MumbleCommunicator.hpp ICommunicator.hpp Configuration.cpp - Configuration.hpp) + Configuration.hpp + IncomingConnectionValidator.cpp + IncomingConnectionValidator.hpp) add_executable(mumsi ${SOURCE_FILES} main.cpp) target_link_libraries(mumsi ${PJSIP_LIBRARIES}) diff --git a/IncomingConnectionValidator.cpp b/IncomingConnectionValidator.cpp new file mode 100644 index 0000000..293e920 --- /dev/null +++ b/IncomingConnectionValidator.cpp @@ -0,0 +1,11 @@ +#include "IncomingConnectionValidator.hpp" + +sip::IncomingConnectionValidator::IncomingConnectionValidator(std::string validUriExpression) + : validUriExpression(validUriExpression), + logger(log4cpp::Category::getInstance("IncomingConnectionValidator")) { + +} + +bool sip::IncomingConnectionValidator::validateUri(std::string uri) { + return true; +} diff --git a/IncomingConnectionValidator.hpp b/IncomingConnectionValidator.hpp new file mode 100644 index 0000000..564bd20 --- /dev/null +++ b/IncomingConnectionValidator.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +#include + +namespace sip { + class IncomingConnectionValidator : boost::noncopyable { + public: + IncomingConnectionValidator(std::string validUriExpression); + + bool validateUri(std::string uri); + + private: + log4cpp::Category &logger; + std::string validUriExpression; + }; +} \ No newline at end of file diff --git a/PjsuaCommunicator.cpp b/PjsuaCommunicator.cpp index 0ead5cd..481e792 100644 --- a/PjsuaCommunicator.cpp +++ b/PjsuaCommunicator.cpp @@ -93,49 +93,11 @@ namespace sip { communicator(comm), account(acc) { } - virtual void onCallState(pj::OnCallStateParam &prm) { - auto ci = getInfo(); + virtual void onCallState(pj::OnCallStateParam &prm); - communicator.logger.info("Call %d state=%s.", ci.id, ci.stateText.c_str()); + virtual void onCallMediaState(pj::OnCallMediaStateParam &prm); - string address = ci.remoteUri; - - boost::replace_all(address, "<", ""); - boost::replace_all(address, ">", ""); - - if (ci.state == PJSIP_INV_STATE_CONFIRMED) { - auto msgText = "Incoming call from " + address + "."; - - communicator.logger.notice(msgText); - communicator.onStateChange(msgText); - } else if (ci.state == PJSIP_INV_STATE_DISCONNECTED) { - auto msgText = "Call from " + address + " finished."; - - communicator.logger.notice(msgText); - communicator.onStateChange(msgText); - - delete this; - } - } - - virtual void onCallMediaState(pj::OnCallMediaStateParam &prm) { - auto ci = getInfo(); - - if (ci.media.size() != 1) { - throw sip::Exception("ci.media.size is not 1"); - } - - if (ci.media[0].status == PJSUA_CALL_MEDIA_ACTIVE) { - auto *aud_med = static_cast(getMedia(0)); - - communicator.media->startTransmit(*aud_med); - aud_med->startTransmit(*communicator.media); - } - } - - virtual void onDtmfDigit(pj::OnDtmfDigitParam &prm) { - communicator.logger.notice("DTMF digit '%s' (call %d).", prm.digit.c_str(), getId()); - } + virtual void onDtmfDigit(pj::OnDtmfDigitParam &prm); private: sip::PjsuaCommunicator &communicator; @@ -147,33 +109,100 @@ namespace sip { _Account(sip::PjsuaCommunicator &comm) : communicator(comm) { } - virtual void onRegState(pj::OnRegStateParam &prm) { - pj::AccountInfo ai = getInfo(); - communicator.logger << log4cpp::Priority::INFO - << (ai.regIsActive ? "Register:" : "Unregister:") << " code=" << prm.code; - } + virtual void onRegState(pj::OnRegStateParam &prm); - virtual void onIncomingCall(pj::OnIncomingCallParam &iprm) { - auto *call = new _Call(communicator, *this, iprm.callId); - - communicator.logger.info("Incoming call from %s.", call->getInfo().remoteUri.c_str()); - - pj::CallOpParam param; - param.statusCode = PJSIP_SC_OK; - - call->answer(param); - } + virtual void onIncomingCall(pj::OnIncomingCallParam &iprm); private: sip::PjsuaCommunicator &communicator; + bool available = true; + friend class _Call; }; + + void _Call::onCallState(pj::OnCallStateParam &prm) { + auto ci = getInfo(); + + communicator.logger.info("Call %d state=%s.", ci.id, ci.stateText.c_str()); + + string address = ci.remoteUri; + + boost::replace_all(address, "<", ""); + boost::replace_all(address, ">", ""); + + if (ci.state == PJSIP_INV_STATE_CONFIRMED) { + auto msgText = "Incoming call from " + address + "."; + + communicator.logger.notice(msgText); + communicator.onStateChange(msgText); + } else if (ci.state == PJSIP_INV_STATE_DISCONNECTED) { + auto msgText = "Call from " + address + " finished."; + + communicator.logger.notice(msgText); + communicator.onStateChange(msgText); + + dynamic_cast<_Account &>(account).available = true; + + delete this; + } + } + + void _Call::onCallMediaState(pj::OnCallMediaStateParam &prm) { + auto ci = getInfo(); + + if (ci.media.size() != 1) { + throw sip::Exception("ci.media.size is not 1"); + } + + if (ci.media[0].status == PJSUA_CALL_MEDIA_ACTIVE) { + auto *aud_med = static_cast(getMedia(0)); + + communicator.media->startTransmit(*aud_med); + aud_med->startTransmit(*communicator.media); + } else if (ci.media[0].status == PJSUA_CALL_MEDIA_NONE) { + dynamic_cast<_Account &>(account).available = true; + } + } + + void _Call::onDtmfDigit(pj::OnDtmfDigitParam &prm) { + communicator.logger.notice("DTMF digit '%s' (call %d).", prm.digit.c_str(), getId()); + } + + void _Account::onRegState(pj::OnRegStateParam &prm) { + pj::AccountInfo ai = getInfo(); + communicator.logger << log4cpp::Priority::INFO + << (ai.regIsActive ? "Register:" : "Unregister:") << " code=" << prm.code; + } + + void _Account::onIncomingCall(pj::OnIncomingCallParam &iprm) { + auto *call = new _Call(communicator, *this, iprm.callId); + + string uri = call->getInfo().remoteUri; + + communicator.logger.info("Incoming call from %s.", uri.c_str()); + + if (communicator.uriValidator.validateUri(uri)) { + pj::CallOpParam param; + + if (available) { + param.statusCode = PJSIP_SC_OK; + available = false; + } else { + param.statusCode = PJSIP_SC_BUSY_EVERYWHERE; + } + + call->answer(param); + } else { + communicator.logger.warn("Refusing call from %s.", uri.c_str()); + } + } } -sip::PjsuaCommunicator::PjsuaCommunicator() +sip::PjsuaCommunicator::PjsuaCommunicator(IncomingConnectionValidator &validator) : logger(log4cpp::Category::getInstance("SipCommunicator")), - pjsuaLogger(log4cpp::Category::getInstance("Pjsua")) { + pjsuaLogger(log4cpp::Category::getInstance("Pjsua")), + uriValidator(validator) { logWriter.reset(new sip::_LogWriter(pjsuaLogger)); diff --git a/PjsuaCommunicator.hpp b/PjsuaCommunicator.hpp index 636b016..133d23f 100644 --- a/PjsuaCommunicator.hpp +++ b/PjsuaCommunicator.hpp @@ -1,6 +1,7 @@ #pragma once #include "ICommunicator.hpp" +#include "IncomingConnectionValidator.hpp" #include #include @@ -56,7 +57,7 @@ namespace sip { class PjsuaCommunicator : public ICommunicator, boost::noncopyable { public: - PjsuaCommunicator(); + PjsuaCommunicator(IncomingConnectionValidator &validator); void connect( std::string host, @@ -90,6 +91,8 @@ namespace sip { std::mutex inBuffAccessMutex; + IncomingConnectionValidator &uriValidator; + void registerAccount(std::string host, std::string user, std::string password); diff --git a/config.ini.example b/config.ini.example index 7dfbfe4..005c624 100644 --- a/config.ini.example +++ b/config.ini.example @@ -1,4 +1,5 @@ [sip] +validUriExpression = *@sip.example.com *@127.0.0.1 host = sip.example.org port = 5060 user = mumsi diff --git a/main.cpp b/main.cpp index 7ff468b..30f237f 100644 --- a/main.cpp +++ b/main.cpp @@ -1,14 +1,18 @@ #include "PjsuaCommunicator.hpp" #include "MumbleCommunicator.hpp" +#include "IncomingConnectionValidator.hpp" #include "Configuration.hpp" #include #include +#include int main(int argc, char *argv[]) { log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout); - appender1->setLayout(new log4cpp::BasicLayout()); + log4cpp::PatternLayout layout; + layout.setConversionPattern("%d [%p] %c: %m%n"); + appender1->setLayout(&layout); log4cpp::Category &logger = log4cpp::Category::getRoot(); logger.setPriority(log4cpp::Priority::NOTICE); logger.addAppender(appender1); @@ -20,9 +24,11 @@ int main(int argc, char *argv[]) { config::Configuration conf(argv[1]); + sip::IncomingConnectionValidator connectionValidator(conf.getString("sip.validUriExpression")); + boost::asio::io_service ioService; - sip::PjsuaCommunicator pjsuaCommunicator; + sip::PjsuaCommunicator pjsuaCommunicator(connectionValidator); mumble::MumbleCommunicator mumbleCommunicator(ioService);