412 lines
12 KiB
C++
412 lines
12 KiB
C++
/* Copyright(C) 2007-2014 VoIP objects (voipobjects.com)
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef __SESSION_H
|
|
#define __SESSION_H
|
|
|
|
#include "resip/stack/SdpContents.hxx"
|
|
#include "resip/stack/SipMessage.hxx"
|
|
#include "resip/stack/ShutdownMessage.hxx"
|
|
#include "resip/stack/SipStack.hxx"
|
|
#include "resip/dum/ClientAuthManager.hxx"
|
|
#include "resip/dum/ClientInviteSession.hxx"
|
|
#include "resip/dum/ClientRegistration.hxx"
|
|
#include "resip/dum/DialogUsageManager.hxx"
|
|
#include "resip/dum/DumShutdownHandler.hxx"
|
|
#include "resip/dum/InviteSessionHandler.hxx"
|
|
#include "resip/dum/MasterProfile.hxx"
|
|
#include "resip/dum/RegistrationHandler.hxx"
|
|
#include "resip/dum/ServerInviteSession.hxx"
|
|
#include "resip/dum/ServerOutOfDialogReq.hxx"
|
|
#include "resip/dum/OutOfDialogHandler.hxx"
|
|
#include "resip/dum/AppDialog.hxx"
|
|
#include "resip/dum/AppDialogSet.hxx"
|
|
#include "resip/dum/AppDialogSetFactory.hxx"
|
|
#include "rutil/Log.hxx"
|
|
#include "rutil/Logger.hxx"
|
|
#include "rutil/Random.hxx"
|
|
#include "rutil/WinLeakCheck.hxx"
|
|
#include "rutil/AtomicCounter.hxx"
|
|
|
|
#include "../ice/ICEBox.h"
|
|
|
|
#include <sstream>
|
|
#include <time.h>
|
|
|
|
#include "../config.h"
|
|
#include "EP_Session.h"
|
|
#include "EP_Account.h"
|
|
#include "EP_DataProvider.h"
|
|
#include "EP_AudioProvider.h"
|
|
#include "../helper/HL_VariantMap.h"
|
|
#include "../helper/HL_SocketHeap.h"
|
|
|
|
using namespace std;
|
|
|
|
class UserAgent;
|
|
class ResipSession;
|
|
|
|
enum SessionInfo
|
|
{
|
|
SessionInfo_RemoteSipAddress, // remote sip address
|
|
SessionInfo_ReceivedTraffic, // amount of received traffic in session in bytes
|
|
SessionInfo_SentTraffic, // amount of sent traffic in session in bytes
|
|
SessionInfo_PacketLoss, // lost packets counter; returns number of 1/1000 fractions (0.1%)
|
|
SessionInfo_AudioPeer, // remote peer rtp address in text
|
|
SessionInfo_AudioCodec, // selected audio codec as text
|
|
SessionInfo_DtmfInterface, // Pointer to DtmfQueue class; returned as void*
|
|
SessionInfo_IceState,
|
|
SessionInfo_NetworkMos,
|
|
SessionInfo_PvqaMos,
|
|
SessionInfo_PvqaReport,
|
|
SessionInfo_SentRtp,
|
|
SessionInfo_SentRtcp,
|
|
SessionInfo_ReceivedRtp,
|
|
SessionInfo_ReceivedRtcp,
|
|
SessionInfo_LostRtp,
|
|
SessionInfo_DroppedRtp,
|
|
SessionInfo_Duration,
|
|
SessionInfo_Jitter,
|
|
SessionInfo_Rtt,
|
|
SessionInfo_BitrateSwitchCounter, // It is for AMR codecs only
|
|
SessionInfo_RemotePeer,
|
|
SessionInfo_SSRC,
|
|
};
|
|
|
|
|
|
class Session :
|
|
public SocketSink,
|
|
public ice::StageHandler
|
|
{
|
|
public:
|
|
class Command
|
|
{
|
|
public:
|
|
virtual void run(Session& s) = 0;
|
|
};
|
|
|
|
// Describes ice stream/component
|
|
struct IceInfo
|
|
{
|
|
IceInfo()
|
|
:mStreamId(-1)
|
|
{
|
|
mPort4 = mPort6 = 0;
|
|
mComponentId.mRtp = mComponentId.mRtcp = -1;
|
|
}
|
|
|
|
RtpPair<int> mComponentId;
|
|
int mStreamId;
|
|
unsigned short mPort4;
|
|
unsigned short mPort6;
|
|
};
|
|
|
|
// Describes media stream (audio/video) in session
|
|
class Stream
|
|
{
|
|
public:
|
|
Stream();
|
|
~Stream();
|
|
|
|
void setProvider(PDataProvider provider);
|
|
PDataProvider provider();
|
|
|
|
void setSocket4(const RtpPair<PDatagramSocket>& socket);
|
|
RtpPair<PDatagramSocket>& socket4();
|
|
|
|
void setSocket6(const RtpPair<PDatagramSocket>& socket);
|
|
RtpPair<PDatagramSocket>& socket6();
|
|
|
|
void setIceInfo(const IceInfo& info);
|
|
IceInfo iceInfo() const;
|
|
|
|
// rtcpAttr/rtcpMuxAttr signals about corresponding sip attribute in offer/answer from remote peer
|
|
bool rtcpAttr() const;
|
|
void setRtcpAttr(bool value);
|
|
|
|
bool rtcpMuxAttr() const;
|
|
void setRtcpMuxAttr(bool value);
|
|
|
|
protected:
|
|
// Provider for corresponding stream
|
|
PDataProvider mProvider;
|
|
|
|
// Socket for stream
|
|
RtpPair<PDatagramSocket> mSocket4, mSocket6;
|
|
|
|
bool mRtcpAttr;
|
|
bool mRtcpMuxAttr;
|
|
IceInfo mIceInfo;
|
|
};
|
|
|
|
Session(PAccount account);
|
|
virtual ~Session();
|
|
|
|
// Starts call to specified peer
|
|
void start(const std::string& peer);
|
|
|
|
// Stops call
|
|
void stop();
|
|
|
|
// Accepts call
|
|
void accept();
|
|
|
|
// Rejects call
|
|
void reject(int code);
|
|
|
|
enum class InfoOptions
|
|
{
|
|
Standard = 0,
|
|
Detailed = 1,
|
|
};
|
|
|
|
void getSessionInfo(InfoOptions options, VariantMap& result);
|
|
|
|
// Returns integer identifier of the session; it is unique amongst all session in application
|
|
int id() const;
|
|
|
|
// Returns owning account
|
|
PAccount account();
|
|
|
|
typedef std::map<std::string, std::string> UserHeaders;
|
|
void setUserHeaders(const UserHeaders& headers);
|
|
|
|
// Called when new media data are available for this session
|
|
void onReceivedData(PDatagramSocket socket, InternetAddress& src, const void* receivedPtr, unsigned receivedSize);
|
|
|
|
// Called when new candidate is gathered
|
|
void onCandidateGathered(ice::Stack* stack, void* tag, const char* address);
|
|
|
|
// Called when connectivity check is finished
|
|
void onCheckFinished(ice::Stack* stack, void* tag, const char* checkDescription);
|
|
|
|
// Called when ICE candidates are gathered - with success or timeout.
|
|
void onGathered(ice::Stack* stack, void* tag);
|
|
|
|
// Called when ICE connectivity check is good at least for one of required streams
|
|
void onSuccess(ice::Stack* stack, void* tag);
|
|
|
|
// Called when ICE connectivity check is failed for all of required streams
|
|
void onFailed(ice::Stack* stack, void* tag);
|
|
|
|
// Called when ICE stack detects network change during the call
|
|
void onNetworkChange(ice::Stack* stack, void* tag);
|
|
|
|
// Fills SDP according to ICE and provider's data
|
|
void buildSdp(resip::SdpContents& sdp, SdpDirection sdpDirection);
|
|
|
|
// Searches provider by its local port number
|
|
PDataProvider findProviderByPort(int family, unsigned short port);
|
|
|
|
// Add provider to internal list
|
|
void addProvider(PDataProvider provider);
|
|
PDataProvider providerAt(int index);
|
|
int getProviderCount();
|
|
|
|
void setUserAgent(UserAgent* agent);
|
|
UserAgent* userAgent();
|
|
|
|
// Pauses and resumes all providers; updates states
|
|
void pause();
|
|
void resume();
|
|
void refreshMediaPath();
|
|
|
|
// Processes new sdp from offer. Returns response code (200 is ok, 488 bad codec, 503 internal error).
|
|
int processSdp(UInt64 version, bool iceAvailable, std::string icePwd, std::string iceUfrag,
|
|
std::string remoteIp, const resip::SdpContents::Session::MediumContainer& media);
|
|
|
|
// Session ID
|
|
int mSessionId;
|
|
|
|
// Media streams collection
|
|
std::vector<Stream> mStreamList;
|
|
|
|
// Smart pointer to ICE stack. Actually stack is created in CreateICEStack() method
|
|
resip::SharedPtr<ice::Stack> mIceStack;
|
|
|
|
// Pointer to owner user agent instance
|
|
UserAgent* mUserAgent;
|
|
|
|
// Remote peer SIP address
|
|
resip::NameAddr mRemotePeer;
|
|
|
|
// Mutex to protect this instance
|
|
Mutex mGuard;
|
|
|
|
// SDP's origin version for sending
|
|
int mOriginVersion;
|
|
UInt64 mRemoteOriginVersion;
|
|
|
|
// SDP's session version
|
|
int mSessionVersion;
|
|
|
|
// Marks if this session does not need OnNewSession event
|
|
bool mAcceptedByEngine;
|
|
bool mAcceptedByUser;
|
|
|
|
// Invite session handle
|
|
resip::InviteSessionHandle mInviteHandle;
|
|
|
|
// Dialog set object pointer
|
|
ResipSession* mResipSession;
|
|
|
|
// Reference counter
|
|
int mRefCount;
|
|
|
|
enum
|
|
{
|
|
Initiator = 1,
|
|
Acceptor = 2
|
|
};
|
|
|
|
// Specifies session role - caller (Initiator) or callee (Acceptor)
|
|
volatile int mRole;
|
|
|
|
// Marks if candidates are gather already
|
|
volatile bool mGatheredCandidates;
|
|
|
|
// Marks if OnTerminated event was called already on session
|
|
volatile bool mTerminated;
|
|
|
|
// User friend remote peer's sip address
|
|
std::string mRemoteAddress;
|
|
|
|
// Application specific data
|
|
void* mTag;
|
|
|
|
// Used to count number of transistions to Connected state and avoid multiple onEstablished events.
|
|
int mOfferAnswerCounter;
|
|
|
|
// List of turn prefixes related to sessioj
|
|
std::vector<int> mTurnPrefixList;
|
|
|
|
// True if user agent has to send offer
|
|
bool mHasToSendOffer;
|
|
|
|
// True if user agent has to enqueue offer after ice gather finished
|
|
bool mSendOfferUpdateAfterIceGather;
|
|
|
|
// Related sip account
|
|
PAccount mAccount;
|
|
|
|
// User headers for INVITE transaction
|
|
UserHeaders mUserHeaders;
|
|
|
|
std::string remoteAddress() const;
|
|
void setRemoteAddress(const std::string& address);
|
|
|
|
void* tag();
|
|
void setTag(void* tag);
|
|
int sessionId();
|
|
int increaseSdpVersion();
|
|
int addRef();
|
|
int release();
|
|
|
|
// Deletes providers and media sockets
|
|
void clearProvidersAndSockets();
|
|
|
|
// Deletes providers
|
|
void clearProviders();
|
|
|
|
// Helper method to find audio provider for active sip stream
|
|
AudioProvider* findProviderForActiveAudio();
|
|
|
|
void processCommandList();
|
|
void addCommand(Command* cmd);
|
|
void enqueueOffer();
|
|
void processQueuedOffer();
|
|
static int generateId();
|
|
static resip::AtomicCounter IdGenerator;
|
|
static resip::AtomicCounter InstanceCounter;
|
|
};
|
|
|
|
typedef std::shared_ptr<Session> PSession;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Classes that provide the mapping between Application Data and DUM
|
|
// dialogs/dialogsets
|
|
//
|
|
// The DUM layer creates an AppDialog/AppDialogSet object for inbound/outbound
|
|
// SIP Request that results in Dialog creation.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
class ResipSessionAppDialog : public resip::AppDialog
|
|
{
|
|
public:
|
|
ResipSessionAppDialog(resip::HandleManager& ham);
|
|
virtual ~ResipSessionAppDialog();
|
|
};
|
|
|
|
class ResipSession: public resip::AppDialogSet
|
|
{
|
|
friend class UserAgent;
|
|
friend class Account;
|
|
|
|
public:
|
|
enum Type
|
|
{
|
|
Type_None,
|
|
Type_Registration,
|
|
Type_Subscription,
|
|
Type_Call,
|
|
Type_Auto
|
|
};
|
|
static resip::AtomicCounter InstanceCounter;
|
|
|
|
|
|
ResipSession(resip::DialogUsageManager& dum);
|
|
virtual ~ResipSession();
|
|
virtual resip::AppDialog* createAppDialog(const resip::SipMessage& msg);
|
|
virtual resip::SharedPtr<resip::UserProfile> selectUASUserProfile(const resip::SipMessage& msg);
|
|
|
|
void setType(Type type);
|
|
Type type();
|
|
|
|
Session* session();
|
|
void setSession(Session* session);
|
|
|
|
UserAgent* ua();
|
|
void setUa(UserAgent* ua);
|
|
|
|
// Used for subscriptions/messages
|
|
int sessionId();
|
|
|
|
// Used for subscriptions/messages
|
|
void* tag() const;
|
|
void setTag(void* tag);
|
|
|
|
// Used for subscriptions/messages
|
|
std::string remoteAddress() const;
|
|
void setRemoteAddress(std::string address);
|
|
|
|
void runTerminatedEvent(Type type, int code = 0, int reason = 0);
|
|
|
|
void setUASProfile(std::shared_ptr<resip::UserProfile> profile);
|
|
|
|
protected:
|
|
bool mTerminated;
|
|
UserAgent* mUserAgent;
|
|
Type mType;
|
|
Session* mSession;
|
|
int mSessionId;
|
|
std::string mRemoteAddress;
|
|
void* mTag;
|
|
bool mOnWatchingStartSent;
|
|
std::shared_ptr<resip::UserProfile> mUASProfile;
|
|
};
|
|
|
|
|
|
class ResipSessionFactory : public resip::AppDialogSetFactory
|
|
{
|
|
public:
|
|
ResipSessionFactory(UserAgent* agent);
|
|
virtual resip::AppDialogSet* createAppDialogSet(resip::DialogUsageManager& dum, const resip::SipMessage& msg);
|
|
protected:
|
|
UserAgent* mAgent;
|
|
};
|
|
|
|
#endif
|