363 lines
16 KiB
C++
363 lines
16 KiB
C++
#if !defined(Server_hxx)
|
|
#define Server_hxx
|
|
|
|
#include <map>
|
|
|
|
#include <resip/stack/TransactionUser.hxx>
|
|
#include <resip/stack/EventStackThread.hxx>
|
|
#include <rutil/SelectInterruptor.hxx>
|
|
#include <resip/stack/UdpTransport.hxx>
|
|
#include <resip/dum/MasterProfile.hxx>
|
|
#include <resip/dum/DumShutdownHandler.hxx>
|
|
#include <resip/dum/DialogUsageManager.hxx>
|
|
#include <resip/dum/InviteSessionHandler.hxx>
|
|
#include <resip/dum/DialogSetHandler.hxx>
|
|
#include <resip/dum/OutOfDialogHandler.hxx>
|
|
#include <resip/dum/RedirectHandler.hxx>
|
|
#include <resip/dum/SubscriptionHandler.hxx>
|
|
#include <resip/dum/RegistrationHandler.hxx>
|
|
#include <rutil/Log.hxx>
|
|
#include <rutil/Mutex.hxx>
|
|
|
|
#include "ConfigParser.hxx"
|
|
#include "B2BSession.hxx"
|
|
#include "SipRegistration.hxx"
|
|
#include "AddressTranslator.hxx"
|
|
#include "MediaRelay.hxx"
|
|
#include "IChatIPPortData.hxx"
|
|
#include "IPCThread.hxx"
|
|
|
|
#include <memory>
|
|
|
|
#ifdef WIN32
|
|
#define sleepMs(t) Sleep(t)
|
|
#else
|
|
#define sleepMs(t) usleep(t*1000)
|
|
#endif
|
|
|
|
#define SDP_ICHATGW_ORIGIN_USER "iChat-gw"
|
|
|
|
namespace gateway
|
|
{
|
|
|
|
class ShutdownCmd;
|
|
class B2BSession;
|
|
|
|
class Server : public ConfigParser,
|
|
public IPCHandler,
|
|
public resip::DumShutdownHandler,
|
|
public resip::InviteSessionHandler,
|
|
public resip::DialogSetHandler,
|
|
public resip::OutOfDialogHandler,
|
|
public resip::RedirectHandler,
|
|
public resip::ClientSubscriptionHandler,
|
|
public resip::ServerSubscriptionHandler,
|
|
public resip::ClientRegistrationHandler,
|
|
public resip::ExternalUnknownDatagramHandler
|
|
{
|
|
public:
|
|
Server(int argc, char** argv);
|
|
virtual ~Server();
|
|
|
|
/**
|
|
Starts the SIP stack thread.
|
|
|
|
@note This should be called before calling process() in a loop
|
|
*/
|
|
void startup();
|
|
|
|
/**
|
|
This should be called in a loop to give process cycles to the server.
|
|
|
|
@param timeoutMs Will return after timeoutMs if nothing to do.
|
|
Application can do some work, but should call
|
|
process again ASAP.
|
|
*/
|
|
void process(int timeoutMs); // call this in a loop
|
|
|
|
/**
|
|
Used to initiate a shutdown of the server. This function blocks
|
|
until the shutdown is complete.
|
|
|
|
@note There should not be an active process request when this
|
|
is called.
|
|
*/
|
|
void shutdown();
|
|
|
|
// Utility Methods ////////////////////////////////////////////////////////////
|
|
typedef enum
|
|
{
|
|
SubsystemAll,
|
|
SubsystemContents,
|
|
SubsystemDns,
|
|
SubsystemDum,
|
|
SubsystemSdp,
|
|
SubsystemSip,
|
|
SubsystemTransaction,
|
|
SubsystemTransport,
|
|
SubsystemStats,
|
|
SubsystemGateway
|
|
} LoggingSubsystem;
|
|
|
|
/**
|
|
Static method that sets the logging level for a particular subsystem,
|
|
or all subsystems.
|
|
|
|
@param level Logging level to set
|
|
@param subsystem Subsystem to set level on
|
|
|
|
@note: Use Server::SubsystemAll to set the logging level on all
|
|
subsystems
|
|
*/
|
|
static void setLogLevel(resip::Log::Level level, LoggingSubsystem subsystem=SubsystemAll);
|
|
|
|
/**
|
|
Called by Jabber side of gateway to notify SIP side of iChat call request.
|
|
|
|
@param to Bare JID of endpoint we are proceeding to ring
|
|
@param from Full JID of endpoint requesting the call
|
|
*/
|
|
void notifyIChatCallRequest(const std::string& to, const std::string& from);
|
|
|
|
/**
|
|
Called by Jabber side of gateway to notify SIP side of cancelled iChat call request.
|
|
|
|
@param handle Handle of the B2BSession object for the call
|
|
*/
|
|
void notifyIChatCallCancelled(const B2BSessionHandle& handle);
|
|
|
|
/**
|
|
Called by Jabber side of gateway to notify B2BSession that iChat call is proceeding.
|
|
This call will cause a timeout timer to be deactiviated.
|
|
|
|
@param handle Handle of the B2BSession object for the call
|
|
@param to Full JID of endpoint we are proceeding to ring
|
|
*/
|
|
void notifyIChatCallProceeding(const B2BSessionHandle& handle, const std::string& to);
|
|
|
|
/**
|
|
Called by Jabber side of gateway to notify B2BSession that iChat call has failed.
|
|
|
|
@param handle Handle of the B2BSession object for the call
|
|
@param statusCode Code representing the reason for the failure
|
|
*/
|
|
void notifyIChatCallFailed(const B2BSessionHandle& handle, unsigned int statusCode);
|
|
|
|
/**
|
|
Called by Jabber side of gateway to notify B2BSession that iChat call setup
|
|
has completed on the Jabber side, and that it now needs to continue via SIP.
|
|
|
|
@param handle Handle of the B2BSession object for the call
|
|
@param remoteIPPortListBlob List of transports received from the iChat client via
|
|
Jabber messaging - in proprietary iChat blob format
|
|
*/
|
|
void continueIChatCall(const B2BSessionHandle& handle, const std::string& remoteIPPortListBlob);
|
|
|
|
/**
|
|
Called by Jabber side of gateway to request that a jabber user be registered on the
|
|
configured SIP server. Note: The jabber user's JID is first transformed into a
|
|
SIP URI using the configured translation rules. Note: calling this multiple times
|
|
with the same jidToRegister is safe and will result in a no op.
|
|
|
|
@param jidToRegister - Jabber user's JID to register on the SIP server.
|
|
*/
|
|
void sipRegisterJabberUser(const std::string& jidToRegister);
|
|
|
|
/**
|
|
Called by Jabber side of gateway to request that a jabber user be unregistered from the
|
|
configured SIP server. Note: The jabber user's JID is first transformed into a
|
|
SIP URI using the configured translation rules.
|
|
|
|
@param jidToUnregister - Jabber user's JID to unregister from the SIP server.
|
|
*/
|
|
void sipUnregisterJabberUser(const std::string& jidToUnregister);
|
|
|
|
/**
|
|
Called by Jabber side of gateway to check if the JID to be subscribed will pass the
|
|
translation rules.
|
|
|
|
@param to - JID of address being subscribed to
|
|
@param from - JID of subscriber
|
|
*/
|
|
void checkSubscription(const std::string& to, const std::string& from);
|
|
|
|
B2BSession* findMatchingIChatB2BSession(const resip::SipMessage& msg);
|
|
|
|
protected:
|
|
std::shared_ptr<resip::MasterProfile>& getMasterProfile() noexcept { return mProfile; }
|
|
bool translateAddress(const resip::Data& address, resip::Data& translation, bool failIfNoRule=false);
|
|
|
|
// IPC Handler
|
|
virtual void onNewIPCMsg(const IPCMsg& msg);
|
|
|
|
// External Unknown Packet Handler//////////////////////////////////////////////
|
|
virtual void operator()(resip::UdpTransport* transport, const resip::Tuple& source, std::unique_ptr<resip::Data> unknownPacket);
|
|
|
|
// Shutdown Handler ////////////////////////////////////////////////////////////
|
|
void onDumCanBeDeleted();
|
|
|
|
// Invite Session Handler /////////////////////////////////////////////////////
|
|
virtual void onNewSession(resip::ClientInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
|
|
virtual void onNewSession(resip::ServerInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
|
|
virtual void onFailure(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
|
|
virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&, const resip::SdpContents&);
|
|
virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onConnected(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
|
|
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onStaleCallTimeout(resip::ClientInviteSessionHandle);
|
|
virtual void onTerminated(resip::InviteSessionHandle h, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* msg);
|
|
virtual void onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onAnswer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&);
|
|
virtual void onOffer(resip::InviteSessionHandle handle, const resip::SipMessage& msg, const resip::SdpContents& offer);
|
|
virtual void onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg);
|
|
virtual void onOfferRequestRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onRemoteSdpChanged(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents& sdp);
|
|
virtual void onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
|
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg);
|
|
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
|
virtual void onForkDestroyed(resip::ClientInviteSessionHandle);
|
|
|
|
// DialogSetHandler //////////////////////////////////////////////
|
|
virtual void onTrying(resip::AppDialogSetHandle, const resip::SipMessage& msg);
|
|
virtual void onNonDialogCreatingProvisional(resip::AppDialogSetHandle, const resip::SipMessage& msg);
|
|
|
|
// ClientSubscriptionHandler ///////////////////////////////////////////////////
|
|
virtual void onUpdatePending(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
|
virtual void onUpdateActive(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
|
virtual void onUpdateExtension(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder);
|
|
virtual void onTerminated(resip::ClientSubscriptionHandle h, const resip::SipMessage* notify);
|
|
virtual void onNewSubscription(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify);
|
|
virtual int onRequestRetry(resip::ClientSubscriptionHandle h, int retryMinimum, const resip::SipMessage& notify);
|
|
|
|
// ServerSubscriptionHandler ///////////////////////////////////////////////////
|
|
virtual void onNewSubscription(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
|
|
virtual void onNewSubscriptionFromRefer(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
|
|
virtual void onRefresh(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
|
|
virtual void onTerminated(resip::ServerSubscriptionHandle);
|
|
virtual void onReadyToSend(resip::ServerSubscriptionHandle, resip::SipMessage&);
|
|
virtual void onNotifyRejected(resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
|
virtual void onError(resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
|
virtual void onExpiredByClient(resip::ServerSubscriptionHandle, const resip::SipMessage& sub, resip::SipMessage& notify);
|
|
virtual void onExpired(resip::ServerSubscriptionHandle, resip::SipMessage& notify);
|
|
virtual bool hasDefaultExpires() const;
|
|
virtual uint32_t getDefaultExpires() const;
|
|
|
|
// OutOfDialogHandler //////////////////////////////////////////////////////////
|
|
virtual void onSuccess(resip::ClientOutOfDialogReqHandle, const resip::SipMessage& response);
|
|
virtual void onFailure(resip::ClientOutOfDialogReqHandle, const resip::SipMessage& response);
|
|
virtual void onReceivedRequest(resip::ServerOutOfDialogReqHandle, const resip::SipMessage& request);
|
|
|
|
// RedirectHandler /////////////////////////////////////////////////////////////
|
|
virtual void onRedirectReceived(resip::AppDialogSetHandle, const resip::SipMessage& response);
|
|
virtual bool onTryingNextTarget(resip::AppDialogSetHandle, const resip::SipMessage& request);
|
|
|
|
// Registration Handler ////////////////////////////////////////////////////////
|
|
virtual void onSuccess(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
|
|
virtual void onFailure(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
|
|
virtual void onRemoved(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
|
|
virtual int onRequestRetry(resip::ClientRegistrationHandle h, int retryMinimum, const resip::SipMessage& msg);
|
|
|
|
private:
|
|
friend class ShutdownCmd;
|
|
friend class B2BSession;
|
|
friend class IChatCallTimeout;
|
|
|
|
resip::DialogUsageManager& getDialogUsageManager();
|
|
|
|
void post(resip::ApplicationMessage& message, unsigned int ms=0);
|
|
void shutdownImpl();
|
|
|
|
friend class NotifyIChatCallRequestCmd;
|
|
void notifyIChatCallRequestImpl(const std::string& to, const std::string& from);
|
|
friend class NotifyIChatCallCancelledCmd;
|
|
void notifyIChatCallCancelledImpl(const B2BSessionHandle& handle);
|
|
friend class NotifyIChatCallProceedingCmd;
|
|
void notifyIChatCallProceedingImpl(const B2BSessionHandle& handle, const std::string& to);
|
|
friend class NotifyIChatCallFailedCmd;
|
|
void notifyIChatCallFailedImpl(const B2BSessionHandle& handle, unsigned int statusCode);
|
|
friend class ContinueIChatCallCmd;
|
|
void continueIChatCallImpl(const B2BSessionHandle& handle, const std::string& remoteIPPortListBlob);
|
|
friend class SipRegisterJabberUserCmd;
|
|
void sipRegisterJabberUserImpl(const std::string& jidToRegister);
|
|
friend class SipUnregisterJabberUserCmd;
|
|
void sipUnregisterJabberUserImpl(const std::string& jidToUnregister);
|
|
|
|
std::shared_ptr<resip::MasterProfile> mProfile;
|
|
resip::Security* mSecurity;
|
|
resip::FdPollGrp *mPollGrp;
|
|
resip::EventThreadInterruptor *mEventInterruptor;
|
|
resip::SipStack mStack;
|
|
resip::DialogUsageManager mDum;
|
|
resip::EventStackThread mStackThread;
|
|
volatile bool mDumShutdown;
|
|
|
|
typedef std::map<B2BSessionHandle, B2BSession*> B2BSessionMap;
|
|
B2BSessionMap mB2BSessions;
|
|
B2BSessionHandle mCurrentB2BSessionHandle;
|
|
B2BSession* getB2BSession(const B2BSessionHandle& handle) const;
|
|
B2BSessionHandle registerB2BSession(B2BSession *);
|
|
void unregisterB2BSession(const B2BSessionHandle& handle);
|
|
|
|
friend class SipRegistration;
|
|
typedef std::map<resip::Uri, SipRegistration*> RegistrationMap;
|
|
RegistrationMap mRegistrations;
|
|
void registerRegistration(SipRegistration *);
|
|
void unregisterRegistration(SipRegistration *);
|
|
|
|
bool mIsV6Avail;
|
|
IChatIPPortData mLocalIPPortData;
|
|
|
|
MediaRelay* mMediaRelay;
|
|
|
|
IPCThread* mIPCThread;
|
|
|
|
AddressTranslator mAddressTranslator;
|
|
std::map<resip::DialogSetId,B2BSession*> mActiveSessions;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/* ====================================================================
|
|
|
|
Copyright (c) 2009, SIP Spectrum, Inc.
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
3. Neither the name of SIP Spectrum nor the names of its contributors
|
|
may be used to endorse or promote products derived from this
|
|
software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
==================================================================== */
|