зеркало из https://github.com/mozilla/gecko-dev.git
Bug 792188: rollup of changes to signaling from alder r=jesup,ekr,derf,ehugg,ted
Bug 797258: Increase max sdp line length to work with longer SHA-256 fingerprints. r=jesup
This commit is contained in:
Родитель
1995a1f5d1
Коммит
f769554f67
|
@ -5244,8 +5244,8 @@ if test -n "$MOZ_WEBRTC"; then
|
|||
MOZ_VP8_ENCODER=1
|
||||
MOZ_VP8_ERROR_CONCEALMENT=1
|
||||
dnl enable once Signaling lands
|
||||
dnl MOZ_WEBRTC_SIGNALING=1
|
||||
dnl AC_DEFINE(MOZ_WEBRTC_SIGNALING)
|
||||
MOZ_WEBRTC_SIGNALING=1
|
||||
AC_DEFINE(MOZ_WEBRTC_SIGNALING)
|
||||
if test "${OS_TARGET}" = "WINNT"; then
|
||||
MOZ_WEBRTC_IN_LIBXUL=1
|
||||
fi
|
||||
|
|
|
@ -12,6 +12,8 @@ include $(DEPTH)/config/autoconf.mk
|
|||
DIRS = \
|
||||
trunk \
|
||||
trunk/testing \
|
||||
signaling \
|
||||
signalingtest \
|
||||
$(NULL)
|
||||
|
||||
# These Makefiles don't have corresponding Makefile.ins
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace CSF
|
|||
|
||||
@return true or false.
|
||||
*/
|
||||
virtual bool originateCall (cc_sdp_direction_t video_pref, const std::string & digits, char* sdp, int audioPort, int videoPort) = 0;
|
||||
virtual bool originateCall (cc_sdp_direction_t video_pref, const std::string & digits) = 0;
|
||||
|
||||
/**
|
||||
Use this function to answer an incoming call.
|
||||
|
@ -299,9 +299,27 @@ namespace CSF
|
|||
@param [in] digits - digits to be dialed. can be empty then this API simply goes offhook
|
||||
@param [in] ip address - the ip address of the peer to call
|
||||
|
||||
@return true or false.
|
||||
*/
|
||||
virtual bool originateP2PCall (cc_sdp_direction_t video_pref, const std::string & digits, const std::string & ip) = 0;
|
||||
@return void
|
||||
*/
|
||||
virtual void originateP2PCall (cc_sdp_direction_t video_pref, const std::string & digits, const std::string & ip) = 0;
|
||||
|
||||
virtual void createOffer (const std::string & hints) = 0;
|
||||
|
||||
virtual void createAnswer(const std::string & hints, const std::string & offersdp) = 0;
|
||||
|
||||
virtual void setLocalDescription(cc_jsep_action_t action, const std::string & sdp) = 0;
|
||||
|
||||
virtual void setRemoteDescription(cc_jsep_action_t action, const std::string & sdp) = 0;
|
||||
|
||||
virtual void setPeerConnection(const std::string& handle) = 0;
|
||||
|
||||
virtual void addStream(cc_media_stream_id_t stream_id, cc_media_track_id_t track_id, cc_media_type_t media_type) = 0;
|
||||
|
||||
virtual void removeStream(cc_media_stream_id_t stream_id, cc_media_track_id_t track_id, cc_media_type_t media_type) = 0;
|
||||
|
||||
virtual const std::string& getPeerConnection() const = 0;
|
||||
|
||||
virtual void addICECandidate(const std::string & candidate, const std::string & mid, unsigned short level) = 0;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ extern "C"
|
|||
|
||||
#include "CC_Common.h"
|
||||
#include "CC_CallTypes.h"
|
||||
#include "peer_connection_types.h"
|
||||
|
||||
namespace CSF
|
||||
{
|
||||
|
@ -75,6 +76,20 @@ namespace CSF
|
|||
*/
|
||||
virtual cc_call_state_t getCallState () = 0;
|
||||
|
||||
/**
|
||||
print Call state
|
||||
@param [in] handle - call info handle
|
||||
@return call state as string
|
||||
*/
|
||||
virtual std::string callStateToString (cc_call_state_t state) = 0;
|
||||
|
||||
/**
|
||||
print Call event
|
||||
@param [in] call event
|
||||
@return call event as string
|
||||
*/
|
||||
virtual std::string callEventToString (ccapi_call_event_e callEvent) = 0;
|
||||
|
||||
/**
|
||||
Get ringer state.
|
||||
|
||||
|
@ -330,5 +345,27 @@ namespace CSF
|
|||
@return int - the current call volume level, or -1 if it cannot be determined
|
||||
*/
|
||||
virtual int getVolume() = 0;
|
||||
|
||||
/**
|
||||
get SDP from info object returned from JSEP functions
|
||||
@param [in] handle - call info handle
|
||||
@return SDP string
|
||||
*/
|
||||
virtual std::string getSDP() = 0;
|
||||
|
||||
/**
|
||||
get status code
|
||||
@param [in] handle - call info handle
|
||||
@return code
|
||||
*/
|
||||
virtual cc_int32_t getStatusCode() = 0;
|
||||
|
||||
/**
|
||||
get media streams
|
||||
@return media stream table
|
||||
Note:Ownership of the MediaStreamTable is responsibiliy of
|
||||
the caller.
|
||||
*/
|
||||
virtual MediaStreamTable* getMediaStreams() const = 0;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -53,17 +53,17 @@
|
|||
|
||||
namespace CSF
|
||||
{
|
||||
DECLARE_PTR(CallControlManager);
|
||||
DECLARE_PTR_VECTOR(PhoneDetails);
|
||||
DECLARE_PTR(CC_Service);
|
||||
DECLARE_PTR(VideoControl);
|
||||
DECLARE_PTR(AudioControl);
|
||||
DECLARE_PTR_VECTOR(CC_Device);
|
||||
DECLARE_PTR(CC_DeviceInfo);
|
||||
DECLARE_PTR(CC_CallServerInfo);
|
||||
DECLARE_PTR(CC_FeatureInfo);
|
||||
DECLARE_PTR_VECTOR(CC_Line);
|
||||
DECLARE_PTR(CC_LineInfo);
|
||||
DECLARE_PTR_VECTOR(CC_Call);
|
||||
DECLARE_PTR(CC_CallInfo);
|
||||
DECLARE_PTR(CallControlManager)
|
||||
DECLARE_PTR_VECTOR(PhoneDetails)
|
||||
DECLARE_PTR(CC_Service)
|
||||
DECLARE_PTR(VideoControl)
|
||||
DECLARE_PTR(AudioControl)
|
||||
DECLARE_PTR_VECTOR(CC_Device)
|
||||
DECLARE_PTR(CC_DeviceInfo)
|
||||
DECLARE_PTR(CC_CallServerInfo)
|
||||
DECLARE_PTR(CC_FeatureInfo)
|
||||
DECLARE_PTR_VECTOR(CC_Line)
|
||||
DECLARE_PTR(CC_LineInfo)
|
||||
DECLARE_PTR_VECTOR(CC_Call)
|
||||
DECLARE_PTR(CC_CallInfo)
|
||||
}
|
||||
|
|
|
@ -80,4 +80,4 @@ namespace CSF
|
|||
CC_Device& operator=(const CC_Device& rhs);
|
||||
CC_Device(const CC_Device&);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace CSF
|
|||
virtual void onDeviceEvent ( ccapi_device_event_e deviceEvent, CC_DevicePtr device, CC_DeviceInfoPtr info ) = 0;
|
||||
virtual void onFeatureEvent ( ccapi_device_event_e deviceEvent, CC_DevicePtr device, CC_FeatureInfoPtr feature_info) = 0;
|
||||
virtual void onLineEvent ( ccapi_line_event_e lineEvent, CC_LinePtr line, CC_LineInfoPtr info ) = 0;
|
||||
virtual void onCallEvent ( ccapi_call_event_e callEvent, CC_CallPtr call, CC_CallInfoPtr infog, char* sdp ) = 0;
|
||||
virtual void onCallEvent ( ccapi_call_event_e callEvent, CC_CallPtr call, CC_CallInfoPtr infog ) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -112,8 +112,7 @@ namespace CSF
|
|||
virtual bool setLocalVoipPort(int port) = 0;
|
||||
virtual bool setRemoteVoipPort(int port) = 0;
|
||||
virtual bool setP2PMode(bool mode) = 0;
|
||||
virtual bool setROAPProxyMode(bool mode) = 0;
|
||||
virtual bool setROAPClientMode(bool mode) = 0;
|
||||
virtual bool setSDPMode(bool mode) = 0;
|
||||
|
||||
private:
|
||||
CC_Service(const CC_Service& rhs);
|
||||
|
|
|
@ -51,6 +51,8 @@ namespace CSF
|
|||
class ECC_API VideoControl
|
||||
{
|
||||
public:
|
||||
virtual ~VideoControl() {};
|
||||
|
||||
virtual void setVideoMode( bool enable ) = 0;
|
||||
|
||||
// window type is platform-specific
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
|
||||
namespace CSF
|
||||
{
|
||||
DECLARE_PTR(CallControlManager);
|
||||
DECLARE_PTR(CallControlManager)
|
||||
/**
|
||||
* CallControlManager
|
||||
*
|
||||
|
@ -116,11 +116,9 @@ namespace CSF
|
|||
virtual void setAuthenticationString(const std::string &authString) = 0;
|
||||
virtual void setSecureCachePath(const std::string &secureCachePath) = 0;
|
||||
|
||||
/**
|
||||
* For now, recovery is not implemented.
|
||||
* setLocalIpAddressAndGateway must be called before connect()ing in softphone mode.
|
||||
*/
|
||||
virtual void setLocalIpAddressAndGateway(const std::string& localIpAddress, const std::string& defaultGW) = 0;
|
||||
// Add local codecs
|
||||
virtual void setAudioCodecs(int codecMask) = 0;
|
||||
virtual void setVideoCodecs(int codecMask) = 0;
|
||||
|
||||
virtual bool registerUser(const std::string& deviceName, const std::string& user, const std::string& password, const std::string& domain) = 0;
|
||||
virtual bool disconnect() = 0;
|
||||
|
@ -129,11 +127,11 @@ namespace CSF
|
|||
virtual ConnectionStatusEnum::ConnectionStatus getConnectionStatus() = 0;
|
||||
virtual std::string getCurrentServer() = 0;
|
||||
|
||||
/* P2P API */
|
||||
/* P2P MODE */
|
||||
virtual bool startP2PMode(const std::string& user) = 0;
|
||||
|
||||
/* ROAP Proxy Mode */
|
||||
virtual bool startROAPProxy( const std::string& deviceName, const std::string& user, const std::string& password, const std::string& domain ) = 0;
|
||||
|
||||
/* SDP MODE */
|
||||
virtual bool startSDPMode() = 0;
|
||||
|
||||
/**
|
||||
* Obtain the device object, from which call control can be done.
|
||||
|
@ -162,6 +160,4 @@ namespace CSF
|
|||
CallControlManager(const CallControlManager&);
|
||||
CallControlManager& operator=(const CallControlManager&);
|
||||
};
|
||||
|
||||
|
||||
};//end namespace CSF
|
||||
} //end namespace CSF
|
||||
|
|
|
@ -59,4 +59,4 @@ namespace CSF
|
|||
virtual void onAuthenticationStatusChange (AuthenticationStatusEnum::AuthenticationStatus) = 0;
|
||||
virtual void onConnectionStatusChange(ConnectionStatusEnum::ConnectionStatus status) = 0;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -72,8 +72,8 @@
|
|||
|
||||
namespace CSFUnified
|
||||
{
|
||||
DECLARE_PTR(DeviceInfo);
|
||||
};
|
||||
DECLARE_PTR(DeviceInfo)
|
||||
}
|
||||
|
||||
namespace CSF
|
||||
{
|
||||
|
@ -115,7 +115,7 @@ namespace CSF
|
|||
eFileInvalid
|
||||
} DeviceRetrievalFailureCode;
|
||||
std::string ECC_API toString(DeviceRetrievalFailureCode value);
|
||||
};
|
||||
}
|
||||
|
||||
namespace ConnectionStatusEnum
|
||||
{
|
||||
|
@ -130,7 +130,7 @@ namespace CSF
|
|||
eFailed
|
||||
} ConnectionStatus;
|
||||
std::string ECC_API toString(ConnectionStatus value);
|
||||
};
|
||||
}
|
||||
|
||||
namespace ServiceStateType {
|
||||
typedef enum
|
||||
|
@ -140,7 +140,7 @@ namespace CSF
|
|||
eOutOfService
|
||||
} ServiceState;
|
||||
std::string ECC_API toString(ServiceState value);
|
||||
};
|
||||
}
|
||||
|
||||
namespace AvailablePhoneEventType
|
||||
{
|
||||
|
@ -150,7 +150,7 @@ namespace CSF
|
|||
eLost // Phone device removed from the Available list.
|
||||
} AvailablePhoneEvent;
|
||||
std::string ECC_API toString(AvailablePhoneEvent value);
|
||||
};
|
||||
}
|
||||
|
||||
namespace ConfigPropertyKeysEnum
|
||||
{
|
||||
|
@ -183,4 +183,5 @@ namespace CSF
|
|||
typedef void *VideoWindowHandle;
|
||||
typedef void* ExternalRendererHandle;
|
||||
typedef unsigned int VideoFormat;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include <vector>
|
||||
#include "base/linked_ptr.h"
|
||||
|
||||
|
||||
#ifndef DECLARE_PTR
|
||||
#define DECLARE_PTR(className)\
|
||||
class className;\
|
||||
|
@ -52,9 +51,9 @@
|
|||
|
||||
#ifndef DECLARE_PTR_VECTOR
|
||||
#define DECLARE_PTR_VECTOR(className)\
|
||||
DECLARE_PTR(className);\
|
||||
DECLARE_PTR(className)\
|
||||
typedef std::vector<className##Ptr> className##Vtr;\
|
||||
typedef linked_ptr<className##Vtr> className##Vtr##Ptr
|
||||
typedef linked_ptr<className##Vtr> className##Vtr##Ptr;
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
'variables': {
|
||||
'chromium_code': 1,
|
||||
},
|
||||
|
||||
|
||||
'targets': [
|
||||
|
||||
#
|
||||
|
@ -32,7 +32,10 @@
|
|||
'./src/common',
|
||||
'./src/common/browser_logging',
|
||||
'./src/media',
|
||||
'./src/media-conduit',
|
||||
'./src/mediapipeline',
|
||||
'./src/softphonewrapper',
|
||||
'./src/peerconnection',
|
||||
'./include',
|
||||
'./src/sipcc/include',
|
||||
'./src/sipcc/cpr/include',
|
||||
|
@ -41,9 +44,16 @@
|
|||
'../../../ipc/chromium/src/base/third_party/nspr',
|
||||
'../../../xpcom/base',
|
||||
'$(DEPTH)/dist/include',
|
||||
'../../../dom/base',
|
||||
'../../../media/mtransport',
|
||||
'../trunk/src',
|
||||
'../trunk/src/video_engine/include',
|
||||
'../trunk/src/voice_engine/main/interface',
|
||||
'../trunk/src/voice_engine/include',
|
||||
'../trunk/src/modules/interface',
|
||||
'../trunk/src/peerconnection',
|
||||
'../../../netwerk/srtp/src/include',
|
||||
'../../../netwerk/srtp/src/crypto/include',
|
||||
'../../../ipc/chromium/src',
|
||||
],
|
||||
|
||||
#
|
||||
|
@ -60,6 +70,11 @@
|
|||
# SOURCES
|
||||
#
|
||||
'sources': [
|
||||
# Media Conduit
|
||||
'./src/media-conduit/AudioConduit.h',
|
||||
'./src/media-conduit/AudioConduit.cpp',
|
||||
'./src/media-conduit/VideoConduit.h',
|
||||
'./src/media-conduit/VideoConduit.cpp',
|
||||
# Common
|
||||
'./src/common/CommonTypes.h',
|
||||
'./src/common/csf_common.h',
|
||||
|
@ -91,19 +106,6 @@
|
|||
'./src/media/CSFVideoCallMediaControl.h',
|
||||
'./src/media/CSFVideoControlWrapper.h',
|
||||
'./src/media/CSFVideoTermination.h',
|
||||
'./src/media/webrtc/WebrtcAudioCodecSelector.cpp',
|
||||
'./src/media/webrtc/WebrtcAudioProvider.cpp',
|
||||
'./src/media/webrtc/WebrtcMediaProvider.cpp',
|
||||
'./src/media/webrtc/WebrtcRingGenerator.cpp',
|
||||
'./src/media/webrtc/WebrtcToneGenerator.cpp',
|
||||
'./src/media/webrtc/WebrtcVideoProvider.cpp',
|
||||
'./src/media/webrtc/WebrtcAudioCodecSelector.h',
|
||||
'./src/media/webrtc/WebrtcAudioProvider.h',
|
||||
'./src/media/webrtc/WebrtcMediaProvider.h',
|
||||
'./src/media/webrtc/WebrtcRingGenerator.h',
|
||||
'./src/media/webrtc/WebrtcToneGenerator.h',
|
||||
'./src/media/webrtc/WebrtcVideoProvider.h',
|
||||
'./src/media/webrtc/WebrtcLogging.h',
|
||||
'./src/media/VcmSIPCCBinding.h',
|
||||
# SoftPhoneWrapper
|
||||
'./src/softphonewrapper/CC_SIPCCCall.cpp',
|
||||
|
@ -125,7 +127,16 @@
|
|||
'./src/softphonewrapper/CC_SIPCCLine.h',
|
||||
'./src/softphonewrapper/CC_SIPCCLineInfo.h',
|
||||
'./src/softphonewrapper/CC_SIPCCService.h',
|
||||
|
||||
# PeerConnection
|
||||
'./src/peerconnection/PeerConnectionCtx.cpp',
|
||||
'./src/peerconnection/PeerConnectionCtx.h',
|
||||
'./src/peerconnection/PeerConnectionImpl.cpp',
|
||||
'./src/peerconnection/PeerConnectionImpl.h',
|
||||
# Media pipeline
|
||||
'./src/mediapipeline/MediaPipeline.h',
|
||||
'./src/mediapipeline/MediaPipeline.cpp',
|
||||
'./src/mediapipeline/SrtpFlow.h',
|
||||
'./src/mediapipeline/SrtpFlow.cpp',
|
||||
],
|
||||
|
||||
#
|
||||
|
@ -136,17 +147,30 @@
|
|||
'LOG4CXX_STATIC',
|
||||
'_NO_LOG4CXX',
|
||||
'USE_SSLEAY',
|
||||
'LIBXML_STATIC',
|
||||
'_CPR_USE_EXTERNAL_LOGGER',
|
||||
'WEBRTC_RELATIVE_PATH',
|
||||
'WEBRTC_RELATIVE_PATH',
|
||||
'HAVE_WEBRTC_VIDEO',
|
||||
'HAVE_WEBRTC_VOICE',
|
||||
],
|
||||
|
||||
#
|
||||
# OS SPECIFIC
|
||||
#
|
||||
# Conditionals
|
||||
#
|
||||
'conditions': [
|
||||
['build_for_test==0', {
|
||||
'defines' : [
|
||||
'MOZILLA_INTERNAL_API'
|
||||
],
|
||||
}],
|
||||
['build_for_test!=0', {
|
||||
'include_dirs': [
|
||||
'./test'
|
||||
],
|
||||
'defines' : [
|
||||
'NO_CHROMIUM_LOGGING',
|
||||
'USE_FAKE_MEDIA_STREAMS'
|
||||
],
|
||||
}],
|
||||
['OS=="linux"', {
|
||||
'include_dirs': [
|
||||
],
|
||||
|
@ -159,9 +183,8 @@
|
|||
'SECLIB_OPENSSL',
|
||||
],
|
||||
|
||||
'cflags': [
|
||||
'-fexceptions',
|
||||
'-fno-common',
|
||||
'cflags_mozilla': [
|
||||
'-Werror',
|
||||
],
|
||||
}],
|
||||
['OS=="win"', {
|
||||
|
@ -171,10 +194,12 @@
|
|||
'SIP_OS_WINDOWS',
|
||||
'WIN32',
|
||||
'GIPS_VER=3480',
|
||||
'SIPCC_BUILD'
|
||||
'SIPCC_BUILD',
|
||||
'HAVE_WINSOCK2_H',
|
||||
'CPR_STDINT_INCLUDE=\\"mozilla/StandardInteger.h\\"'
|
||||
],
|
||||
|
||||
'cflags': [
|
||||
'cflags_mozilla': [
|
||||
],
|
||||
}],
|
||||
['OS=="mac"', {
|
||||
|
@ -186,9 +211,9 @@
|
|||
'_FORTIFY_SOURCE=2',
|
||||
],
|
||||
|
||||
'cflags': [
|
||||
'-fexceptions',
|
||||
'-fno-common'
|
||||
'cflags_mozilla': [
|
||||
'-Werror',
|
||||
'-Wno-error=conversion'
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
@ -216,6 +241,13 @@
|
|||
'./src/sipcc/core/gsm/h',
|
||||
'./src/sipcc/plat/common',
|
||||
'../../../nsprpub/pr/include',
|
||||
'../../../media/mtransport',
|
||||
'../../../dom/base',
|
||||
'../trunk/third_party/libsrtp/srtp/include',
|
||||
'../trunk/third_party/libsrtp/srtp/crypto/include',
|
||||
'$(DEPTH)/dist/include',
|
||||
# Danger: this is to include config.h. This could be bad.
|
||||
'../trunk/third_party/libsrtp/config',
|
||||
],
|
||||
|
||||
#
|
||||
|
@ -290,7 +322,6 @@
|
|||
'./src/sipcc/core/common/text_strings.h',
|
||||
'./src/sipcc/core/common/ui.c',
|
||||
'./src/sipcc/core/common/vcm_util.c',
|
||||
'./src/sipcc/core/common/xml_util.c',
|
||||
# GSM
|
||||
'./src/sipcc/core/gsm/ccapi.c',
|
||||
'./src/sipcc/core/gsm/ccapi_strings.c',
|
||||
|
@ -372,7 +403,6 @@
|
|||
'./src/sipcc/core/includes/vcm_util.h',
|
||||
'./src/sipcc/core/includes/www.h',
|
||||
'./src/sipcc/core/includes/xml_defs.h',
|
||||
'./src/sipcc/core/includes/xml_util.h',
|
||||
# SDP
|
||||
'./src/sipcc/core/sdp/ccsdp.c',
|
||||
'./src/sipcc/core/sdp/sdp_access.c',
|
||||
|
@ -485,6 +515,7 @@
|
|||
'./src/sipcc/cpr/include/cpr_time.h',
|
||||
'./src/sipcc/cpr/include/cpr_timers.h',
|
||||
'./src/sipcc/cpr/include/cpr_types.h',
|
||||
'./src/sipcc/cpr/common/cpr_string.c',
|
||||
# INCLUDE
|
||||
'./src/sipcc/include/cc_blf.h',
|
||||
'./src/sipcc/include/cc_blf_listener.h',
|
||||
|
@ -521,12 +552,9 @@
|
|||
'./src/sipcc/include/reset_api.h',
|
||||
'./src/sipcc/include/sll_lite.h',
|
||||
'./src/sipcc/include/vcm.h',
|
||||
'./src/sipcc/include/xml_parser.h',
|
||||
'./src/sipcc/include/xml_parser_defines.h',
|
||||
|
||||
# PLAT
|
||||
# './src/sipcc/plat/common/plat_sec_api.c',
|
||||
'./src/sipcc/plat/common/libxml_parser.c',
|
||||
'./src/sipcc/plat/csf2g/model.c',
|
||||
'./src/sipcc/plat/csf2g/reset_api.c',
|
||||
#
|
||||
|
@ -552,7 +580,6 @@
|
|||
'conditions': [
|
||||
['OS=="linux"', {
|
||||
'include_dirs': [
|
||||
'/usr/include/libxml2',
|
||||
],
|
||||
|
||||
'sources': [
|
||||
|
@ -561,19 +588,14 @@
|
|||
|
||||
# PLAT
|
||||
'./src/sipcc/plat/common/dns_utils.c',
|
||||
'./src/sipcc/plat/unix-common/random.c',
|
||||
'./src/sipcc/plat/linux/plat_api_stub.c',
|
||||
|
||||
# CPR
|
||||
'./src/sipcc/cpr/linux/cpr_linux_chunk.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_errno.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_init.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_ipc.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_locks.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_memory.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_socket.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_stdio.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_stdlib.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_string.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_threads.c',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_timers_using_select.c',
|
||||
|
@ -581,18 +603,14 @@
|
|||
'./src/sipcc/cpr/linux/cpr_assert.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_align.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_assert.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_chunk.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_errno.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_in.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_ipc.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_locks.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_memory_api.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_memory.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_private.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_rand.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_socket.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_stdio.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_stdlib.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_string.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_strings.h',
|
||||
'./src/sipcc/cpr/linux/cpr_linux_time.h',
|
||||
|
@ -614,13 +632,12 @@
|
|||
'LINUX',
|
||||
],
|
||||
|
||||
'cflags': [
|
||||
'-g',
|
||||
'cflags_mozilla': [
|
||||
'-Werror',
|
||||
],
|
||||
}],
|
||||
['OS=="win"', {
|
||||
'include_dirs': [
|
||||
'./third_party/libxml2/include',
|
||||
],
|
||||
|
||||
'sources': [
|
||||
|
@ -647,16 +664,12 @@
|
|||
'./src/sipcc/cpr/win32/cpr_win_ipc.h',
|
||||
'./src/sipcc/cpr/win32/cpr_win_locks.c',
|
||||
'./src/sipcc/cpr/win32/cpr_win_locks.h',
|
||||
'./src/sipcc/cpr/win32/cpr_win_memory.c',
|
||||
'./src/sipcc/cpr/win32/cpr_win_memory.h',
|
||||
'./src/sipcc/cpr/win32/cpr_win_rand.c',
|
||||
'./src/sipcc/cpr/win32/cpr_win_rand.h',
|
||||
'./src/sipcc/cpr/win32/cpr_win_socket.c',
|
||||
'./src/sipcc/cpr/win32/cpr_win_socket.h',
|
||||
'./src/sipcc/cpr/win32/cpr_win_stdio.c',
|
||||
'./src/sipcc/cpr/win32/cpr_win_stdio.h',
|
||||
'./src/sipcc/cpr/win32/cpr_win_stdlib.c',
|
||||
'./src/sipcc/cpr/win32/cpr_win_stdlib.h',
|
||||
'./src/sipcc/cpr/win32/cpr_win_string.c',
|
||||
'./src/sipcc/cpr/win32/cpr_win_string.h',
|
||||
'./src/sipcc/cpr/win32/cpr_win_strings.h',
|
||||
|
@ -678,14 +691,13 @@
|
|||
'GIPS_VER=3480',
|
||||
],
|
||||
|
||||
'cflags': [
|
||||
'cflags_mozilla': [
|
||||
],
|
||||
|
||||
}],
|
||||
['OS=="mac"', {
|
||||
|
||||
'include_dirs': [
|
||||
'/usr/include/libxml2',
|
||||
],
|
||||
|
||||
'sources': [
|
||||
|
@ -700,8 +712,6 @@
|
|||
|
||||
# CPR
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_assert.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_chunk.c',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_chunk.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_errno.c',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_errno.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_in.h',
|
||||
|
@ -710,17 +720,12 @@
|
|||
'./src/sipcc/cpr/darwin/cpr_darwin_ipc.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_locks.c',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_locks.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_memory.c',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_memory.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_memory_api.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_private.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_rand.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_socket.c',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_socket.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_stdio.c',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_stdio.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_stdlib.c',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_stdlib.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_string.c',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_string.h',
|
||||
'./src/sipcc/cpr/darwin/cpr_darwin_strings.h',
|
||||
|
@ -743,15 +748,12 @@
|
|||
'STUBBED_OUT',
|
||||
'USE_PRINTF',
|
||||
'_DARWIN_C_SOURCE',
|
||||
'NO_NSPR_10_SUPPORT',
|
||||
],
|
||||
|
||||
'cflags': [
|
||||
'-g',
|
||||
'-fexceptions',
|
||||
'-fno-common',
|
||||
'-isysroot', '/Developer/SDKs/MacOSX10.6.sdk',
|
||||
'-mmacosx-version-min=10.5',
|
||||
'-fast'
|
||||
'cflags_mozilla': [
|
||||
'-Werror',
|
||||
'-Wno-error=conversion'
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string>
|
||||
|
||||
#include "CC_SIPCCDevice.h"
|
||||
#include "CC_SIPCCDeviceInfo.h"
|
||||
#include "CC_SIPCCFeatureInfo.h"
|
||||
|
@ -59,12 +62,13 @@ static std::string logDestination = "CallControl.log";
|
|||
using namespace std;
|
||||
using namespace CSFUnified;
|
||||
|
||||
|
||||
namespace CSF
|
||||
{
|
||||
|
||||
|
||||
CallControlManagerImpl::CallControlManagerImpl()
|
||||
: multiClusterMode(false),
|
||||
: m_lock("CallControlManagerImpl"),
|
||||
multiClusterMode(false),
|
||||
sipccLoggingMask(0),
|
||||
authenticationStatus(AuthenticationStatusEnum::eNotAuthenticated),
|
||||
connectionState(ConnectionStatusEnum::eIdle)
|
||||
|
@ -92,7 +96,7 @@ bool CallControlManagerImpl::destroy()
|
|||
// Observers
|
||||
void CallControlManagerImpl::addCCObserver ( CC_Observer * observer )
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
if (observer == NULL)
|
||||
{
|
||||
CSFLogErrorS(logTag, "NULL value for \"observer\" passed to addCCObserver().");
|
||||
|
@ -104,13 +108,13 @@ void CallControlManagerImpl::addCCObserver ( CC_Observer * observer )
|
|||
|
||||
void CallControlManagerImpl::removeCCObserver ( CC_Observer * observer )
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
ccObservers.erase(observer);
|
||||
}
|
||||
|
||||
void CallControlManagerImpl::addECCObserver ( ECC_Observer * observer )
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
if (observer == NULL)
|
||||
{
|
||||
CSFLogErrorS(logTag, "NULL value for \"observer\" passed to addECCObserver().");
|
||||
|
@ -122,7 +126,7 @@ void CallControlManagerImpl::addECCObserver ( ECC_Observer * observer )
|
|||
|
||||
void CallControlManagerImpl::removeECCObserver ( ECC_Observer * observer )
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
eccObservers.erase(observer);
|
||||
}
|
||||
|
||||
|
@ -150,17 +154,19 @@ void CallControlManagerImpl::setSecureCachePath(const std::string &secureCachePa
|
|||
this->secureCachePath = secureCachePath;
|
||||
}
|
||||
|
||||
// Local IP Address
|
||||
void CallControlManagerImpl::setLocalIpAddressAndGateway(const std::string& localIpAddress, const std::string& defaultGW)
|
||||
// Add local codecs
|
||||
void CallControlManagerImpl::setAudioCodecs(int codecMask)
|
||||
{
|
||||
CSFLogInfoS(logTag, "setLocalIpAddressAndGateway(" << localIpAddress << ", " << defaultGW << ")");
|
||||
this->localIpAddress = localIpAddress;
|
||||
this->defaultGW = defaultGW;
|
||||
CSFLogDebug(logTag, "setAudioCodecs %X", codecMask);
|
||||
|
||||
if(softPhone != NULL)
|
||||
{
|
||||
softPhone->setLocalAddressAndGateway(this->localIpAddress, this->defaultGW);
|
||||
}
|
||||
VcmSIPCCBinding::setAudioCodecs(codecMask);
|
||||
}
|
||||
|
||||
void CallControlManagerImpl::setVideoCodecs(int codecMask)
|
||||
{
|
||||
CSFLogDebug(logTag, "setVideoCodecs %X", codecMask);
|
||||
|
||||
VcmSIPCCBinding::setVideoCodecs(codecMask);
|
||||
}
|
||||
|
||||
AuthenticationStatusEnum::AuthenticationStatus CallControlManagerImpl::getAuthenticationStatus()
|
||||
|
@ -181,19 +187,10 @@ bool CallControlManagerImpl::registerUser( const std::string& deviceName, const
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check preconditions.
|
||||
if(localIpAddress.empty() || localIpAddress == "127.0.0.1")
|
||||
{
|
||||
setConnectionState(ConnectionStatusEnum::eFailed);
|
||||
CSFLogErrorS(logTag, "registerUser() failed - No local IP address set!");
|
||||
return false;
|
||||
}
|
||||
|
||||
softPhone = CC_SIPCCServicePtr(new CC_SIPCCService());
|
||||
phone = softPhone;
|
||||
phone->init(user, password, domain, deviceName);
|
||||
softPhone->setLoggingMask(sipccLoggingMask);
|
||||
softPhone->setLocalAddressAndGateway(localIpAddress, defaultGW);
|
||||
phone->addCCObserver(this);
|
||||
|
||||
phone->setP2PMode(false);
|
||||
|
@ -221,19 +218,10 @@ bool CallControlManagerImpl::startP2PMode(const std::string& user)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check preconditions.
|
||||
if(localIpAddress.empty() || localIpAddress == "127.0.0.1")
|
||||
{
|
||||
setConnectionState(ConnectionStatusEnum::eFailed);
|
||||
CSFLogErrorS(logTag, "startP2PMode() failed - No local IP address set!");
|
||||
return false;
|
||||
}
|
||||
|
||||
softPhone = CC_SIPCCServicePtr(new CC_SIPCCService());
|
||||
phone = softPhone;
|
||||
phone->init(user, "", "127.0.0.1", "sipdevice");
|
||||
softPhone->setLoggingMask(sipccLoggingMask);
|
||||
softPhone->setLocalAddressAndGateway(localIpAddress, defaultGW);
|
||||
phone->addCCObserver(this);
|
||||
|
||||
phone->setP2PMode(true);
|
||||
|
@ -248,45 +236,23 @@ bool CallControlManagerImpl::startP2PMode(const std::string& user)
|
|||
return bStarted;
|
||||
}
|
||||
|
||||
bool CallControlManagerImpl::startROAPProxy( const std::string& deviceName, const std::string& user, const std::string& password, const std::string& domain )
|
||||
bool CallControlManagerImpl::startSDPMode()
|
||||
{
|
||||
setConnectionState(ConnectionStatusEnum::eRegistering);
|
||||
|
||||
CSFLogInfoS(logTag, "startROAPProxy(" << user << ", " << domain << " )");
|
||||
CSFLogInfoS(logTag, "startSDPMode");
|
||||
if(phone != NULL)
|
||||
{
|
||||
setConnectionState(ConnectionStatusEnum::eReady);
|
||||
|
||||
CSFLogErrorS(logTag, "startROAPProxy() failed - already connected!");
|
||||
CSFLogError(logTag, "%s failed - already started in SDP mode!",__FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check preconditions.
|
||||
if(localIpAddress.empty() || localIpAddress == "127.0.0.1")
|
||||
{
|
||||
setConnectionState(ConnectionStatusEnum::eFailed);
|
||||
CSFLogErrorS(logTag, "startROAPProxy() failed - No local IP address set!");
|
||||
return false;
|
||||
}
|
||||
|
||||
softPhone = CC_SIPCCServicePtr(new CC_SIPCCService());
|
||||
phone = softPhone;
|
||||
phone->init(user, password, domain, deviceName);
|
||||
phone->init("JSEP", "", "127.0.0.1", "sipdevice");
|
||||
softPhone->setLoggingMask(sipccLoggingMask);
|
||||
softPhone->setLocalAddressAndGateway(localIpAddress, defaultGW);
|
||||
phone->addCCObserver(this);
|
||||
|
||||
phone->setP2PMode(false);
|
||||
phone->setROAPProxyMode(true);
|
||||
|
||||
bool bStarted = phone->startService();
|
||||
if (!bStarted) {
|
||||
setConnectionState(ConnectionStatusEnum::eFailed);
|
||||
} else {
|
||||
setConnectionState(ConnectionStatusEnum::eReady);
|
||||
}
|
||||
|
||||
return bStarted;
|
||||
phone->setSDPMode(true);
|
||||
|
||||
return phone->startService();
|
||||
}
|
||||
|
||||
bool CallControlManagerImpl::disconnect()
|
||||
|
@ -337,14 +303,15 @@ CC_DevicePtr CallControlManagerImpl::getActiveDevice()
|
|||
// All known devices
|
||||
PhoneDetailsVtrPtr CallControlManagerImpl::getAvailablePhoneDetails()
|
||||
{
|
||||
PhoneDetailsVtrPtr result = PhoneDetailsVtrPtr(new PhoneDetailsVtr());
|
||||
for(PhoneDetailsMap::iterator it = phoneDetailsMap.begin(); it != phoneDetailsMap.end(); it++)
|
||||
{
|
||||
PhoneDetailsPtr details = it->second;
|
||||
result->push_back(details);
|
||||
}
|
||||
return result;
|
||||
PhoneDetailsVtrPtr result = PhoneDetailsVtrPtr(new PhoneDetailsVtr());
|
||||
for(PhoneDetailsMap::iterator it = phoneDetailsMap.begin(); it != phoneDetailsMap.end(); it++)
|
||||
{
|
||||
PhoneDetailsPtr details = it->second;
|
||||
result->push_back(details);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PhoneDetailsPtr CallControlManagerImpl::getAvailablePhoneDetails(const std::string& deviceName)
|
||||
{
|
||||
PhoneDetailsMap::iterator it = phoneDetailsMap.find(deviceName);
|
||||
|
@ -354,7 +321,6 @@ PhoneDetailsPtr CallControlManagerImpl::getAvailablePhoneDetails(const std::stri
|
|||
}
|
||||
return PhoneDetailsPtr();
|
||||
}
|
||||
|
||||
// Media setup
|
||||
VideoControlPtr CallControlManagerImpl::getVideoControl()
|
||||
{
|
||||
|
@ -374,43 +340,58 @@ AudioControlPtr CallControlManagerImpl::getAudioControl()
|
|||
|
||||
bool CallControlManagerImpl::setProperty(ConfigPropertyKeysEnum::ConfigPropertyKeys key, std::string& value)
|
||||
{
|
||||
CSFLogInfoS(logTag, "setProperty(" << value << " )");
|
||||
unsigned long strtoul_result;
|
||||
char *strtoul_end;
|
||||
|
||||
if (key == ConfigPropertyKeysEnum::eLocalVoipPort) {
|
||||
CCAPI_Config_set_local_voip_port(atoi(value.c_str()));
|
||||
} else if (key == ConfigPropertyKeysEnum::eRemoteVoipPort) {
|
||||
CCAPI_Config_set_remote_voip_port(atoi(value.c_str()));
|
||||
} else if (key == ConfigPropertyKeysEnum::eTransport) {
|
||||
if (value == "tcp")
|
||||
CCAPI_Config_set_transport_udp(false);
|
||||
else
|
||||
CCAPI_Config_set_transport_udp(true);
|
||||
}
|
||||
CSFLogInfoS(logTag, "setProperty(" << value << " )");
|
||||
|
||||
return true;
|
||||
if (key == ConfigPropertyKeysEnum::eLocalVoipPort) {
|
||||
errno = 0;
|
||||
strtoul_result = strtoul(value.c_str(), &strtoul_end, 10);
|
||||
|
||||
if (errno || value.c_str() == strtoul_end || strtoul_result > USHRT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CCAPI_Config_set_local_voip_port((int) strtoul_result);
|
||||
} else if (key == ConfigPropertyKeysEnum::eRemoteVoipPort) {
|
||||
errno = 0;
|
||||
strtoul_result = strtoul(value.c_str(), &strtoul_end, 10);
|
||||
|
||||
if (errno || value.c_str() == strtoul_end || strtoul_result > USHRT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CCAPI_Config_set_remote_voip_port((int) strtoul_result);
|
||||
} else if (key == ConfigPropertyKeysEnum::eTransport) {
|
||||
if (value == "tcp")
|
||||
CCAPI_Config_set_transport_udp(false);
|
||||
else
|
||||
CCAPI_Config_set_transport_udp(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string CallControlManagerImpl::getProperty(ConfigPropertyKeysEnum::ConfigPropertyKeys key)
|
||||
{
|
||||
CSFLogInfoS(logTag, "getProperty()");
|
||||
std::string retValue = "NONESET";
|
||||
char tmpString[11];
|
||||
|
||||
std::string retValue = "NONESET";
|
||||
if (key == ConfigPropertyKeysEnum::eLocalVoipPort) {
|
||||
int tmpValue = CCAPI_Config_get_local_voip_port();
|
||||
std::stringstream out;
|
||||
out << tmpValue;
|
||||
retValue = out.str();
|
||||
} else if (key == ConfigPropertyKeysEnum::eRemoteVoipPort) {
|
||||
int tmpValue = CCAPI_Config_get_remote_voip_port();
|
||||
std::stringstream out;
|
||||
out << tmpValue;
|
||||
retValue = out.str();
|
||||
} else if (key == ConfigPropertyKeysEnum::eVersion) {
|
||||
const char* version = CCAPI_Config_get_version();
|
||||
retValue = version;
|
||||
}
|
||||
CSFLogInfoS(logTag, "getProperty()");
|
||||
|
||||
return retValue;
|
||||
if (key == ConfigPropertyKeysEnum::eLocalVoipPort) {
|
||||
csf_sprintf(tmpString, sizeof(tmpString), "%u", CCAPI_Config_get_local_voip_port());
|
||||
retValue = tmpString;
|
||||
} else if (key == ConfigPropertyKeysEnum::eRemoteVoipPort) {
|
||||
csf_sprintf(tmpString, sizeof(tmpString), "%u", CCAPI_Config_get_remote_voip_port());
|
||||
retValue = tmpString;
|
||||
} else if (key == ConfigPropertyKeysEnum::eVersion) {
|
||||
const char* version = CCAPI_Config_get_version();
|
||||
retValue = version;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
/*
|
||||
There are a number of factors that determine PhoneAvailabilityType::PhoneAvailability. The supported states for this enum are:
|
||||
|
@ -502,15 +483,15 @@ void CallControlManagerImpl::onLineEvent(ccapi_line_event_e lineEvent, CC_Li
|
|||
{
|
||||
notifyLineEventObservers(lineEvent, linePtr, info);
|
||||
}
|
||||
void CallControlManagerImpl::onCallEvent(ccapi_call_event_e callEvent, CC_CallPtr callPtr, CC_CallInfoPtr info, char* sdp)
|
||||
void CallControlManagerImpl::onCallEvent(ccapi_call_event_e callEvent, CC_CallPtr callPtr, CC_CallInfoPtr info)
|
||||
{
|
||||
notifyCallEventObservers(callEvent, callPtr, info, sdp);
|
||||
notifyCallEventObservers(callEvent, callPtr, info);
|
||||
}
|
||||
|
||||
|
||||
void CallControlManagerImpl::notifyDeviceEventObservers (ccapi_device_event_e deviceEvent, CC_DevicePtr devicePtr, CC_DeviceInfoPtr info)
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
set<CC_Observer*>::const_iterator it = ccObservers.begin();
|
||||
for ( ; it != ccObservers.end(); it++ )
|
||||
{
|
||||
|
@ -520,7 +501,7 @@ void CallControlManagerImpl::notifyDeviceEventObservers (ccapi_device_event_e de
|
|||
|
||||
void CallControlManagerImpl::notifyFeatureEventObservers (ccapi_device_event_e deviceEvent, CC_DevicePtr devicePtr, CC_FeatureInfoPtr info)
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
set<CC_Observer*>::const_iterator it = ccObservers.begin();
|
||||
for ( ; it != ccObservers.end(); it++ )
|
||||
{
|
||||
|
@ -530,7 +511,7 @@ void CallControlManagerImpl::notifyFeatureEventObservers (ccapi_device_event_e d
|
|||
|
||||
void CallControlManagerImpl::notifyLineEventObservers (ccapi_line_event_e lineEvent, CC_LinePtr linePtr, CC_LineInfoPtr info)
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
set<CC_Observer*>::const_iterator it = ccObservers.begin();
|
||||
for ( ; it != ccObservers.end(); it++ )
|
||||
{
|
||||
|
@ -538,20 +519,20 @@ void CallControlManagerImpl::notifyLineEventObservers (ccapi_line_event_e lineEv
|
|||
}
|
||||
}
|
||||
|
||||
void CallControlManagerImpl::notifyCallEventObservers (ccapi_call_event_e callEvent, CC_CallPtr callPtr, CC_CallInfoPtr info, char* sdp)
|
||||
void CallControlManagerImpl::notifyCallEventObservers (ccapi_call_event_e callEvent, CC_CallPtr callPtr, CC_CallInfoPtr info)
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
set<CC_Observer*>::const_iterator it = ccObservers.begin();
|
||||
for ( ; it != ccObservers.end(); it++ )
|
||||
{
|
||||
(*it)->onCallEvent(callEvent, callPtr, info, sdp);
|
||||
(*it)->onCallEvent(callEvent, callPtr, info);
|
||||
}
|
||||
}
|
||||
|
||||
void CallControlManagerImpl::notifyAvailablePhoneEvent (AvailablePhoneEventType::AvailablePhoneEvent event,
|
||||
const PhoneDetailsPtr availablePhoneDetails)
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
set<ECC_Observer*>::const_iterator it = eccObservers.begin();
|
||||
for ( ; it != eccObservers.end(); it++ )
|
||||
{
|
||||
|
@ -561,7 +542,7 @@ void CallControlManagerImpl::notifyAvailablePhoneEvent (AvailablePhoneEventType:
|
|||
|
||||
void CallControlManagerImpl::notifyAuthenticationStatusChange (AuthenticationStatusEnum::AuthenticationStatus status)
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
set<ECC_Observer*>::const_iterator it = eccObservers.begin();
|
||||
for ( ; it != eccObservers.end(); it++ )
|
||||
{
|
||||
|
@ -571,7 +552,7 @@ void CallControlManagerImpl::notifyAuthenticationStatusChange (AuthenticationSta
|
|||
|
||||
void CallControlManagerImpl::notifyConnectionStatusChange(ConnectionStatusEnum::ConnectionStatus status)
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
mozilla::MutexAutoLock lock(m_lock);
|
||||
set<ECC_Observer*>::const_iterator it = eccObservers.begin();
|
||||
for ( ; it != eccObservers.end(); it++ )
|
||||
{
|
||||
|
@ -584,5 +565,4 @@ void CallControlManagerImpl::setConnectionState(ConnectionStatusEnum::Connection
|
|||
connectionState = status;
|
||||
notifyConnectionStatusChange(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,8 +42,7 @@
|
|||
#include "CallControlManager.h"
|
||||
#include "PhoneDetailsImpl.h"
|
||||
#include "CC_SIPCCService.h"
|
||||
|
||||
#include "base/lock.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
|
||||
#include <set>
|
||||
|
@ -71,8 +70,9 @@ namespace CSF
|
|||
virtual void setAuthenticationString(const std::string &authString);
|
||||
virtual void setSecureCachePath(const std::string &secureCachePath);
|
||||
|
||||
// Local IP Address and DefaultGateway
|
||||
virtual void setLocalIpAddressAndGateway(const std::string& localIpAddress, const std::string& defaultGW);
|
||||
// Add local codecs
|
||||
virtual void setAudioCodecs(int codecMask);
|
||||
virtual void setVideoCodecs(int codecMask);
|
||||
|
||||
virtual AuthenticationStatusEnum::AuthenticationStatus getAuthenticationStatus();
|
||||
|
||||
|
@ -80,7 +80,7 @@ namespace CSF
|
|||
|
||||
virtual bool startP2PMode(const std::string& user);
|
||||
|
||||
virtual bool startROAPProxy( const std::string& deviceName, const std::string& user, const std::string& password, const std::string& domain );
|
||||
virtual bool startSDPMode();
|
||||
|
||||
virtual bool disconnect();
|
||||
virtual std::string getPreferredDeviceName();
|
||||
|
@ -105,7 +105,7 @@ namespace CSF
|
|||
private: // Data Storage
|
||||
|
||||
// Observers
|
||||
Lock m_lock;;
|
||||
mozilla::Mutex m_lock;
|
||||
std::set<CC_Observer *> ccObservers;
|
||||
std::set<ECC_Observer *> eccObservers;
|
||||
|
||||
|
@ -117,10 +117,6 @@ namespace CSF
|
|||
bool multiClusterMode;
|
||||
cc_int32_t sipccLoggingMask;
|
||||
|
||||
// Local IP Address
|
||||
std::string localIpAddress;
|
||||
std::string defaultGW;
|
||||
|
||||
AuthenticationStatusEnum::AuthenticationStatus authenticationStatus;
|
||||
|
||||
std::string preferredDevice;
|
||||
|
@ -140,7 +136,7 @@ namespace CSF
|
|||
void onDeviceEvent (ccapi_device_event_e deviceEvent, CC_DevicePtr devicePtr, CC_DeviceInfoPtr info);
|
||||
void onFeatureEvent (ccapi_device_event_e deviceEvent, CC_DevicePtr devicePtr, CC_FeatureInfoPtr info);
|
||||
void onLineEvent (ccapi_line_event_e lineEvent, CC_LinePtr linePtr, CC_LineInfoPtr info);
|
||||
void onCallEvent (ccapi_call_event_e callEvent, CC_CallPtr callPtr, CC_CallInfoPtr info, char* sdp);
|
||||
void onCallEvent (ccapi_call_event_e callEvent, CC_CallPtr callPtr, CC_CallInfoPtr info);
|
||||
|
||||
private: //member functions
|
||||
|
||||
|
@ -148,7 +144,7 @@ namespace CSF
|
|||
void notifyDeviceEventObservers (ccapi_device_event_e deviceEvent, CC_DevicePtr devicePtr, CC_DeviceInfoPtr info);
|
||||
void notifyFeatureEventObservers (ccapi_device_event_e deviceEvent, CC_DevicePtr devicePtr, CC_FeatureInfoPtr info);
|
||||
void notifyLineEventObservers (ccapi_line_event_e lineEvent, CC_LinePtr linePtr, CC_LineInfoPtr info);
|
||||
void notifyCallEventObservers (ccapi_call_event_e callEvent, CC_CallPtr callPtr, CC_CallInfoPtr info, char* sdp);
|
||||
void notifyCallEventObservers (ccapi_call_event_e callEvent, CC_CallPtr callPtr, CC_CallInfoPtr info);
|
||||
|
||||
// ECC_Observers
|
||||
void notifyAvailablePhoneEvent (AvailablePhoneEventType::AvailablePhoneEvent event,
|
||||
|
|
|
@ -72,20 +72,65 @@
|
|||
|
||||
#include <map>
|
||||
#include "SharedPtr.h"
|
||||
#include "prlock.h"
|
||||
#include "base/lock.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
/*
|
||||
* Wrapper has its own autolock class because the instances are declared
|
||||
* statically and mozilla::Mutex will not work properly when instantiated
|
||||
* in a static constructor.
|
||||
*/
|
||||
|
||||
class LockNSPR {
|
||||
public:
|
||||
LockNSPR() : lock_(NULL) {
|
||||
lock_ = PR_NewLock();
|
||||
MOZ_ASSERT(lock_);
|
||||
}
|
||||
~LockNSPR() {
|
||||
PR_DestroyLock(lock_);
|
||||
}
|
||||
|
||||
void Acquire() {
|
||||
PR_Lock(lock_);
|
||||
}
|
||||
|
||||
void Release() {
|
||||
PR_Unlock(lock_);
|
||||
}
|
||||
|
||||
private:
|
||||
PRLock *lock_;
|
||||
};
|
||||
|
||||
class AutoLockNSPR {
|
||||
public:
|
||||
AutoLockNSPR(LockNSPR& lock) : lock_(lock) {
|
||||
lock_.Acquire();
|
||||
}
|
||||
~AutoLockNSPR() {
|
||||
lock_.Release();
|
||||
}
|
||||
|
||||
private:
|
||||
LockNSPR& lock_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Wrapper
|
||||
{
|
||||
private:
|
||||
typedef std::map<typename T::Handle, typename T::Ptr> HandleMapType;
|
||||
HandleMapType handleMap;
|
||||
Lock handleMapMutex;
|
||||
HandleMapType handleMap;
|
||||
LockNSPR handleMapMutex;
|
||||
|
||||
public:
|
||||
Wrapper() {}
|
||||
|
||||
typename T::Ptr wrap(typename T::Handle handle)
|
||||
{
|
||||
AutoLock lock(handleMapMutex);
|
||||
AutoLockNSPR lock(handleMapMutex);
|
||||
typename HandleMapType::iterator it = handleMap.find(handle);
|
||||
if(it != handleMap.end())
|
||||
{
|
||||
|
@ -101,7 +146,7 @@ public:
|
|||
|
||||
bool changeHandle(typename T::Handle oldHandle, typename T::Handle newHandle)
|
||||
{
|
||||
AutoLock lock(handleMapMutex);
|
||||
AutoLockNSPR lock(handleMapMutex);
|
||||
typename HandleMapType::iterator it = handleMap.find(oldHandle);
|
||||
if(it != handleMap.end())
|
||||
{
|
||||
|
@ -118,7 +163,7 @@ public:
|
|||
|
||||
bool release(typename T::Handle handle)
|
||||
{
|
||||
AutoLock lock(handleMapMutex);
|
||||
AutoLockNSPR lock(handleMapMutex);
|
||||
typename HandleMapType::iterator it = handleMap.find(handle);
|
||||
if(it != handleMap.end())
|
||||
{
|
||||
|
@ -133,7 +178,7 @@ public:
|
|||
|
||||
void reset()
|
||||
{
|
||||
AutoLock lock(handleMapMutex);
|
||||
AutoLockNSPR lock(handleMapMutex);
|
||||
handleMap.clear();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#define CSFLogStream_h
|
||||
|
||||
#include "CSFLog.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
@ -52,4 +54,15 @@
|
|||
#define CSFLogInfoS(tag, message) { std::ostringstream _oss; _oss << message << std::endl; CSFLog( CSF_LOG_INFO, __FILE__ , __LINE__ , tag, _oss.str().c_str()); }
|
||||
#define CSFLogDebugS(tag, message) { std::ostringstream _oss; _oss << message << std::endl; CSFLog( CSF_LOG_DEBUG, __FILE__ , __LINE__ , tag, _oss.str().c_str()); }
|
||||
|
||||
#else // DEBUG
|
||||
|
||||
#define CSFLogCriticalS(tag, message) {}
|
||||
#define CSFLogErrorS(tag, message) {}
|
||||
#define CSFLogWarnS(tag, message) {}
|
||||
#define CSFLogNoticeS(tag, message) {}
|
||||
#define CSFLogInfoS(tag, message) {}
|
||||
#define CSFLogDebugS(tag, message) {}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
This header file defines:
|
||||
|
||||
csf_countof
|
||||
csf_strcpy
|
||||
csf_sprintf
|
||||
csf_vsprintf
|
||||
|
||||
|
@ -88,18 +87,6 @@ csf_vsprintf
|
|||
|
||||
#define csf_countof(anArray) _countof(anArray)
|
||||
|
||||
//csf_strcpy
|
||||
|
||||
#ifdef _WIN32
|
||||
#define csf_strcpy(/* char* */ pDestination, /* size_t */ sizeOfBufferInCharsInclNullTerm, /* const char * */ pSource)\
|
||||
strcpy_s(pDestination, sizeOfBufferInCharsInclNullTerm, pSource)
|
||||
#else
|
||||
#define csf_strcpy(/* char * */ pDestination, /* size_t */ sizeOfBufferInCharsInclNullTerm, /* const char * */ pSource)\
|
||||
strncpy(pDestination, pSource, sizeOfBufferInCharsInclNullTerm);\
|
||||
pDestination[sizeOfBufferInCharsInclNullTerm-1] = '\0'
|
||||
#endif
|
||||
|
||||
|
||||
//csf_sprintf
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -0,0 +1,733 @@
|
|||
/* 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/. */
|
||||
|
||||
#include "AudioConduit.h"
|
||||
#include "CSFLog.h"
|
||||
#include "voice_engine/include/voe_errors.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static const char* logTag ="WebrtcAudioSessionConduit";
|
||||
|
||||
// 32 bytes is what WebRTC CodecInst expects
|
||||
const unsigned int WebrtcAudioConduit::CODEC_PLNAME_SIZE = 32;
|
||||
|
||||
/**
|
||||
* Factory Method for AudioConduit
|
||||
*/
|
||||
mozilla::RefPtr<AudioSessionConduit> AudioSessionConduit::Create()
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
WebrtcAudioConduit* obj = new WebrtcAudioConduit();
|
||||
if(obj->Init() != kMediaConduitNoError)
|
||||
{
|
||||
CSFLogError(logTag, "%s AudioConduit Init Failed ", __FUNCTION__);
|
||||
delete obj;
|
||||
return NULL;
|
||||
}
|
||||
CSFLogDebug(logTag, "%s Successfully created AudioConduit ", __FUNCTION__);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destruction defines for our super-classes
|
||||
*/
|
||||
WebrtcAudioConduit::~WebrtcAudioConduit()
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
for(std::vector<AudioCodecConfig*>::size_type i=0;i < mRecvCodecList.size();i++)
|
||||
{
|
||||
delete mRecvCodecList[i];
|
||||
}
|
||||
|
||||
delete mCurSendCodecConfig;
|
||||
|
||||
if(mPtrVoEXmedia)
|
||||
{
|
||||
mPtrVoEXmedia->SetExternalRecordingStatus(false);
|
||||
mPtrVoEXmedia->SetExternalPlayoutStatus(false);
|
||||
mPtrVoEXmedia->Release();
|
||||
}
|
||||
|
||||
//Deal with the transport
|
||||
if(mPtrVoENetwork)
|
||||
{
|
||||
mPtrVoENetwork->DeRegisterExternalTransport(mChannel);
|
||||
mPtrVoENetwork->Release();
|
||||
}
|
||||
|
||||
if(mPtrVoECodec)
|
||||
{
|
||||
mPtrVoECodec->Release();
|
||||
}
|
||||
|
||||
if(mPtrVoEBase)
|
||||
{
|
||||
mPtrVoEBase->StopPlayout(mChannel);
|
||||
mPtrVoEBase->StopSend(mChannel);
|
||||
mPtrVoEBase->StopReceive(mChannel);
|
||||
mPtrVoEBase->DeleteChannel(mChannel);
|
||||
mPtrVoEBase->Terminate();
|
||||
mPtrVoEBase->Release();
|
||||
}
|
||||
|
||||
if(mVoiceEngine)
|
||||
{
|
||||
webrtc::VoiceEngine::Delete(mVoiceEngine);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WebRTCAudioConduit Implementation
|
||||
*/
|
||||
MediaConduitErrorCode WebrtcAudioConduit::Init()
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
//Per WebRTC APIs below function calls return NULL on failure
|
||||
if(!(mVoiceEngine = webrtc::VoiceEngine::Create()))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to create voice engine", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if(!(mPtrVoEBase = VoEBase::GetInterface(mVoiceEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to initialize VoEBase", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if(!(mPtrVoENetwork = VoENetwork::GetInterface(mVoiceEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to initialize VoENetwork", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if(!(mPtrVoECodec = VoECodec::GetInterface(mVoiceEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to initialize VoEBCodec", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if(!(mPtrVoEXmedia = VoEExternalMedia::GetInterface(mVoiceEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to initialize VoEExternalMedia", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
// init the engine with our audio device layer
|
||||
if(mPtrVoEBase->Init() == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s VoiceEngine Base Not Initialized", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if( (mChannel = mPtrVoEBase->CreateChannel()) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s VoiceEngine Channel creation failed",__FUNCTION__);
|
||||
return kMediaConduitChannelError;
|
||||
}
|
||||
|
||||
CSFLogDebug(logTag, "%s Channel Created %d ",__FUNCTION__, mChannel);
|
||||
|
||||
if(mPtrVoENetwork->RegisterExternalTransport(mChannel, *this) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s VoiceEngine, External Transport Failed",__FUNCTION__);
|
||||
return kMediaConduitTransportRegistrationFail;
|
||||
}
|
||||
|
||||
if(mPtrVoEXmedia->SetExternalRecordingStatus(true) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s SetExternalRecordingStatus Failed %d",__FUNCTION__,
|
||||
mPtrVoEBase->LastError());
|
||||
return kMediaConduitExternalPlayoutError;
|
||||
}
|
||||
|
||||
if(mPtrVoEXmedia->SetExternalPlayoutStatus(true) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s SetExternalPlayoutStatus Failed %d ",__FUNCTION__,
|
||||
mPtrVoEBase->LastError());
|
||||
return kMediaConduitExternalRecordingError;
|
||||
}
|
||||
CSFLogDebug(logTag , "%s AudioSessionConduit Initialization Done",__FUNCTION__);
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
|
||||
// AudioSessionConduit Implementation
|
||||
MediaConduitErrorCode
|
||||
WebrtcAudioConduit::AttachTransport(mozilla::RefPtr<TransportInterface> aTransport)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
if(!aTransport)
|
||||
{
|
||||
CSFLogError(logTag, "%s NULL Transport", __FUNCTION__);
|
||||
return kMediaConduitInvalidTransport;
|
||||
}
|
||||
// set the transport
|
||||
mTransport = aTransport;
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcAudioConduit::ConfigureSendMediaCodec(const AudioCodecConfig* codecConfig)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
MediaConduitErrorCode condError = kMediaConduitNoError;
|
||||
int error = 0;//webrtc engine errors
|
||||
webrtc::CodecInst cinst;
|
||||
|
||||
//validate codec param
|
||||
if((condError = ValidateCodecConfig(codecConfig, true)) != kMediaConduitNoError)
|
||||
{
|
||||
return condError;
|
||||
}
|
||||
|
||||
//are we transmitting already, stop and apply the send codec
|
||||
if(mEngineTransmitting)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Engine Already Sending. Attemping to Stop ", __FUNCTION__);
|
||||
if(mPtrVoEBase->StopSend(mChannel) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s StopSend() Failed %d ", __FUNCTION__,
|
||||
mPtrVoEBase->LastError());
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
}
|
||||
|
||||
mEngineTransmitting = false;
|
||||
|
||||
if(!CodecConfigToWebRTCCodec(codecConfig,cinst))
|
||||
{
|
||||
CSFLogError(logTag,"%s CodecConfig to WebRTC Codec Failed ",__FUNCTION__);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
if(mPtrVoECodec->SetSendCodec(mChannel, cinst) == -1)
|
||||
{
|
||||
error = mPtrVoEBase->LastError();
|
||||
CSFLogError(logTag, "%s SetSendCodec - Invalid Codec %d ",__FUNCTION__,
|
||||
error);
|
||||
|
||||
if(error == VE_CANNOT_SET_SEND_CODEC || error == VE_CODEC_ERROR)
|
||||
{
|
||||
return kMediaConduitInvalidSendCodec;
|
||||
}
|
||||
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
//Let's Send Transport State-machine on the Engine
|
||||
if(mPtrVoEBase->StartSend(mChannel) == -1)
|
||||
{
|
||||
error = mPtrVoEBase->LastError();
|
||||
CSFLogError(logTag, "%s StartSend failed %d", __FUNCTION__, error);
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
//Copy the applied config for future reference.
|
||||
delete mCurSendCodecConfig;
|
||||
|
||||
mCurSendCodecConfig = new AudioCodecConfig(codecConfig->mType,
|
||||
codecConfig->mName,
|
||||
codecConfig->mFreq,
|
||||
codecConfig->mPacSize,
|
||||
codecConfig->mChannels,
|
||||
codecConfig->mRate);
|
||||
|
||||
|
||||
mEngineTransmitting = true;
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcAudioConduit::ConfigureRecvMediaCodecs(
|
||||
const std::vector<AudioCodecConfig*>& codecConfigList)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
MediaConduitErrorCode condError = kMediaConduitNoError;
|
||||
int error = 0; //webrtc engine errors
|
||||
bool success = false;
|
||||
|
||||
// are we receiving already. If so, stop receiving and playout
|
||||
// since we can't apply new recv codec when the engine is playing
|
||||
if(mEngineReceiving)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Engine Already Receiving. Attemping to Stop ", __FUNCTION__);
|
||||
// AudioEngine doesn't fail fatal on stop reception. Ref:voe_errors.h.
|
||||
// hence we need-not be strict in failing here on error
|
||||
mPtrVoEBase->StopReceive(mChannel);
|
||||
CSFLogDebug(logTag, "%s Attemping to Stop playout ", __FUNCTION__);
|
||||
if(mPtrVoEBase->StopPlayout(mChannel) == -1)
|
||||
{
|
||||
if( mPtrVoEBase->LastError() == VE_CANNOT_STOP_PLAYOUT)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Stop-Playout Failed %d", mPtrVoEBase->LastError());
|
||||
return kMediaConduitPlayoutError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mEngineReceiving = false;
|
||||
|
||||
if(!codecConfigList.size())
|
||||
{
|
||||
CSFLogError(logTag, "%s Zero number of codecs to configure", __FUNCTION__);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
//Try Applying the codecs in the list
|
||||
for(std::vector<AudioCodecConfig*>::size_type i=0 ;i<codecConfigList.size();i++)
|
||||
{
|
||||
//if the codec param is invalid or diplicate, return error
|
||||
if((condError = ValidateCodecConfig(codecConfigList[i],false)) != kMediaConduitNoError)
|
||||
{
|
||||
return condError;
|
||||
}
|
||||
|
||||
webrtc::CodecInst cinst;
|
||||
if(!CodecConfigToWebRTCCodec(codecConfigList[i],cinst))
|
||||
{
|
||||
CSFLogError(logTag,"%s CodecConfig to WebRTC Codec Failed ",__FUNCTION__);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(mPtrVoECodec->SetRecPayloadType(mChannel,cinst) == -1)
|
||||
{
|
||||
error = mPtrVoEBase->LastError();
|
||||
CSFLogError(logTag, "%s SetRecvCodec Failed %d ",__FUNCTION__, error);
|
||||
continue;
|
||||
} else {
|
||||
CSFLogDebug(logTag, "%s Successfully Set RecvCodec %s", __FUNCTION__,
|
||||
codecConfigList[i]->mName.c_str());
|
||||
//copy this to local database
|
||||
if(CopyCodecToDB(codecConfigList[i]))
|
||||
{
|
||||
success = true;
|
||||
} else {
|
||||
CSFLogError(logTag,"%s Unable to updated Codec Database", __FUNCTION__);
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} //end for
|
||||
|
||||
//Success == false indicates none of the codec was applied
|
||||
if(!success)
|
||||
{
|
||||
CSFLogError(logTag, "%s Setting Receive Codec Failed ", __FUNCTION__);
|
||||
return kMediaConduitInvalidReceiveCodec;
|
||||
}
|
||||
|
||||
//If we are here, atleast one codec should have been set
|
||||
if(mPtrVoEBase->StartReceive(mChannel) == -1)
|
||||
{
|
||||
error = mPtrVoEBase->LastError();
|
||||
CSFLogError(logTag , "StartReceive Failed %d ",error);
|
||||
if(error == VE_RECV_SOCKET_ERROR)
|
||||
{
|
||||
return kMediaConduitSocketError;
|
||||
}
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
|
||||
if(mPtrVoEBase->StartPlayout(mChannel) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "Starting playout Failed");
|
||||
return kMediaConduitPlayoutError;
|
||||
}
|
||||
|
||||
//we should be good here for setting this.
|
||||
mEngineReceiving = true;
|
||||
DumpCodecDB();
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcAudioConduit::SendAudioFrame(const int16_t audio_data[],
|
||||
int32_t lengthSamples,
|
||||
int32_t samplingFreqHz,
|
||||
int32_t capture_delay)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
// Following checks need to be performed
|
||||
// 1. Non null audio buffer pointer,
|
||||
// 2. invalid sampling frequency - less than 0 or unsupported ones
|
||||
// 3. Appropriate Sample Length for 10 ms audio-frame. This represents
|
||||
// block size the VoiceEngine feeds into encoder for passed in audio-frame
|
||||
// Ex: for 16000 sampling rate , valid block-length is 160
|
||||
// Similarly for 32000 sampling rate, valid block length is 320
|
||||
// We do the check by the verify modular operator below to be zero
|
||||
|
||||
if(!audio_data || (lengthSamples <= 0) ||
|
||||
(IsSamplingFreqSupported(samplingFreqHz) == false) ||
|
||||
((lengthSamples % (samplingFreqHz / 100) != 0)) )
|
||||
{
|
||||
CSFLogError(logTag, "%s Invalid Params ", __FUNCTION__);
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
//validate capture time
|
||||
if(capture_delay < 0 )
|
||||
{
|
||||
CSFLogError(logTag,"%s Invalid Capture Delay ", __FUNCTION__);
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
// if transmission is not started .. conduit cannot insert frames
|
||||
if(!mEngineTransmitting)
|
||||
{
|
||||
CSFLogError(logTag, "%s Engine not transmitting ", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
|
||||
//Insert the samples
|
||||
if(mPtrVoEXmedia->ExternalRecordingInsertData(audio_data,
|
||||
lengthSamples,
|
||||
samplingFreqHz,
|
||||
capture_delay) == -1)
|
||||
{
|
||||
int error = mPtrVoEBase->LastError();
|
||||
CSFLogError(logTag, "Inserting audio data Failed %d", error);
|
||||
if(error == VE_RUNTIME_REC_ERROR)
|
||||
{
|
||||
return kMediaConduitRecordingError;
|
||||
}
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
// we should be good here
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcAudioConduit::GetAudioFrame(int16_t speechData[],
|
||||
int32_t samplingFreqHz,
|
||||
int32_t capture_delay,
|
||||
int& lengthSamples)
|
||||
{
|
||||
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
unsigned int numSamples = 0;
|
||||
|
||||
//validate params
|
||||
if(!speechData )
|
||||
{
|
||||
CSFLogError(logTag,"%s Null Audio Buffer Pointer", __FUNCTION__);
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
// Validate sample length
|
||||
if((numSamples = GetNum10msSamplesForFrequency(samplingFreqHz)) == 0 )
|
||||
{
|
||||
CSFLogError(logTag,"%s Invalid Sampling Frequency ", __FUNCTION__);
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
//validate capture time
|
||||
if(capture_delay < 0 )
|
||||
{
|
||||
CSFLogError(logTag,"%s Invalid Capture Delay ", __FUNCTION__);
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
//Conduit should have reception enabled before we ask for decoded
|
||||
// samples
|
||||
if(!mEngineReceiving)
|
||||
{
|
||||
CSFLogError(logTag, "%s Engine not Receiving ", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
|
||||
lengthSamples = 0; //output paramter
|
||||
|
||||
if(mPtrVoEXmedia->ExternalPlayoutGetData( speechData,
|
||||
samplingFreqHz,
|
||||
capture_delay,
|
||||
lengthSamples) == -1)
|
||||
{
|
||||
int error = mPtrVoEBase->LastError();
|
||||
CSFLogError(logTag, "Getting audio data Failed %d", error);
|
||||
if(error == VE_RUNTIME_PLAY_ERROR)
|
||||
{
|
||||
return kMediaConduitPlayoutError;
|
||||
}
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
CSFLogDebug(logTag,"%s GetAudioFrame:Got samples: length %d ",__FUNCTION__,
|
||||
lengthSamples);
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
// Transport Layer Callbacks
|
||||
MediaConduitErrorCode
|
||||
WebrtcAudioConduit::ReceivedRTPPacket(const void *data, int len)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s : channel %d", __FUNCTION__, mChannel);
|
||||
|
||||
if(mEngineReceiving)
|
||||
{
|
||||
if(mPtrVoENetwork->ReceivedRTPPacket(mChannel,data,len) == -1)
|
||||
{
|
||||
int error = mPtrVoEBase->LastError();
|
||||
CSFLogError(logTag, "%s RTP Processing Error %d ", error);
|
||||
if(error == VE_RTP_RTCP_MODULE_ERROR)
|
||||
{
|
||||
return kMediaConduitRTPRTCPModuleError;
|
||||
}
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
} else {
|
||||
//engine not receiving
|
||||
CSFLogError(logTag, "ReceivedRTPPacket: Engine Error");
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
//good here
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcAudioConduit::ReceivedRTCPPacket(const void *data, int len)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s : channel %d ",__FUNCTION__, mChannel);
|
||||
|
||||
if(mEngineReceiving)
|
||||
{
|
||||
if(mPtrVoENetwork->ReceivedRTCPPacket(mChannel, data, len) == -1)
|
||||
{
|
||||
int error = mPtrVoEBase->LastError();
|
||||
CSFLogError(logTag, "%s RTCP Processing Error %d ", error);
|
||||
if(error == VE_RTP_RTCP_MODULE_ERROR)
|
||||
{
|
||||
return kMediaConduitRTPRTCPModuleError;
|
||||
}
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
} else {
|
||||
//engine not running
|
||||
CSFLogError(logTag, "ReceivedRTPPacket: Engine Error");
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
//good here
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
//WebRTC::RTP Callback Implementation
|
||||
|
||||
int WebrtcAudioConduit::SendPacket(int channel, const void* data, int len)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s : channel %d",__FUNCTION__,channel);
|
||||
|
||||
if(mTransport && (mTransport->SendRtpPacket(data, len) == NS_OK))
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Sent RTP Packet ", __FUNCTION__);
|
||||
return 0;
|
||||
} else {
|
||||
CSFLogError(logTag, "%s RTP Packet Send Failed ", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int WebrtcAudioConduit::SendRTCPPacket(int channel, const void* data, int len)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s : channel %d", __FUNCTION__, channel);
|
||||
if(mTransport && mTransport->SendRtcpPacket(data, len) == NS_OK)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Sent RTCP Packet ", __FUNCTION__);
|
||||
return 0;
|
||||
} else {
|
||||
CSFLogError(logTag, "%s RTCP Packet Send Failed ", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts between CodecConfig to WebRTC Codec Structure.
|
||||
*/
|
||||
|
||||
bool
|
||||
WebrtcAudioConduit::CodecConfigToWebRTCCodec(const AudioCodecConfig* codecInfo,
|
||||
webrtc::CodecInst& cinst)
|
||||
{
|
||||
const unsigned int plNameLength = codecInfo->mName.length()+1;
|
||||
memset(&cinst, 0, sizeof(webrtc::CodecInst));
|
||||
if(sizeof(cinst.plname) < plNameLength)
|
||||
{
|
||||
CSFLogError(logTag, "%s Payload name buffer capacity mismatch ",
|
||||
__FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
memcpy(cinst.plname, codecInfo->mName.c_str(),codecInfo->mName.length());
|
||||
cinst.plname[plNameLength]='\0';
|
||||
cinst.pltype = codecInfo->mType;
|
||||
cinst.rate = codecInfo->mRate;
|
||||
cinst.pacsize = codecInfo->mPacSize;
|
||||
cinst.plfreq = codecInfo->mFreq;
|
||||
cinst.channels = codecInfo->mChannels;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supported Sampling Frequncies.
|
||||
*/
|
||||
bool
|
||||
WebrtcAudioConduit::IsSamplingFreqSupported(int freq) const
|
||||
{
|
||||
if(GetNum10msSamplesForFrequency(freq))
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return block-length of 10 ms audio frame in number of samples */
|
||||
unsigned int
|
||||
WebrtcAudioConduit::GetNum10msSamplesForFrequency(int samplingFreqHz) const
|
||||
{
|
||||
switch(samplingFreqHz)
|
||||
{
|
||||
case 16000: return 160; //160 samples
|
||||
case 32000: return 320; //320 samples
|
||||
case 44000: return 440; //440 samples
|
||||
case 48000: return 480; //480 samples
|
||||
default: return 0; // invalid or unsupported
|
||||
}
|
||||
}
|
||||
|
||||
//Copy the codec passed into Conduit's database
|
||||
bool
|
||||
WebrtcAudioConduit::CopyCodecToDB(const AudioCodecConfig* codecInfo)
|
||||
{
|
||||
|
||||
AudioCodecConfig* cdcConfig = new AudioCodecConfig(codecInfo->mType,
|
||||
codecInfo->mName,
|
||||
codecInfo->mFreq,
|
||||
codecInfo->mPacSize,
|
||||
codecInfo->mChannels,
|
||||
codecInfo->mRate);
|
||||
mRecvCodecList.push_back(cdcConfig);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if 2 codec structs are same
|
||||
*/
|
||||
bool
|
||||
WebrtcAudioConduit::CheckCodecsForMatch(const AudioCodecConfig* curCodecConfig,
|
||||
const AudioCodecConfig* codecInfo) const
|
||||
{
|
||||
if(!curCodecConfig)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(curCodecConfig->mType == codecInfo->mType &&
|
||||
(curCodecConfig->mName.compare(codecInfo->mName) == 0) &&
|
||||
curCodecConfig->mFreq == codecInfo->mFreq &&
|
||||
curCodecConfig->mPacSize == codecInfo->mPacSize &&
|
||||
curCodecConfig->mChannels == codecInfo->mChannels &&
|
||||
curCodecConfig->mRate == codecInfo->mRate)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the codec is already in Conduit's database
|
||||
*/
|
||||
bool
|
||||
WebrtcAudioConduit::CheckCodecForMatch(const AudioCodecConfig* codecInfo) const
|
||||
{
|
||||
//the db should have atleast one codec
|
||||
for(std::vector<AudioCodecConfig*>::size_type i=0;i < mRecvCodecList.size();i++)
|
||||
{
|
||||
if(CheckCodecsForMatch(mRecvCodecList[i],codecInfo))
|
||||
{
|
||||
//match
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//no match or empty local db
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform validation on the codecCofig to be applied
|
||||
* Verifies if the codec is already applied.
|
||||
*/
|
||||
MediaConduitErrorCode
|
||||
WebrtcAudioConduit::ValidateCodecConfig(const AudioCodecConfig* codecInfo,
|
||||
bool send) const
|
||||
{
|
||||
bool codecAppliedAlready = false;
|
||||
|
||||
if(!codecInfo)
|
||||
{
|
||||
CSFLogError(logTag, "%s Null CodecConfig ", __FUNCTION__);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
if((codecInfo->mName.empty()) ||
|
||||
(codecInfo->mName.length() >= CODEC_PLNAME_SIZE))
|
||||
{
|
||||
CSFLogError(logTag, "%s Invalid Payload Name Length ", __FUNCTION__);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
//Only mono or stereo channels supported
|
||||
if( (codecInfo->mChannels != 1) && (codecInfo->mChannels != 2))
|
||||
{
|
||||
CSFLogError(logTag, "%s Channel Unsupported ", __FUNCTION__);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
//check if we have the same codec already applied
|
||||
if(send)
|
||||
{
|
||||
codecAppliedAlready = CheckCodecsForMatch(mCurSendCodecConfig,codecInfo);
|
||||
} else {
|
||||
codecAppliedAlready = CheckCodecForMatch(codecInfo);
|
||||
}
|
||||
|
||||
if(codecAppliedAlready)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Codec %s Already Applied ", __FUNCTION__, codecInfo->mName.c_str());
|
||||
return kMediaConduitCodecInUse;
|
||||
}
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
void
|
||||
WebrtcAudioConduit::DumpCodecDB() const
|
||||
{
|
||||
for(std::vector<AudioCodecConfig*>::size_type i=0;i < mRecvCodecList.size();i++)
|
||||
{
|
||||
CSFLogDebug(logTag,"Payload Name: %s", mRecvCodecList[i]->mName.c_str());
|
||||
CSFLogDebug(logTag,"Payload Type: %d", mRecvCodecList[i]->mType);
|
||||
CSFLogDebug(logTag,"Payload Frequency: %d", mRecvCodecList[i]->mFreq);
|
||||
CSFLogDebug(logTag,"Payload PacketSize: %d", mRecvCodecList[i]->mPacSize);
|
||||
CSFLogDebug(logTag,"Payload Channels: %d", mRecvCodecList[i]->mChannels);
|
||||
CSFLogDebug(logTag,"Payload Sampling Rate: %d", mRecvCodecList[i]->mRate);
|
||||
}
|
||||
}
|
||||
}// end namespace
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
/* 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 AUDIO_SESSION_H_
|
||||
#define AUDIO_SESSION_H_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "MediaConduitInterface.h"
|
||||
|
||||
// Audio Engine Includes
|
||||
#include "common_types.h"
|
||||
#include "voice_engine/include/voe_base.h"
|
||||
#include "voice_engine/include/voe_volume_control.h"
|
||||
#include "voice_engine/include/voe_codec.h"
|
||||
#include "voice_engine/include/voe_file.h"
|
||||
#include "voice_engine/include/voe_network.h"
|
||||
#include "voice_engine/include/voe_external_media.h"
|
||||
|
||||
//Some WebRTC types for short notations
|
||||
using webrtc::VoEBase;
|
||||
using webrtc::VoENetwork;
|
||||
using webrtc::VoECodec;
|
||||
using webrtc::VoEExternalMedia;
|
||||
|
||||
/** This file hosts several structures identifying different aspects
|
||||
* of a RTP Session.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Concrete class for Audio session. Hooks up
|
||||
* - media-source and target to external transport
|
||||
*/
|
||||
class WebrtcAudioConduit:public AudioSessionConduit
|
||||
,public webrtc::Transport
|
||||
{
|
||||
public:
|
||||
//VoiceEngine defined constant for Payload Name Size.
|
||||
static const unsigned int CODEC_PLNAME_SIZE;
|
||||
|
||||
/**
|
||||
* APIs used by the registered external transport to this Conduit to
|
||||
* feed in received RTP Frames to the VoiceEngine for decoding
|
||||
*/
|
||||
virtual MediaConduitErrorCode ReceivedRTPPacket(const void *data, int len);
|
||||
|
||||
/**
|
||||
* APIs used by the registered external transport to this Conduit to
|
||||
* feed in received RTCP Frames to the VoiceEngine for decoding
|
||||
*/
|
||||
virtual MediaConduitErrorCode ReceivedRTCPPacket(const void *data, int len);
|
||||
|
||||
/**
|
||||
* Function to configure send codec for the audio session
|
||||
* @param sendSessionConfig: CodecConfiguration
|
||||
* @result: On Success, the audio engine is configured with passed in codec for send
|
||||
* On failure, audio engine transmit functionality is disabled.
|
||||
* NOTE: This API can be invoked multiple time. Invoking this API may involve restarting
|
||||
* transmission sub-system on the engine.
|
||||
*/
|
||||
virtual MediaConduitErrorCode ConfigureSendMediaCodec(
|
||||
const AudioCodecConfig* codecConfig);
|
||||
/**
|
||||
* Function to configure list of receive codecs for the audio session
|
||||
* @param sendSessionConfig: CodecConfiguration
|
||||
* @result: On Success, the audio engine is configured with passed in codec for send
|
||||
* Also the playout is enabled.
|
||||
* On failure, audio engine transmit functionality is disabled.
|
||||
* NOTE: This API can be invoked multiple time. Invoking this API may involve restarting
|
||||
* transmission sub-system on the engine.
|
||||
*/
|
||||
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
||||
const std::vector<AudioCodecConfig* >& codecConfigList);
|
||||
|
||||
/**
|
||||
* Register External Transport to this Conduit. RTP and RTCP frames from the VoiceEnigne
|
||||
* shall be passed to the registered transport for transporting externally.
|
||||
*/
|
||||
virtual MediaConduitErrorCode AttachTransport(
|
||||
mozilla::RefPtr<TransportInterface> aTransport);
|
||||
|
||||
/**
|
||||
* Function to deliver externally captured audio sample for encoding and transport
|
||||
* @param audioData [in]: Pointer to array containing a frame of audio
|
||||
* @param lengthSamples [in]: Length of audio frame in samples in multiple of 10 milliseconds
|
||||
* Ex: Frame length is 160, 320, 440 for 16, 32, 44 kHz sampling rates
|
||||
respectively.
|
||||
audioData[] should be of lengthSamples in size
|
||||
say, for 16kz sampling rate, audioData[] should contain 160
|
||||
samples of 16-bits each for a 10m audio frame.
|
||||
* @param samplingFreqHz [in]: Frequency/rate of the sampling in Hz ( 16000, 32000 ...)
|
||||
* @param capture_delay [in]: Approx Delay from recording until it is delivered to VoiceEngine
|
||||
in milliseconds.
|
||||
* NOTE: ConfigureSendMediaCodec() SHOULD be called before this function can be invoked
|
||||
* This ensures the inserted audio-samples can be transmitted by the conduit
|
||||
*
|
||||
*/
|
||||
virtual MediaConduitErrorCode SendAudioFrame(const int16_t speechData[],
|
||||
int32_t lengthSamples,
|
||||
int32_t samplingFreqHz,
|
||||
int32_t capture_time);
|
||||
|
||||
/**
|
||||
* Function to grab a decoded audio-sample from the media engine for rendering
|
||||
* / playoutof length 10 milliseconds.
|
||||
*
|
||||
* @param speechData [in]: Pointer to a array to which a 10ms frame of audio will be copied
|
||||
* @param samplingFreqHz [in]: Frequency of the sampling for playback in Hertz (16000, 32000,..)
|
||||
* @param capture_delay [in]: Estimated Time between reading of the samples to rendering/playback
|
||||
* @param lengthSamples [out]: Will contain length of the audio frame in samples at return.
|
||||
Ex: A value of 160 implies 160 samples each of 16-bits was copied
|
||||
into speechData
|
||||
* NOTE: This function should be invoked every 10 milliseconds for the best
|
||||
* peformance
|
||||
* NOTE: ConfigureRecvMediaCodec() SHOULD be called before this function can be invoked
|
||||
* This ensures the decoded samples are ready for reading and playout is enabled.
|
||||
*
|
||||
*/
|
||||
virtual MediaConduitErrorCode GetAudioFrame(int16_t speechData[],
|
||||
int32_t samplingFreqHz,
|
||||
int32_t capture_delay,
|
||||
int& lengthSamples);
|
||||
|
||||
|
||||
/**
|
||||
* Webrtc transport implementation to send and receive RTP packet.
|
||||
* AudioConduit registers itself as ExternalTransport to the VoiceEngine
|
||||
*/
|
||||
virtual int SendPacket(int channel, const void *data, int len) ;
|
||||
|
||||
/**
|
||||
* Webrtc transport implementation to send and receive RTCP packet.
|
||||
* AudioConduit registers itself as ExternalTransport to the VoiceEngine
|
||||
*/
|
||||
virtual int SendRTCPPacket(int channel, const void *data, int len) ;
|
||||
|
||||
|
||||
|
||||
WebrtcAudioConduit():
|
||||
mVoiceEngine(NULL),
|
||||
mTransport(NULL),
|
||||
mEngineTransmitting(false),
|
||||
mEngineReceiving(false),
|
||||
mChannel(-1),
|
||||
mCurSendCodecConfig(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~WebrtcAudioConduit();
|
||||
|
||||
MediaConduitErrorCode Init();
|
||||
|
||||
private:
|
||||
WebrtcAudioConduit(const WebrtcAudioConduit& other) MOZ_DELETE;
|
||||
void operator=(const WebrtcAudioConduit& other) MOZ_DELETE;
|
||||
|
||||
//Local database of currently applied receive codecs
|
||||
typedef std::vector<AudioCodecConfig* > RecvCodecList;
|
||||
|
||||
//Function to convert between WebRTC and Conduit codec structures
|
||||
bool CodecConfigToWebRTCCodec(const AudioCodecConfig* codecInfo,
|
||||
webrtc::CodecInst& cinst);
|
||||
|
||||
//Checks if given sampling frequency is supported
|
||||
bool IsSamplingFreqSupported(int freq) const;
|
||||
|
||||
//Generate block size in sample lenght for a given sampling frequency
|
||||
unsigned int GetNum10msSamplesForFrequency(int samplingFreqHz) const;
|
||||
|
||||
// Function to copy a codec structure to Conduit's database
|
||||
bool CopyCodecToDB(const AudioCodecConfig* codecInfo);
|
||||
|
||||
// Functions to verify if the codec passed is already in
|
||||
// conduits database
|
||||
bool CheckCodecForMatch(const AudioCodecConfig* codecInfo) const;
|
||||
bool CheckCodecsForMatch(const AudioCodecConfig* curCodecConfig,
|
||||
const AudioCodecConfig* codecInfo) const;
|
||||
//Checks the codec to be applied
|
||||
MediaConduitErrorCode ValidateCodecConfig(const AudioCodecConfig* codecInfo, bool send) const;
|
||||
|
||||
//Utility function to dump recv codec database
|
||||
void DumpCodecDB() const;
|
||||
|
||||
webrtc::VoiceEngine* mVoiceEngine;
|
||||
mozilla::RefPtr<TransportInterface> mTransport;
|
||||
webrtc::VoENetwork* mPtrVoENetwork;
|
||||
webrtc::VoEBase* mPtrVoEBase;
|
||||
webrtc::VoECodec* mPtrVoECodec;
|
||||
webrtc::VoEExternalMedia* mPtrVoEXmedia;
|
||||
|
||||
//engine states of our interets
|
||||
bool mEngineTransmitting; // If true => VoiceEngine Send-subsystem is up
|
||||
bool mEngineReceiving; // If true => VoiceEngine Receive-subsystem is up
|
||||
// and playout is enabled
|
||||
|
||||
int mChannel;
|
||||
RecvCodecList mRecvCodecList;
|
||||
AudioCodecConfig* mCurSendCodecConfig;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
/* 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 CODEC_CONFIG_H_
|
||||
#define CODEC_CONFIG_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Minimalistic Audio Codec Config Params
|
||||
*/
|
||||
struct AudioCodecConfig
|
||||
{
|
||||
/*
|
||||
* The data-types for these properties mimic the
|
||||
* corresponding webrtc::CodecInst data-types.
|
||||
*/
|
||||
int mType;
|
||||
std::string mName;
|
||||
int mFreq;
|
||||
int mPacSize;
|
||||
int mChannels;
|
||||
int mRate;
|
||||
|
||||
/* Default constructor is not provided since as a consumer, we
|
||||
* can't decide the default configuration for the codec
|
||||
*/
|
||||
explicit AudioCodecConfig(int type, std::string name,
|
||||
int freq,int pacSize,
|
||||
int channels, int rate): mType(type),
|
||||
mName(name),
|
||||
mFreq(freq),
|
||||
mPacSize(pacSize),
|
||||
mChannels(channels),
|
||||
mRate(rate)
|
||||
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Minimalisitc video codec configuration
|
||||
* More to be added later depending on the use-case
|
||||
*/
|
||||
|
||||
struct VideoCodecConfig
|
||||
{
|
||||
|
||||
/*
|
||||
* The data-types for these properties mimic the
|
||||
* corresponding webrtc::VideoCodec data-types.
|
||||
*/
|
||||
int mType;
|
||||
std::string mName;
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
|
||||
VideoCodecConfig(int type, std::string name,int width,
|
||||
int height): mType(type),
|
||||
mName(name),
|
||||
mWidth(width),
|
||||
mHeight(height)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/* 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 MEDIA_SESSION_ERRORS_H_
|
||||
#define MEDIA_SESSION_ERRORS_H_
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
enum MediaConduitErrorCode
|
||||
{
|
||||
kMediaConduitNoError = 0, // 0 for Success,greater than 0 imples error
|
||||
kMediaConduitSessionNotInited = 10100, // Session not initialized.10100 serves as
|
||||
// base for the conduit errors
|
||||
kMediaConduitMalformedArgument, // Malformed input to Conduit API
|
||||
kMediaConduitCaptureError, // WebRTC capture APIs failed
|
||||
kMediaConduitInvalidSendCodec, // Wrong Send codec
|
||||
kMediaConduitInvalidReceiveCodec, // Wrong Recv Codec
|
||||
kMediaConduitCodecInUse, // Already applied Codec
|
||||
kMediaConduitInvalidRenderer, // NULL or Wrong Renderer object
|
||||
kMediaConduitRendererFail, // Add Render called multiple times
|
||||
kMediaConduitSendingAlready, // Engine already trasmitting
|
||||
kMediaConduitReceivingAlready, // Engine already receiving
|
||||
kMediaConduitTransportRegistrationFail,// NULL or wrong transport interface
|
||||
kMediaConduitInvalidTransport, // NULL or wrong transport interface
|
||||
kMediaConduitChannelError, // Configuration Error
|
||||
kMediaConduitSocketError, // Media Engine transport socket error
|
||||
kMediaConduitRTPRTCPModuleError, // Couldn't start RTP/RTCP processing
|
||||
kMediaConduitRTPProcessingFailed, // Processing incoming RTP frame failed
|
||||
kMediaConduitUnknownError, // More information can be found in logs
|
||||
kMediaConduitExternalRecordingError, // Couldn't start external recording
|
||||
kMediaConduitRecordingError, // Runtime recording error
|
||||
kMediaConduitExternalPlayoutError, // Couldn't start external playout
|
||||
kMediaConduitPlayoutError // Runtime playout error
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,306 @@
|
|||
/* 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 MEDIA_CONDUIT_ABSTRACTION_
|
||||
#define MEDIA_CONDUIT_ABSTRACTION_
|
||||
|
||||
#include "nspr.h"
|
||||
#include "prerror.h"
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "CodecConfig.h"
|
||||
#include "VideoTypes.h"
|
||||
#include "MediaConduitErrors.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mozilla {
|
||||
/**
|
||||
* Abstract Interface for transporting RTP packets - audio/vidoeo
|
||||
* The consumers of this interface are responsible for passing in
|
||||
* the RTPfied media packets
|
||||
*/
|
||||
class TransportInterface
|
||||
{
|
||||
public:
|
||||
virtual ~TransportInterface() {};
|
||||
|
||||
/**
|
||||
* RTP Transport Function to be implemented by concrete transport implementation
|
||||
* @param data : RTP Packet (audio/video) to be transported
|
||||
* @param len : Length of the media packet
|
||||
* @result : NS_OK on success, NS_ERROR_FAILURE otherwise
|
||||
*/
|
||||
virtual nsresult SendRtpPacket(const void* data, int len) = 0;
|
||||
|
||||
/**
|
||||
* RTCP Transport Function to be implemented by concrete transport implementation
|
||||
* @param data : RTCP Packet to be transported
|
||||
* @param len : Length of the RTCP packet
|
||||
* @result : NS_OK on success, NS_ERROR_FAILURE otherwise
|
||||
*/
|
||||
virtual nsresult SendRtcpPacket(const void* data, int len) = 0;
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TransportInterface)
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 1. Abstract renderer for video data
|
||||
* 2. This class acts as abstract interface between the video-engine and
|
||||
* video-engine agnostic renderer implementation.
|
||||
* 3. Concrete implementation of this interface is responsible for
|
||||
* processing and/or rendering the obtained raw video frame to appropriate
|
||||
* output , say, <video>
|
||||
*/
|
||||
class VideoRenderer
|
||||
{
|
||||
public:
|
||||
virtual ~VideoRenderer() {} ;
|
||||
|
||||
/**
|
||||
* Callback Function reportng any change in the video-frame dimensions
|
||||
* @param width: current width of the video @ decoder
|
||||
* @param height: current height of the video @ decoder
|
||||
* @param number_of_streams: number of participating video streams
|
||||
*/
|
||||
virtual void FrameSizeChange(unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int number_of_streams) = 0;
|
||||
|
||||
/**
|
||||
* Callback Function reporting decoded I420 frame for processing.
|
||||
* @param buffer: pointer to decoded video frame
|
||||
* @param buffer_size: size of the decoded frame
|
||||
* @param time_stamp: Decoder timestamp, typically 90KHz as per RTP
|
||||
* @render_time: Wall-clock time at the decoder for synchronization
|
||||
* purposes in milliseconds
|
||||
* NOTE: It is the responsibility of the concrete implementations of this
|
||||
* class to own copy of the frame if needed for time longer than scope of
|
||||
* this callback.
|
||||
* Such implementations should be quick in processing the frames and return
|
||||
* immediately.
|
||||
*/
|
||||
virtual void RenderVideoFrame(const unsigned char* buffer,
|
||||
unsigned int buffer_size,
|
||||
uint32_t time_stamp,
|
||||
int64_t render_time) = 0;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoRenderer)
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generic Interface for representing Audio/Video Session
|
||||
* MediaSession conduit is identified by 2 main components
|
||||
* 1. Attached Transport Interface for inbound and outbound RTP transport
|
||||
* 2. Attached Renderer Interface for rendering media data off the network
|
||||
* This class hides specifics of Media-Engine implementation from the consumers
|
||||
* of this interface.
|
||||
* Also provides codec configuration API for the media sent and recevied
|
||||
*/
|
||||
class MediaSessionConduit
|
||||
{
|
||||
public:
|
||||
enum Type { AUDIO, VIDEO } ;
|
||||
|
||||
virtual ~MediaSessionConduit() {};
|
||||
|
||||
virtual Type type() const = 0;
|
||||
|
||||
/**
|
||||
* Function triggered on Incoming RTP packet from the remote
|
||||
* endpoint by the transport implementation.
|
||||
* @param data : RTP Packet (audio/video) to be processed
|
||||
* @param len : Length of the media packet
|
||||
* Obtained packets are passed to the Media-Engine for further
|
||||
* processing , say, decoding
|
||||
*/
|
||||
virtual MediaConduitErrorCode ReceivedRTPPacket(const void *data, int len) = 0;
|
||||
|
||||
/**
|
||||
* Function triggered on Incoming RTCP packet from the remote
|
||||
* endpoint by the transport implementation.
|
||||
* @param data : RTCP Packet (audio/video) to be processed
|
||||
* @param len : Length of the media packet
|
||||
* Obtained packets are passed to the Media-Engine for further
|
||||
* processing , say, decoding
|
||||
*/
|
||||
virtual MediaConduitErrorCode ReceivedRTCPPacket(const void *data, int len) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Function to attach Transport end-point of the Media conduit.
|
||||
* @param aTransport: Reference to the concrete teansport implementation
|
||||
* Note: Multiple invocations of this call , replaces existing transport with
|
||||
* with the new one.
|
||||
*/
|
||||
virtual MediaConduitErrorCode AttachTransport(RefPtr<TransportInterface> aTransport) = 0;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaSessionConduit)
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* MediaSessionConduit for video
|
||||
* Refer to the comments on MediaSessionConduit above for overall
|
||||
* information
|
||||
*/
|
||||
class VideoSessionConduit : public MediaSessionConduit
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Factory function to create and initialize a Video Conduit Session
|
||||
* return: Concrete VideoSessionConduitObject or NULL in the case
|
||||
* of failure
|
||||
*/
|
||||
static RefPtr<VideoSessionConduit> Create();
|
||||
|
||||
virtual ~VideoSessionConduit() {};
|
||||
|
||||
virtual Type type() const { return VIDEO; }
|
||||
|
||||
/**
|
||||
* Function to attach Renderer end-point of the Media-Video conduit.
|
||||
* @param aRenderer : Reference to the concrete Video renderer implementation
|
||||
* Note: Multiple invocations of this API shall remove an existing renderer
|
||||
* and attaches the new to the Conduit.
|
||||
*/
|
||||
virtual MediaConduitErrorCode AttachRenderer(RefPtr<VideoRenderer> aRenderer) = 0;
|
||||
|
||||
/**
|
||||
* Function to deliver a capture video frame for encoding and transport
|
||||
* @param video_frame: pointer to captured video-frame.
|
||||
* @param video_frame_length: size of the frame
|
||||
* @param width, height: dimensions of the frame
|
||||
* @param video_type: Type of the video frame - I420, RAW
|
||||
* @param captured_time: timestamp when the frame was captured.
|
||||
* if 0 timestamp is automatcally generated
|
||||
* NOTE: ConfigureSendMediaCodec() MUST be called before this function can be invoked
|
||||
* This ensures the inserted video-frames can be transmitted by the conduit
|
||||
*/
|
||||
virtual MediaConduitErrorCode SendVideoFrame(unsigned char* video_frame,
|
||||
unsigned int video_frame_length,
|
||||
unsigned short width,
|
||||
unsigned short height,
|
||||
VideoType video_type,
|
||||
uint64_t capture_time) = 0;
|
||||
|
||||
/**
|
||||
* Function to configure send codec for the video session
|
||||
* @param sendSessionConfig: CodecConfiguration
|
||||
* @result: On Success, the video engine is configured with passed in codec for send
|
||||
* On failure, video engine transmit functionality is disabled.
|
||||
* NOTE: This API can be invoked multiple time. Invoking this API may involve restarting
|
||||
* transmission sub-system on the engine
|
||||
*
|
||||
*/
|
||||
virtual MediaConduitErrorCode ConfigureSendMediaCodec(const VideoCodecConfig* sendSessionConfig) = 0;
|
||||
|
||||
/**
|
||||
* Function to configurelist of receive codecs for the video session
|
||||
* @param sendSessionConfig: CodecConfiguration
|
||||
* NOTE: This API can be invoked multiple time. Invoking this API may involve restarting
|
||||
* reception sub-system on the engine
|
||||
*
|
||||
*/
|
||||
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
||||
const std::vector<VideoCodecConfig* >& recvCodecConfigList) = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* MediaSessionConduit for audio
|
||||
* Refer to the comments on MediaSessionConduit above for overall
|
||||
* information
|
||||
*/
|
||||
class AudioSessionConduit : public MediaSessionConduit
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Factory function to create and initialize a Video Conduit Session
|
||||
* return: Concrete VideoSessionConduitObject or NULL in the case
|
||||
* of failure
|
||||
*/
|
||||
static mozilla::RefPtr<AudioSessionConduit> Create();
|
||||
|
||||
virtual ~AudioSessionConduit() {};
|
||||
|
||||
virtual Type type() const { return AUDIO; }
|
||||
|
||||
|
||||
/**
|
||||
* Function to deliver externally captured audio sample for encoding and transport
|
||||
* @param audioData [in]: Pointer to array containing a frame of audio
|
||||
* @param lengthSamples [in]: Length of audio frame in samples in multiple of 10 milliseconds
|
||||
* Ex: Frame length is 160, 320, 440 for 16, 32, 44 kHz sampling rates
|
||||
respectively.
|
||||
audioData[] is lengthSamples in size
|
||||
say, for 16kz sampling rate, audioData[] should contain 160
|
||||
samples of 16-bits each for a 10m audio frame.
|
||||
* @param samplingFreqHz [in]: Frequency/rate of the sampling in Hz ( 16000, 32000 ...)
|
||||
* @param capture_delay [in]: Approx Delay from recording until it is delivered to VoiceEngine
|
||||
in milliseconds.
|
||||
* NOTE: ConfigureSendMediaCodec() SHOULD be called before this function can be invoked
|
||||
* This ensures the inserted audio-samples can be transmitted by the conduit
|
||||
*
|
||||
*/
|
||||
virtual MediaConduitErrorCode SendAudioFrame(const int16_t audioData[],
|
||||
int32_t lengthSamples,
|
||||
int32_t samplingFreqHz,
|
||||
int32_t capture_delay) = 0;
|
||||
|
||||
/**
|
||||
* Function to grab a decoded audio-sample from the media engine for rendering
|
||||
* / playoutof length 10 milliseconds.
|
||||
*
|
||||
* @param speechData [in]: Pointer to a array to which a 10ms frame of audio will be copied
|
||||
* @param samplingFreqHz [in]: Frequency of the sampling for playback in Hertz (16000, 32000,..)
|
||||
* @param capture_delay [in]: Estimated Time between reading of the samples to rendering/playback
|
||||
* @param lengthSamples [out]: Will contain length of the audio frame in samples at return.
|
||||
Ex: A value of 160 implies 160 samples each of 16-bits was copied
|
||||
into speechData
|
||||
* NOTE: This function should be invoked every 10 milliseconds for the best
|
||||
* peformance
|
||||
* NOTE: ConfigureRecvMediaCodec() SHOULD be called before this function can be invoked
|
||||
* This ensures the decoded samples are ready for reading.
|
||||
*
|
||||
*/
|
||||
virtual MediaConduitErrorCode GetAudioFrame(int16_t speechData[],
|
||||
int32_t samplingFreqHz,
|
||||
int32_t capture_delay,
|
||||
int& lengthSamples) = 0;
|
||||
|
||||
/**
|
||||
* Function to configure send codec for the audio session
|
||||
* @param sendSessionConfig: CodecConfiguration
|
||||
* NOTE: See VideoConduit for more information
|
||||
*/
|
||||
|
||||
virtual MediaConduitErrorCode ConfigureSendMediaCodec(const AudioCodecConfig* sendCodecConfig) = 0;
|
||||
|
||||
/**
|
||||
* Function to configure list of receive codecs for the audio session
|
||||
* @param sendSessionConfig: CodecConfiguration
|
||||
* NOTE: See VideoConduit for more information
|
||||
*/
|
||||
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
||||
const std::vector<AudioCodecConfig* >& recvCodecConfigList) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* 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 MEDIA_ENGINE_WRAPPER_H_
|
||||
#define MEDIA_ENGINE_WRAPPER_H_
|
||||
|
||||
#include <mozilla/Scoped.h>
|
||||
|
||||
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
/**
|
||||
* A Custom scoped template to release a resoure of Type T
|
||||
* with a function of Type F
|
||||
* ScopedCustomReleasePtr<webrtc::VoENetwork> ptr =
|
||||
* webrtc::VoENetwork->GetInterface(voiceEngine);
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
struct ScopedCustomReleaseTraits0 : public ScopedFreePtrTraits<T>
|
||||
{
|
||||
static void release(T* ptr)
|
||||
{
|
||||
if(ptr)
|
||||
{
|
||||
(ptr)->Release();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SCOPED_TEMPLATE(ScopedCustomReleasePtr, ScopedCustomReleaseTraits0)
|
||||
}//namespace
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,719 @@
|
|||
/* 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/. */
|
||||
|
||||
#include "VideoConduit.h"
|
||||
#include "video_engine/include/vie_errors.h"
|
||||
#include "CSFLog.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static const char* logTag ="WebrtcVideoSessionConduit";
|
||||
|
||||
const unsigned int WebrtcVideoConduit::CODEC_PLNAME_SIZE = 32;
|
||||
|
||||
//Factory Implementation
|
||||
mozilla::RefPtr<VideoSessionConduit> VideoSessionConduit::Create()
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
WebrtcVideoConduit* obj = new WebrtcVideoConduit();
|
||||
if(obj->Init() != kMediaConduitNoError)
|
||||
{
|
||||
CSFLogError(logTag, "%s VideoConduit Init Failed ", __FUNCTION__);
|
||||
delete obj;
|
||||
return NULL;
|
||||
}
|
||||
CSFLogDebug(logTag, "%s Successfully created VideoConduit ", __FUNCTION__);
|
||||
return obj;
|
||||
}
|
||||
|
||||
WebrtcVideoConduit::~WebrtcVideoConduit()
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
for(std::vector<VideoCodecConfig*>::size_type i=0;i < mRecvCodecList.size();i++)
|
||||
{
|
||||
delete mRecvCodecList[i];
|
||||
}
|
||||
|
||||
delete mCurSendCodecConfig;
|
||||
|
||||
//Deal with External Capturer
|
||||
if(mPtrViECapture)
|
||||
{
|
||||
mPtrViECapture->DisconnectCaptureDevice(mCapId);
|
||||
mPtrViECapture->ReleaseCaptureDevice(mCapId);
|
||||
mPtrExtCapture = NULL;
|
||||
mPtrViECapture->Release();
|
||||
}
|
||||
|
||||
//Deal with External Renderer
|
||||
if(mPtrViERender)
|
||||
{
|
||||
mPtrViERender->StopRender(mChannel);
|
||||
mPtrViERender->RemoveRenderer(mChannel);
|
||||
mPtrViERender->Release();
|
||||
}
|
||||
|
||||
//Deal with the transport
|
||||
if(mPtrViENetwork)
|
||||
{
|
||||
mPtrViENetwork->DeregisterSendTransport(mChannel);
|
||||
mPtrViENetwork->Release();
|
||||
}
|
||||
|
||||
if(mPtrViECodec)
|
||||
{
|
||||
mPtrViECodec->Release();
|
||||
}
|
||||
|
||||
if(mPtrViEBase)
|
||||
{
|
||||
mPtrViEBase->StopSend(mChannel);
|
||||
mPtrViEBase->StopReceive(mChannel);
|
||||
mPtrViEBase->DeleteChannel(mChannel);
|
||||
mPtrViEBase->Release();
|
||||
}
|
||||
|
||||
if(mVideoEngine)
|
||||
{
|
||||
webrtc::VideoEngine::Delete(mVideoEngine);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Peforms intialization of the MANDATORY components of the Video Engine
|
||||
*/
|
||||
MediaConduitErrorCode WebrtcVideoConduit::Init()
|
||||
{
|
||||
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
if( !(mVideoEngine = webrtc::VideoEngine::Create()) )
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to create video engine ", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// TRACING
|
||||
mVideoEngine->SetTraceFilter(webrtc::kTraceAll);
|
||||
mVideoEngine->SetTraceFile( "Vievideotrace.out" );
|
||||
#endif
|
||||
|
||||
if( !(mPtrViEBase = ViEBase::GetInterface(mVideoEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to create video engine ", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if( !(mPtrViECapture = ViECapture::GetInterface(mVideoEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to create video engine ", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if( !(mPtrViECodec = ViECodec::GetInterface(mVideoEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to create video engine ", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if( !(mPtrViENetwork = ViENetwork::GetInterface(mVideoEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to create video engine ", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if( !(mPtrViERender = ViERender::GetInterface(mVideoEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to create video engine ", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
|
||||
CSFLogDebug(logTag, "%sEngine Created: Init'ng the interfaces ",__FUNCTION__);
|
||||
|
||||
if(mPtrViEBase->Init() == -1)
|
||||
{
|
||||
CSFLogError(logTag, " %s Video Engine Init Failed %d ",__FUNCTION__,
|
||||
mPtrViEBase->LastError());
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
|
||||
if(mPtrViEBase->CreateChannel(mChannel) == -1)
|
||||
{
|
||||
CSFLogError(logTag, " %s Channel creation Failed %d ",__FUNCTION__,
|
||||
mPtrViEBase->LastError());
|
||||
return kMediaConduitChannelError;
|
||||
}
|
||||
|
||||
if(mPtrViENetwork->RegisterSendTransport(mChannel, *this) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s ViENetwork Failed %d ", __FUNCTION__,
|
||||
mPtrViEBase->LastError());
|
||||
return kMediaConduitTransportRegistrationFail;
|
||||
}
|
||||
|
||||
|
||||
mPtrExtCapture = 0;
|
||||
|
||||
if(mPtrViECapture->AllocateExternalCaptureDevice(mCapId,
|
||||
mPtrExtCapture) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to Allocate capture module: %d ",
|
||||
__FUNCTION__, mPtrViEBase->LastError());
|
||||
return kMediaConduitCaptureError;
|
||||
}
|
||||
|
||||
if(mPtrViECapture->ConnectCaptureDevice(mCapId,mChannel) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to Connect capture module: %d ",
|
||||
__FUNCTION__,mPtrViEBase->LastError());
|
||||
return kMediaConduitCaptureError;
|
||||
}
|
||||
|
||||
if(mPtrViERender->AddRenderer(mChannel,
|
||||
webrtc::kVideoI420,
|
||||
(webrtc::ExternalRenderer*) this) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s Failed to added external renderer ", __FUNCTION__);
|
||||
return kMediaConduitInvalidRenderer;
|
||||
}
|
||||
|
||||
|
||||
CSFLogError(logTag, "Initialization Done");
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcVideoConduit::AttachRenderer(mozilla::RefPtr<VideoRenderer> aVideoRenderer)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
//null renderer
|
||||
if(!aVideoRenderer)
|
||||
{
|
||||
CSFLogError(logTag, "%s NULL Renderer", __FUNCTION__);
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
return kMediaConduitInvalidRenderer;
|
||||
}
|
||||
//Assign the new renderer - overwrites if there is already one
|
||||
mRenderer = aVideoRenderer;
|
||||
|
||||
//Start Rendering if we haven't already
|
||||
if(!mEngineRendererStarted)
|
||||
{
|
||||
if(mPtrViERender->StartRender(mChannel) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s Starting the Renderer Failed %d ", __FUNCTION__,
|
||||
mPtrViEBase->LastError());
|
||||
mRenderer = NULL;
|
||||
return kMediaConduitRendererFail;
|
||||
}
|
||||
mEngineRendererStarted = true;
|
||||
}
|
||||
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcVideoConduit::AttachTransport(mozilla::RefPtr<TransportInterface> aTransport)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
if(!aTransport)
|
||||
{
|
||||
CSFLogError(logTag, "%s NULL Transport ", __FUNCTION__);
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
return kMediaConduitInvalidTransport;
|
||||
}
|
||||
//Assign the transport
|
||||
mTransport = aTransport;
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: Setting the send-codec on the Video Engine will restart the encoder,
|
||||
* sets up new SSRC and reset RTP_RTCP module with the new codec setting.
|
||||
*/
|
||||
MediaConduitErrorCode
|
||||
WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
bool codecFound = false;
|
||||
MediaConduitErrorCode condError = kMediaConduitNoError;
|
||||
int error = 0; //webrtc engine errors
|
||||
webrtc::VideoCodec video_codec;
|
||||
std::string payloadName;
|
||||
|
||||
//validate basic params
|
||||
if((condError = ValidateCodecConfig(codecConfig,true)) != kMediaConduitNoError)
|
||||
{
|
||||
return condError;
|
||||
}
|
||||
|
||||
//Check if we have same codec already applied
|
||||
if(CheckCodecsForMatch(mCurSendCodecConfig, codecConfig))
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Codec has been applied already ", __FUNCTION__);
|
||||
return kMediaConduitCodecInUse;
|
||||
}
|
||||
|
||||
//transmitting already ?
|
||||
if(mEngineTransmitting)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Engine Already Sending. Attemping to Stop ", __FUNCTION__);
|
||||
if(mPtrViEBase->StopSend(mChannel) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s StopSend() Failed %d ",__FUNCTION__,
|
||||
mPtrViEBase->LastError());
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
}
|
||||
|
||||
//reset the flag
|
||||
mEngineTransmitting = false;
|
||||
|
||||
// we should be good here to set the new codec.
|
||||
for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++)
|
||||
{
|
||||
if(0 == mPtrViECodec->GetCodec(idx, video_codec))
|
||||
{
|
||||
payloadName = video_codec.plName;
|
||||
if(codecConfig->mName.compare(payloadName) == 0)
|
||||
{
|
||||
CodecConfigToWebRTCCodec(codecConfig, video_codec);
|
||||
codecFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}//for
|
||||
|
||||
if(codecFound == false)
|
||||
{
|
||||
CSFLogError(logTag, "%s Codec Mismatch ", __FUNCTION__);
|
||||
return kMediaConduitInvalidSendCodec;
|
||||
}
|
||||
|
||||
if(mPtrViECodec->SetSendCodec(mChannel, video_codec) == -1)
|
||||
{
|
||||
error = mPtrViEBase->LastError();
|
||||
if(error == kViECodecInvalidCodec)
|
||||
{
|
||||
CSFLogError(logTag, "%s Invalid Send Codec", __FUNCTION__);
|
||||
return kMediaConduitInvalidSendCodec;
|
||||
}
|
||||
CSFLogError(logTag, "%s SetSendCodec Failed %d ", __FUNCTION__,
|
||||
mPtrViEBase->LastError());
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
if(mPtrViEBase->StartSend(mChannel) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s Start Send Error %d ", __FUNCTION__,
|
||||
mPtrViEBase->LastError());
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
//Copy the applied codec for future reference
|
||||
delete mCurSendCodecConfig;
|
||||
|
||||
mCurSendCodecConfig = new VideoCodecConfig(codecConfig->mType,
|
||||
codecConfig->mName,
|
||||
codecConfig->mWidth,
|
||||
codecConfig->mHeight);
|
||||
|
||||
// by now we should be successfully started the transmission
|
||||
mEngineTransmitting = true;
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcVideoConduit::ConfigureRecvMediaCodecs(
|
||||
const std::vector<VideoCodecConfig* >& codecConfigList)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
MediaConduitErrorCode condError = kMediaConduitNoError;
|
||||
int error = 0; //webrtc engine errors
|
||||
bool success = false;
|
||||
std::string payloadName;
|
||||
|
||||
if(mEngineReceiving)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Engine Already Receiving . Attemping to Stop ", __FUNCTION__);
|
||||
if(mPtrViEBase->StopReceive(mChannel) == -1)
|
||||
{
|
||||
error = mPtrViEBase->LastError();
|
||||
if(error == kViEBaseUnknownError)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s StopReceive() Success ", __FUNCTION__);
|
||||
mEngineReceiving = false;
|
||||
} else {
|
||||
CSFLogError(logTag, "%s StopReceive() Failed %d ", __FUNCTION__,
|
||||
mPtrViEBase->LastError());
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(codecConfigList.empty())
|
||||
{
|
||||
CSFLogError(logTag, "%s Zero number of codecs to configure", __FUNCTION__);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
//Try Applying the codecs in the list
|
||||
// we treat as success if atleast one codec was applied and reception was
|
||||
// started successfully.
|
||||
for(std::vector<VideoCodecConfig*>::size_type i=0;i < codecConfigList.size();i++)
|
||||
{
|
||||
//if the codec param is invalid or diplicate, return error
|
||||
if((condError = ValidateCodecConfig(codecConfigList[i],false)) != kMediaConduitNoError)
|
||||
{
|
||||
return condError;
|
||||
}
|
||||
|
||||
webrtc::VideoCodec video_codec;
|
||||
mEngineReceiving = false;
|
||||
memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
|
||||
//Retrieve pre-populated codec structure for our codec.
|
||||
for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++)
|
||||
{
|
||||
if(mPtrViECodec->GetCodec(idx, video_codec) == 0)
|
||||
{
|
||||
payloadName = video_codec.plName;
|
||||
if(codecConfigList[i]->mName.compare(payloadName) == 0)
|
||||
{
|
||||
CodecConfigToWebRTCCodec(codecConfigList[i], video_codec);
|
||||
if(mPtrViECodec->SetReceiveCodec(mChannel,video_codec) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s Invalid Receive Codec %d ", __FUNCTION__,
|
||||
mPtrViEBase->LastError());
|
||||
} else {
|
||||
CSFLogError(logTag, "%s Successfully Set the codec %s", __FUNCTION__,
|
||||
codecConfigList[i]->mName.c_str());
|
||||
if(CopyCodecToDB(codecConfigList[i]))
|
||||
{
|
||||
success = true;
|
||||
} else {
|
||||
CSFLogError(logTag,"%s Unable to updated Codec Database", __FUNCTION__);
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
}
|
||||
break; //we found a match
|
||||
}
|
||||
}
|
||||
}//end for codeclist
|
||||
|
||||
}//end for
|
||||
|
||||
if(!success)
|
||||
{
|
||||
CSFLogError(logTag, "%s Setting Receive Codec Failed ", __FUNCTION__);
|
||||
return kMediaConduitInvalidReceiveCodec;
|
||||
}
|
||||
|
||||
//Start Receive on the video engine
|
||||
if(mPtrViEBase->StartReceive(mChannel) == -1)
|
||||
{
|
||||
error = mPtrViEBase->LastError();
|
||||
CSFLogError(logTag, "%s Start Receive Error %d ", __FUNCTION__, error);
|
||||
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
// by now we should be successfully started the reception
|
||||
mEngineReceiving = true;
|
||||
DumpCodecDB();
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcVideoConduit::SendVideoFrame(unsigned char* video_frame,
|
||||
unsigned int video_frame_length,
|
||||
unsigned short width,
|
||||
unsigned short height,
|
||||
VideoType video_type,
|
||||
uint64_t capture_time)
|
||||
{
|
||||
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
//check for the parameters sanity
|
||||
if(!video_frame || video_frame_length == 0 ||
|
||||
width == 0 || height == 0)
|
||||
{
|
||||
CSFLogError(logTag, "%s Invalid Parameters ",__FUNCTION__);
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
if(video_type != kVideoI420)
|
||||
{
|
||||
CSFLogError(logTag, "%s VideoType Invalid. Only 1420 Supported",__FUNCTION__);
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
//Transmission should be enabled before we insert any frames.
|
||||
if(!mEngineTransmitting)
|
||||
{
|
||||
CSFLogError(logTag, "%s Engine not transmitting ", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
//insert the frame to video engine in I420 format only
|
||||
if(mPtrExtCapture->IncomingFrame(video_frame,
|
||||
video_frame_length,
|
||||
width, height,
|
||||
webrtc::kVideoI420,
|
||||
(unsigned long long)capture_time) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s IncomingFrame Failed %d ", __FUNCTION__,
|
||||
mPtrViEBase->LastError());
|
||||
return kMediaConduitCaptureError;
|
||||
}
|
||||
|
||||
CSFLogError(logTag, "%s Inserted A Frame", __FUNCTION__);
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
// Transport Layer Callbacks
|
||||
MediaConduitErrorCode
|
||||
WebrtcVideoConduit::ReceivedRTPPacket(const void *data, int len)
|
||||
{
|
||||
CSFLogError(logTag, "%s: Channel %d, Len %d ", __FUNCTION__, mChannel, len);
|
||||
|
||||
// Media Engine should be receiving already.
|
||||
if(mEngineReceiving)
|
||||
{
|
||||
// let the engine know of a RTP packet to decode
|
||||
if(mPtrViENetwork->ReceivedRTPPacket(mChannel,data,len) == -1)
|
||||
{
|
||||
int error = mPtrViEBase->LastError();
|
||||
CSFLogError(logTag, "%s RTP Processing Failed %d ", __FUNCTION__, error);
|
||||
if(error >= kViERtpRtcpInvalidChannelId && error <= kViERtpRtcpRtcpDisabled)
|
||||
{
|
||||
return kMediaConduitRTPProcessingFailed;
|
||||
}
|
||||
return kMediaConduitRTPRTCPModuleError;
|
||||
}
|
||||
} else {
|
||||
CSFLogError(logTag, "%s Engine Error: Not Receiving !!! ", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcVideoConduit::ReceivedRTCPPacket(const void *data, int len)
|
||||
{
|
||||
CSFLogError(logTag, " %s Channel %d, Len %d ", __FUNCTION__, mChannel, len);
|
||||
|
||||
//Media Engine should be receiving already
|
||||
if(mEngineReceiving)
|
||||
{
|
||||
//let the engine know of RTCP packet to decode.
|
||||
if(mPtrViENetwork->ReceivedRTCPPacket(mChannel,data,len) == -1)
|
||||
{
|
||||
int error = mPtrViEBase->LastError();
|
||||
CSFLogError(logTag, "%s RTP Processing Failed %d", __FUNCTION__, error);
|
||||
if(error >= kViERtpRtcpInvalidChannelId && error <= kViERtpRtcpRtcpDisabled)
|
||||
{
|
||||
return kMediaConduitRTPProcessingFailed;
|
||||
}
|
||||
return kMediaConduitRTPRTCPModuleError;
|
||||
}
|
||||
} else {
|
||||
CSFLogError(logTag, "%s: Engine Error: Not Receiving", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
//WebRTC::RTP Callback Implementation
|
||||
int WebrtcVideoConduit::SendPacket(int channel, const void* data, int len)
|
||||
{
|
||||
CSFLogError(logTag, "%s Channel %d, len %d ", __FUNCTION__, channel, len);
|
||||
|
||||
if(mTransport && (mTransport->SendRtpPacket(data, len) == NS_OK))
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Sent RTP Packet ", __FUNCTION__);
|
||||
return 0;
|
||||
} else {
|
||||
CSFLogError(logTag, "%s Failed", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int WebrtcVideoConduit::SendRTCPPacket(int channel, const void* data, int len)
|
||||
{
|
||||
CSFLogError(logTag, "%s : channel %d , len %d ", __FUNCTION__, channel,len);
|
||||
|
||||
if(mTransport && (mTransport->SendRtcpPacket(data, len) == NS_OK))
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Sent RTCP Packet ", __FUNCTION__);
|
||||
return 0;
|
||||
} else {
|
||||
CSFLogError(logTag, "%s Failed", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// WebRTC::ExternalMedia Implementation
|
||||
int
|
||||
WebrtcVideoConduit::FrameSizeChange(unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int numStreams)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
if(mRenderer)
|
||||
{
|
||||
mRenderer->FrameSizeChange(width, height, numStreams);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CSFLogError(logTag, "%s Renderer is NULL ", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
WebrtcVideoConduit::DeliverFrame(unsigned char* buffer,
|
||||
int buffer_size,
|
||||
uint32_t time_stamp,
|
||||
int64_t render_time)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Buffer Size %d", __FUNCTION__, buffer_size);
|
||||
|
||||
if(mRenderer)
|
||||
{
|
||||
mRenderer->RenderVideoFrame(buffer, buffer_size, time_stamp, render_time);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CSFLogError(logTag, "%s Renderer is NULL ", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the codec passed into Conduit's database
|
||||
*/
|
||||
|
||||
void
|
||||
WebrtcVideoConduit::CodecConfigToWebRTCCodec(const VideoCodecConfig* codecInfo,
|
||||
webrtc::VideoCodec& cinst)
|
||||
{
|
||||
cinst.plType = codecInfo->mType;
|
||||
cinst.width = codecInfo->mWidth;
|
||||
cinst.height = codecInfo->mHeight;
|
||||
}
|
||||
|
||||
bool
|
||||
WebrtcVideoConduit::CopyCodecToDB(const VideoCodecConfig* codecInfo)
|
||||
{
|
||||
VideoCodecConfig* cdcConfig = new VideoCodecConfig(codecInfo->mType,
|
||||
codecInfo->mName,
|
||||
codecInfo->mWidth,
|
||||
codecInfo->mHeight);
|
||||
mRecvCodecList.push_back(cdcConfig);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the codec is already in Conduit's database
|
||||
*/
|
||||
|
||||
bool
|
||||
WebrtcVideoConduit::CheckCodecForMatch(const VideoCodecConfig* codecInfo) const
|
||||
{
|
||||
//the db should have atleast one codec
|
||||
for(std::vector<VideoCodecConfig*>::size_type i=0;i < mRecvCodecList.size();i++)
|
||||
{
|
||||
if(CheckCodecsForMatch(mRecvCodecList[i],codecInfo))
|
||||
{
|
||||
//match
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//no match
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
WebrtcVideoConduit::CheckCodecsForMatch(const VideoCodecConfig* curCodecConfig,
|
||||
const VideoCodecConfig* codecInfo) const
|
||||
{
|
||||
if(!curCodecConfig)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(curCodecConfig->mType == codecInfo->mType &&
|
||||
(curCodecConfig->mName.compare(codecInfo->mName) == 0) &&
|
||||
curCodecConfig->mWidth == codecInfo->mWidth &&
|
||||
curCodecConfig->mHeight == codecInfo->mHeight)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform validation on the codecConfig to be applied
|
||||
* Verifies if the codec is already applied.
|
||||
*/
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcVideoConduit::ValidateCodecConfig(const VideoCodecConfig* codecInfo,
|
||||
bool send) const
|
||||
{
|
||||
bool codecAppliedAlready = false;
|
||||
if(!codecInfo)
|
||||
{
|
||||
CSFLogError(logTag, "%s Null CodecConfig ", __FUNCTION__);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
if((codecInfo->mName.empty()) ||
|
||||
(codecInfo->mName.length() >= CODEC_PLNAME_SIZE))
|
||||
{
|
||||
CSFLogError(logTag, "%s Invalid Payload Name Length ", __FUNCTION__);
|
||||
return kMediaConduitMalformedArgument;
|
||||
}
|
||||
|
||||
//check if we have the same codec already applied
|
||||
if(send)
|
||||
{
|
||||
codecAppliedAlready = CheckCodecsForMatch(mCurSendCodecConfig,codecInfo);
|
||||
} else {
|
||||
codecAppliedAlready = CheckCodecForMatch(codecInfo);
|
||||
}
|
||||
|
||||
if(codecAppliedAlready)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Codec %s Already Applied ", __FUNCTION__, codecInfo->mName.c_str());
|
||||
return kMediaConduitCodecInUse;
|
||||
}
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
void
|
||||
WebrtcVideoConduit::DumpCodecDB() const
|
||||
{
|
||||
for(std::vector<VideoCodecConfig*>::size_type i=0;i<mRecvCodecList.size();i++)
|
||||
{
|
||||
CSFLogDebug(logTag,"Payload Name: %s", mRecvCodecList[i]->mName.c_str());
|
||||
CSFLogDebug(logTag,"Payload Type: %d", mRecvCodecList[i]->mType);
|
||||
CSFLogDebug(logTag,"Payload Width: %d", mRecvCodecList[i]->mWidth);
|
||||
CSFLogDebug(logTag,"Payload Height: %d", mRecvCodecList[i]->mHeight);
|
||||
}
|
||||
}
|
||||
|
||||
}// end namespace
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
/* 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 VIDEO_SESSION_H_
|
||||
#define VIDEO_SESSION_H_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "MediaConduitInterface.h"
|
||||
|
||||
// Video Engine Includes
|
||||
#include "common_types.h"
|
||||
#include "video_engine/include/vie_base.h"
|
||||
#include "video_engine/include/vie_capture.h"
|
||||
#include "video_engine/include/vie_codec.h"
|
||||
#include "video_engine/include/vie_render.h"
|
||||
#include "video_engine/include/vie_network.h"
|
||||
#include "video_engine/include/vie_file.h"
|
||||
|
||||
/** This file hosts several structures identifying different aspects
|
||||
* of a RTP Session.
|
||||
*/
|
||||
|
||||
using webrtc::ViEBase;
|
||||
using webrtc::ViENetwork;
|
||||
using webrtc::ViECodec;
|
||||
using webrtc::ViECapture;
|
||||
using webrtc::ViERender;
|
||||
using webrtc::ViEExternalCapture;
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Concrete class for Video session. Hooks up
|
||||
* - media-source and target to external transport
|
||||
*/
|
||||
class WebrtcVideoConduit:public VideoSessionConduit
|
||||
,public webrtc::Transport
|
||||
,public webrtc::ExternalRenderer
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//VoiceEngine defined constant for Payload Name Size.
|
||||
static const unsigned int CODEC_PLNAME_SIZE;
|
||||
|
||||
/**
|
||||
* Function to attach Renderer end-point for the Media-Video conduit.
|
||||
* @param aRenderer : Reference to the concrete Video renderer implementation
|
||||
* Note: Multiple invocations of this API shall remove an existing renderer
|
||||
* and attaches the new to the Conduit.
|
||||
*/
|
||||
MediaConduitErrorCode AttachRenderer(mozilla::RefPtr<VideoRenderer> aVideoRenderer);
|
||||
|
||||
/**
|
||||
* APIs used by the registered external transport to this Conduit to
|
||||
* feed in received RTP Frames to the VideoEngine for decoding
|
||||
*/
|
||||
virtual MediaConduitErrorCode ReceivedRTPPacket(const void *data, int len);
|
||||
|
||||
/**
|
||||
* APIs used by the registered external transport to this Conduit to
|
||||
* feed in received RTP Frames to the VideoEngine for decoding
|
||||
*/
|
||||
virtual MediaConduitErrorCode ReceivedRTCPPacket(const void *data, int len);
|
||||
|
||||
/**
|
||||
* Function to configure send codec for the video session
|
||||
* @param sendSessionConfig: CodecConfiguration
|
||||
* @result: On Success, the video engine is configured with passed in codec for send
|
||||
* On failure, video engine transmit functionality is disabled.
|
||||
* NOTE: This API can be invoked multiple time. Invoking this API may involve restarting
|
||||
* transmission sub-system on the engine.
|
||||
*/
|
||||
virtual MediaConduitErrorCode ConfigureSendMediaCodec(const VideoCodecConfig* codecInfo);
|
||||
|
||||
/**
|
||||
* Function to configure list of receive codecs for the video session
|
||||
* @param sendSessionConfig: CodecConfiguration
|
||||
* @result: On Success, the video engine is configured with passed in codec for send
|
||||
* Also the playout is enabled.
|
||||
* On failure, video engine transmit functionality is disabled.
|
||||
* NOTE: This API can be invoked multiple time. Invoking this API may involve restarting
|
||||
* transmission sub-system on the engine.
|
||||
*/
|
||||
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
||||
const std::vector<VideoCodecConfig* >& codecConfigList);
|
||||
|
||||
/**
|
||||
* Register External Transport to this Conduit. RTP and RTCP frames from the VoiceEnigne
|
||||
* shall be passed to the registered transport for transporting externally.
|
||||
*/
|
||||
virtual MediaConduitErrorCode AttachTransport(mozilla::RefPtr<TransportInterface> aTransport);
|
||||
|
||||
/**
|
||||
* Function to deliver a capture video frame for encoding and transport
|
||||
* @param video_frame: pointer to captured video-frame.
|
||||
* @param video_frame_length: size of the frame
|
||||
* @param width, height: dimensions of the frame
|
||||
* @param video_type: Type of the video frame - I420, RAW
|
||||
* @param captured_time: timestamp when the frame was captured.
|
||||
* if 0 timestamp is automatcally generated by the engine.
|
||||
*NOTE: ConfigureSendMediaCodec() SHOULD be called before this function can be invoked
|
||||
* This ensures the inserted video-frames can be transmitted by the conduit
|
||||
*/
|
||||
virtual MediaConduitErrorCode SendVideoFrame(unsigned char* video_frame,
|
||||
unsigned int video_frame_length,
|
||||
unsigned short width,
|
||||
unsigned short height,
|
||||
VideoType video_type,
|
||||
uint64_t capture_time);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Webrtc transport implementation to send and receive RTP packet.
|
||||
* AudioConduit registers itself as ExternalTransport to the VideoEngine
|
||||
*/
|
||||
virtual int SendPacket(int channel, const void *data, int len) ;
|
||||
|
||||
/**
|
||||
* Webrtc transport implementation to send and receive RTCP packet.
|
||||
* AudioConduit registers itself as ExternalTransport to the VideoEngine
|
||||
*/
|
||||
virtual int SendRTCPPacket(int channel, const void *data, int len) ;
|
||||
|
||||
|
||||
/**
|
||||
* Webrtc External Renderer Implementation APIs.
|
||||
* Raw I420 Frames are delivred to the VideoConduit by the VideoEngine
|
||||
*/
|
||||
virtual int FrameSizeChange(unsigned int, unsigned int, unsigned int);
|
||||
|
||||
virtual int DeliverFrame(unsigned char*,int, uint32_t , int64_t);
|
||||
|
||||
|
||||
WebrtcVideoConduit():
|
||||
mVideoEngine(NULL),
|
||||
mTransport(NULL),
|
||||
mRenderer(NULL),
|
||||
mEngineTransmitting(false),
|
||||
mEngineReceiving(false),
|
||||
mEngineRendererStarted(false),
|
||||
mChannel(-1),
|
||||
mCapId(-1),
|
||||
mCurSendCodecConfig(NULL)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual ~WebrtcVideoConduit() ;
|
||||
|
||||
|
||||
|
||||
MediaConduitErrorCode Init();
|
||||
|
||||
private:
|
||||
|
||||
WebrtcVideoConduit(const WebrtcVideoConduit& other) MOZ_DELETE;
|
||||
void operator=(const WebrtcVideoConduit& other) MOZ_DELETE;
|
||||
|
||||
//Local database of currently applied receive codecs
|
||||
typedef std::vector<VideoCodecConfig* > RecvCodecList;
|
||||
|
||||
//Function to convert between WebRTC and Conduit codec structures
|
||||
void CodecConfigToWebRTCCodec(const VideoCodecConfig* codecInfo,
|
||||
webrtc::VideoCodec& cinst);
|
||||
|
||||
// Function to copy a codec structure to Conduit's database
|
||||
bool CopyCodecToDB(const VideoCodecConfig* codecInfo);
|
||||
|
||||
// Functions to verify if the codec passed is already in
|
||||
// conduits database
|
||||
bool CheckCodecForMatch(const VideoCodecConfig* codecInfo) const;
|
||||
bool CheckCodecsForMatch(const VideoCodecConfig* curCodecConfig,
|
||||
const VideoCodecConfig* codecInfo) const;
|
||||
|
||||
//Checks the codec to be applied
|
||||
MediaConduitErrorCode ValidateCodecConfig(const VideoCodecConfig* codecInfo, bool send) const;
|
||||
|
||||
//Utility function to dump recv codec database
|
||||
void DumpCodecDB() const;
|
||||
|
||||
webrtc::VideoEngine* mVideoEngine;
|
||||
|
||||
mozilla::RefPtr<TransportInterface> mTransport;
|
||||
mozilla::RefPtr<VideoRenderer> mRenderer;
|
||||
|
||||
webrtc::ViEBase* mPtrViEBase;
|
||||
webrtc::ViECapture* mPtrViECapture;
|
||||
webrtc::ViECodec* mPtrViECodec;
|
||||
webrtc::ViENetwork* mPtrViENetwork;
|
||||
webrtc::ViERender* mPtrViERender;
|
||||
webrtc::ViEExternalCapture* mPtrExtCapture;
|
||||
|
||||
// Engine state we are concerned with.
|
||||
bool mEngineTransmitting; //If true ==> Transmit Sub-system is up and running
|
||||
bool mEngineReceiving; // if true ==> Receive Sus-sysmtem up and running
|
||||
bool mEngineRendererStarted; // If true ==> Rendering Sub-system is up and running
|
||||
|
||||
int mChannel; // Video Channel for this conduit
|
||||
int mCapId; // Capturer for this conduit
|
||||
RecvCodecList mRecvCodecList;
|
||||
VideoCodecConfig* mCurSendCodecConfig;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,47 @@
|
|||
/* 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/. */
|
||||
|
||||
// These constants are picked from WebRTC Implementation. Copyright from the same is
|
||||
// given below
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef VIDEO_TYPE_
|
||||
#define VIDEO_TYPE_
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
/*
|
||||
* Enumeration for different video types supported by the
|
||||
* video-engine. If more types will be supported in the future
|
||||
* newer one shall be appended to the bottom of the list
|
||||
*/
|
||||
enum VideoType
|
||||
{
|
||||
kVideoI420 = 0,
|
||||
kVideoYV12 = 1,
|
||||
kVideoYUY2 = 2,
|
||||
kVideoUYVY = 3,
|
||||
kVideoIYUV = 4,
|
||||
kVideoARGB = 5,
|
||||
kVideoRGB24 = 6,
|
||||
kVideoRGB565 = 7,
|
||||
kVideoARGB4444 = 8,
|
||||
kVideoARGB1555 = 9,
|
||||
kVideoMJPEG = 10,
|
||||
kVideoNV12 = 11,
|
||||
kVideoNV21 = 12,
|
||||
kVideoBGRA = 13,
|
||||
kVideoUnknown = 99
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -116,7 +116,8 @@ typedef enum
|
|||
AudioPayloadType_RFC2833 = 38,
|
||||
AudioPayloadType_ILBC20 = 39,
|
||||
AudioPayloadType_ILBC30 = 40,
|
||||
AudioPayloadType_ISAC = 41
|
||||
AudioPayloadType_ISAC = 41,
|
||||
AudioPayloadType_OPUS = 109
|
||||
|
||||
} AudioPayloadType;
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -65,7 +65,7 @@ namespace CSF
|
|||
class VcmSIPCCBinding
|
||||
{
|
||||
public:
|
||||
VcmSIPCCBinding (MediaProvider *mp);
|
||||
VcmSIPCCBinding ();
|
||||
virtual ~VcmSIPCCBinding();
|
||||
|
||||
|
||||
|
@ -81,11 +81,19 @@ namespace CSF
|
|||
|
||||
void setMediaProviderObserver(MediaProviderObserver* obs);
|
||||
static MediaProviderObserver * getMediaProviderObserver();
|
||||
|
||||
static void setAudioCodecs(int codecMask);
|
||||
static void setVideoCodecs(int codecMask);
|
||||
|
||||
static int getAudioCodecs();
|
||||
static int getVideoCodecs();
|
||||
|
||||
private:
|
||||
static VcmSIPCCBinding * _pSelf;
|
||||
MediaProvider * pMediaProvider;
|
||||
StreamObserver* streamObserver;
|
||||
MediaProviderObserver *mediaProviderObserver;
|
||||
static int mAudioCodecMask;
|
||||
static int mVideoCodecMask;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,10 @@ extern "C" {
|
|||
#define cip_mmgr_MediaDefinitions_MEDIA_TYPE_ILBC30 40L
|
||||
#undef cip_mmgr_MediaDefinitions_MEDIA_TYPE_ISAC
|
||||
#define cip_mmgr_MediaDefinitions_MEDIA_TYPE_ISAC 41L
|
||||
#undef cip_mmgr_MediaDefinitions_MEDIA_TYPE_VP8
|
||||
#define cip_mmgr_MediaDefinitions_MEDIA_TYPE_VP8 42L
|
||||
#undef cip_mmgr_MediaDefinitions_MEDIA_TYPE_OPUS
|
||||
#define cip_mmgr_MediaDefinitions_MEDIA_TYPE_OPUS 109L
|
||||
|
||||
|
||||
#undef cip_mmgr_MediaDefinitions_BANDWIDTH_NARROWBAND
|
||||
|
|
|
@ -1,393 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include "CC_Common.h"
|
||||
#include "WebrtcLogging.h"
|
||||
|
||||
#include "WebrtcAudioCodecSelector.h"
|
||||
#include "voe_codec.h"
|
||||
#include "csf_common.h"
|
||||
|
||||
static const char* logTag = "AudioCodecSelector";
|
||||
|
||||
using namespace std;
|
||||
using namespace CSF;
|
||||
|
||||
typedef struct _CSFCodecMapping
|
||||
{
|
||||
AudioPayloadType csfAudioPayloadType;
|
||||
WebrtcAudioPayloadType webrtcAudioPayloadType;
|
||||
} CSFCodecMapping;
|
||||
|
||||
static CSFCodecMapping WebrtcMappingInfo[] =
|
||||
{
|
||||
{ AudioPayloadType_G711ALAW64K, WebrtcAudioPayloadType_PCMA },
|
||||
{ AudioPayloadType_G711ALAW56K, WebrtcAudioPayloadType_PCMA },
|
||||
{ AudioPayloadType_G711ULAW64K, WebrtcAudioPayloadType_PCMU },
|
||||
{ AudioPayloadType_G711ULAW56K, WebrtcAudioPayloadType_PCMU },
|
||||
{ AudioPayloadType_G722_56K, WebrtcAudioPayloadType_G722 },
|
||||
{ AudioPayloadType_G722_64K, WebrtcAudioPayloadType_G722 },
|
||||
{ AudioPayloadType_G722_48K, WebrtcAudioPayloadType_G722 },
|
||||
{ AudioPayloadType_RFC2833, WebrtcAudioPayloadType_TELEPHONE_EVENT }
|
||||
};
|
||||
|
||||
WebrtcAudioCodecSelector::WebrtcAudioCodecSelector()
|
||||
: voeCodec(NULL)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::constructor" );
|
||||
}
|
||||
|
||||
WebrtcAudioCodecSelector::~WebrtcAudioCodecSelector()
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::destructor" );
|
||||
release();
|
||||
}
|
||||
|
||||
void WebrtcAudioCodecSelector::release()
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::release" );
|
||||
|
||||
// release the VoE Codec sub-interface
|
||||
if (voeCodec != NULL)
|
||||
{
|
||||
if (voeCodec->Release() != 0)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::release voeCodec->Release() failed" );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::release voeCodec released" );
|
||||
}
|
||||
|
||||
voeCodec = NULL;
|
||||
|
||||
std::map<int, webrtc::CodecInst*>::iterator iterVoeCodecs;
|
||||
for( iterVoeCodecs = codecMap.begin(); iterVoeCodecs != codecMap.end(); ++iterVoeCodecs ) {
|
||||
delete iterVoeCodecs->second;
|
||||
}
|
||||
|
||||
codecMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
int WebrtcAudioCodecSelector::init( webrtc::VoiceEngine* voeVoice, bool useLowBandwidthCodecOnly, bool advertiseG722Codec )
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::init useLowBandwidthCodecOnly=%d, advertiseG722Codec=%d", useLowBandwidthCodecOnly, advertiseG722Codec );
|
||||
|
||||
voeCodec = webrtc::VoECodec::GetInterface( voeVoice );
|
||||
|
||||
if (voeCodec == NULL)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::init cannot get reference to VOE codec interface" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// clear the existing codec map
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::init clearing map" );
|
||||
codecMap.clear();
|
||||
|
||||
// get the number of codecs supported by VOE
|
||||
int numOfSupportedCodecs = voeCodec->NumOfCodecs();
|
||||
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::init found %d supported codec(s)", numOfSupportedCodecs );
|
||||
|
||||
// iterate over supported codecs
|
||||
for (int codecIndex = 0; codecIndex < numOfSupportedCodecs; codecIndex++)
|
||||
{
|
||||
webrtc::CodecInst supportedCodec;
|
||||
|
||||
if (voeCodec->GetCodec(codecIndex, supportedCodec) == -1)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::init codecIndex=%d: cannot get supported codec information", codecIndex );
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::init codecIndex=%d: channels=%d, pacsize=%d, plfreq=%d, plname=%s, pltype=%d, rate=%d",
|
||||
codecIndex, supportedCodec.channels, supportedCodec.pacsize, supportedCodec.plfreq,
|
||||
supportedCodec.plname, supportedCodec.pltype, supportedCodec.rate );
|
||||
|
||||
// iterate over the payload conversion table
|
||||
for (int i=0; i< (int) csf_countof(WebrtcMappingInfo); i++)
|
||||
{
|
||||
WebrtcAudioPayloadType webrtcPayload = WebrtcMappingInfo[i].webrtcAudioPayloadType;
|
||||
|
||||
if (supportedCodec.pltype == webrtcPayload)
|
||||
{
|
||||
bool addCodec = false;
|
||||
|
||||
AudioPayloadType csfPayload = WebrtcMappingInfo[i].csfAudioPayloadType;
|
||||
|
||||
switch (csfPayload)
|
||||
{
|
||||
case AudioPayloadType_G711ALAW64K:
|
||||
case AudioPayloadType_G711ULAW64K:
|
||||
if (!useLowBandwidthCodecOnly)
|
||||
{
|
||||
addCodec = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case AudioPayloadType_G722_56K:
|
||||
case AudioPayloadType_G722_64K:
|
||||
if (!useLowBandwidthCodecOnly &&
|
||||
advertiseG722Codec)
|
||||
{
|
||||
addCodec = true;
|
||||
}
|
||||
break;
|
||||
|
||||
// iLBC and iSAC support is postponed
|
||||
//case AudioPayloadType_ILBC20:
|
||||
//case AudioPayloadType_ILBC30:
|
||||
// addCodec = true;
|
||||
// break;
|
||||
//
|
||||
//case AudioPayloadType_ISAC:
|
||||
// addCodec = true;
|
||||
// break;
|
||||
|
||||
case AudioPayloadType_RFC2833:
|
||||
addCodec = true;
|
||||
break;
|
||||
|
||||
case AudioPayloadType_G711ALAW56K:
|
||||
case AudioPayloadType_G711ULAW56K:
|
||||
case AudioPayloadType_G722_48K:
|
||||
case AudioPayloadType_ILBC20:
|
||||
case AudioPayloadType_ILBC30:
|
||||
case AudioPayloadType_ISAC:
|
||||
break;
|
||||
|
||||
} // end of switch(csfPayload)
|
||||
|
||||
if (addCodec)
|
||||
{
|
||||
// add to codec map
|
||||
webrtc::CodecInst* mappedCodec = new webrtc::CodecInst; // not sure when it should be deleted
|
||||
memcpy(mappedCodec, &supportedCodec, sizeof(webrtc::CodecInst));
|
||||
|
||||
codecMap[csfPayload] = mappedCodec;
|
||||
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::init added mapping payload %d to VoE codec %s", csfPayload, mappedCodec->plname);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::init no mapping found for VoE codec %s (payload %d)", supportedCodec.plname, webrtcPayload );
|
||||
}
|
||||
}
|
||||
} // end of iteration over the payload conversion table
|
||||
|
||||
} // end of iteration over supported codecs
|
||||
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::init %d codec(s) added to map", (int)codecMap.size() );
|
||||
|
||||
// return success
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebrtcAudioCodecSelector::advertiseCodecs( CodecRequestType requestType )
|
||||
{
|
||||
return AudioCodecMask_G711 |AudioCodecMask_G722;
|
||||
}
|
||||
|
||||
int WebrtcAudioCodecSelector::select( int payloadType, int dynamicPayloadType, int packPeriod, webrtc::CodecInst& selectedCodec )
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::select payloadType=%d, dynamicPayloadType=%d, packPeriod=%d", payloadType, dynamicPayloadType, packPeriod );
|
||||
|
||||
// TO DO: calculate packet size ?
|
||||
// packPeriod "represents the number of milliseconds of audio encoded in a single packet" ?
|
||||
int packetSize = packPeriod;
|
||||
|
||||
webrtc::CodecInst* supportedCodec = codecMap[payloadType];
|
||||
|
||||
if (supportedCodec == NULL)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::select no VoE codec found for payload %d", payloadType);
|
||||
return -1; // return failure
|
||||
}
|
||||
|
||||
memcpy(&selectedCodec, supportedCodec, sizeof(webrtc::CodecInst));
|
||||
|
||||
// adapt dynamic payload type if required
|
||||
if (dynamicPayloadType != -1)
|
||||
{
|
||||
selectedCodec.pltype = dynamicPayloadType;
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::select pltype = %d", selectedCodec.pltype);
|
||||
}
|
||||
|
||||
// adapt packet size
|
||||
int pacsize; // packet size in samples = sample rate * packet size
|
||||
|
||||
switch ( payloadType )
|
||||
{
|
||||
case AudioPayloadType_G711ALAW64K:
|
||||
case AudioPayloadType_G711ULAW64K:
|
||||
// VoE allowed packet sizes for G.711 u/a law: 10, 20, 30, 40, 50, 60 ms
|
||||
// (or 80, 160, 240, 320, 400, 480 samples)
|
||||
pacsize = ( 8 * packetSize );
|
||||
if (( pacsize == 80 ) || ( pacsize == 160 ) ||
|
||||
( pacsize == 240) || ( pacsize == 320 ) ||
|
||||
( pacsize == 400) || ( pacsize == 480 ))
|
||||
{
|
||||
selectedCodec.pacsize = pacsize;
|
||||
}
|
||||
break;
|
||||
|
||||
case AudioPayloadType_ILBC20:
|
||||
// VoE allowed packet sizes for iLBC: 20 30, 40, 60 ms
|
||||
pacsize = ( 8 * packetSize );
|
||||
if ( pacsize == 160 )
|
||||
{
|
||||
selectedCodec.pacsize = pacsize;
|
||||
}
|
||||
break;
|
||||
|
||||
case AudioPayloadType_ILBC30:
|
||||
// VoE allowed packet sizes for iLBC: 20 30, 40, 60 ms
|
||||
pacsize = ( 8 * packetSize );
|
||||
if ( pacsize == 240 )
|
||||
{
|
||||
selectedCodec.pacsize = pacsize;
|
||||
}
|
||||
break;
|
||||
|
||||
case AudioPayloadType_G722_56K:
|
||||
case AudioPayloadType_G722_64K:
|
||||
// VoE allowed packet size for G.722: 20ms (or 320 samples).
|
||||
pacsize = ( 16 * packetSize );
|
||||
if ( pacsize == 320 )
|
||||
{
|
||||
selectedCodec.pacsize = pacsize;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::select found codec %s (payload=%d, packetSize=%d)",
|
||||
selectedCodec.plname, selectedCodec.pltype, selectedCodec.pacsize);
|
||||
|
||||
// return success
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebrtcAudioCodecSelector::setSend(int channel, const webrtc::CodecInst& codec,int payloadType,bool vad)
|
||||
{
|
||||
webrtc::PayloadFrequencies freq;
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::setSend channel=%d codec %s (payload=%d, packetSize=%d)",
|
||||
channel, codec.plname, codec.pltype, codec.pacsize);
|
||||
|
||||
if (voeCodec == NULL)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::setSend voeCodec is null" );
|
||||
return -1;
|
||||
}
|
||||
bool vadEnable=vad;
|
||||
|
||||
if (voeCodec->SetVADStatus( channel, vadEnable, webrtc::kVadConventional,false) != 0)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::SetVADStatus cannot set VAD to channel %d", channel );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check the codec's sampling frequency and use appropriate enum
|
||||
switch (codec.plfreq)
|
||||
{
|
||||
case SamplingFreq8000Hz:
|
||||
freq=webrtc::kFreq8000Hz;
|
||||
break;
|
||||
case SamplingFreq16000Hz:
|
||||
freq=webrtc::kFreq16000Hz;
|
||||
break;
|
||||
case SamplingFreq32000Hz:
|
||||
freq=webrtc::kFreq32000Hz;
|
||||
break;
|
||||
default:
|
||||
freq=webrtc::kFreq8000Hz;
|
||||
|
||||
}
|
||||
|
||||
if (voeCodec->SetSendCNPayloadType(channel, ComfortNoisePayloadType, freq) != 0)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "SetSendCNPayloadType cannot set CN payload type to channel %d", channel );
|
||||
//return -1;
|
||||
}
|
||||
// apply the codec to the channel
|
||||
if (voeCodec->SetSendCodec(channel, codec) != 0)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::setSend cannot set send codec to channel %d", channel );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::setSend applied codec %s (payload=%d, packetSize=%d) to channel %d",
|
||||
codec.plname, codec.pltype, codec.pacsize, channel);
|
||||
|
||||
// return success
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebrtcAudioCodecSelector::setReceive(int channel, const webrtc::CodecInst& codec)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::setReceive channel=%d codec %s (payload=%d, packetSize=%d)",
|
||||
channel, codec.plname, codec.pltype, codec.pacsize);
|
||||
|
||||
if (voeCodec == NULL)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::setSend voeCodec is null" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (voeCodec->SetRecPayloadType(channel, codec) != 0)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::setReceive cannot set receive codec to channel %d", channel );
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioCodecSelector::setReceive applied codec %s (payload=%d, packetSize=%d) to channel %d",
|
||||
codec.plname, codec.pltype, codec.pacsize, channel);
|
||||
|
||||
// return success
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,110 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*Webrtc
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef WEBRTCAUDIOCODECSELECTOR_H_
|
||||
#define WEBRTCAUDIOCODECSELECTOR_H_
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include <CSFAudioTermination.h>
|
||||
#include "voe_base.h"
|
||||
#include "voe_codec.h"
|
||||
#include <map>
|
||||
|
||||
|
||||
typedef enum {
|
||||
WebrtcAudioPayloadType_PCMU = 0,
|
||||
WebrtcAudioPayloadType_PCMA = 8,
|
||||
WebrtcAudioPayloadType_G722 = 9,
|
||||
WebrtcAudioPayloadType_iLBC = 102,
|
||||
WebrtcAudioPayloadType_ISAC = 103,
|
||||
WebrtcAudioPayloadType_TELEPHONE_EVENT = 106,
|
||||
WebrtcAudioPayloadType_ISACLC = 119,
|
||||
WebrtcAudioPayloadType_DIM = -1
|
||||
|
||||
} WebrtcAudioPayloadType;
|
||||
|
||||
const int ComfortNoisePayloadType = 13;
|
||||
const int SamplingFreq8000Hz =8000;
|
||||
const int SamplingFreq16000Hz =16000;
|
||||
const int SamplingFreq32000Hz =32000;
|
||||
|
||||
namespace CSF
|
||||
{
|
||||
|
||||
// A class to select a VOE audio codec
|
||||
class WebrtcAudioCodecSelector
|
||||
{
|
||||
public:
|
||||
// the constructor
|
||||
WebrtcAudioCodecSelector();
|
||||
|
||||
// the destructor
|
||||
~WebrtcAudioCodecSelector();
|
||||
|
||||
int init( webrtc::VoiceEngine* voeVoice, bool useLowBandwidthCodecOnly, bool advertiseG722Codec );
|
||||
|
||||
void release();
|
||||
|
||||
// return a bit mask of the available codecs
|
||||
int advertiseCodecs( CodecRequestType requestType );
|
||||
|
||||
// select the VOE codec according to payload type and packet size
|
||||
// return 0 if a codec was selected
|
||||
int select( int payloadType, int dynamicPayloadType, int packetSize, webrtc::CodecInst& selectedCoded );
|
||||
|
||||
// apply a sending codec to the channel
|
||||
// return 0 if codec could be applied
|
||||
int setSend(int channel, const webrtc::CodecInst& codec,int payloadType,bool vad);
|
||||
|
||||
// apply a receiving codec to the channel
|
||||
// return 0 if codec could be applied
|
||||
int setReceive(int channel, const webrtc::CodecInst& codec);
|
||||
|
||||
private:
|
||||
// the reference to the GIPS Codec sub-interface
|
||||
webrtc::VoECodec* voeCodec;
|
||||
|
||||
std::map<int, webrtc::CodecInst*> codecMap;
|
||||
};
|
||||
|
||||
} // namespace CSF
|
||||
|
||||
#endif
|
||||
#endif /* WEBRTCAUDIOCODECSELECTOR_H_ */
|
|
@ -1,961 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include "CC_Common.h"
|
||||
|
||||
#include "string.h"
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "WebrtcMediaProvider.h"
|
||||
#include "WebrtcAudioProvider.h"
|
||||
#include "WebrtcToneGenerator.h"
|
||||
#include "WebrtcRingGenerator.h"
|
||||
#include "voe_file.h"
|
||||
#include "voe_hardware.h"
|
||||
#include "voe_errors.h"
|
||||
#include "voe_network.h"
|
||||
#include "voe_audio_processing.h"
|
||||
#include "WebrtcLogging.h"
|
||||
|
||||
#include "CSFLog.h"
|
||||
static const char* logTag = "WebrtcAudioProvider";
|
||||
using namespace std;
|
||||
|
||||
extern "C" void config_get_value (int id, void *buffer, int length);
|
||||
|
||||
|
||||
namespace CSF {
|
||||
|
||||
#define EXTRACT_DYNAMIC_PAYLOAD_TYPE(PTYPE) ((PTYPE)>>16)
|
||||
#define CLEAR_DYNAMIC_PAYLOAD_TYPE(PTYPE) (PTYPE & 0x0000FFFF)
|
||||
#define CHECK_DYNAMIC_PAYLOAD_TYPE(PTYPE) (PTYPE & 0xFFFF0000)
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
bool IsUserAdmin();
|
||||
bool IsVistaOrNewer();
|
||||
#endif
|
||||
|
||||
class WebrtcAudioStream {
|
||||
public:
|
||||
WebrtcAudioStream(int _streamId, int _channelId):
|
||||
streamId(_streamId), channelId(_channelId),
|
||||
isRxStarted(false), isTxStarted(false), isAlive(false)
|
||||
{}
|
||||
int streamId;
|
||||
int channelId;
|
||||
bool isRxStarted;
|
||||
bool isTxStarted;
|
||||
bool isAlive;
|
||||
};
|
||||
|
||||
WebrtcAudioProvider::WebrtcAudioProvider( WebrtcMediaProvider* provider )
|
||||
: provider(provider),
|
||||
voeVoice(NULL),
|
||||
voeBase(NULL),
|
||||
voeFile(NULL),
|
||||
voeHw(NULL),
|
||||
voeDTMF(NULL),
|
||||
voeNetwork(NULL),
|
||||
voeVolumeControl(NULL),
|
||||
voeVoiceQuality(NULL),
|
||||
voeEncryption(NULL),
|
||||
toneGen(NULL),
|
||||
ringGen(NULL),
|
||||
startPort(1024),
|
||||
endPort(65535),
|
||||
defaultVolume(100),
|
||||
ringerVolume(100),
|
||||
DSCPValue(0),
|
||||
VADEnabled(false),
|
||||
stopping(false)
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioProvider::WebrtcAudioProvider");
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::init()
|
||||
{
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioProvider::init");
|
||||
|
||||
if (voeVoice != NULL) {
|
||||
LOG_WEBRTC_ERROR( logTag, "WebrtcAudioProvider::init : already initialized");
|
||||
return -1;
|
||||
}
|
||||
|
||||
voeVoice = webrtc::VoiceEngine::Create();
|
||||
if (voeVoice == NULL) {
|
||||
LOG_WEBRTC_ERROR( logTag, "WebrtcAudioProvider():VoiceEngine::Create failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
voeBase = webrtc::VoEBase::GetInterface( voeVoice );
|
||||
if (voeBase == NULL) {
|
||||
LOG_WEBRTC_ERROR( logTag, "WebrtcAudioProvider(): VoEBase::GetInterface failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int VERSIONBUFLEN=1024;
|
||||
char versionbuf[VERSIONBUFLEN];
|
||||
voeBase->GetVersion(versionbuf);
|
||||
LOG_WEBRTC_INFO( logTag, "%s", versionbuf );
|
||||
//voeBase->voeVE_SetObserver( *this );
|
||||
|
||||
//#ifdef ENABLE_WEBRTC_AUDIO_TRACE
|
||||
//LOG_WEBRTC_ERROR( logTag, "VoEAudioProvider(): Enabling Trace ");
|
||||
//voeVoice->SetTraceFilter(webrtc::kTraceAll);
|
||||
//voeVoice->SetTraceFile( "voeaudiotrace.out" );
|
||||
//voeVoice->SetTraceCallback(this);
|
||||
//#endif
|
||||
|
||||
voeDTMF = webrtc::VoEDtmf::GetInterface( voeVoice );
|
||||
voeFile = webrtc::VoEFile::GetInterface( voeVoice );
|
||||
voeHw = webrtc::VoEHardware::GetInterface( voeVoice );
|
||||
voeNetwork = webrtc::VoENetwork::GetInterface( voeVoice );
|
||||
voeVolumeControl = webrtc::VoEVolumeControl::GetInterface( voeVoice );
|
||||
voeVoiceQuality = webrtc::VoEAudioProcessing::GetInterface( voeVoice );
|
||||
voeEncryption = webrtc::VoEEncryption::GetInterface(voeVoice);
|
||||
|
||||
if ((!voeDTMF) || (!voeFile) || (!voeHw) ||(!voeNetwork) || (!voeVolumeControl) || (!voeVoiceQuality) || (!voeEncryption)) {
|
||||
LOG_WEBRTC_ERROR( logTag, "WebrtcAudioProvider(): voeVE_GetInterface failed voeDTMF=%p voeFile=%p voeHw=%p voeNetwork=%p voeVolumeControl=%p voeVoiceQuality=%p voeEncryption=%p",
|
||||
voeDTMF,voeFile,voeHw,voeNetwork,voeVolumeControl,voeVoiceQuality,voeEncryption);
|
||||
return -1;
|
||||
}
|
||||
|
||||
codecSelector.init(voeVoice, false, true);
|
||||
voeBase->Init();
|
||||
|
||||
localRingChannel = voeBase->CreateChannel();
|
||||
localToneChannel = voeBase->CreateChannel();
|
||||
|
||||
/*
|
||||
Set up Voice Quality Enhancement Parameters
|
||||
*/
|
||||
webrtc::AgcConfig webphone_agc_config = {3,9,1};
|
||||
voeVoiceQuality->SetAgcConfig(webphone_agc_config);
|
||||
voeVoiceQuality->SetAgcStatus(true, webrtc::kAgcFixedDigital);
|
||||
voeVoiceQuality->SetNsStatus(true, webrtc::kNsModerateSuppression);
|
||||
|
||||
// get default device names
|
||||
int nDevices, error = 0;
|
||||
//returning the first found recording and playout device name
|
||||
error = voeHw->GetNumOfRecordingDevices(nDevices);
|
||||
for(int i = 0; i < nDevices; i++) {
|
||||
char name[128];
|
||||
char guid[128];
|
||||
memset(name,0,128);
|
||||
memset(guid,0,128);
|
||||
error = voeHw->GetRecordingDeviceName(i, name, guid);
|
||||
if(error == 0) {
|
||||
recordingDevice = name;
|
||||
} else {
|
||||
LOG_WEBRTC_ERROR( logTag, "WebrtcAudioProvider: GetRecordingDeviceNamefailed: Error: %d", voeBase->LastError() );
|
||||
}
|
||||
}
|
||||
|
||||
//playout
|
||||
nDevices = 0;
|
||||
error = voeHw->GetNumOfPlayoutDevices(nDevices);
|
||||
for(int i=0; i < nDevices; i++) {
|
||||
char pname[128], pguid[128];
|
||||
memset(pname,0,128);
|
||||
memset(pguid,0,128);
|
||||
if ( voeHw->GetPlayoutDeviceName( i, pname, pguid ) == 0 ) {
|
||||
playoutDevice = pname;
|
||||
} else {
|
||||
LOG_WEBRTC_ERROR( logTag, "WebrtcAudioProvider: GetlayoutDeviceNamefailed: Error: %d", voeBase->LastError() );
|
||||
}
|
||||
}
|
||||
|
||||
LOG_WEBRTC_DEBUG( logTag, "local IP: \"%s\"", localIP.c_str());
|
||||
LOG_WEBRTC_DEBUG( logTag, "RecordingDeviceName: \"%s\"", recordingDevice.c_str());
|
||||
LOG_WEBRTC_DEBUG( logTag, "PlayoutDeviceName: \"%s\"", playoutDevice.c_str());
|
||||
// success
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebrtcAudioProvider::~WebrtcAudioProvider() {
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioProvider::~WebrtcAudioProvider");
|
||||
|
||||
int num_ifs=0;
|
||||
stopping = true;
|
||||
// tear down in reverse order, for symmetry
|
||||
codecSelector.release();
|
||||
|
||||
voeBase->DeleteChannel( localToneChannel );
|
||||
voeBase->DeleteChannel( localRingChannel );
|
||||
voeBase->Terminate();
|
||||
|
||||
if(voeBase->Release() !=0) {
|
||||
LOG_WEBRTC_ERROR( logTag, "~WebrtcAudioProvider(): voeBase->Release failed");
|
||||
}
|
||||
|
||||
if ((num_ifs=voeDTMF->Release())!=0)
|
||||
LOG_WEBRTC_ERROR( logTag, "~WebrtcAudioProvider(): voeDTMF->Release failed, num_ifs left= %d",num_ifs);
|
||||
if ((num_ifs=voeFile->Release())!=0)
|
||||
LOG_WEBRTC_ERROR( logTag, "~WebrtcAudioProvider(): voeFile->Release failed, num_ifs left= %d ",num_ifs);
|
||||
if((num_ifs=voeHw->Release())!=0)
|
||||
LOG_WEBRTC_ERROR( logTag, "~WebrtcAudioProvider(): voeHw->Release failed, num_ifs left= %d " ,num_ifs);
|
||||
if((num_ifs=voeNetwork->Release())!=0)
|
||||
LOG_WEBRTC_ERROR( logTag, "~WebrtcAudioProvider(): voeNetwork->Release() failed, num_ifs left= %d" ,num_ifs);
|
||||
if((num_ifs=voeVolumeControl->Release())!=0)
|
||||
LOG_WEBRTC_ERROR( logTag, "~WebrtcAudioProvider(): voeVolumeControl->Release() failed, num_ifs left= %d" ,num_ifs);
|
||||
if((num_ifs=voeVoiceQuality->Release())!=0)
|
||||
LOG_WEBRTC_ERROR( logTag, "~WebrtcAudioProvider(): voeVoiceQuality->Release() failed, num_ifs left= %d ",num_ifs );
|
||||
if((num_ifs=voeEncryption->Release())!=0)
|
||||
LOG_WEBRTC_ERROR( logTag, "~WebrtcAudioProvider(): voeEncryption->Release() failed, num_ifs left= %d ",num_ifs );
|
||||
if(webrtc::VoiceEngine::Delete( voeVoice, true ) == false)
|
||||
LOG_WEBRTC_ERROR( logTag, "~WebrtcAudioProvider(): voeVoiceEngine::Delete failed" );
|
||||
|
||||
delete toneGen;
|
||||
toneGen = NULL;
|
||||
|
||||
delete ringGen;
|
||||
ringGen = NULL;
|
||||
|
||||
// Clear all our pointers
|
||||
voeFile = NULL;
|
||||
voeHw = NULL;
|
||||
voeDTMF = NULL;
|
||||
voeNetwork = NULL;
|
||||
voeVolumeControl = NULL;
|
||||
voeVoiceQuality = NULL;
|
||||
voeVoice = NULL;
|
||||
voeBase = NULL;
|
||||
voeEncryption = NULL;
|
||||
|
||||
LOG_WEBRTC_INFO( logTag, "WebrtcAudioProvider::shutdown done");
|
||||
}
|
||||
|
||||
std::vector<std::string> WebrtcAudioProvider::getRecordingDevices() {
|
||||
AutoLock lock(m_lock);
|
||||
char name[128];
|
||||
char guid[128];
|
||||
int nRec = 0;
|
||||
memset(name,0,128);
|
||||
memset(guid,0,128);
|
||||
std::vector<std::string> deviceList;
|
||||
voeHw->GetNumOfRecordingDevices(nRec);
|
||||
|
||||
for ( int i = 0; i < nRec; i++ ) {
|
||||
if ( voeHw->GetRecordingDeviceName( i, name, guid ) == 0 )
|
||||
deviceList.push_back( name );
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
std::vector<std::string> WebrtcAudioProvider::getPlayoutDevices() {
|
||||
AutoLock lock(m_lock);
|
||||
char name[128];
|
||||
char guid[128];
|
||||
int nPlay = 0;
|
||||
std::vector<std::string> deviceList;
|
||||
memset(name,0,128);
|
||||
memset(guid,0,128);
|
||||
voeHw->GetNumOfPlayoutDevices( nPlay);
|
||||
for ( int i = 0; i < nPlay; i++ ) {
|
||||
if ( voeHw->GetPlayoutDeviceName( i, name, guid ) == 0 )
|
||||
deviceList.push_back( name );
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
bool WebrtcAudioProvider::setRecordingDevice( const std::string& device ) {
|
||||
AutoLock lock(m_lock);
|
||||
char name[128];
|
||||
char guid[128];
|
||||
int nRec = 0, nPlay = 0;
|
||||
int playoutIndex, recordingIndex;
|
||||
memset(name,0,128);
|
||||
memset(guid,0,128);
|
||||
voeHw->GetNumOfRecordingDevices( nRec );
|
||||
voeHw->GetNumOfPlayoutDevices( nPlay );
|
||||
|
||||
// find requested recording device
|
||||
for ( recordingIndex = 0; recordingIndex < nRec; recordingIndex++ ) {
|
||||
if ( voeHw->GetRecordingDeviceName( recordingIndex, name, guid ) == 0 ) {
|
||||
if ( device.compare( name ) == 0 ) break;
|
||||
}
|
||||
}
|
||||
if ( recordingIndex == nRec ) {
|
||||
return false; // we didn't find the requested device, fail
|
||||
}
|
||||
|
||||
// find existing playout device, to preserve its index
|
||||
// search downward until we reach the default device
|
||||
name[0] = '\0';
|
||||
for ( playoutIndex = nPlay - 1; playoutIndex >= -1; playoutIndex-- ) {
|
||||
if ( voeHw->GetPlayoutDeviceName( playoutIndex, name, guid ) == 0 ) {
|
||||
if ( playoutDevice.compare( name ) == 0 ) break;
|
||||
}
|
||||
else name[0] = '\0';
|
||||
}
|
||||
if ( playoutIndex < -1 ) {
|
||||
playoutIndex = -1; // we didn't find the current device, use default
|
||||
}
|
||||
|
||||
if ( voeHw->SetRecordingDevice( recordingIndex ) == 0
|
||||
&& voeHw->SetPlayoutDevice( playoutIndex) == 0 ) {
|
||||
recordingDevice = device;
|
||||
playoutDevice = name; // the current name
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebrtcAudioProvider::setPlayoutDevice( const std::string& device ) {
|
||||
AutoLock lock(m_lock);
|
||||
char name[128];
|
||||
char guid[128];
|
||||
int nPlay = 0, nRec = 0;
|
||||
int playoutIndex, recordingIndex;
|
||||
|
||||
voeHw->GetNumOfRecordingDevices( nRec );
|
||||
voeHw->GetNumOfPlayoutDevices( nPlay );
|
||||
|
||||
// find requested playout device
|
||||
for ( playoutIndex = 0; playoutIndex < nPlay; playoutIndex++ ) {
|
||||
if ( voeHw->GetPlayoutDeviceName( playoutIndex, name, guid ) == 0 ) {
|
||||
if ( device.compare( name ) == 0 ) break;
|
||||
}
|
||||
}
|
||||
if ( playoutIndex == nPlay ) {
|
||||
return false; // we didn't find the requested device, fail
|
||||
}
|
||||
|
||||
// find existing recording device, to preserve its index
|
||||
// search downward until we reach the default device
|
||||
name[0] = '\0';
|
||||
guid[0] = '\0';
|
||||
for ( recordingIndex = nRec - 1; recordingIndex >= -1; recordingIndex-- ) {
|
||||
if ( voeHw->GetRecordingDeviceName( recordingIndex, name, guid ) == 0 ) {
|
||||
if ( recordingDevice.compare( name ) == 0 ) break;
|
||||
}
|
||||
else name[0] = '\0';
|
||||
}
|
||||
if ( recordingIndex < -1 ) {
|
||||
recordingIndex = -1; // we didn't find the current device, use default
|
||||
}
|
||||
|
||||
if ( voeHw->SetRecordingDevice( recordingIndex ) == 0 &&
|
||||
voeHw->SetPlayoutDevice( playoutIndex) == 0 ) {
|
||||
playoutDevice = device;
|
||||
recordingDevice = name; // the current name
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
WebrtcAudioStreamPtr WebrtcAudioProvider::getStreamByChannel( int channel ) {
|
||||
AutoLock lock(streamMapMutex);
|
||||
for( std::map<int, WebrtcAudioStreamPtr>::const_iterator it = streamMap.begin(); it != streamMap.end(); it++ ) {
|
||||
WebrtcAudioStreamPtr stream = it->second;
|
||||
if(stream->channelId == channel)
|
||||
return stream;
|
||||
}
|
||||
return WebrtcAudioStreamPtr();
|
||||
}
|
||||
|
||||
WebrtcAudioStreamPtr WebrtcAudioProvider::getStream( int streamId ) {
|
||||
AutoLock lock(streamMapMutex);
|
||||
std::map<int, WebrtcAudioStreamPtr>::const_iterator it = streamMap.find( streamId );
|
||||
return ( it != streamMap.end() ) ? it->second : WebrtcAudioStreamPtr();
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::getChannelForStreamId( int streamId ) {
|
||||
WebrtcAudioStreamPtr stream = getStream(streamId);
|
||||
return ( stream != NULL ) ? stream->channelId : -1;
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::getCodecList( CodecRequestType requestType ) {
|
||||
AutoLock lock(m_lock);
|
||||
return codecSelector.advertiseCodecs(requestType);
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::rxAlloc( int groupId, int streamId, int requestedPort ) {
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "rxAllocAudio: groupId=%d, streamId=%d, requestedPort=%d", groupId, streamId, requestedPort );
|
||||
int channel = voeBase->CreateChannel();
|
||||
if ( channel == -1 ) {
|
||||
LOG_WEBRTC_ERROR( logTag, "rxAllocAudio: CreateChannel failed, error %d", voeBase->LastError() );
|
||||
return 0;
|
||||
}
|
||||
LOG_WEBRTC_DEBUG( logTag, "rxAllocAudio: Created channel %d", channel );
|
||||
voeNetwork->SetPeriodicDeadOrAliveStatus(channel, true);
|
||||
|
||||
int beginPort; // where we started
|
||||
int tryPort; // where we are now
|
||||
|
||||
if ( requestedPort == 0 || requestedPort < startPort || requestedPort >= endPort )
|
||||
tryPort = startPort;
|
||||
else
|
||||
tryPort = requestedPort;
|
||||
|
||||
beginPort = tryPort;
|
||||
|
||||
const char * pLocalAddr = NULL;
|
||||
|
||||
if (localIP.size() > 0) {
|
||||
pLocalAddr = localIP.c_str();
|
||||
}
|
||||
|
||||
do {
|
||||
if ( voeBase->SetLocalReceiver( channel, tryPort, webrtc::kVoEDefault, pLocalAddr ) == 0 ) {
|
||||
int port, RTCPport;
|
||||
char ipaddr[64];
|
||||
ipaddr[0]='\0';
|
||||
// retrieve local receiver settings for channel
|
||||
voeBase->GetLocalReceiver(channel, port,RTCPport, ipaddr);
|
||||
localIP = ipaddr;
|
||||
LOG_WEBRTC_DEBUG( logTag, "rxAllocAudio: IPAddr: %d", ipaddr );
|
||||
LOG_WEBRTC_DEBUG( logTag, "rxAllocAudio: Allocated port %d", tryPort );
|
||||
WebrtcAudioStreamPtr stream(new WebrtcAudioStream(streamId, channel)); {
|
||||
AutoLock lock(streamMapMutex);
|
||||
streamMap[streamId] = stream;
|
||||
}
|
||||
setVolume(streamId, defaultVolume);
|
||||
return tryPort;
|
||||
}
|
||||
|
||||
int errCode = voeBase->LastError();
|
||||
if ( errCode == VE_SOCKET_ERROR ||
|
||||
errCode == VE_BINDING_SOCKET_TO_LOCAL_ADDRESS_FAILED ||
|
||||
errCode == VE_RTCP_SOCKET_ERROR ) {
|
||||
tryPort += 2;
|
||||
if ( tryPort >= endPort )
|
||||
tryPort = startPort;
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_ERROR( logTag, "rxAllocAudio: SetLocalReceiver returned error %d", errCode );
|
||||
voeBase->DeleteChannel( channel );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while ( tryPort != beginPort );
|
||||
|
||||
LOG_WEBRTC_WARN( logTag, "rxAllocAudio: No ports available?" );
|
||||
voeBase->DeleteChannel( channel );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::rxOpen( int groupId, int streamId, int requestedPort, int listenIp, bool isMulticast ) {
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "rxOpenAudio: groupId=%d, streamId=%d", groupId, streamId );
|
||||
int channel = getChannelForStreamId( streamId );
|
||||
if ( channel >= 0 ) {
|
||||
LOG_WEBRTC_DEBUG( logTag, "rxOpenAudio: return requestedPort=%d", requestedPort );
|
||||
return requestedPort;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::rxStart( int groupId, int streamId, int payloadType, int packPeriod, int localPort,
|
||||
int rfc2833PayloadType, EncryptionAlgorithm algorithm, unsigned char* key, int keyLen, unsigned char* salt, int saltLen, int mode, int party ) {
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "rxStartAudio: groupId=%d, streamId=%d", groupId, streamId );
|
||||
int channel = getChannelForStreamId( streamId );
|
||||
if ( channel >= 0 ) {
|
||||
int dynamicPayloadType = -1;
|
||||
|
||||
if (CHECK_DYNAMIC_PAYLOAD_TYPE(payloadType)) {
|
||||
dynamicPayloadType = EXTRACT_DYNAMIC_PAYLOAD_TYPE(payloadType);
|
||||
payloadType = CLEAR_DYNAMIC_PAYLOAD_TYPE(payloadType);
|
||||
}
|
||||
|
||||
if (dynamicPayloadType != -1) {
|
||||
webrtc::CodecInst codec;
|
||||
|
||||
if (codecSelector.select(payloadType, dynamicPayloadType, packPeriod, codec) != 0) {
|
||||
LOG_WEBRTC_ERROR( logTag, "rxStartAudio cannot select codec (payloadType=%d, packPeriod=%d)",
|
||||
payloadType, packPeriod );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (codecSelector.setReceive(channel, codec) != 0) {
|
||||
LOG_WEBRTC_ERROR( logTag, "rxStartAudio cannot set receive codec to channel=%d", channel );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch(algorithm) {
|
||||
case EncryptionAlgorithm_NONE:
|
||||
LOG_WEBRTC_DEBUG( logTag, "rxStartAudio: using non-secure RTP for channel %d", channel);
|
||||
break;
|
||||
|
||||
case EncryptionAlgorithm_AES_128_COUNTER: {
|
||||
unsigned char key[WEBRTC_KEY_LENGTH];
|
||||
|
||||
LOG_WEBRTC_DEBUG( logTag, "rxStartAudio: using secure RTP for channel %d", channel);
|
||||
|
||||
if(!provider->getKey(key, keyLen, salt, saltLen, key, sizeof(key))) {
|
||||
LOG_WEBRTC_ERROR( logTag, "rxStartAudio: failed to generate key on channel %d", channel );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* EnableSRTPReceive removed from webrtc
|
||||
if(voeEncryption->EnableSRTPReceive(channel,
|
||||
webrtc::kCipherAes128CounterMode,
|
||||
WEBRTC_CIPHER_LENGTH,
|
||||
webrtc::kAuthNull, 0, 0, webrtc::kEncryption, key) != 0) {
|
||||
LOG_WEBRTC_ERROR( logTag, "rxStartAudio: voeVE_EnableSRTPReceive on channel %d failed", channel );
|
||||
memset(key, 0x00, sizeof(key));
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
memset(key, 0x00, sizeof(key));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (voeBase->StartReceive( channel ) == -1) {
|
||||
LOG_WEBRTC_ERROR( logTag, "rxStartAudio: cannot start listen on channel %d", channel );
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_WEBRTC_DEBUG( logTag, "rxStartAudio: Listening on channel %d", channel );
|
||||
|
||||
if (voeBase->StartPlayout( channel ) == -1) {
|
||||
LOG_WEBRTC_ERROR( logTag, "rxStartAudio: cannot start playout on channel %d, stop listen", channel );
|
||||
//voeBase->voeVE_StopListen( channel );
|
||||
}
|
||||
|
||||
WebrtcAudioStreamPtr stream = getStream(streamId);
|
||||
if(stream != NULL)
|
||||
stream->isRxStarted = true;
|
||||
LOG_WEBRTC_DEBUG( logTag, "rxStartAudio: Playing on channel %d", channel );
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_ERROR( logTag, "rxStartAudio: getChannelForStreamId failed streamId %d",streamId );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void WebrtcAudioProvider::rxClose( int groupId, int streamId ) {
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "rxCloseAudio: groupId=%d, streamId=%d", groupId, streamId );
|
||||
int channel = getChannelForStreamId( streamId );
|
||||
if ( channel >= 0 ) {
|
||||
WebrtcAudioStreamPtr stream = getStream(streamId);
|
||||
if(stream != NULL)
|
||||
stream->isRxStarted = false;
|
||||
voeBase->StopPlayout( channel );
|
||||
LOG_WEBRTC_DEBUG( logTag, "rxCloseAudio: Stop playout on channel %d", channel );
|
||||
}
|
||||
}
|
||||
|
||||
void WebrtcAudioProvider::rxRelease( int groupId, int streamId, int port )
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "rxReleaseAudio: groupId=%d, streamId=%d", groupId, streamId );
|
||||
int channel = getChannelForStreamId( streamId );
|
||||
if ( channel >= 0 ) {
|
||||
voeBase->StopReceive( channel );
|
||||
voeBase->DeleteChannel( channel ); {
|
||||
AutoLock lock(streamMapMutex);
|
||||
streamMap.erase(streamId);
|
||||
}
|
||||
LOG_WEBRTC_DEBUG( logTag, "rxReleaseAudio: Delete channel %d, release port %d", channel, port);
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_ERROR( logTag, "rxReleaseAudio: getChannelForStreamId failed streamId %d",streamId );
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned char m_iGQOSServiceType =0x00000003;
|
||||
|
||||
int WebrtcAudioProvider::txStart( int groupId, int streamId, int payloadType, int packPeriod, bool vad, short tos,
|
||||
char* remoteIpAddr, int remotePort, int rfc2833PayloadType, EncryptionAlgorithm algorithm, unsigned char* key, int keyLen,
|
||||
unsigned char* salt, int saltLen, int mode, int party ) {
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "txStartAudio: groupId=%d, streamId=%d", groupId, streamId);
|
||||
int channel = getChannelForStreamId( streamId );
|
||||
if ( channel >= 0 ) {
|
||||
int dynamicPayloadType = -1;
|
||||
|
||||
if (CHECK_DYNAMIC_PAYLOAD_TYPE(payloadType)) {
|
||||
dynamicPayloadType = EXTRACT_DYNAMIC_PAYLOAD_TYPE(payloadType);
|
||||
payloadType = CLEAR_DYNAMIC_PAYLOAD_TYPE(payloadType);
|
||||
}
|
||||
|
||||
webrtc::CodecInst codec;
|
||||
|
||||
// select codec from payload type
|
||||
if (codecSelector.select(payloadType, dynamicPayloadType, packPeriod, codec) != 0) {
|
||||
LOG_WEBRTC_ERROR( logTag, "txStartAudio cannot select codec (payloadType=%d, packPeriod=%d)",
|
||||
payloadType, packPeriod );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// apply codec to channel
|
||||
if (codecSelector.setSend(channel, codec,payloadType,vad) != 0) {
|
||||
LOG_WEBRTC_ERROR( logTag, "txStartAudio cannot set send codec on channel=%d", channel );
|
||||
LOG_WEBRTC_ERROR( logTag, "VoEAudioProvider: Error: %d", voeBase->LastError() );
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(algorithm) {
|
||||
case EncryptionAlgorithm_NONE:
|
||||
LOG_WEBRTC_DEBUG( logTag, "txStartAudio: using non-secure RTP for channel %d", channel);
|
||||
break;
|
||||
|
||||
case EncryptionAlgorithm_AES_128_COUNTER: {
|
||||
unsigned char key[WEBRTC_KEY_LENGTH];
|
||||
|
||||
LOG_WEBRTC_DEBUG( logTag, "txStartAudio: using secure RTP for channel %d", channel);
|
||||
|
||||
if(!provider->getKey(key, keyLen, salt, saltLen, key, sizeof(key))) {
|
||||
LOG_WEBRTC_ERROR( logTag, "txStartAudio: failed to generate key on channel %d", channel );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
if(voeEncryption->EnableSRTPSend(channel,
|
||||
webrtc::kCipherAes128CounterMode,
|
||||
WEBRTC_CIPHER_LENGTH,
|
||||
webrtc::kAuthNull, 0, 0, webrtc::kEncryption, key) != 0) {
|
||||
LOG_WEBRTC_ERROR( logTag, "txStartAudio:EnableSRTPSend on channel %d failed", channel );
|
||||
memset(key, 0x00, sizeof(key));
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
memset(key, 0x00, sizeof(key));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char dscpSixBit = DSCPValue>>2;
|
||||
voeBase->SetSendDestination( channel, remotePort, remoteIpAddr );
|
||||
#ifdef WIN32
|
||||
if (IsVistaOrNewer()) {
|
||||
LOG_WEBRTC_DEBUG( logTag, "Vista or later");
|
||||
if(voeNetwork->SetSendTOS(channel, dscpSixBit, false ) == -1) {
|
||||
LOG_WEBRTC_DEBUG( logTag, "openIngressChannel():voeVE_SetSendTOS() returned error");
|
||||
}
|
||||
LOG_WEBRTC_DEBUG( logTag, " Wrapper::openIngressChannel:- voeVE_SetSendTOS(), useSetSockOpt = false");
|
||||
}
|
||||
else {
|
||||
if(voeNetwork->SetSendTOS(channel, dscpSixBit, true ) == -1) {
|
||||
LOG_WEBRTC_DEBUG( logTag, "openIngressChannel():voeVE_SetSendTOS() returned error");
|
||||
}
|
||||
LOG_WEBRTC_DEBUG( logTag, "Wrapper::openIngressChannel:- voeVE_SetSendTOS(), useSetSockOpt = true");
|
||||
}
|
||||
#else
|
||||
voeNetwork->SetSendTOS(channel, dscpSixBit, -1, true );
|
||||
#endif
|
||||
voeBase->StartSend( channel );
|
||||
WebrtcAudioStreamPtr stream = getStream(streamId);
|
||||
if(stream != NULL)
|
||||
stream->isTxStarted = true;
|
||||
LOG_WEBRTC_DEBUG( logTag, "txStartAudio: Sending to %s:%d on channel %d", remoteIpAddr, remotePort, channel );
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_ERROR( logTag, "txStartAudio: getChannelForStreamId failed streamId %d",streamId );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void WebrtcAudioProvider::txClose( int groupId, int streamId ) {
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "txCloseAudio: groupId=%d, streamId=%d", groupId, streamId);
|
||||
int channel = getChannelForStreamId( streamId );
|
||||
if ( channel >= 0 ) {
|
||||
WebrtcAudioStreamPtr stream = getStream(streamId);
|
||||
if(stream != NULL)
|
||||
stream->isTxStarted = false;
|
||||
voeBase->StopSend( channel );
|
||||
LOG_WEBRTC_DEBUG( logTag, "txCloseAudio: Stop transmit on channel %d", channel );
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_ERROR( logTag, "txClose: getChannelForStreamId failed streanId %d",streamId );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::toneStart( ToneType type, ToneDirection direction, int alertInfo, int groupId, int streamId, bool useBackup ) {
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "mediaToneStart: tone=%d, direction=%d, groupId=%d, streamId=%d", type, direction, groupId, streamId );
|
||||
if(toneGen != NULL) {
|
||||
LOG_WEBRTC_INFO( logTag, "mediaToneStart: tone already in progress - stop current tone [using dodgy parameters] and replace it." );
|
||||
toneStop(type, groupId, streamId);
|
||||
}
|
||||
toneGen = new WebrtcToneGenerator( type );
|
||||
voeBase->StartPlayout( localToneChannel );
|
||||
voeFile->StartPlayingFileLocally( localToneChannel, toneGen, webrtc::kFileFormatPcm8kHzFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::toneStop( ToneType type, int groupId, int streamId ) {
|
||||
//AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "mediaToneStop: tone=%d, groupId=%d, streamId=%d", type, groupId, streamId );
|
||||
if ( voeFile->IsPlayingFileLocally( localToneChannel ) == 1 ) {
|
||||
voeBase->StopPlayout( localToneChannel );
|
||||
voeFile->StopPlayingFileLocally( localToneChannel );
|
||||
}
|
||||
delete toneGen;
|
||||
toneGen = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::ringStart( int lineId, RingMode mode, bool once )
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "mediaRingStart: line=%d, mode=%d, once=%d", lineId, mode, once );
|
||||
if(ringGen != NULL) {
|
||||
LOG_WEBRTC_INFO( logTag, "mediaRingStart: ringing already in progress - do nothing." );
|
||||
return 0;
|
||||
}
|
||||
ringGen = new WebrtcRingGenerator( mode, once );
|
||||
ringGen->SetScaleFactor(ringerVolume);
|
||||
voeBase->StartPlayout( localRingChannel );
|
||||
voeFile->StartPlayingFileLocally( localRingChannel, ringGen, webrtc::kFileFormatPcm8kHzFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::ringStop( int lineId ) {
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "mediaRingStop: line=%d", lineId );
|
||||
if ( voeFile->IsPlayingFileLocally( localRingChannel ) == 1 ) {
|
||||
voeBase->StopPlayout( localRingChannel );
|
||||
voeFile->StopPlayingFileLocally( localRingChannel );
|
||||
}
|
||||
delete ringGen;
|
||||
ringGen = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::sendDtmf( int streamId, int digit) {
|
||||
AutoLock lock(m_lock);
|
||||
|
||||
int rfc2833Payload=101;
|
||||
int channel = getChannelForStreamId( streamId );
|
||||
|
||||
if(channel >= 0) {
|
||||
voeDTMF->SetDtmfFeedbackStatus(true);
|
||||
voeDTMF->SetSendTelephoneEventPayloadType(channel, rfc2833Payload); // Need to get rfc2833Payload
|
||||
voeDTMF->SendTelephoneEvent(channel, digit);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_INFO( logTag, "sendDtmf() failed to map stream to channel");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// returns -1 on failure
|
||||
bool WebrtcAudioProvider::mute( int streamId, bool mute )
|
||||
{
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "audio mute: streamId=%d, mute=%d", streamId, mute );
|
||||
int channel = getChannelForStreamId( streamId );
|
||||
bool returnVal = false;
|
||||
|
||||
if ( channel >= 0 ) {
|
||||
if (voeVolumeControl->SetInputMute(channel, mute) != -1) {
|
||||
returnVal= true;
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_INFO( logTag, "mute returned failure from SetInputMute");
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_INFO( logTag, "failed to map stream to channel");
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
bool WebrtcAudioProvider::isMuted( int streamId ) {
|
||||
AutoLock lock(m_lock);
|
||||
bool mute=false;
|
||||
|
||||
voeVolumeControl->GetInputMute(getChannelForStreamId(streamId), mute);
|
||||
return mute;
|
||||
}
|
||||
|
||||
bool WebrtcAudioProvider::setDefaultVolume( int volume ) {
|
||||
AutoLock lock(m_lock);
|
||||
defaultVolume = volume;
|
||||
return true;
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::getDefaultVolume() {
|
||||
AutoLock lock(m_lock);
|
||||
return defaultVolume;
|
||||
}
|
||||
|
||||
bool WebrtcAudioProvider::setRingerVolume( int volume ) {
|
||||
AutoLock lock(m_lock);
|
||||
LOG_WEBRTC_INFO( logTag, "setRingerVolume: volume=%d", volume );
|
||||
if (voeVolumeControl->SetChannelOutputVolumeScaling(localRingChannel, volume * 0.01f) != -1) {
|
||||
ringerVolume = volume;
|
||||
if(ringGen != NULL) {
|
||||
ringGen->SetScaleFactor(ringerVolume);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_INFO( logTag, "setRingerVolume() returned failure from SetChannelOutputVolumeScaling");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::getRingerVolume() {
|
||||
AutoLock lock(m_lock);
|
||||
return ringerVolume;
|
||||
}
|
||||
|
||||
bool WebrtcAudioProvider::setVolume( int streamId, int volume ) {
|
||||
LOG_WEBRTC_INFO( logTag, "setVolume: streamId=%d, volume=%d", streamId, volume );
|
||||
int channel = getChannelForStreamId( streamId );
|
||||
bool returnVal = false;
|
||||
|
||||
if ( channel >= 0 ) {
|
||||
// Input is scaled 0-100. voe scale is 0.0f - 1.0f. (Larger values are allowable but liable to distortion)
|
||||
if (voeVolumeControl->SetChannelOutputVolumeScaling(channel, volume * 0.01f) != -1) {
|
||||
returnVal = true;
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_INFO( logTag, "setVolume() retuned failure from SetChannelOutputVolumeScaling");
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_INFO( logTag, "failed to map stream to channel");
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
int WebrtcAudioProvider::getVolume( int streamId ) {
|
||||
AutoLock lock(m_lock);
|
||||
float voeVolume = 0;
|
||||
|
||||
if(voeVolumeControl->GetChannelOutputVolumeScaling(getChannelForStreamId(streamId), voeVolume) != -1) {
|
||||
// Output is scaled 0-100. voe scale is 0.0f - 1.0f.
|
||||
float volume = voeVolume * 100.0f; // Scale to 0-100 for presentation.
|
||||
return (int)(volume + 0.5f); // And round neatly.
|
||||
}
|
||||
else {
|
||||
LOG_WEBRTC_INFO( logTag, "getVolume retuned failure from GetChannelOutputVolumeScaling");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// voeVoiceEngineObserver
|
||||
void WebrtcAudioProvider::Print(const webrtc::TraceLevel level, const char* message, const int length) {
|
||||
if (strstr(message, "eventNumber=") != NULL || strstr(message, "DTMF event ") != NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
void WebrtcAudioProvider::CallbackOnError(const int errCode, const int channel) {
|
||||
LOG_WEBRTC_ERROR( logTag, "CallbackOnError() ERROR %d on channel %d", errCode, channel );
|
||||
}
|
||||
|
||||
void WebrtcAudioProvider::OnPeriodicDeadOrAlive(int channel, bool isAlive) {
|
||||
WebrtcAudioStreamPtr stream = getStreamByChannel(channel);
|
||||
if(stream != NULL && (stream->isRxStarted || stream->isTxStarted)) {
|
||||
if(stream->isAlive != isAlive) {
|
||||
LOG_WEBRTC_INFO( logTag, "voe channel %d is %s", channel, (isAlive ? "alive" : "dead") );
|
||||
stream->isAlive = isAlive;
|
||||
// TODO should use postEvent and rely on Engine to drive dispatch.
|
||||
/* Component::Event event;
|
||||
event.component = provider;
|
||||
event.context = (void*)stream->callId;
|
||||
stream->isAlive = isAlive;
|
||||
if(isAlive)
|
||||
event.id = eMediaRestored;
|
||||
else
|
||||
event.id = eMediaLost;
|
||||
provider->dispatchEvent( event );
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef WIN32
|
||||
bool IsUserAdmin() {
|
||||
BOOL bAdm = TRUE;
|
||||
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
||||
PSID AdministratorsGroup;
|
||||
bAdm = AllocateAndInitializeSid(
|
||||
&NtAuthority,
|
||||
2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_ADMINS,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
&AdministratorsGroup);
|
||||
if(bAdm) {
|
||||
if (!CheckTokenMembership( NULL, AdministratorsGroup, &bAdm)) {
|
||||
bAdm = FALSE;
|
||||
}
|
||||
//Free the memory for PSID structure;
|
||||
FreeSid(AdministratorsGroup);
|
||||
}
|
||||
return (bAdm == TRUE);
|
||||
}
|
||||
|
||||
bool IsVistaOrNewer()
|
||||
{
|
||||
OSVERSIONINFOEX osVersion;
|
||||
ZeroMemory(&osVersion, sizeof(OSVERSIONINFOEX));
|
||||
osVersion.dwOSVersionInfoSize = sizeof(osVersion);
|
||||
|
||||
if (GetVersionEx((LPOSVERSIONINFO)&osVersion)) {
|
||||
|
||||
// Determine if this is Windows Vista or newer
|
||||
if (osVersion.dwMajorVersion >= 6) {
|
||||
// Vista
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//Lets proceed with XP as OS.
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
} // namespace CSF
|
||||
|
||||
#endif
|
|
@ -1,195 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef WebrtcAUDIOMEDIAPROVIDER_H_
|
||||
#define WebrtcAUDIOMEDIAPROVIDER_H_
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include "csf_common.h"
|
||||
#include "CSFAudioControl.h"
|
||||
#include "CSFAudioTermination.h"
|
||||
#include "WebrtcAudioCodecSelector.h"
|
||||
|
||||
#include "voe_base.h"
|
||||
#include "voe_file.h"
|
||||
#include "voe_hardware.h"
|
||||
#include "voe_dtmf.h"
|
||||
#include "voe_network.h"
|
||||
#include "voe_audio_processing.h"
|
||||
#include "voe_volume_control.h"
|
||||
#include "voe_encryption.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "base/lock.h"
|
||||
|
||||
|
||||
namespace CSF
|
||||
{
|
||||
class WebrtcMediaProvider;
|
||||
class WebrtcToneGenerator;
|
||||
class WebrtcRingGenerator;
|
||||
class WebrtcAudioStream;
|
||||
class WebrtcVideoProvider;
|
||||
DECLARE_PTR(WebrtcAudioStream);
|
||||
|
||||
class WebrtcAudioProvider : public AudioControl, AudioTermination, webrtc::VoiceEngineObserver,
|
||||
webrtc::VoEConnectionObserver
|
||||
,webrtc::TraceCallback {
|
||||
friend class WebrtcVideoProvider;
|
||||
|
||||
public:
|
||||
|
||||
WebrtcAudioProvider( WebrtcMediaProvider* provider );
|
||||
|
||||
// destructor
|
||||
~WebrtcAudioProvider();
|
||||
|
||||
// initialize members and Webrtc API
|
||||
// return 0 if initialzation succeeded
|
||||
int init();
|
||||
|
||||
// AudioControl
|
||||
AudioControl* getAudioControl() { return this; }
|
||||
|
||||
std::vector<std::string> getRecordingDevices();
|
||||
std::vector<std::string> getPlayoutDevices();
|
||||
|
||||
std::string getRecordingDevice() { return recordingDevice; }
|
||||
std::string getPlayoutDevice() { return playoutDevice; }
|
||||
|
||||
bool setRecordingDevice( const std::string& name );
|
||||
bool setPlayoutDevice( const std::string& name );
|
||||
|
||||
bool setDefaultVolume( int volume );
|
||||
int getDefaultVolume();
|
||||
|
||||
bool setRingerVolume( int volume );
|
||||
int getRingerVolume();
|
||||
|
||||
bool setVolume( int streamId, int volume );
|
||||
int getVolume( int streamId );
|
||||
|
||||
AudioTermination * getAudioTermination() { return this; }
|
||||
|
||||
int getCodecList( CodecRequestType requestType );
|
||||
|
||||
int rxAlloc ( int groupId, int streamId, int requestedPort );
|
||||
void setLocalIP ( const char* addr ) { localIP = addr; }
|
||||
int rxOpen ( int groupId, int streamId, int requestedPort, int listenIp, bool isMulticast );
|
||||
int rxStart ( int groupId, int streamId, int payloadType, int packPeriod, int localPort, int rfc2833PayloadType,
|
||||
EncryptionAlgorithm algorithm, unsigned char* key, int keyLen, unsigned char* salt, int saltLen, int mode, int party );
|
||||
void rxClose ( int groupId, int streamId);
|
||||
void rxRelease ( int groupId, int streamId, int port );
|
||||
int txStart ( int groupId, int streamId, int payloadType, int packPeriod, bool vad, short tos,
|
||||
char* remoteIpAddr, int remotePort, int rfc2833PayloadType, EncryptionAlgorithm algorithm,
|
||||
unsigned char* key, int keyLen, unsigned char* salt, int saltLen, int mode, int party );
|
||||
void txClose ( int groupId, int streamId);
|
||||
|
||||
int toneStart ( ToneType type, ToneDirection direction, int alertInfo, int groupId, int streamId, bool useBackup );
|
||||
int toneStop ( ToneType type, int groupId, int streamId);
|
||||
int ringStart ( int lineId, RingMode mode, bool once );
|
||||
int ringStop ( int lineId );
|
||||
int sendDtmf ( int streamId, int digit);
|
||||
bool mute ( int streamId, bool mute );
|
||||
bool isMuted ( int streamId );
|
||||
void setMediaPorts( int startPort, int endPort ) { this->startPort = startPort; this->endPort = endPort; }
|
||||
void setDSCPValue (int value){this->DSCPValue = value;}
|
||||
void setVADEnabled(bool VADEnabled){this->VADEnabled = VADEnabled;}
|
||||
|
||||
// used by video, for lip sync
|
||||
webrtc::VoiceEngine* getVoiceEngine() { return voeVoice; }
|
||||
|
||||
protected:
|
||||
// WebrtcVoiceEngineObserver
|
||||
void CallbackOnError(const int errCode, const int channel);
|
||||
void Print(const webrtc::TraceLevel level, const char* message, const int length);
|
||||
// WebrtcVEConnectionObserver
|
||||
void OnPeriodicDeadOrAlive(int channel, bool alive);
|
||||
|
||||
int getChannelForStreamId( int streamId );
|
||||
WebrtcAudioStreamPtr getStream( int streamId );
|
||||
WebrtcAudioStreamPtr getStreamByChannel( int channelId );
|
||||
|
||||
private:
|
||||
WebrtcMediaProvider* provider;
|
||||
webrtc::VoiceEngine* voeVoice;
|
||||
webrtc::VoEBase* voeBase;
|
||||
webrtc::VoEFile* voeFile;
|
||||
webrtc::VoEHardware* voeHw;
|
||||
webrtc::VoEDtmf* voeDTMF;
|
||||
webrtc::VoENetwork* voeNetwork;
|
||||
webrtc::VoEVolumeControl* voeVolumeControl;
|
||||
webrtc::VoEAudioProcessing* voeVoiceQuality;
|
||||
webrtc::VoEEncryption* voeEncryption;
|
||||
int localToneChannel;
|
||||
int localRingChannel;
|
||||
std::string recordingDevice;
|
||||
std::string playoutDevice;
|
||||
std::map<int, int> streamToChannel;
|
||||
std::map<int, WebrtcAudioStreamPtr> streamMap;
|
||||
WebrtcToneGenerator* toneGen; // temporary, need to manage multiple tones
|
||||
WebrtcRingGenerator* ringGen; // temporary, need to use audio device directly
|
||||
std::string localIP;
|
||||
int startPort;
|
||||
int endPort;
|
||||
int defaultVolume; // Range 0-100
|
||||
int ringerVolume; // Range 0-100
|
||||
int DSCPValue;
|
||||
bool VADEnabled;
|
||||
|
||||
WebrtcAudioCodecSelector codecSelector;
|
||||
|
||||
// Synchronisation (to avoid data corruption and worse given that so many threads call the media provider)
|
||||
// Never use this mutex in a callback from Webrtc - high probability of deadlock.
|
||||
|
||||
Lock m_lock;
|
||||
// This mutex is to be held only for the narrowest possible scope while accessing the stream map
|
||||
// (but not while inspecting or changing a stream object).
|
||||
// Might be used in northbound and southbound calls.
|
||||
Lock streamMapMutex;
|
||||
bool stopping;
|
||||
};
|
||||
const unsigned short targetLeveldBOvdefault =3 ;
|
||||
const unsigned short digitalCompressionGaindBdefault =9;
|
||||
const bool limiterEnableon = true;
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
#endif /* WebrtcAUDIOMEDIAPROVIDER_H_ */
|
|
@ -1,261 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include "CC_Common.h"
|
||||
|
||||
#ifdef LINUX
|
||||
#include "X11/Xlib.h"
|
||||
#endif
|
||||
|
||||
#include "WebrtcMediaProvider.h"
|
||||
#include "WebrtcAudioProvider.h"
|
||||
#ifndef NO_WEBRTC_VIDEO
|
||||
#include "WebrtcVideoProvider.h"
|
||||
#endif
|
||||
#include "WebrtcLogging.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if (defined (_MSC_VER) && defined (_DEBUG))
|
||||
/**
|
||||
* Workaround to allow the use of mixed debug & release code
|
||||
* since the Webrtc library is release only, but we still want debug projects
|
||||
* to test our own stuff. This symbol is missing from the debug crt library.
|
||||
*/
|
||||
extern "C" __declspec(dllexport) void __cdecl _invalid_parameter_noinfo(void) { }
|
||||
#endif /* (defined (_MSC_VER) && defined (_DEBUG)) */
|
||||
|
||||
bool g_IncludeWebrtcLogging=false;
|
||||
|
||||
static const char* logTag = "WebrtcMediaProvider";
|
||||
|
||||
namespace CSF {
|
||||
|
||||
// Public interface class
|
||||
|
||||
MediaProvider::~MediaProvider()
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
MediaProvider * MediaProvider::create( )
|
||||
{
|
||||
LOG_WEBRTC_DEBUG( logTag, "MediaProvider::create");
|
||||
|
||||
WebrtcMediaProvider* mediaProvider = new WebrtcMediaProvider();
|
||||
LOG_WEBRTC_DEBUG( logTag, "MediaProvider::create new instance");
|
||||
|
||||
if ( mediaProvider->init() != 0)
|
||||
{
|
||||
LOG_WEBRTC_ERROR( logTag, "cannot initialize WebrtcMediaProvider");
|
||||
delete mediaProvider;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mediaProvider;
|
||||
}
|
||||
|
||||
// Implementation classes
|
||||
|
||||
WebrtcMediaProvider::WebrtcMediaProvider( )
|
||||
{
|
||||
pAudio = new WebrtcAudioProvider( this );
|
||||
if (pAudio->init() != 0)
|
||||
{
|
||||
LOG_WEBRTC_ERROR( logTag, "Error calling pAudio->Init in WebrtcMediaProvider");
|
||||
}
|
||||
|
||||
// for the moment, we only have video lib for windows
|
||||
#ifndef NO_WEBRTC_VIDEO
|
||||
pVideo = new WebrtcVideoProvider( this );
|
||||
#else
|
||||
pVideo = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
WebrtcMediaProvider::~WebrtcMediaProvider()
|
||||
{
|
||||
#ifndef NO_WEBRTC_VIDEO
|
||||
delete pVideo;
|
||||
#endif
|
||||
delete pAudio;
|
||||
}
|
||||
|
||||
int WebrtcMediaProvider::init()
|
||||
{
|
||||
#ifndef NO_WEBRTC_VIDEO
|
||||
if (pVideo->init() != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WebrtcMediaProvider::shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void WebrtcMediaProvider::addMediaProviderObserver( MediaProviderObserver* observer )
|
||||
{
|
||||
// just add all the events at once
|
||||
/*
|
||||
componentImpl->addObserver( eVideoModeChanged, observer);
|
||||
componentImpl->addObserver( eKeyFrameRequest, observer);
|
||||
componentImpl->addObserver( eMediaLost, observer);
|
||||
componentImpl->addObserver( eMediaRestored, observer);
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
void WebrtcMediaProvider::dispatchEvent(Event event)
|
||||
{
|
||||
ComponentImpl::ObserverMapRange range = componentImpl->observerMapRangeForEventID(event.id);
|
||||
|
||||
for (ComponentImpl::ObserverMapIterator it = range.first; it != range.second; it++)
|
||||
{
|
||||
switch (event.id)
|
||||
{
|
||||
case eVideoModeChanged:
|
||||
LOG_Webrtc_DEBUG( logTag, "Dispatching eVideoMode");
|
||||
((MediaProviderObserver*)(*it).second)->onVideoModeChanged( event.context != 0 );
|
||||
break;
|
||||
|
||||
case eKeyFrameRequest:
|
||||
LOG_Webrtc_DEBUG( logTag, "Dispatching eKeyFrameRequest");
|
||||
((MediaProviderObserver*)(*it).second)->onKeyFrameRequested( (long)event.context );
|
||||
break;
|
||||
|
||||
case eMediaLost:
|
||||
LOG_Webrtc_DEBUG( logTag, "Dispatching eMediaLost");
|
||||
((MediaProviderObserver*)(*it).second)->onMediaLost( (long)event.context );
|
||||
break;
|
||||
|
||||
case eMediaRestored:
|
||||
LOG_Webrtc_DEBUG( logTag, "Dispatching eMediaRestored");
|
||||
((MediaProviderObserver*)(*it).second)->onMediaRestored( (long)event.context );
|
||||
break;
|
||||
|
||||
default:
|
||||
CSFAssert(false, "Bad event id passed to WebrtcMediaProvider: %d", event.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSFComponentRole WebrtcMediaProvider::getRole() const
|
||||
{
|
||||
return kCSFMediaProvider_ComponentRole;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
AudioControl* WebrtcMediaProvider::getAudioControl()
|
||||
{
|
||||
return pAudio ? pAudio->getAudioControl() : NULL;
|
||||
}
|
||||
|
||||
VideoControl* WebrtcMediaProvider::getVideoControl()
|
||||
{
|
||||
#ifndef NO_WEBRTC_VIDEO
|
||||
return pVideo ? pVideo->getMediaControl() : NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
webrtc::VoiceEngine* WebrtcMediaProvider::getWebrtcVoiceEngine () {
|
||||
return ((pAudio != NULL) ? pAudio->getVoiceEngine() : NULL);
|
||||
}
|
||||
|
||||
AudioTermination* WebrtcMediaProvider::getAudioTermination()
|
||||
{
|
||||
return pAudio ? pAudio->getAudioTermination() : NULL;
|
||||
}
|
||||
|
||||
VideoTermination* WebrtcMediaProvider::getVideoTermination()
|
||||
{
|
||||
#ifndef NO_WEBRTC_VIDEO
|
||||
return pVideo ? pVideo->getMediaTermination() : NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool WebrtcMediaProvider::getKey(
|
||||
const unsigned char* masterKey,
|
||||
int masterKeyLen,
|
||||
const unsigned char* masterSalt,
|
||||
int masterSaltLen,
|
||||
unsigned char* key,
|
||||
unsigned int keyLen
|
||||
)
|
||||
{
|
||||
LOG_WEBRTC_DEBUG( logTag, "getKey() masterKeyLen = %d, masterSaltLen = %d", masterKeyLen, masterSaltLen);
|
||||
|
||||
if(masterKey == NULL || masterSalt == NULL)
|
||||
{
|
||||
LOG_WEBRTC_ERROR( logTag, "getKey() masterKey or masterSalt is NULL");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((masterKeyLen != WEBRTC_MASTER_KEY_LENGTH) || (masterSaltLen != WEBRTC_MASTER_SALT_LENGTH))
|
||||
{
|
||||
LOG_WEBRTC_ERROR( logTag, "getKey() invalid masterKeyLen or masterSaltLen length");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((key == NULL) || (keyLen != WEBRTC_KEY_LENGTH))
|
||||
{
|
||||
LOG_WEBRTC_ERROR( logTag, "getKey() invalid key or keyLen");
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(key, masterKey, WEBRTC_MASTER_KEY_LENGTH);
|
||||
memcpy(key + WEBRTC_MASTER_KEY_LENGTH, masterSalt, WEBRTC_MASTER_SALT_LENGTH);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace CSF
|
||||
|
||||
#endif
|
|
@ -1,107 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef WebrtcMEDIAPROVIDER_H_
|
||||
#define WebrtcMEDIAPROVIDER_H_
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include <CSFMediaProvider.h>
|
||||
#include "voe_base.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace CSF
|
||||
{
|
||||
enum // Event ids
|
||||
{
|
||||
eVideoModeChanged,
|
||||
eKeyFrameRequest,
|
||||
eMediaLost,
|
||||
eMediaRestored
|
||||
};
|
||||
|
||||
// Master key is 128 bits, master salt 112 bits.
|
||||
#define WEBRTC_MASTER_KEY_LENGTH 16
|
||||
#define WEBRTC_MASTER_SALT_LENGTH 14
|
||||
#define WEBRTC_KEY_LENGTH (WEBRTC_MASTER_KEY_LENGTH + WEBRTC_MASTER_SALT_LENGTH)
|
||||
#define WEBRTC_CIPHER_LENGTH WEBRTC_KEY_LENGTH
|
||||
|
||||
class WebrtcAudioProvider;
|
||||
class WebrtcVideoProvider;
|
||||
|
||||
class WebrtcMediaProvider : public MediaProvider
|
||||
{
|
||||
friend class MediaProvider;
|
||||
friend class WebrtcVideoProvider;
|
||||
friend class WebrtcAudioProvider;
|
||||
|
||||
protected:
|
||||
WebrtcMediaProvider( );
|
||||
~WebrtcMediaProvider();
|
||||
|
||||
int init();
|
||||
virtual void shutdown();
|
||||
|
||||
AudioControl* getAudioControl();
|
||||
VideoControl* getVideoControl();
|
||||
AudioTermination* getAudioTermination();
|
||||
VideoTermination* getVideoTermination();
|
||||
void addMediaProviderObserver( MediaProviderObserver* observer );
|
||||
|
||||
bool getKey(
|
||||
const unsigned char* masterKey,
|
||||
int masterKeyLen,
|
||||
const unsigned char* masterSalt,
|
||||
int masterSaltLen,
|
||||
unsigned char* key,
|
||||
unsigned int keyLen
|
||||
);
|
||||
|
||||
private:
|
||||
WebrtcAudioProvider* pAudio;
|
||||
WebrtcVideoProvider* pVideo;
|
||||
|
||||
webrtc::VoiceEngine * getWebrtcVoiceEngine ();
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
#endif /* WebrtcMEDIAPROVIDER_H_ */
|
|
@ -1,281 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include <string.h>
|
||||
#include "WebrtcRingGenerator.h"
|
||||
|
||||
namespace CSF {
|
||||
|
||||
/*
|
||||
* 480 samples of 16-bit, 8kHz linear PCM ring tone,
|
||||
* for a total duration of 60 milliseconds.
|
||||
* Repeat as directed.
|
||||
*/
|
||||
static short Ring1[480] =
|
||||
{
|
||||
0, 0, 0, -112, 988, 1564, -1564, -3260,
|
||||
-180, -104, -4860, -3004, 5628, 5628, -876, 2236,
|
||||
9340, 1308, -10876, -5884, 1980, -6652, -12412, 3644,
|
||||
14972, 3772, -1564, 12924, 12924, -10876, -17788, -372,
|
||||
-1372, -19836, -9340, 18812, 15484, -2620, 6652, 21884,
|
||||
1436, -21884, -9852, 3260, -12412, -19836, 6908, 21884,
|
||||
4348, -1564, 17788, 14972, -13948, -18812, 180, -2364,
|
||||
-20860, -8316, 19836, 14460, -2876, 7676, 20860, 8,
|
||||
-21884, -8828, 3132, -13436, -18812, 8316, 21884, 3516,
|
||||
-1052, 17788, 13948, -15484, -18812, 780, -3132, -20860,
|
||||
-6908, 19836, 13436, -3132, 8316, 20860, -1436, -21884,
|
||||
-7932, 3004, -13948, -18812, 9340, 20860, 2620, -460,
|
||||
18812, 12924, -15996, -17788, 1308, -4092, -20860, -5372,
|
||||
20860, 12924, -3260, 9340, 20860, -2876, -21884, -7164,
|
||||
2748, -14972, -17788, 10876, 20860, 1884, 164, 18812,
|
||||
11900, -16764, -16764, 1820, -4860, -20860, -4092, 20860,
|
||||
11900, -3388, 10364, 20860, -4348, -21884, -6140, 2364,
|
||||
-15996, -16764, 11900, 19836, 1116, 844, 19836, 10364,
|
||||
-17788, -16764, 2236, -5884, -20860, -2748, 21884, 10876,
|
||||
-3388, 11388, 19836, -5628, -21884, -5116, 1980, -16764,
|
||||
-15996, 13436, 19836, 428, 1564, 19836, 9340, -18812,
|
||||
-15484, 2620, -6652, -20860, -1244, 19836, 8828, -2748,
|
||||
9852, 15484, -5116, -15484, -3004, 924, -10876, -8828,
|
||||
7932, 10364, -56, 1180, 8828, 3260, -7164, -4860,
|
||||
812, -2236, -5372, 0, 4092, 1372, -308, 1244,
|
||||
1180, -212, 72, -8, 0, 0, 0, 0,
|
||||
/* remainder is all zeroes */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short* samples;
|
||||
int sampleCnt;
|
||||
int stepDuration; // milliseconds, replay samples as needed
|
||||
|
||||
} RingCadence;
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define MILLIS_TO_SAMPLES(millis) ((millis) * (8000/1000))
|
||||
#define SAMPLES_TO_MILLIS(samples) ((samples) / (8000/1000))
|
||||
|
||||
#define SILENCE NULL
|
||||
|
||||
static RingCadence INSIDE_RING[] =
|
||||
{
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 1020 },
|
||||
{ SILENCE, 0, 3000 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static RingCadence OUTSIDE_RING[] =
|
||||
{
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 420 },
|
||||
{ SILENCE, 0, 200 },
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 420 },
|
||||
{ SILENCE, 0, 3000 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static RingCadence FEATURE_RING[] =
|
||||
{
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 240 },
|
||||
{ SILENCE, 0, 150 },
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 120 },
|
||||
{ SILENCE, 0, 150 },
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 360 },
|
||||
{ SILENCE, 0, 3000 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static RingCadence BELLCORE_DR1[] =
|
||||
{
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 1980 },
|
||||
{ SILENCE, 0, 4000 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static RingCadence BELLCORE_DR2[] =
|
||||
{
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 780 },
|
||||
{ SILENCE, 0, 400 },
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 780 },
|
||||
{ SILENCE, 0, 4000 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static RingCadence BELLCORE_DR3[] =
|
||||
{
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 420 },
|
||||
{ SILENCE, 0, 200 },
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 300 },
|
||||
{ SILENCE, 0, 200 },
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 780 },
|
||||
{ SILENCE, 0, 4000 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static RingCadence BELLCORE_DR4[] =
|
||||
{
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 300 },
|
||||
{ SILENCE, 0, 200 },
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 1020 },
|
||||
{ SILENCE, 0, 200 },
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 300 },
|
||||
{ SILENCE, 0, 4000 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static RingCadence BELLCORE_DR5[] =
|
||||
{
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 480 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static RingCadence FLASHONLY_RING[] =
|
||||
{
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static RingCadence PRECEDENCE_RING[] =
|
||||
{
|
||||
{ Ring1, sizeof(Ring1)/sizeof(short), 1680 },
|
||||
{ SILENCE, 0, 360 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static RingCadence* CadenceTable[] =
|
||||
{
|
||||
// Must remain in sync with RingMode in CSFMediaTermination.h
|
||||
|
||||
&INSIDE_RING[0],
|
||||
&OUTSIDE_RING[0],
|
||||
&FEATURE_RING[0],
|
||||
&BELLCORE_DR1[0],
|
||||
&BELLCORE_DR2[0],
|
||||
&BELLCORE_DR3[0],
|
||||
&BELLCORE_DR4[0],
|
||||
&BELLCORE_DR5[0],
|
||||
&FLASHONLY_RING[0],
|
||||
&PRECEDENCE_RING[0]
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
WebrtcRingGenerator::WebrtcRingGenerator( RingMode mode, bool once )
|
||||
: mode(mode), once(once), currentStep(0), done(false), scaleFactor(100)
|
||||
{
|
||||
timeRemaining = CadenceTable[mode]->stepDuration;
|
||||
// if sole entry is empty (FLASHONLY_RING case), generate no samples
|
||||
if ( timeRemaining == 0 ) done = true;
|
||||
}
|
||||
|
||||
void WebrtcRingGenerator::SetScaleFactor(int scaleFactor)
|
||||
{
|
||||
this->scaleFactor = scaleFactor;
|
||||
}
|
||||
|
||||
// Webrtc InStream implementation
|
||||
int WebrtcRingGenerator::Read( void *buf, int len /* bytes */ )
|
||||
{
|
||||
int result = generateTone( (short *)buf, len/sizeof(short) );
|
||||
applyScaleFactor( (short *)buf, len/sizeof(short) );
|
||||
return result;
|
||||
}
|
||||
|
||||
int WebrtcRingGenerator::generateTone( short *buf, int numSamples )
|
||||
{
|
||||
RingCadence* cadence = CadenceTable[mode];
|
||||
int samplesGenerated = 0;
|
||||
|
||||
while ( !done && samplesGenerated < numSamples )
|
||||
{
|
||||
RingCadence* step = &cadence[currentStep];
|
||||
|
||||
int samplesToCopy = min( numSamples, MILLIS_TO_SAMPLES(timeRemaining) );
|
||||
if ( step->samples != SILENCE )
|
||||
{
|
||||
int elapsedSamples = MILLIS_TO_SAMPLES(step->stepDuration - timeRemaining);
|
||||
int sampleOffset = elapsedSamples % step->sampleCnt;
|
||||
int samplesRemaining = step->sampleCnt - sampleOffset;
|
||||
|
||||
if ( samplesRemaining < samplesToCopy )
|
||||
samplesToCopy = samplesRemaining;
|
||||
|
||||
memcpy( buf, &step->samples[sampleOffset], samplesToCopy*sizeof(short) );
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( buf, 0, samplesToCopy*sizeof(short) );
|
||||
}
|
||||
samplesGenerated += samplesToCopy;
|
||||
timeRemaining -= SAMPLES_TO_MILLIS(samplesToCopy);
|
||||
|
||||
if ( timeRemaining <= 0 )
|
||||
{
|
||||
// if there's no SILENCE at the end of a sequence, it's a one-shot
|
||||
bool noSilence = (step->samples != SILENCE);
|
||||
|
||||
step = &cadence[++currentStep];
|
||||
if ( step->stepDuration == 0 ) // end of sequence, start over
|
||||
{
|
||||
step = cadence;
|
||||
currentStep = 0;
|
||||
|
||||
if ( once || noSilence ) // one-shot
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
timeRemaining = step->stepDuration;
|
||||
}
|
||||
}
|
||||
return samplesGenerated * sizeof(short);
|
||||
}
|
||||
|
||||
void WebrtcRingGenerator::applyScaleFactor( short *buf, int numSamples )
|
||||
{
|
||||
for(int i = 0; i < numSamples; i++)
|
||||
{
|
||||
buf[i] = (short)((buf[i] * scaleFactor)/100);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace CSF
|
||||
|
||||
#endif
|
|
@ -1,74 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef WebrtcRINGGENERATOR_H
|
||||
#define WebrtcRINGGENERATOR_H
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include <CSFAudioTermination.h>
|
||||
#include "common_types.h"
|
||||
|
||||
namespace CSF {
|
||||
|
||||
class WebrtcRingGenerator : public webrtc::InStream
|
||||
{
|
||||
public:
|
||||
WebrtcRingGenerator( RingMode mode, bool once );
|
||||
|
||||
// InStream interface
|
||||
int Read( void *buf, int len );
|
||||
void SetScaleFactor(int scaleFactor); // 0-100
|
||||
|
||||
private:
|
||||
RingMode mode;
|
||||
bool once;
|
||||
int currentStep;
|
||||
int timeRemaining; // in current step
|
||||
bool done;
|
||||
int scaleFactor;
|
||||
|
||||
int generateTone( short *buf, int numSamples );
|
||||
void applyScaleFactor( short *buf, int numSamples );
|
||||
};
|
||||
|
||||
} // namespace CSF
|
||||
|
||||
#endif
|
||||
#endif // WEBRTCRINGGENERATOR_H
|
|
@ -1,398 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
Webrtc*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include <string.h>
|
||||
#include "WebrtcToneGenerator.h"
|
||||
#include "CSFToneDefinitions.h"
|
||||
|
||||
namespace CSF {
|
||||
|
||||
static TONE_TABLE_TYPE ToneTable[] =
|
||||
{
|
||||
// Must remain in sync with ToneType in CSFMediaTermination.h
|
||||
|
||||
// INSIDE DIAL TONE pair (440 Hz, 350 Hz)
|
||||
{{{(short)TGN_INFINITE_REPEAT, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440, TGN_COEF_440}, {TGN_YN_2_350, TGN_COEF_350}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0002},
|
||||
|
||||
// OUTSIDE DIAL TONE pair (450 Hz, 548 Hz)
|
||||
{{{(short)TGN_INFINITE_REPEAT, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_450, TGN_COEF_450}, {TGN_YN_2_548, TGN_COEF_548}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0002},
|
||||
|
||||
// BUSY pair (480 Hz, 620 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(500), MILLISECONDS_TO_SAMPLES(500)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_480, TGN_COEF_480}, {TGN_YN_2_620, TGN_COEF_620}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0002},
|
||||
|
||||
// ALERTING pair (440 Hz, 480 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(2000), MILLISECONDS_TO_SAMPLES(4000)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440, TGN_COEF_440}, {TGN_YN_2_480, TGN_COEF_480}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0002},
|
||||
|
||||
// BUSY VERIFICATION tone (440 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(2000), MILLISECONDS_TO_SAMPLES(100)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440, TGN_COEF_440}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0000, 0x0002},
|
||||
|
||||
// STUTTER pair (350 Hz, 440 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(100), MILLISECONDS_TO_SAMPLES(100)}, {(short)TGN_INFINITE_REPEAT, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_350, TGN_COEF_350}, {TGN_YN_2_440, TGN_COEF_440}, {TGN_YN_2_350, TGN_COEF_350}, {TGN_YN_2_440, TGN_COEF_440}},
|
||||
{{9},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0022},
|
||||
|
||||
// MESSAGE WAITING pair (350 Hz, 440 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(100), MILLISECONDS_TO_SAMPLES(100)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_350, TGN_COEF_350}, {TGN_YN_2_440, TGN_COEF_440}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0009, 0x0002},
|
||||
|
||||
// REORDER pair (480 Hz, 620 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(250), MILLISECONDS_TO_SAMPLES(250)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_480, TGN_COEF_480}, {TGN_YN_2_620, TGN_COEF_620}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0002},
|
||||
|
||||
// CALL WAITING tone (440 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(400), MILLISECONDS_TO_SAMPLES(100)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440, TGN_COEF_440}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0000, 0x0001},
|
||||
|
||||
// CALL WAITING 2 tone (440 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(100), MILLISECONDS_TO_SAMPLES(100)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440, TGN_COEF_440}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0001, 0x0001},
|
||||
|
||||
// CALL WAITING 3 tone (440 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(100), MILLISECONDS_TO_SAMPLES(100)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440, TGN_COEF_440}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0002, 0x0001},
|
||||
|
||||
// CALL WAITING 4 tone (440 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(100), MILLISECONDS_TO_SAMPLES(100)}, {MILLISECONDS_TO_SAMPLES(300), MILLISECONDS_TO_SAMPLES(100)},
|
||||
{MILLISECONDS_TO_SAMPLES(100), 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440, TGN_COEF_440}, {TGN_YN_2_440, TGN_COEF_440}, {TGN_YN_2_440, TGN_COEF_440}, {TGN_YN_2_440, TGN_COEF_440}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0000, 0x0111},
|
||||
|
||||
// HOLD tone (500 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(100), MILLISECONDS_TO_SAMPLES(150)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_500, TGN_COEF_500}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0002, 0x0001},
|
||||
|
||||
// CONFIRMATION TONE pair (440 Hz, 350 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(100), MILLISECONDS_TO_SAMPLES(100)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440, TGN_COEF_440}, {TGN_YN_2_350, TGN_COEF_350}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0002, 0x0001},
|
||||
|
||||
// PERMANENT SIGNAL TONE (480 Hz)
|
||||
{{{(short)TGN_INFINITE_REPEAT, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_480, TGN_COEF_480}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0001},
|
||||
|
||||
// REMINDER RING pair (440 Hz, 480 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(500), MILLISECONDS_TO_SAMPLES(500)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440, TGN_COEF_440}, {TGN_YN_2_480, TGN_COEF_480}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0000, 0x0001},
|
||||
|
||||
// dummy
|
||||
{{{MILLISECONDS_TO_SAMPLES(250), MILLISECONDS_TO_SAMPLES(250)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_480, TGN_COEF_480}, {TGN_YN_2_620, TGN_COEF_620}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0002},
|
||||
|
||||
// ZIP ZIP tone (480 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(300), MILLISECONDS_TO_SAMPLES(100)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_480, TGN_COEF_480}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0001, 0x0001},
|
||||
|
||||
// ZIP tone (480 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(300), MILLISECONDS_TO_SAMPLES(100)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_480, TGN_COEF_480}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0000, 0x0001},
|
||||
|
||||
// BEEP BONK tone (1000 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(2000), MILLISECONDS_TO_SAMPLES(100)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_1000, TGN_COEF_1000}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0000, 0x0001},
|
||||
|
||||
// TODO: the next two don't quite match the definitions...
|
||||
|
||||
// RECORDING TONE - must use multiple offs to prevent overflow of short type
|
||||
{{{BEEP_REC_ON, BEEP_REC_OFF}, {0x0000, BEEP_REC_OFF}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_1400, TGN_COEF_1400}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0001},
|
||||
|
||||
// RECORDING TONE - must use multiple offs to prevent overflow of short type
|
||||
{{{BEEP_REC_ON, BEEP_REC_OFF}, {0x0000, BEEP_REC_OFF}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_1400, TGN_COEF_1400}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0001},
|
||||
|
||||
// MONITORING TONE - must use multiple offs to prevent overflow of short type
|
||||
{{{BEEP_MON_ON1, BEEP_MON_OFF1}, {BEEP_MON_ON2, BEEP_MON_OFF2},{0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_480, TGN_COEF_480}, {TGN_YN_2_480, TGN_COEF_480}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
TGN_INFINITE_REPEAT, 0x0011},
|
||||
|
||||
// SECURE TONE
|
||||
{{{MILLISECONDS_TO_SAMPLES(333), 0x0000}, {MILLISECONDS_TO_SAMPLES(333), 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_425, TGN_COEF_425}, {TGN_YN_2_300, TGN_COEF_300}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{0},{0},{0},{0}},
|
||||
0x0002, 0x0011},
|
||||
/*
|
||||
// 10 Milliwatt (1004 Hz, -15 dB)
|
||||
{{{0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_1MW_neg15dBm, TGN_COEF_1MW_neg15dBm}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{0,0,0,0},
|
||||
0x0000, 0x0001},
|
||||
|
||||
// 12 PRECEDENCE_RINGBACK_TONE - Precedence Ringback pair (440 Hz, 480 Hz), JIEO Technical Report 8249
|
||||
{{{MILLISECONDS_TO_SAMPLES(1640), MILLISECONDS_TO_SAMPLES(360)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440_PREC_RB, TGN_COEF_440_PREC_RB}, {TGN_YN_2_480_PREC_RB, TGN_COEF_480_PREC_RB}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{0,0,0,0},
|
||||
TGN_INFINITE_REPEAT, 0x0002},
|
||||
|
||||
// 13 PREEMPTION_TONE - Preemption pair (440 Hz, 620 Hz), JIEO Technical Report 8249
|
||||
{{{(short)TGN_INFINITE_REPEAT, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440_PREEMP, TGN_COEF_440_PREEMP}, {TGN_YN_2_620_PREEMP, TGN_COEF_620_PREEMP}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{0,0,0,0},
|
||||
TGN_INFINITE_REPEAT, 0x0002},
|
||||
|
||||
// 14 PRECEDENCE_CALL_WAITING_TONE - Precedence Call Waiting (440 Hz), JIEO Technical Report 8249
|
||||
// This tone is 3 short bursts followed by a 9.7 seconds of silience. Since we cannot
|
||||
// exceed 8.192 seconds (2 bytes), we split the 9.7 and used the last tone slot. (descriptor changed from 0x0111 to 0x1111)
|
||||
{{{MILLISECONDS_TO_SAMPLES(80), MILLISECONDS_TO_SAMPLES(20)}, {MILLISECONDS_TO_SAMPLES(80), MILLISECONDS_TO_SAMPLES(20)},
|
||||
{MILLISECONDS_TO_SAMPLES(80), 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_440_PREC_CW, TGN_COEF_440_PREC_CW}, {TGN_YN_2_440_PREC_CW, TGN_COEF_440_PREC_CW}, {TGN_YN_2_440_PREC_CW, TGN_COEF_440_PREC_CW}, {0x0000, 0x0000}},
|
||||
{0,0,0,0},
|
||||
0x0000, 0x1111},
|
||||
|
||||
// 15 MUTE ON tone (600 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(100), MILLISECONDS_TO_SAMPLES(100)}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_600, TGN_COEF_600}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{0,0,0,0},
|
||||
0x0000, 0x0001},
|
||||
|
||||
// 16 MUTE OFF tone (600 Hz)
|
||||
{{{MILLISECONDS_TO_SAMPLES(100), MILLISECONDS_TO_SAMPLES(100)}, {MILLISECONDS_TO_SAMPLES(100), MILLISECONDS_TO_SAMPLES(200)},
|
||||
{0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_600, TGN_COEF_600}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{0,0,0,0},
|
||||
0x0000, 0x0011},
|
||||
|
||||
// 26 Single beep - must use multiple offs to prevent overflow of short type
|
||||
{{{BEEP_REC_ON, BEEP_REC_OFF}, {0x0000, BEEP_REC_OFF}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_1400, TGN_COEF_1400}, {0x0000, 0x0000}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{0,0,0,0},
|
||||
0, 0x0001},
|
||||
|
||||
// 27 Single beep monitoring
|
||||
{{{BEEP_MON_ON1, BEEP_MON_OFF1}, {BEEP_MON_ON2, BEEP_MON_OFF2}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{{TGN_YN_2_480, TGN_COEF_480}, {TGN_YN_2_480, TGN_COEF_480}, {0x0000, 0x0000}, {0x0000, 0x0000}},
|
||||
{0,0,0,0},
|
||||
0, 0x0011},
|
||||
*/
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
WebrtcToneGenerator::WebrtcToneGenerator( ToneType type )
|
||||
{
|
||||
TONE_TABLE_TYPE *tone = &ToneTable[type];
|
||||
|
||||
// fill in tone memory
|
||||
m_SinewaveIdx = 0;
|
||||
m_CadenceIdx = 0;
|
||||
memcpy( m_Cadence, tone->Cadence, sizeof( m_Cadence ) );
|
||||
for ( int i = 0; i < MAX_TONEGENS; i++ )
|
||||
{
|
||||
m_Sinewave[i].Coef = tone->Coefmem[i].FilterCoef;
|
||||
m_Sinewave[i].Yn_1 = 0;
|
||||
m_Sinewave[i].Yn_2 = tone->Coefmem[i].FilterMemory;
|
||||
}
|
||||
m_RepeatCount = tone->RepeatCount;
|
||||
m_Descriptor = tone->Descriptor;
|
||||
|
||||
// set first sample
|
||||
m_Sample = m_Cadence[0];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void WebrtcToneGenerator::ToneGen( PSINEWAVE param, short *dst, unsigned long length, unsigned long numTones )
|
||||
{
|
||||
unsigned long j;
|
||||
unsigned long i;
|
||||
long A, B;
|
||||
short T;
|
||||
|
||||
memset( dst, 0, length * sizeof( short ) );
|
||||
|
||||
for ( i = 0; i < numTones; i++ )
|
||||
{
|
||||
for ( j = 0; j < length; j++ )
|
||||
{
|
||||
A = -(((long)param->Yn_2) << 15);
|
||||
T = param->Yn_1;
|
||||
param->Yn_2 = param->Yn_1;
|
||||
B = T * ((long)param->Coef) * 2;
|
||||
A = A + B;
|
||||
|
||||
// this is evidently intended to "clip", but I don't think the math really works...
|
||||
if ( A >= (long)2147483647 )
|
||||
{
|
||||
A = (long)2147483647;
|
||||
}
|
||||
if ( A <= (long)-2147483647 )
|
||||
{
|
||||
A = (long)-2147483647;
|
||||
}
|
||||
param->Yn_1 = (short)(A >> 15);
|
||||
dst[j] += (short)(A >> 15);
|
||||
}
|
||||
param++;
|
||||
}
|
||||
}
|
||||
|
||||
// Webrtc InStream implementation
|
||||
int WebrtcToneGenerator::Read( void *buf, int len )
|
||||
{
|
||||
return TGNGenerateTone( (short *)buf, (unsigned long)(len/sizeof(short)) ) ? len : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool WebrtcToneGenerator::TGNGenerateTone( short *dst, unsigned long length )
|
||||
{
|
||||
unsigned long numTone = 0;
|
||||
|
||||
// tone or silent period done
|
||||
if ( m_Sample == 0 )
|
||||
{
|
||||
// the current ON or OFF duration has expired
|
||||
|
||||
// go to the next ON or OFF duration
|
||||
m_CadenceIdx = (m_CadenceIdx + 1) & (MAX_CADENCES - 1);
|
||||
|
||||
// look for the next non-zero ON or OFF duration in the sequence
|
||||
while ( (m_CadenceIdx != 0) && (m_Cadence[m_CadenceIdx] == 0) )
|
||||
{
|
||||
m_CadenceIdx = (m_CadenceIdx + 1) & (MAX_CADENCES - 1);
|
||||
}
|
||||
|
||||
// set the duration to the next ON or OFF duration
|
||||
m_Sample = m_Cadence[m_CadenceIdx];
|
||||
|
||||
// the complete ON/OFF sequence has been done => decrease the number of repeats
|
||||
if ( m_CadenceIdx == 0 )
|
||||
{
|
||||
// reset to beginning of parameters
|
||||
m_SinewaveIdx = 0;
|
||||
|
||||
// finite number of repeats
|
||||
if ( m_RepeatCount != TGN_INFINITE_REPEAT )
|
||||
{
|
||||
// no more repeats -> stop the tone generator
|
||||
if ( m_RepeatCount <= 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RepeatCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// corresponds to the ON duration
|
||||
if ( (m_CadenceIdx & 0x1) == 0 )
|
||||
{
|
||||
numTone = (m_Descriptor >> (m_CadenceIdx << 1)) & 0xf;
|
||||
|
||||
ToneGen( &m_Sinewave[m_SinewaveIdx], dst, length, numTone );
|
||||
}
|
||||
else // insert silence
|
||||
{
|
||||
memset( dst, 0, length * sizeof( short ) );
|
||||
}
|
||||
|
||||
if ( m_Sample != TGN_INFINITE_REPEAT )
|
||||
{
|
||||
if ( (length) < m_Sample )
|
||||
{
|
||||
m_Sample -= length;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Sample = 0;
|
||||
}
|
||||
|
||||
if ( !m_Sample )
|
||||
{
|
||||
// corresponds to the ON duration
|
||||
if ( (m_CadenceIdx & 0x1) == 0 )
|
||||
{
|
||||
m_SinewaveIdx += numTone;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace CSF
|
||||
|
||||
#endif
|
|
@ -1,113 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef WebrtcTONEGENERATOR_H
|
||||
#define WebrtcTONEGENERATOR_H
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include <CSFAudioTermination.h>
|
||||
#include "common_types.h"
|
||||
|
||||
#define MAX_TONEGENS 4
|
||||
#define MAX_CADENCES 4
|
||||
#define MAX_REPEATCNTS 4
|
||||
#define TGN_INFINITE_REPEAT 65535L
|
||||
|
||||
#define TG_DESCRIPTOR_CADENCE_MASK 0xF // descriptor cadence mask
|
||||
#define TG_MAX_CADENCES MAX_CADENCES * sizeof(CADENCE_DURATION) / sizeof(unsigned short)
|
||||
#define TG_MAX_REPEATCNTS MAX_REPEATCNTS * sizeof (REPEAT_COUNT_TABLE) / sizeof(short)
|
||||
|
||||
namespace CSF {
|
||||
|
||||
typedef struct {
|
||||
short OnDuration;
|
||||
short OffDuration;
|
||||
} CADENCE_DURATION;
|
||||
|
||||
typedef struct {
|
||||
short FilterMemory;
|
||||
short FilterCoef;
|
||||
} FREQ_COEF_TABLE;
|
||||
|
||||
typedef struct {
|
||||
short RepeatCount;
|
||||
} REPEAT_COUNT_TABLE;
|
||||
|
||||
typedef struct {
|
||||
CADENCE_DURATION Cadence[MAX_CADENCES]; // on/off pairs
|
||||
FREQ_COEF_TABLE Coefmem[MAX_TONEGENS]; // coeff mem
|
||||
REPEAT_COUNT_TABLE rCount[MAX_REPEATCNTS];
|
||||
unsigned short RepeatCount;
|
||||
unsigned short Descriptor;
|
||||
} TONE_TABLE_TYPE, *PTONE_TABLE_TYPE;
|
||||
|
||||
class WebrtcToneGenerator : public webrtc::InStream
|
||||
{
|
||||
public:
|
||||
WebrtcToneGenerator( ToneType type );
|
||||
|
||||
// InStream interface
|
||||
int Read( void *buf, int len );
|
||||
|
||||
private:
|
||||
typedef struct {
|
||||
short Coef;
|
||||
short Yn_1;
|
||||
short Yn_2;
|
||||
} SINEWAVE, *PSINEWAVE;
|
||||
|
||||
SINEWAVE m_Sinewave[MAX_TONEGENS];
|
||||
unsigned long m_SinewaveIdx;
|
||||
unsigned short m_Cadence[TG_MAX_CADENCES];
|
||||
unsigned long m_CadenceIdx;
|
||||
short m_rCount[TG_MAX_REPEATCNTS];
|
||||
unsigned long m_Sample;
|
||||
int m_RepeatCount;
|
||||
unsigned short m_Descriptor;
|
||||
short m_CadenceRepeatCount;
|
||||
|
||||
bool TGNGenerateTone( short *dst, unsigned long length );
|
||||
void ToneGen( PSINEWAVE param, short *dst, unsigned long length, unsigned long numTones );
|
||||
};
|
||||
|
||||
} // namespace CSF
|
||||
|
||||
#endif
|
||||
#endif // WebrtcTONEGENERATOR_H
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,216 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef WebrtcVideoProvider_H_
|
||||
#define WebrtcVideoProvider_H_
|
||||
|
||||
#ifndef _USE_CPVE
|
||||
|
||||
#include <CSFVideoControl.h>
|
||||
#include <CSFVideoTermination.h>
|
||||
|
||||
#include "vie_base.h"
|
||||
#include "vie_codec.h"
|
||||
#include "vie_render.h"
|
||||
#include "vie_capture.h"
|
||||
#include "vie_rtp_rtcp.h"
|
||||
#include "vie_encryption.h"
|
||||
#include "vie_network.h"
|
||||
|
||||
#ifdef WIN32
|
||||
typedef HWND WebrtcPlatformWindow;
|
||||
#endif
|
||||
#ifdef LINUX
|
||||
typedef void* WebrtcPlatformWindow; // temporary placeholder
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
typedef void* WebrtcPlatformWindow;
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace CSF
|
||||
{
|
||||
|
||||
class WebrtcVideoStream
|
||||
{
|
||||
public:
|
||||
WebrtcVideoStream(int _streamId, int _channelId):
|
||||
streamId(_streamId), channelId(_channelId), isMuted(false), txInitialised(false)
|
||||
{}
|
||||
int streamId;
|
||||
int channelId;
|
||||
bool isMuted;
|
||||
bool txInitialised;
|
||||
};
|
||||
|
||||
class WebrtcMediaProvider;
|
||||
|
||||
DECLARE_PTR(WebrtcVideoStream);
|
||||
|
||||
class WebrtcVideoProvider : public VideoControl,
|
||||
VideoTermination,
|
||||
webrtc::ViEEncoderObserver,
|
||||
webrtc::ViEDecoderObserver,
|
||||
webrtc::ViERTPObserver
|
||||
{
|
||||
public:
|
||||
WebrtcVideoProvider( WebrtcMediaProvider* provider );
|
||||
~WebrtcVideoProvider();
|
||||
|
||||
// initialize members and Webrtc API
|
||||
// return 0 if initialzation succeeded
|
||||
int init();
|
||||
|
||||
// VideoMediaControl
|
||||
VideoControl* getMediaControl() { return this; }
|
||||
|
||||
void setVideoMode( bool enable );
|
||||
|
||||
std::vector<std::string> getCaptureDevices();
|
||||
|
||||
std::string getCaptureDevice() { return captureDevice; }
|
||||
bool setCaptureDevice( const std::string& name );
|
||||
|
||||
// VideoTermination
|
||||
VideoTermination* getMediaTermination() { return this; }
|
||||
|
||||
//VideoTermination APIs
|
||||
void setRemoteWindow( int streamId, VideoWindowHandle window );
|
||||
int setExternalRenderer( int streamId, VideoFormat videoFormat, ExternalRendererHandle renderer);
|
||||
|
||||
// window type is platform-specific
|
||||
void setPreviewWindow( VideoWindowHandle window, int top, int left, int bottom, int right, RenderScaling style );
|
||||
void showPreviewWindow( bool show ) {} // TODO
|
||||
|
||||
void sendIFrame ( int streamId );
|
||||
|
||||
// MediaTermination APIs
|
||||
int getCodecList( CodecRequestType requestType );
|
||||
|
||||
int rxAlloc ( int groupId, int streamId, int requestedPort );
|
||||
int rxOpen ( int groupId, int streamId, int requestedPort, int listenIp, bool isMulticast );
|
||||
int rxStart ( int groupId, int streamId, int payloadType, int packPeriod, int localPort, int rfc2833PayloadType,
|
||||
EncryptionAlgorithm algorithm, unsigned char* key, int keyLen, unsigned char* salt, int saltLen, int mode, int party);
|
||||
void rxClose ( int groupId, int streamId );
|
||||
void rxRelease ( int groupId, int streamId, int port );
|
||||
int txStart ( int groupId, int streamId, int payloadType, int packPeriod, bool vad, short tos,
|
||||
char* remoteIpAddr, int remotePort, int rfc2833PayloadType, EncryptionAlgorithm algorithm,
|
||||
unsigned char* key, int keyLen, unsigned char* salt, int saltLen, int mode, int party );
|
||||
void txClose ( int groupId, int streamId );
|
||||
|
||||
void setLocalIP ( const char* addr ) { localIP = addr; }
|
||||
void setMediaPorts ( int startPort, int endPort ) { this->startPort = startPort; this->endPort = endPort; }
|
||||
void setDSCPValue (int value){this->DSCPValue = value;}
|
||||
//void Print(const Webrtc::TraceLevel level, const char* message, const int length);
|
||||
|
||||
bool mute(int streamID, bool muteVideo);
|
||||
bool isMuted(int streamID);
|
||||
|
||||
bool setFullScreen(int streamId, bool fullScreen);
|
||||
void setRenderWindowForStreamIdFromMap(int streamId);
|
||||
void setAudioStreamId( int streamId );
|
||||
|
||||
protected:
|
||||
// DecoderObserver, EncoderObserver , RTP observer channel callbacks
|
||||
void RequestNewKeyFrame (int channel);
|
||||
void OutgoingRate ( int channel, unsigned int frameRate, unsigned int bitrate );
|
||||
void IncomingRate ( int channel, unsigned int frameRate, unsigned int bitrate );
|
||||
void IncomingCodecChanged ( int channel, const webrtc::VideoCodec& videoCodec);
|
||||
void IncomingCSRCChanged ( int channel, unsigned int csrc, bool added );
|
||||
void IncomingSSRCChanged ( int channel, unsigned int ssrc);
|
||||
|
||||
WebrtcVideoStreamPtr getStreamByChannel( int channel );
|
||||
|
||||
int getChannelForStreamId( int streamId );
|
||||
WebrtcVideoStreamPtr getStream( int streamId );
|
||||
void setMuteForStreamId( int streamId, bool muteVideo );
|
||||
void setTxInitiatedForStreamId( int streamId, bool txInitiatedValue );
|
||||
|
||||
class RenderWindow
|
||||
{
|
||||
public:
|
||||
RenderWindow( WebrtcPlatformWindow window )
|
||||
: window(window) {}
|
||||
|
||||
WebrtcPlatformWindow window;
|
||||
};
|
||||
|
||||
void setRenderWindow( int streamId, WebrtcPlatformWindow window);
|
||||
const RenderWindow* getRenderWindow( int streamId );
|
||||
|
||||
private:
|
||||
WebrtcMediaProvider* provider;
|
||||
webrtc::VideoEngine* vieVideo;
|
||||
webrtc::ViEBase* vieBase;
|
||||
webrtc::ViECapture* vieCapture;
|
||||
webrtc::ViERender* vieRender;
|
||||
webrtc::ViECodec* vieCodec;
|
||||
webrtc::ViENetwork* vieNetwork;
|
||||
webrtc::ViEEncryption* vieEncryption;
|
||||
webrtc::ViERTP_RTCP* vieRtpRtcp;
|
||||
std::map<int, RenderWindow> streamIdToWindow;
|
||||
std::map<int, WebrtcVideoStreamPtr> streamMap;
|
||||
std::string captureDevice;
|
||||
std::string capureDevieUniqueId;
|
||||
std::string localIP;
|
||||
bool videoMode;
|
||||
int startPort;
|
||||
int endPort;
|
||||
int localRenderId;
|
||||
int webCaptureId;
|
||||
int vp8Idx;
|
||||
RenderWindow* previewWindow;
|
||||
int DSCPValue;
|
||||
// Synchronisation (to avoid data corruption and worse given that so many threads call the media provider)
|
||||
// Never use this mutex in a callback from Webrtc - high probability of deadlock.
|
||||
Lock m_lock;
|
||||
// This mutex is to be held only for the narrowest possible scope while accessing the stream map
|
||||
// (but not while inspecting or changing a stream object).
|
||||
// Might be used in northbound and southbound calls.
|
||||
Lock streamMapMutex;
|
||||
int audioStreamId;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,731 @@
|
|||
/* 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/. */
|
||||
|
||||
// Original author: ekr@rtfm.com
|
||||
|
||||
#include "MediaPipeline.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "nspr.h"
|
||||
#include <prlog.h>
|
||||
#include "srtp.h"
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#include "VideoSegment.h"
|
||||
#include "Layers.h"
|
||||
#include "ImageTypes.h"
|
||||
#include "ImageContainer.h"
|
||||
#endif
|
||||
|
||||
#include "logging.h"
|
||||
#include "nsError.h"
|
||||
#include "AudioSegment.h"
|
||||
#include "MediaSegment.h"
|
||||
#include "transportflow.h"
|
||||
#include "transportlayer.h"
|
||||
#include "transportlayerdtls.h"
|
||||
#include "transportlayerice.h"
|
||||
|
||||
#include "runnable_utils.h"
|
||||
|
||||
#ifdef ERROR
|
||||
#undef ERROR
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// Logging context
|
||||
MOZ_MTLOG_MODULE("mediapipeline");
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static char kDTLSExporterLabel[] = "EXTRACTOR-dtls_srtp";
|
||||
|
||||
nsresult MediaPipeline::Init() {
|
||||
conduit_->AttachTransport(transport_);
|
||||
|
||||
PR_ASSERT(rtp_transport_);
|
||||
|
||||
nsresult res;
|
||||
|
||||
// TODO(ekr@rtfm.com): Danger....
|
||||
// Look to see if the transport is ready
|
||||
if (rtp_transport_->state() == TransportLayer::TS_OPEN) {
|
||||
res = TransportReady(rtp_transport_);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
} else {
|
||||
rtp_transport_->SignalStateChange.connect(this,
|
||||
&MediaPipeline::StateChange);
|
||||
|
||||
if (!muxed_) {
|
||||
if (rtcp_transport_->state() == TransportLayer::TS_OPEN) {
|
||||
res = TransportReady(rtcp_transport_);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
} else {
|
||||
rtcp_transport_->SignalStateChange.connect(this,
|
||||
&MediaPipeline::StateChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void MediaPipeline::DetachTransportInt() {
|
||||
transport_->Detach();
|
||||
}
|
||||
|
||||
void MediaPipeline::DetachTransport() {
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
WrapRunnable(this, &MediaPipeline::DetachTransportInt),
|
||||
NS_DISPATCH_SYNC);
|
||||
}
|
||||
|
||||
void MediaPipeline::StateChange(TransportFlow *flow, TransportLayer::State state) {
|
||||
// TODO(ekr@rtfm.com): check for double changes. This shouldn't happen,
|
||||
// but...
|
||||
if (state == TransportLayer::TS_OPEN) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Flow is ready");
|
||||
TransportReady(flow);
|
||||
} else if (state == TransportLayer::TS_CLOSED ||
|
||||
state == TransportLayer::TS_ERROR) {
|
||||
TransportFailed(flow);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::TransportReady(TransportFlow *flow) {
|
||||
bool rtcp = flow == rtp_transport_.get() ? false : true;
|
||||
nsresult res;
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Transport ready for flow " << (rtcp ? "rtcp" : "rtp"));
|
||||
|
||||
// Now instantiate the SRTP objects
|
||||
TransportLayerDtls *dtls = static_cast<TransportLayerDtls *>(
|
||||
flow->GetLayer(TransportLayerDtls::ID()));
|
||||
PR_ASSERT(dtls); // DTLS is mandatory
|
||||
|
||||
PRUint16 cipher_suite;
|
||||
res = dtls->GetSrtpCipher(&cipher_suite);
|
||||
if (NS_FAILED(res)) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Failed to negotiate DTLS-SRTP. This is an error");
|
||||
return res;
|
||||
}
|
||||
|
||||
// SRTP Key Exporter as per RFC 5764 S 4.2
|
||||
unsigned char srtp_block[SRTP_TOTAL_KEY_LENGTH * 2];
|
||||
res = dtls->ExportKeyingMaterial(kDTLSExporterLabel, false, "",
|
||||
srtp_block, sizeof(srtp_block));
|
||||
|
||||
// Slice and dice as per RFC 5764 S 4.2
|
||||
unsigned char client_write_key[SRTP_TOTAL_KEY_LENGTH];
|
||||
unsigned char server_write_key[SRTP_TOTAL_KEY_LENGTH];
|
||||
int offset = 0;
|
||||
memcpy(client_write_key, srtp_block + offset, SRTP_MASTER_KEY_LENGTH);
|
||||
offset += SRTP_MASTER_KEY_LENGTH;
|
||||
memcpy(server_write_key, srtp_block + offset, SRTP_MASTER_KEY_LENGTH);
|
||||
offset += SRTP_MASTER_KEY_LENGTH;
|
||||
memcpy(client_write_key + SRTP_MASTER_KEY_LENGTH,
|
||||
srtp_block + offset, SRTP_MASTER_SALT_LENGTH);
|
||||
offset += SRTP_MASTER_SALT_LENGTH;
|
||||
memcpy(server_write_key + SRTP_MASTER_KEY_LENGTH,
|
||||
srtp_block + offset, SRTP_MASTER_SALT_LENGTH);
|
||||
offset += SRTP_MASTER_SALT_LENGTH;
|
||||
PR_ASSERT(offset == sizeof(srtp_block));
|
||||
|
||||
unsigned char *write_key;
|
||||
unsigned char *read_key;
|
||||
|
||||
if (dtls->role() == TransportLayerDtls::CLIENT) {
|
||||
write_key = client_write_key;
|
||||
read_key = server_write_key;
|
||||
} else {
|
||||
write_key = server_write_key;
|
||||
read_key = client_write_key;
|
||||
}
|
||||
|
||||
if (!rtcp) {
|
||||
// RTP side
|
||||
PR_ASSERT(!rtp_send_srtp_ && !rtp_recv_srtp_);
|
||||
rtp_send_srtp_ = SrtpFlow::Create(cipher_suite, false,
|
||||
write_key, SRTP_TOTAL_KEY_LENGTH);
|
||||
rtp_recv_srtp_ = SrtpFlow::Create(cipher_suite, true,
|
||||
read_key, SRTP_TOTAL_KEY_LENGTH);
|
||||
if (!rtp_send_srtp_ || !rtp_recv_srtp_) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Couldn't create SRTP flow for RTCP");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Start listening
|
||||
if (muxed_) {
|
||||
PR_ASSERT(!rtcp_send_srtp_ && !rtcp_recv_srtp_);
|
||||
rtcp_send_srtp_ = rtp_send_srtp_;
|
||||
rtcp_recv_srtp_ = rtp_recv_srtp_;
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Listening for packets received on " <<
|
||||
static_cast<void *>(dtls->downward()));
|
||||
|
||||
dtls->downward()->SignalPacketReceived.connect(this,
|
||||
&MediaPipeline::
|
||||
PacketReceived);
|
||||
} else {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Listening for RTP packets received on " <<
|
||||
static_cast<void *>(dtls->downward()));
|
||||
|
||||
dtls->downward()->SignalPacketReceived.connect(this,
|
||||
&MediaPipeline::
|
||||
RtpPacketReceived);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PR_ASSERT(!rtcp_send_srtp_ && !rtcp_recv_srtp_);
|
||||
rtcp_send_srtp_ = SrtpFlow::Create(cipher_suite, false,
|
||||
write_key, SRTP_TOTAL_KEY_LENGTH);
|
||||
rtcp_recv_srtp_ = SrtpFlow::Create(cipher_suite, true,
|
||||
read_key, SRTP_TOTAL_KEY_LENGTH);
|
||||
if (!rtcp_send_srtp_ || !rtcp_recv_srtp_) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Couldn't create SRTCP flow for RTCP");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Listening for RTCP packets received on " <<
|
||||
static_cast<void *>(dtls->downward()));
|
||||
|
||||
// Start listening
|
||||
dtls->downward()->SignalPacketReceived.connect(this,
|
||||
&MediaPipeline::
|
||||
RtcpPacketReceived);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::TransportFailed(TransportFlow *flow) {
|
||||
bool rtcp = flow == rtp_transport_.get() ? false : true;
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Transport ready for flow " << (rtcp ? "rtcp" : "rtp"));
|
||||
|
||||
// TODO(ekr@rtfm.com): SECURITY: Figure out how to clean up if the
|
||||
// connection was good and now it is bad.
|
||||
// TODO(ekr@rtfm.com): Report up so that the PC knows we
|
||||
// have experienced an error.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::SendPacket(TransportFlow *flow, const void *data,
|
||||
int len) {
|
||||
// Note that we bypass the DTLS layer here
|
||||
TransportLayerDtls *dtls = static_cast<TransportLayerDtls *>(
|
||||
flow->GetLayer(TransportLayerDtls::ID()));
|
||||
PR_ASSERT(dtls);
|
||||
|
||||
TransportResult res = dtls->downward()->
|
||||
SendPacket(static_cast<const unsigned char *>(data), len);
|
||||
|
||||
if (res != len) {
|
||||
// Ignore blocking indications
|
||||
if (res == TE_WOULDBLOCK)
|
||||
return NS_OK;
|
||||
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Failed write on stream");
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void MediaPipeline::increment_rtp_packets_sent() {
|
||||
++rtp_packets_sent_;
|
||||
if (!(rtp_packets_sent_ % 1000)) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "RTP packet count " << static_cast<void *>(this)
|
||||
<< ": " << rtp_packets_sent_);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPipeline::increment_rtcp_packets_sent() {
|
||||
if (!(rtcp_packets_sent_ % 1000)) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "RTCP packet count " << static_cast<void *>(this)
|
||||
<< ": " << rtcp_packets_sent_);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPipeline::increment_rtp_packets_received() {
|
||||
++rtp_packets_received_;
|
||||
if (!(rtp_packets_received_ % 1000)) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "RTP packet count " << static_cast<void *>(this)
|
||||
<< ": " << rtp_packets_received_);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPipeline::increment_rtcp_packets_received() {
|
||||
if (!(rtcp_packets_received_ % 1000)) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "RTCP packet count " << static_cast<void *>(this)
|
||||
<< ": " << rtcp_packets_received_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MediaPipeline::RtpPacketReceived(TransportLayer *layer,
|
||||
const unsigned char *data,
|
||||
size_t len) {
|
||||
if (!transport_->pipeline()) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Discarding incoming packet; transport disconnected");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(ekr@rtfm.com): filter for DTLS here and in RtcpPacketReceived
|
||||
// TODO(ekr@rtfm.com): filter on SSRC for bundle
|
||||
increment_rtp_packets_received();
|
||||
|
||||
PR_ASSERT(rtp_recv_srtp_); // This should never happen
|
||||
|
||||
if (direction_ == TRANSMIT) {
|
||||
// Discard any media that is being transmitted to us
|
||||
// This will be unnecessary when we have SSRC filtering.
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a copy rather than cast away constness
|
||||
ScopedDeletePtr<unsigned char> inner_data(
|
||||
new unsigned char[len]);
|
||||
memcpy(inner_data, data, len);
|
||||
int out_len;
|
||||
nsresult res = rtp_recv_srtp_->UnprotectRtp(inner_data,
|
||||
len, len, &out_len);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return;
|
||||
|
||||
(void)conduit_->ReceivedRTPPacket(inner_data, out_len); // Ignore error codes
|
||||
}
|
||||
|
||||
void MediaPipeline::RtcpPacketReceived(TransportLayer *layer,
|
||||
const unsigned char *data,
|
||||
size_t len) {
|
||||
if (!transport_->pipeline()) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Discarding incoming packet; transport disconnected");
|
||||
return;
|
||||
}
|
||||
|
||||
increment_rtcp_packets_received();
|
||||
|
||||
PR_ASSERT(rtcp_recv_srtp_); // This should never happen
|
||||
|
||||
// Make a copy rather than cast away constness
|
||||
ScopedDeletePtr<unsigned char> inner_data(
|
||||
new unsigned char[len]);
|
||||
memcpy(inner_data, data, len);
|
||||
int out_len;
|
||||
|
||||
nsresult res = rtcp_recv_srtp_->UnprotectRtcp(inner_data, len, len, &out_len);
|
||||
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return;
|
||||
|
||||
(void)conduit_->ReceivedRTCPPacket(inner_data, out_len); // Ignore error codes
|
||||
}
|
||||
|
||||
bool MediaPipeline::IsRtp(const unsigned char *data, size_t len) {
|
||||
if (len < 2)
|
||||
return false;
|
||||
|
||||
// TODO(ekr@rtfm.com): this needs updating in light of RFC5761
|
||||
if ((data[1] >= 200) && (data[1] <= 204))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void MediaPipeline::PacketReceived(TransportLayer *layer,
|
||||
const unsigned char *data,
|
||||
size_t len) {
|
||||
if (!transport_->pipeline()) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Discarding incoming packet; transport disconnected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsRtp(data, len)) {
|
||||
RtpPacketReceived(layer, data, len);
|
||||
} else {
|
||||
RtcpPacketReceived(layer, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult MediaPipelineTransmit::Init() {
|
||||
// TODO(ekr@rtfm.com): Check for errors
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Attaching pipeline to stream " << static_cast<void *>(stream_) <<
|
||||
" conduit type=" << (conduit_->type() == MediaSessionConduit::AUDIO ?
|
||||
"audio" : "video") <<
|
||||
" hints=" << stream_->GetHintContents());
|
||||
|
||||
if (main_thread_) {
|
||||
main_thread_->Dispatch(WrapRunnable(
|
||||
stream_->GetStream(), &MediaStream::AddListener, listener_),
|
||||
NS_DISPATCH_SYNC);
|
||||
}
|
||||
else {
|
||||
stream_->GetStream()->AddListener(listener_);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::PipelineTransport::SendRtpPacket(
|
||||
const void *data, int len) {
|
||||
if (!pipeline_)
|
||||
return NS_OK; // Detached
|
||||
|
||||
if (!pipeline_->rtp_send_srtp_) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Couldn't write RTP packet; SRTP not set up yet");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_ASSERT(pipeline_->rtp_transport_);
|
||||
if (!pipeline_->rtp_transport_) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Couldn't write RTP packet (null flow)");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
// libsrtp enciphers in place, so we need a new, big enough
|
||||
// buffer.
|
||||
int max_len = len + SRTP_MAX_EXPANSION;
|
||||
ScopedDeletePtr<unsigned char> inner_data(
|
||||
new unsigned char[max_len]);
|
||||
memcpy(inner_data, data, len);
|
||||
|
||||
int out_len;
|
||||
nsresult res = pipeline_->rtp_send_srtp_->ProtectRtp(inner_data,
|
||||
len,
|
||||
max_len,
|
||||
&out_len);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
|
||||
pipeline_->increment_rtp_packets_sent();
|
||||
return pipeline_->SendPacket(pipeline_->rtp_transport_, inner_data,
|
||||
out_len);
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::PipelineTransport::SendRtcpPacket(
|
||||
const void *data, int len) {
|
||||
if (!pipeline_)
|
||||
return NS_OK; // Detached
|
||||
|
||||
if (!pipeline_->rtcp_send_srtp_) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Couldn't write RTCP packet; SRTCP not set up yet");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!pipeline_->rtcp_transport_) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Couldn't write RTCP packet (null flow)");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
// libsrtp enciphers in place, so we need a new, big enough
|
||||
// buffer.
|
||||
int max_len = len + SRTP_MAX_EXPANSION;
|
||||
ScopedDeletePtr<unsigned char> inner_data(
|
||||
new unsigned char[max_len]);
|
||||
memcpy(inner_data, data, len);
|
||||
|
||||
int out_len;
|
||||
nsresult res = pipeline_->rtcp_send_srtp_->ProtectRtcp(inner_data,
|
||||
len,
|
||||
max_len,
|
||||
&out_len);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
|
||||
pipeline_->increment_rtcp_packets_sent();
|
||||
return pipeline_->SendPacket(pipeline_->rtcp_transport_, inner_data,
|
||||
out_len);
|
||||
}
|
||||
|
||||
void MediaPipelineTransmit::PipelineListener::
|
||||
NotifyQueuedTrackChanges(MediaStreamGraph* graph, TrackID tid,
|
||||
TrackRate rate,
|
||||
TrackTicks offset,
|
||||
PRUint32 events,
|
||||
const MediaSegment& queued_media) {
|
||||
if (!pipeline_)
|
||||
return; // Detached
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "MediaPipeline::NotifyQueuedTrackChanges()");
|
||||
|
||||
// Return early if we are not connected to avoid queueing stuff
|
||||
// up in the conduit
|
||||
if (pipeline_->rtp_transport_->state() != TransportLayer::TS_OPEN) {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Transport not ready yet, dropping packets");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(ekr@rtfm.com): For now assume that we have only one
|
||||
// track type and it's destined for us
|
||||
if (queued_media.GetType() == MediaSegment::AUDIO) {
|
||||
if (pipeline_->conduit_->type() != MediaSessionConduit::AUDIO) {
|
||||
// Ignore data in case we have a muxed stream
|
||||
return;
|
||||
}
|
||||
AudioSegment* audio = const_cast<AudioSegment *>(
|
||||
static_cast<const AudioSegment *>(&queued_media));
|
||||
|
||||
AudioSegment::ChunkIterator iter(*audio);
|
||||
while(!iter.IsEnded()) {
|
||||
pipeline_->ProcessAudioChunk(static_cast<AudioSessionConduit *>
|
||||
(pipeline_->conduit_.get()),
|
||||
rate, *iter);
|
||||
iter.Next();
|
||||
}
|
||||
} else if (queued_media.GetType() == MediaSegment::VIDEO) {
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
if (pipeline_->conduit_->type() != MediaSessionConduit::VIDEO) {
|
||||
// Ignore data in case we have a muxed stream
|
||||
return;
|
||||
}
|
||||
VideoSegment* video = const_cast<VideoSegment *>(
|
||||
static_cast<const VideoSegment *>(&queued_media));
|
||||
|
||||
VideoSegment::ChunkIterator iter(*video);
|
||||
while(!iter.IsEnded()) {
|
||||
pipeline_->ProcessVideoChunk(static_cast<VideoSessionConduit *>
|
||||
(pipeline_->conduit_.get()),
|
||||
rate, *iter);
|
||||
iter.Next();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPipelineTransmit::ProcessAudioChunk(AudioSessionConduit *conduit,
|
||||
TrackRate rate,
|
||||
AudioChunk& chunk) {
|
||||
// TODO(ekr@rtfm.com): Do more than one channel
|
||||
nsAutoArrayPtr<int16_t> samples(new int16_t[chunk.mDuration]);
|
||||
|
||||
if (chunk.mBuffer) {
|
||||
switch(chunk.mBufferFormat) {
|
||||
case nsAudioStream::FORMAT_U8:
|
||||
case nsAudioStream::FORMAT_FLOAT32:
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Can't process audio exceptin 16-bit PCM yet");
|
||||
PR_ASSERT(PR_FALSE);
|
||||
return;
|
||||
break;
|
||||
case nsAudioStream::FORMAT_S16:
|
||||
{
|
||||
// Code based on nsAudioStream
|
||||
const short* buf = static_cast<const short *>(chunk.mBuffer->Data());
|
||||
|
||||
PRInt32 volume = PRInt32((1 << 16) * chunk.mVolume);
|
||||
for (PRUint32 i = 0; i < chunk.mDuration; ++i) {
|
||||
int16_t s = buf[i];
|
||||
#if defined(IS_BIG_ENDIAN)
|
||||
s = ((s & 0x00ff) << 8) | ((s & 0xff00) >> 8);
|
||||
#endif
|
||||
samples[i] = short((PRInt32(s) * volume) >> 16);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(PR_FALSE);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (PRUint32 i = 0; i < chunk.mDuration; ++i) {
|
||||
samples[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Sending an audio frame");
|
||||
conduit->SendAudioFrame(samples.get(), chunk.mDuration, rate, 0);
|
||||
}
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
void MediaPipelineTransmit::ProcessVideoChunk(VideoSessionConduit *conduit,
|
||||
TrackRate rate,
|
||||
VideoChunk& chunk) {
|
||||
// We now need to send the video frame to the other side
|
||||
layers::Image *img = chunk.mFrame.GetImage();
|
||||
|
||||
ImageFormat format = img->GetFormat();
|
||||
|
||||
if (format != PLANAR_YCBCR) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Can't process non-YCBCR video");
|
||||
PR_ASSERT(PR_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cast away constness b/c some of the accessors are non-const
|
||||
layers::PlanarYCbCrImage* yuv =
|
||||
const_cast<layers::PlanarYCbCrImage *>(
|
||||
static_cast<const layers::PlanarYCbCrImage *>(img));
|
||||
|
||||
// TODO(ekr@rtfm.com): Is this really how we get the length?
|
||||
// It's the inverse of the code in MediaEngineDefault
|
||||
unsigned int length = ((yuv->GetSize().width * yuv->GetSize().height) * 3 / 2);
|
||||
|
||||
// Big-time assumption here that this is all contiguous data coming
|
||||
// from Anant's version of gUM. This code here is an attempt to double-check
|
||||
// that
|
||||
PR_ASSERT(length == yuv->GetDataSize());
|
||||
if (length != yuv->GetDataSize())
|
||||
return;
|
||||
|
||||
// OK, pass it on to the conduit
|
||||
// TODO(ekr@rtfm.com): Check return value
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Sending a video frame");
|
||||
conduit->SendVideoFrame(yuv->mBuffer.get(), yuv->GetDataSize(),
|
||||
yuv->GetSize().width, yuv->GetSize().height, kVideoI420, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult MediaPipelineReceiveAudio::Init() {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, __FUNCTION__);
|
||||
if (main_thread_) {
|
||||
main_thread_->Dispatch(WrapRunnable(
|
||||
stream_->GetStream(), &MediaStream::AddListener, listener_),
|
||||
NS_DISPATCH_SYNC);
|
||||
}
|
||||
else {
|
||||
stream_->GetStream()->AddListener(listener_);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void MediaPipelineReceiveAudio::PipelineListener::
|
||||
NotifyPull(MediaStreamGraph* graph, StreamTime total) {
|
||||
if (!pipeline_)
|
||||
return; // Detached
|
||||
|
||||
SourceMediaStream *source =
|
||||
pipeline_->stream_->GetStream()->AsSourceStream();
|
||||
|
||||
PR_ASSERT(source);
|
||||
if (!source) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "NotifyPull() called from a non-SourceMediaStream");
|
||||
return;
|
||||
}
|
||||
|
||||
// "total" is absolute stream time.
|
||||
// StreamTime desired = total - played_;
|
||||
played_ = total;
|
||||
//double time_s = MediaTimeToSeconds(desired);
|
||||
|
||||
// Number of 10 ms samples we need
|
||||
//int num_samples = ceil(time_s / .01f);
|
||||
|
||||
// Doesn't matter what was asked for, always give 160 samples per 10 ms.
|
||||
int num_samples = 1;
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Asking for " << num_samples << "sample from Audio Conduit");
|
||||
|
||||
if (num_samples <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (num_samples--) {
|
||||
// TODO(ekr@rtfm.com): Is there a way to avoid mallocating here?
|
||||
nsRefPtr<SharedBuffer> samples = SharedBuffer::Create(1000);
|
||||
int samples_length;
|
||||
|
||||
MediaConduitErrorCode err =
|
||||
static_cast<AudioSessionConduit*>(pipeline_->conduit_.get())->GetAudioFrame(
|
||||
static_cast<int16_t *>(samples->Data()),
|
||||
16000, // Sampling rate fixed at 16 kHz for now
|
||||
0, // TODO(ekr@rtfm.com): better estimate of capture delay
|
||||
samples_length);
|
||||
|
||||
if (err != kMediaConduitNoError)
|
||||
return;
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Audio conduit returned buffer of length " << samples_length);
|
||||
|
||||
AudioSegment segment;
|
||||
segment.Init(1);
|
||||
segment.AppendFrames(samples.forget(), samples_length,
|
||||
0, samples_length, nsAudioStream::FORMAT_S16);
|
||||
|
||||
char buf[32];
|
||||
PR_snprintf(buf, 32, "%p", source);
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Appended audio segments to stream " << buf);
|
||||
source->AppendToTrack(1, // TODO(ekr@rtfm.com): Track ID
|
||||
&segment);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult MediaPipelineReceiveVideo::Init() {
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, __FUNCTION__);
|
||||
|
||||
static_cast<VideoSessionConduit *>(conduit_.get())->
|
||||
AttachRenderer(renderer_);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MediaPipelineReceiveVideo::PipelineRenderer::PipelineRenderer(
|
||||
MediaPipelineReceiveVideo *pipeline) :
|
||||
pipeline_(pipeline),
|
||||
width_(640), height_(480) {
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
image_container_ = layers::LayerManager::CreateImageContainer();
|
||||
SourceMediaStream *source =
|
||||
pipeline_->stream_->GetStream()->AsSourceStream();
|
||||
source->AddTrack(1, 30, 0, new VideoSegment());
|
||||
source->AdvanceKnownTracksTime(STREAM_TIME_MAX);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MediaPipelineReceiveVideo::PipelineRenderer::RenderVideoFrame(
|
||||
const unsigned char* buffer,
|
||||
unsigned int buffer_size,
|
||||
uint32_t time_stamp,
|
||||
int64_t render_time) {
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
SourceMediaStream *source =
|
||||
pipeline_->stream_->GetStream()->AsSourceStream();
|
||||
|
||||
// Create a video frame and append it to the track.
|
||||
ImageFormat format = PLANAR_YCBCR;
|
||||
nsRefPtr<layers::Image> image = image_container_->CreateImage(&format, 1);
|
||||
|
||||
layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
|
||||
PRUint8* frame = const_cast<PRUint8*>(static_cast<const PRUint8*> (buffer));
|
||||
const PRUint8 lumaBpp = 8;
|
||||
const PRUint8 chromaBpp = 4;
|
||||
|
||||
layers::PlanarYCbCrImage::Data data;
|
||||
data.mYChannel = frame;
|
||||
data.mYSize = gfxIntSize(width_, height_);
|
||||
data.mYStride = width_ * lumaBpp/ 8;
|
||||
data.mCbCrStride = width_ * chromaBpp / 8;
|
||||
data.mCbChannel = frame + height_ * data.mYStride;
|
||||
data.mCrChannel = data.mCbChannel + height_ * data.mCbCrStride / 2;
|
||||
data.mCbCrSize = gfxIntSize(width_/ 2, height_/ 2);
|
||||
data.mPicX = 0;
|
||||
data.mPicY = 0;
|
||||
data.mPicSize = gfxIntSize(width_, height_);
|
||||
data.mStereoMode = STEREO_MODE_MONO;
|
||||
|
||||
videoImage->SetData(data);
|
||||
|
||||
VideoSegment segment;
|
||||
char buf[32];
|
||||
PR_snprintf(buf, 32, "%p", source);
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Appended video segments to stream " << buf);
|
||||
|
||||
segment.AppendFrame(image.forget(), 1, gfxIntSize(width_, height_));
|
||||
source->AppendToTrack(1, &(segment));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
|
|
@ -0,0 +1,363 @@
|
|||
/* 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/. */
|
||||
|
||||
// Original author: ekr@rtfm.com
|
||||
|
||||
#ifndef mediapipeline_h__
|
||||
#define mediapipeline_h__
|
||||
|
||||
#include "sigslot.h"
|
||||
|
||||
#ifdef USE_FAKE_MEDIA_STREAMS
|
||||
#include "FakeMediaStreams.h"
|
||||
#else
|
||||
#include "nsDOMMediaStream.h"
|
||||
#endif
|
||||
#include "MediaConduitInterface.h"
|
||||
#include "AudioSegment.h"
|
||||
#include "SrtpFlow.h"
|
||||
#include "transportflow.h"
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#include "VideoSegment.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// A class that represents the pipeline of audio and video
|
||||
// The dataflow looks like:
|
||||
//
|
||||
// TRANSMIT
|
||||
// CaptureDevice -> stream -> [us] -> conduit -> [us] -> transport -> network
|
||||
//
|
||||
// RECEIVE
|
||||
// network -> transport -> [us] -> conduit -> [us] -> stream -> Playout
|
||||
//
|
||||
// The boxes labeled [us] are just bridge logic implemented in this class
|
||||
class MediaPipeline : public sigslot::has_slots<> {
|
||||
public:
|
||||
enum Direction { TRANSMIT, RECEIVE };
|
||||
|
||||
MediaPipeline(Direction direction,
|
||||
nsCOMPtr<nsIEventTarget> main_thread,
|
||||
nsCOMPtr<nsIEventTarget> sts_thread,
|
||||
nsDOMMediaStream* stream,
|
||||
RefPtr<MediaSessionConduit> conduit,
|
||||
mozilla::RefPtr<TransportFlow> rtp_transport,
|
||||
mozilla::RefPtr<TransportFlow> rtcp_transport) :
|
||||
direction_(direction),
|
||||
stream_(stream),
|
||||
conduit_(conduit),
|
||||
rtp_transport_(rtp_transport),
|
||||
rtcp_transport_(rtcp_transport),
|
||||
main_thread_(main_thread),
|
||||
sts_thread_(sts_thread),
|
||||
transport_(new PipelineTransport(this)),
|
||||
rtp_send_srtp_(),
|
||||
rtcp_send_srtp_(),
|
||||
rtp_recv_srtp_(),
|
||||
rtcp_recv_srtp_(),
|
||||
rtp_packets_sent_(0),
|
||||
rtcp_packets_sent_(0),
|
||||
rtp_packets_received_(0),
|
||||
rtcp_packets_received_(0),
|
||||
muxed_((rtcp_transport_ == NULL) || (rtp_transport_ == rtcp_transport_)) {
|
||||
Init();
|
||||
}
|
||||
|
||||
virtual ~MediaPipeline() {
|
||||
DetachTransport();
|
||||
}
|
||||
|
||||
virtual nsresult Init();
|
||||
|
||||
virtual Direction direction() const { return direction_; }
|
||||
|
||||
virtual void DetachMediaStream() {}
|
||||
virtual void DetachTransport();
|
||||
|
||||
int rtp_packets_sent() const { return rtp_packets_sent_; }
|
||||
int rtcp_packets_sent() const { return rtp_packets_sent_; }
|
||||
int rtp_packets_received() const { return rtp_packets_received_; }
|
||||
int rtcp_packets_received() const { return rtp_packets_received_; }
|
||||
|
||||
// Thread counting
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaPipeline)
|
||||
|
||||
protected:
|
||||
// Separate class to allow ref counting
|
||||
class PipelineTransport : public TransportInterface {
|
||||
public:
|
||||
// Implement the TransportInterface functions
|
||||
PipelineTransport(MediaPipeline *pipeline) :
|
||||
pipeline_(pipeline) {}
|
||||
void Detach() { pipeline_ = NULL; }
|
||||
MediaPipeline *pipeline() const { return pipeline_; }
|
||||
|
||||
virtual nsresult SendRtpPacket(const void* data, int len);
|
||||
virtual nsresult SendRtcpPacket(const void* data, int len);
|
||||
|
||||
private:
|
||||
MediaPipeline *pipeline_; // Raw pointer to avoid cycles
|
||||
};
|
||||
friend class PipelineTransport;
|
||||
|
||||
virtual nsresult TransportReady(TransportFlow *flow); // The transport is ready
|
||||
virtual nsresult TransportFailed(TransportFlow *flow); // The transport is down
|
||||
|
||||
void increment_rtp_packets_sent();
|
||||
void increment_rtcp_packets_sent();
|
||||
void increment_rtp_packets_received();
|
||||
void increment_rtcp_packets_received();
|
||||
|
||||
virtual nsresult SendPacket(TransportFlow *flow, const void* data, int len);
|
||||
|
||||
// Process slots on transports
|
||||
void StateChange(TransportFlow *flow, TransportLayer::State);
|
||||
void RtpPacketReceived(TransportLayer *layer, const unsigned char *data,
|
||||
size_t len);
|
||||
void RtcpPacketReceived(TransportLayer *layer, const unsigned char *data,
|
||||
size_t len);
|
||||
void PacketReceived(TransportLayer *layer, const unsigned char *data,
|
||||
size_t len);
|
||||
|
||||
|
||||
Direction direction_;
|
||||
nsDOMMediaStream* stream_;
|
||||
RefPtr<MediaSessionConduit> conduit_;
|
||||
RefPtr<TransportFlow> rtp_transport_;
|
||||
RefPtr<TransportFlow> rtcp_transport_;
|
||||
nsCOMPtr<nsIEventTarget> main_thread_;
|
||||
nsCOMPtr<nsIEventTarget> sts_thread_;
|
||||
mozilla::RefPtr<PipelineTransport> transport_;
|
||||
bool transport_connected_;
|
||||
mozilla::RefPtr<SrtpFlow> rtp_send_srtp_;
|
||||
mozilla::RefPtr<SrtpFlow> rtcp_send_srtp_;
|
||||
mozilla::RefPtr<SrtpFlow> rtp_recv_srtp_;
|
||||
mozilla::RefPtr<SrtpFlow> rtcp_recv_srtp_;
|
||||
int rtp_packets_sent_;
|
||||
int rtcp_packets_sent_;
|
||||
int rtp_packets_received_;
|
||||
int rtcp_packets_received_;
|
||||
bool muxed_;
|
||||
|
||||
private:
|
||||
virtual void DetachTransportInt();
|
||||
|
||||
bool IsRtp(const unsigned char *data, size_t len);
|
||||
};
|
||||
|
||||
|
||||
// A specialization of pipeline for reading from an input device
|
||||
// and transmitting to the network.
|
||||
class MediaPipelineTransmit : public MediaPipeline {
|
||||
public:
|
||||
MediaPipelineTransmit(nsCOMPtr<nsIEventTarget> main_thread,
|
||||
nsCOMPtr<nsIEventTarget> sts_thread,
|
||||
nsDOMMediaStream* stream,
|
||||
RefPtr<MediaSessionConduit> conduit,
|
||||
mozilla::RefPtr<TransportFlow> rtp_transport,
|
||||
mozilla::RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipeline(TRANSMIT, main_thread, sts_thread,
|
||||
stream, conduit, rtp_transport,
|
||||
rtcp_transport),
|
||||
listener_(new PipelineListener(this)) {
|
||||
Init(); // TODO(ekr@rtfm.com): ignoring error
|
||||
}
|
||||
|
||||
// Initialize (stuff here may fail)
|
||||
nsresult Init();
|
||||
|
||||
virtual ~MediaPipelineTransmit() {
|
||||
if (stream_ && listener_){
|
||||
stream_->GetStream()->RemoveListener(listener_);
|
||||
|
||||
// These shouldn't be necessary, but just to make sure
|
||||
// that if we have messed up ownership somehow the
|
||||
// interfaces just abort.
|
||||
listener_->Detach();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void DetachMediaStream() {
|
||||
// TODO(ekr@rtfm.com): Are multiple removes a problem?
|
||||
stream_->GetStream()->RemoveListener(listener_);
|
||||
stream_ = NULL;
|
||||
listener_->Detach();
|
||||
}
|
||||
|
||||
// Separate class to allow ref counting
|
||||
class PipelineListener : public MediaStreamListener {
|
||||
public:
|
||||
PipelineListener(MediaPipelineTransmit *pipeline) :
|
||||
pipeline_(pipeline) {}
|
||||
void Detach() { pipeline_ = NULL; }
|
||||
|
||||
|
||||
// Implement MediaStreamListener
|
||||
virtual void NotifyQueuedTrackChanges(MediaStreamGraph* graph, TrackID tid,
|
||||
TrackRate rate,
|
||||
TrackTicks offset,
|
||||
PRUint32 events,
|
||||
const MediaSegment& queued_media);
|
||||
virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) {}
|
||||
|
||||
private:
|
||||
MediaPipelineTransmit *pipeline_; // Raw pointer to avoid cycles
|
||||
};
|
||||
friend class PipelineListener;
|
||||
|
||||
private:
|
||||
virtual void ProcessAudioChunk(AudioSessionConduit *conduit,
|
||||
TrackRate rate, mozilla::AudioChunk& chunk);
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
virtual void ProcessVideoChunk(VideoSessionConduit *conduit,
|
||||
TrackRate rate, mozilla::VideoChunk& chunk);
|
||||
#endif
|
||||
mozilla::RefPtr<PipelineListener> listener_;
|
||||
};
|
||||
|
||||
|
||||
// A specialization of pipeline for reading from the network and
|
||||
// rendering video.
|
||||
class MediaPipelineReceive : public MediaPipeline {
|
||||
public:
|
||||
MediaPipelineReceive(nsCOMPtr<nsIEventTarget> main_thread,
|
||||
nsCOMPtr<nsIEventTarget> sts_thread,
|
||||
nsDOMMediaStream* stream,
|
||||
RefPtr<MediaSessionConduit> conduit,
|
||||
mozilla::RefPtr<TransportFlow> rtp_transport,
|
||||
mozilla::RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipeline(RECEIVE, main_thread, sts_thread,
|
||||
stream, conduit, rtp_transport,
|
||||
rtcp_transport),
|
||||
segments_added_(0) {
|
||||
}
|
||||
|
||||
int segments_added() const { return segments_added_; }
|
||||
|
||||
protected:
|
||||
int segments_added_;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
// A specialization of pipeline for reading from the network and
|
||||
// rendering audio.
|
||||
class MediaPipelineReceiveAudio : public MediaPipelineReceive {
|
||||
public:
|
||||
MediaPipelineReceiveAudio(nsCOMPtr<nsIEventTarget> main_thread,
|
||||
nsCOMPtr<nsIEventTarget> sts_thread,
|
||||
nsDOMMediaStream* stream,
|
||||
RefPtr<AudioSessionConduit> conduit,
|
||||
mozilla::RefPtr<TransportFlow> rtp_transport,
|
||||
mozilla::RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipelineReceive(main_thread, sts_thread,
|
||||
stream, conduit, rtp_transport,
|
||||
rtcp_transport),
|
||||
listener_(new PipelineListener(this)) {
|
||||
Init();
|
||||
}
|
||||
|
||||
~MediaPipelineReceiveAudio() {
|
||||
if (stream_ && listener_) {
|
||||
stream_->GetStream()->RemoveListener(listener_);
|
||||
listener_->Detach();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void DetachMediaStream() {
|
||||
// TODO(ekr@rtfm.com): Are multiple removes a problem?
|
||||
stream_->GetStream()->RemoveListener(listener_);
|
||||
stream_ = NULL;
|
||||
listener_->Detach();
|
||||
}
|
||||
|
||||
private:
|
||||
// Separate class to allow ref counting
|
||||
class PipelineListener : public MediaStreamListener {
|
||||
public:
|
||||
PipelineListener(MediaPipelineReceiveAudio *pipeline)
|
||||
: pipeline_(pipeline)
|
||||
, played_(0) {}
|
||||
void Detach() { pipeline_ = NULL; }
|
||||
|
||||
// Implement MediaStreamListener
|
||||
virtual void NotifyQueuedTrackChanges(MediaStreamGraph* graph, TrackID tid,
|
||||
TrackRate rate,
|
||||
TrackTicks offset,
|
||||
PRUint32 events,
|
||||
const MediaSegment& queued_media) {}
|
||||
virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime);
|
||||
|
||||
private:
|
||||
MediaPipelineReceiveAudio *pipeline_; // Raw pointer to avoid cycles
|
||||
StreamTime played_;
|
||||
};
|
||||
friend class PipelineListener;
|
||||
|
||||
nsresult Init();
|
||||
|
||||
mozilla::RefPtr<PipelineListener> listener_;
|
||||
};
|
||||
|
||||
|
||||
// A specialization of pipeline for reading from the network and
|
||||
// rendering video.
|
||||
class MediaPipelineReceiveVideo : public MediaPipelineReceive {
|
||||
public:
|
||||
MediaPipelineReceiveVideo(nsCOMPtr<nsIEventTarget> main_thread,
|
||||
nsCOMPtr<nsIEventTarget> sts_thread,
|
||||
nsDOMMediaStream* stream,
|
||||
RefPtr<VideoSessionConduit> conduit,
|
||||
mozilla::RefPtr<TransportFlow> rtp_transport,
|
||||
mozilla::RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipelineReceive(main_thread, sts_thread,
|
||||
stream, conduit, rtp_transport,
|
||||
rtcp_transport),
|
||||
renderer_(new PipelineRenderer(this)) {
|
||||
Init();
|
||||
}
|
||||
|
||||
~MediaPipelineReceiveVideo() {
|
||||
}
|
||||
|
||||
private:
|
||||
class PipelineRenderer : public mozilla::VideoRenderer {
|
||||
public:
|
||||
PipelineRenderer(MediaPipelineReceiveVideo *);
|
||||
void Detach() { pipeline_ = NULL; }
|
||||
|
||||
// Implement VideoRenderer
|
||||
virtual void FrameSizeChange(unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int number_of_streams) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
}
|
||||
|
||||
virtual void RenderVideoFrame(const unsigned char* buffer,
|
||||
unsigned int buffer_size,
|
||||
uint32_t time_stamp,
|
||||
int64_t render_time);
|
||||
|
||||
|
||||
private:
|
||||
MediaPipelineReceiveVideo *pipeline_; // Raw pointer to avoid cycles
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
nsRefPtr<layers::ImageContainer> image_container_;
|
||||
#endif
|
||||
int width_;
|
||||
int height_;
|
||||
};
|
||||
friend class PipelineRenderer;
|
||||
|
||||
nsresult Init();
|
||||
mozilla::RefPtr<PipelineRenderer> renderer_;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace
|
||||
#endif
|
|
@ -0,0 +1,248 @@
|
|||
/* 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/. */
|
||||
|
||||
// Original author: ekr@rtfm.com
|
||||
|
||||
#include "SrtpFlow.h"
|
||||
|
||||
#include "srtp.h"
|
||||
#include "ssl.h"
|
||||
#include "sslproto.h"
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
// Logging context
|
||||
using namespace mozilla;
|
||||
MOZ_MTLOG_MODULE("mediapipeline");
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool SrtpFlow::initialized; // Static
|
||||
|
||||
SrtpFlow::~SrtpFlow() {
|
||||
if (policy_) {
|
||||
delete policy_;
|
||||
}
|
||||
if (session_) {
|
||||
srtp_dealloc(session_);
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<SrtpFlow> SrtpFlow::Create(int cipher_suite,
|
||||
bool inbound,
|
||||
const void *key,
|
||||
size_t key_len) {
|
||||
nsresult res = Init();
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return NULL;
|
||||
|
||||
RefPtr<SrtpFlow> flow = new SrtpFlow();
|
||||
|
||||
if (!key) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Null SRTP key specified");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (key_len != SRTP_TOTAL_KEY_LENGTH) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Invalid SRTP key length");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// First create the policy
|
||||
flow->policy_ = new srtp_policy_t();
|
||||
memset(flow->policy_, 0, sizeof(srtp_policy_t));
|
||||
|
||||
// Note that we set the same cipher suite for RTP and RTCP
|
||||
// since any flow can only have one cipher suite with DTLS-SRTP
|
||||
switch (cipher_suite) {
|
||||
case SRTP_AES128_CM_HMAC_SHA1_80:
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Setting SRTP cipher suite SRTP_AES128_CM_HMAC_SHA1_80");
|
||||
crypto_policy_set_aes_cm_128_hmac_sha1_80(&flow->policy_->rtp);
|
||||
crypto_policy_set_aes_cm_128_hmac_sha1_80(&flow->policy_->rtcp);
|
||||
break;
|
||||
case SRTP_AES128_CM_HMAC_SHA1_32:
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Setting SRTP cipher suite SRTP_AES128_CM_HMAC_SHA1_32");
|
||||
crypto_policy_set_aes_cm_128_hmac_sha1_32(&flow->policy_->rtp);
|
||||
crypto_policy_set_aes_cm_128_hmac_sha1_32(&flow->policy_->rtcp);
|
||||
break;
|
||||
default:
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Request to set unknown SRTP cipher suite");
|
||||
return NULL;
|
||||
}
|
||||
flow->policy_->key = const_cast<unsigned char *>(
|
||||
static_cast<const unsigned char *>(key));
|
||||
flow->policy_->ssrc.type = inbound ? ssrc_any_inbound : ssrc_any_outbound;
|
||||
flow->policy_->ssrc.value = 0;
|
||||
flow->policy_->ekt = NULL;
|
||||
flow->policy_->window_size = 1024; // TODO(ekr@rtfm.com): how to set?
|
||||
flow->policy_->allow_repeat_tx = 0; // TODO(ekr@rtfm.com): revisit?
|
||||
flow->policy_->next = NULL;
|
||||
|
||||
// Now make the session
|
||||
err_status_t r = srtp_create(&flow->session_, flow->policy_);
|
||||
if (r != err_status_ok) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Error creating srtp session");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return flow;
|
||||
}
|
||||
|
||||
|
||||
nsresult SrtpFlow::CheckInputs(bool protect, void *in, int in_len,
|
||||
int max_len, int *out_len) {
|
||||
PR_ASSERT(in);
|
||||
if (!in) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "NULL input value");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (in_len < 0) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Input length is negative");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (max_len < 0) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Max output length is negative");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (protect) {
|
||||
if ((max_len < SRTP_MAX_EXPANSION) ||
|
||||
((max_len - SRTP_MAX_EXPANSION) < in_len)) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Output too short");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (in_len > max_len) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Output too short");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SrtpFlow::ProtectRtp(void *in, int in_len,
|
||||
int max_len, int *out_len) {
|
||||
nsresult res = CheckInputs(true, in, in_len, max_len, out_len);
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
int len = in_len;
|
||||
err_status_t r = srtp_protect(session_, in, &len);
|
||||
|
||||
if (r != err_status_ok) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Error protecting SRTP packet");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PR_ASSERT(len < max_len);
|
||||
*out_len = len;
|
||||
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Successfully protected an SRTP packet of len " << *out_len);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SrtpFlow::UnprotectRtp(void *in, int in_len,
|
||||
int max_len, int *out_len) {
|
||||
nsresult res = CheckInputs(false, in, in_len, max_len, out_len);
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
int len = in_len;
|
||||
err_status_t r = srtp_unprotect(session_, in, &len);
|
||||
|
||||
if (r != err_status_ok) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Error unprotecting SRTP packet");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PR_ASSERT(len < max_len);
|
||||
*out_len = len;
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Successfully unprotected an SRTP packet of len " << *out_len);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SrtpFlow::ProtectRtcp(void *in, int in_len,
|
||||
int max_len, int *out_len) {
|
||||
nsresult res = CheckInputs(true, in, in_len, max_len, out_len);
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
int len = in_len;
|
||||
err_status_t r = srtp_protect_rtcp(session_, in, &len);
|
||||
|
||||
if (r != err_status_ok) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Error protecting SRTCP packet");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PR_ASSERT(len <= max_len);
|
||||
*out_len = len;
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Successfully protected an SRTCP packet of len " << *out_len);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SrtpFlow::UnprotectRtcp(void *in, int in_len,
|
||||
int max_len, int *out_len) {
|
||||
nsresult res = CheckInputs(false, in, in_len, max_len, out_len);
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
int len = in_len;
|
||||
err_status_t r = srtp_unprotect_rtcp(session_, in, &len);
|
||||
|
||||
if (r != err_status_ok) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Error unprotecting SRTCP packet");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PR_ASSERT(len <= max_len);
|
||||
*out_len = len;
|
||||
|
||||
MOZ_MTLOG(PR_LOG_DEBUG, "Successfully unprotected an SRTCP packet of len " << *out_len);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Statics
|
||||
void SrtpFlow::srtp_event_handler(srtp_event_data_t *data) {
|
||||
// TODO(ekr@rtfm.com): Implement this
|
||||
abort();
|
||||
}
|
||||
|
||||
nsresult SrtpFlow::Init() {
|
||||
if (!initialized) {
|
||||
err_status_t r = srtp_init();
|
||||
if (r != err_status_ok) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Could not initialize SRTP");
|
||||
PR_ASSERT(PR_FALSE);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
r = srtp_install_event_handler(&SrtpFlow::srtp_event_handler);
|
||||
if (r != err_status_ok) {
|
||||
MOZ_MTLOG(PR_LOG_ERROR, "Could not install SRTP event handler");
|
||||
PR_ASSERT(PR_FALSE);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // end of namespace
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/* 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/. */
|
||||
|
||||
// Original author: ekr@rtfm.com
|
||||
|
||||
#ifndef srtpflow_h__
|
||||
#define srtpflow_h__
|
||||
|
||||
#include "ssl.h"
|
||||
#include "sslproto.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
typedef struct srtp_policy_t srtp_policy_t;
|
||||
typedef struct srtp_ctx_t *srtp_t;
|
||||
typedef struct srtp_event_data_t srtp_event_data_t;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#define SRTP_MASTER_KEY_LENGTH 16
|
||||
#define SRTP_MASTER_SALT_LENGTH 14
|
||||
#define SRTP_TOTAL_KEY_LENGTH (SRTP_MASTER_KEY_LENGTH + SRTP_MASTER_SALT_LENGTH)
|
||||
|
||||
// For some reason libsrtp increases packet size by > 12 for RTCP even though
|
||||
// the doc claims otherwise.
|
||||
#define SRTP_MAX_EXPANSION 20
|
||||
|
||||
|
||||
class SrtpFlow {
|
||||
public:
|
||||
~SrtpFlow();
|
||||
|
||||
|
||||
static mozilla::RefPtr<SrtpFlow> Create(int cipher_suite,
|
||||
bool inbound,
|
||||
const void *key,
|
||||
size_t key_len);
|
||||
|
||||
nsresult ProtectRtp(void *in, int in_len,
|
||||
int max_len, int *out_len);
|
||||
nsresult UnprotectRtp(void *in, int in_len,
|
||||
int max_len, int *out_len);
|
||||
nsresult ProtectRtcp(void *in, int in_len,
|
||||
int max_len, int *out_len);
|
||||
nsresult UnprotectRtcp(void *in, int in_len,
|
||||
int max_len, int *out_len);
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SrtpFlow)
|
||||
|
||||
static void srtp_event_handler(srtp_event_data_t *data);
|
||||
|
||||
|
||||
private:
|
||||
SrtpFlow() : policy_(NULL), session_(NULL) {}
|
||||
|
||||
nsresult CheckInputs(bool protect, void *in, int in_len,
|
||||
int max_len, int *out_len);
|
||||
|
||||
static nsresult Init();
|
||||
static bool initialized; // Was SRTP initialized?
|
||||
|
||||
srtp_policy_t *policy_;
|
||||
srtp_t session_;
|
||||
};
|
||||
|
||||
} // End of namespace
|
||||
#endif
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include "CallControlManager.h"
|
||||
#include "CC_Device.h"
|
||||
#include "CC_Call.h"
|
||||
#include "CC_Observer.h"
|
||||
#include "ccapi_call_info.h"
|
||||
#include "CC_SIPCCCallInfo.h"
|
||||
#include "ccapi_device_info.h"
|
||||
#include "CC_SIPCCDeviceInfo.h"
|
||||
#include "CSFLog.h"
|
||||
#include "vcm.h"
|
||||
#include "PeerConnectionImpl.h"
|
||||
#include "PeerConnectionCtx.h"
|
||||
#include "cpr_socket.h"
|
||||
|
||||
static const char* logTag = "PeerConnectionCtx";
|
||||
|
||||
namespace sipcc {
|
||||
|
||||
PeerConnectionCtx* PeerConnectionCtx::instance;
|
||||
|
||||
PeerConnectionCtx* PeerConnectionCtx::GetInstance() {
|
||||
if (instance)
|
||||
return instance;
|
||||
|
||||
CSFLogDebug(logTag, "Creating PeerConnectionCtx");
|
||||
PeerConnectionCtx *ctx = new PeerConnectionCtx();
|
||||
|
||||
nsresult res = ctx->Initialize();
|
||||
PR_ASSERT(NS_SUCCEEDED(res));
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return NULL;
|
||||
|
||||
instance = ctx;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void PeerConnectionCtx::Destroy() {
|
||||
instance->Cleanup();
|
||||
delete instance;
|
||||
instance = NULL;
|
||||
}
|
||||
|
||||
nsresult PeerConnectionCtx::Initialize() {
|
||||
mCCM = CSF::CallControlManager::create();
|
||||
|
||||
NS_ENSURE_TRUE(mCCM.get(), NS_ERROR_FAILURE);
|
||||
|
||||
// Add the local audio codecs
|
||||
// FIX - Get this list from MediaEngine instead
|
||||
int codecMask = 0;
|
||||
codecMask |= VCM_CODEC_RESOURCE_G711;
|
||||
codecMask |= VCM_CODEC_RESOURCE_OPUS;
|
||||
//codecMask |= VCM_CODEC_RESOURCE_LINEAR;
|
||||
//codecMask |= VCM_CODEC_RESOURCE_G722;
|
||||
//codecMask |= VCM_CODEC_RESOURCE_iLBC;
|
||||
//codecMask |= VCM_CODEC_RESOURCE_iSAC;
|
||||
mCCM->setAudioCodecs(codecMask);
|
||||
|
||||
//Add the local video codecs
|
||||
// FIX - Get this list from MediaEngine instead
|
||||
// Turning them all on for now
|
||||
codecMask = 0;
|
||||
// Only adding codecs supported
|
||||
//codecMask |= VCM_CODEC_RESOURCE_H263;
|
||||
|
||||
//codecMask |= VCM_CODEC_RESOURCE_H264;
|
||||
codecMask |= VCM_CODEC_RESOURCE_VP8;
|
||||
//codecMask |= VCM_CODEC_RESOURCE_I420;
|
||||
mCCM->setVideoCodecs(codecMask);
|
||||
|
||||
if (!mCCM->startSDPMode())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mCCM->addCCObserver(this);
|
||||
mDevice = mCCM->getActiveDevice();
|
||||
NS_ENSURE_TRUE(mDevice.get(), NS_ERROR_FAILURE);
|
||||
ChangeSipccState(PeerConnectionImpl::kStarting);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PeerConnectionCtx::Cleanup() {
|
||||
mCCM->destroy();
|
||||
mCCM->removeCCObserver(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
CSF::CC_CallPtr PeerConnectionCtx::createCall() {
|
||||
return mDevice->createCall();
|
||||
}
|
||||
|
||||
void PeerConnectionCtx::onDeviceEvent(ccapi_device_event_e aDeviceEvent,
|
||||
CSF::CC_DevicePtr aDevice,
|
||||
CSF::CC_DeviceInfoPtr aInfo ) {
|
||||
CSFLogDebug(logTag, "onDeviceEvent()");
|
||||
cc_service_state_t state = aInfo->getServiceState();
|
||||
|
||||
if (CC_STATE_INS == state) {
|
||||
// SIPCC is up
|
||||
if (PeerConnectionImpl::kStarting == mSipccState ||
|
||||
PeerConnectionImpl::kIdle == mSipccState) {
|
||||
ChangeSipccState(PeerConnectionImpl::kStarted);
|
||||
} else {
|
||||
CSFLogError(logTag, "%s PeerConnection in wrong state", __FUNCTION__);
|
||||
Cleanup();
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
}
|
||||
} else {
|
||||
Cleanup();
|
||||
NS_NOTREACHED("Unsupported Signaling State Transition");
|
||||
}
|
||||
}
|
||||
|
||||
// Demux the call event to the right PeerConnection
|
||||
void PeerConnectionCtx::onCallEvent(ccapi_call_event_e aCallEvent,
|
||||
CSF::CC_CallPtr aCall,
|
||||
CSF::CC_CallInfoPtr aInfo) {
|
||||
CSFLogDebug(logTag, "onCallEvent()");
|
||||
mozilla::ScopedDeletePtr<PeerConnectionWrapper> pc(
|
||||
PeerConnectionImpl::AcquireInstance(
|
||||
aCall->getPeerConnection()));
|
||||
|
||||
if (!pc) // This must be an event on a dead PC. Ignore
|
||||
return;
|
||||
|
||||
CSFLogDebug(logTag, "Calling PC");
|
||||
pc->impl()->onCallEvent(aCallEvent, aCall, aInfo);
|
||||
}
|
||||
|
||||
} // namespace sipcc
|
|
@ -0,0 +1,90 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef peerconnectionctx_h___h__
|
||||
#define peerconnectionctx_h___h__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "CallControlManager.h"
|
||||
#include "CC_Device.h"
|
||||
#include "CC_Call.h"
|
||||
#include "CC_Observer.h"
|
||||
|
||||
#include "PeerConnectionImpl.h"
|
||||
|
||||
namespace sipcc {
|
||||
|
||||
// Currently SIPCC only allows a single stack instance to exist in a process
|
||||
// at once. This class implements a singleton object that wraps that
|
||||
// instance. It also hosts the observer class that demuxes events onto
|
||||
// individual PCs.
|
||||
class PeerConnectionCtx : public CSF::CC_Observer {
|
||||
public:
|
||||
static PeerConnectionCtx* GetInstance();
|
||||
static void Destroy();
|
||||
|
||||
// Implementations of CC_Observer methods
|
||||
virtual void onDeviceEvent(ccapi_device_event_e deviceEvent, CSF::CC_DevicePtr device, CSF::CC_DeviceInfoPtr info);
|
||||
virtual void onFeatureEvent(ccapi_device_event_e deviceEvent, CSF::CC_DevicePtr device, CSF::CC_FeatureInfoPtr feature_info) {}
|
||||
virtual void onLineEvent(ccapi_line_event_e lineEvent, CSF::CC_LinePtr line, CSF::CC_LineInfoPtr info) {}
|
||||
virtual void onCallEvent(ccapi_call_event_e callEvent, CSF::CC_CallPtr call, CSF::CC_CallInfoPtr info);
|
||||
|
||||
// Create a SIPCC Call
|
||||
CSF::CC_CallPtr createCall();
|
||||
|
||||
PeerConnectionImpl::SipccState sipcc_state() { return mSipccState; }
|
||||
|
||||
private:
|
||||
PeerConnectionCtx() : mSipccState(PeerConnectionImpl::kIdle),
|
||||
mCCM(NULL), mDevice(NULL) {}
|
||||
// This is a singleton, so don't copy construct it, etc.
|
||||
PeerConnectionCtx(const PeerConnectionCtx& other) MOZ_DELETE;
|
||||
void operator=(const PeerConnectionCtx& other) MOZ_DELETE;
|
||||
virtual ~PeerConnectionCtx() {};
|
||||
|
||||
nsresult Initialize();
|
||||
nsresult Cleanup();
|
||||
|
||||
void ChangeSipccState(PeerConnectionImpl::SipccState aState) {
|
||||
mSipccState = aState;
|
||||
}
|
||||
|
||||
// SIPCC objects
|
||||
PeerConnectionImpl::SipccState mSipccState; // TODO(ekr@rtfm.com): refactor this out? What does it do?
|
||||
CSF::CallControlManagerPtr mCCM;
|
||||
CSF::CC_DevicePtr mDevice;
|
||||
|
||||
static PeerConnectionCtx *instance;
|
||||
};
|
||||
|
||||
} // namespace sipcc
|
||||
|
||||
#endif
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,472 @@
|
|||
/* 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 _PEER_CONNECTION_IMPL_H_
|
||||
#define _PEER_CONNECTION_IMPL_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cmath>
|
||||
|
||||
#include "prlock.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "IPeerConnection.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
#ifdef USE_FAKE_MEDIA_STREAMS
|
||||
#include "FakeMediaStreams.h"
|
||||
#else
|
||||
#include "nsDOMMediaStream.h"
|
||||
#endif
|
||||
|
||||
#include "dtlsidentity.h"
|
||||
#include "nricectx.h"
|
||||
#include "nricemediastream.h"
|
||||
|
||||
#include "peer_connection_types.h"
|
||||
#include "CallControlManager.h"
|
||||
#include "CC_Device.h"
|
||||
#include "CC_Call.h"
|
||||
#include "CC_Observer.h"
|
||||
#include "MediaPipeline.h"
|
||||
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#include "mozilla/net/DataChannel.h"
|
||||
#include "Layers.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "ImageLayers.h"
|
||||
#include "VideoSegment.h"
|
||||
#else
|
||||
namespace mozilla {
|
||||
class DataChannel;
|
||||
}
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace sipcc {
|
||||
|
||||
/* Temporary for providing audio data */
|
||||
class Fake_AudioGenerator {
|
||||
public:
|
||||
Fake_AudioGenerator(nsDOMMediaStream* aStream) : mStream(aStream), mCount(0) {
|
||||
mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
PR_ASSERT(mTimer);
|
||||
|
||||
// Make a track
|
||||
mozilla::AudioSegment *segment = new mozilla::AudioSegment();
|
||||
segment->Init(1); // 1 Channel
|
||||
mStream->GetStream()->AsSourceStream()->AddTrack(1, 16000, 0, segment);
|
||||
|
||||
// Set the timer
|
||||
mTimer->InitWithFuncCallback(Callback, this, 100, nsITimer::TYPE_REPEATING_PRECISE);
|
||||
}
|
||||
|
||||
static void Callback(nsITimer* timer, void *arg) {
|
||||
Fake_AudioGenerator* gen = static_cast<Fake_AudioGenerator*>(arg);
|
||||
|
||||
nsRefPtr<mozilla::SharedBuffer> samples = mozilla::SharedBuffer::Create(1600 * 2 * sizeof(int16_t));
|
||||
for (int i=0; i<1600*2; i++) {
|
||||
reinterpret_cast<int16_t *>(samples->Data())[i] = ((gen->mCount % 8) * 4000) - (7*4000)/2;
|
||||
++gen->mCount;
|
||||
}
|
||||
|
||||
mozilla::AudioSegment segment;
|
||||
segment.Init(1);
|
||||
segment.AppendFrames(samples.forget(), 1600,
|
||||
0, 1600, nsAudioStream::FORMAT_S16);
|
||||
|
||||
gen->mStream->GetStream()->AsSourceStream()->AppendToTrack(1, &segment);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsRefPtr<nsDOMMediaStream> mStream;
|
||||
int mCount;
|
||||
};
|
||||
|
||||
/* Temporary for providing video data */
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
class Fake_VideoGenerator {
|
||||
public:
|
||||
Fake_VideoGenerator(nsDOMMediaStream* aStream) {
|
||||
mStream = aStream;
|
||||
mCount = 0;
|
||||
mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
PR_ASSERT(mTimer);
|
||||
|
||||
// Make a track
|
||||
mozilla::VideoSegment *segment = new mozilla::VideoSegment();
|
||||
mStream->GetStream()->AsSourceStream()->AddTrack(1, USECS_PER_S, 0, segment);
|
||||
mStream->GetStream()->AsSourceStream()->AdvanceKnownTracksTime(mozilla::STREAM_TIME_MAX);
|
||||
|
||||
// Set the timer. Set to 10 fps.
|
||||
mTimer->InitWithFuncCallback(Callback, this, 100, nsITimer::TYPE_REPEATING_SLACK);
|
||||
}
|
||||
|
||||
static void Callback(nsITimer* timer, void *arg) {
|
||||
Fake_VideoGenerator* gen = static_cast<Fake_VideoGenerator*>(arg);
|
||||
|
||||
const PRUint32 WIDTH = 640;
|
||||
const PRUint32 HEIGHT = 480;
|
||||
|
||||
// Allocate a single blank Image
|
||||
mozilla::ImageFormat format = mozilla::PLANAR_YCBCR;
|
||||
nsRefPtr<mozilla::layers::ImageContainer> container =
|
||||
mozilla::layers::LayerManager::CreateImageContainer();
|
||||
|
||||
nsRefPtr<mozilla::layers::Image> image = container->CreateImage(&format, 1);
|
||||
|
||||
int len = ((WIDTH * HEIGHT) * 3 / 2);
|
||||
mozilla::layers::PlanarYCbCrImage* planar =
|
||||
static_cast<mozilla::layers::PlanarYCbCrImage*>(image.get());
|
||||
PRUint8* frame = (PRUint8*) PR_Malloc(len);
|
||||
++gen->mCount;
|
||||
memset(frame, (gen->mCount / 8) & 0xff, len); // Rotating colors
|
||||
|
||||
const PRUint8 lumaBpp = 8;
|
||||
const PRUint8 chromaBpp = 4;
|
||||
|
||||
mozilla::layers::PlanarYCbCrImage::Data data;
|
||||
data.mYChannel = frame;
|
||||
data.mYSize = gfxIntSize(WIDTH, HEIGHT);
|
||||
data.mYStride = (PRInt32) (WIDTH * lumaBpp / 8.0);
|
||||
data.mCbCrStride = (PRInt32) (WIDTH * chromaBpp / 8.0);
|
||||
data.mCbChannel = frame + HEIGHT * data.mYStride;
|
||||
data.mCrChannel = data.mCbChannel + HEIGHT * data.mCbCrStride / 2;
|
||||
data.mCbCrSize = gfxIntSize(WIDTH / 2, HEIGHT / 2);
|
||||
data.mPicX = 0;
|
||||
data.mPicY = 0;
|
||||
data.mPicSize = gfxIntSize(WIDTH, HEIGHT);
|
||||
data.mStereoMode = mozilla::STEREO_MODE_MONO;
|
||||
|
||||
// SetData copies data, so we can free the frame
|
||||
planar->SetData(data);
|
||||
PR_Free(frame);
|
||||
|
||||
// AddTrack takes ownership of segment
|
||||
mozilla::VideoSegment *segment = new mozilla::VideoSegment();
|
||||
// 10 fps.
|
||||
segment->AppendFrame(image.forget(), USECS_PER_S / 10, gfxIntSize(WIDTH, HEIGHT));
|
||||
|
||||
gen->mStream->GetStream()->AsSourceStream()->AppendToTrack(1, segment);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsRefPtr<nsDOMMediaStream> mStream;
|
||||
int mCount;
|
||||
};
|
||||
#endif
|
||||
|
||||
class LocalSourceStreamInfo : public mozilla::MediaStreamListener {
|
||||
public:
|
||||
LocalSourceStreamInfo(nsDOMMediaStream* aMediaStream)
|
||||
: mMediaStream(aMediaStream) {}
|
||||
~LocalSourceStreamInfo() {
|
||||
mMediaStream = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify that changes to one of the stream tracks have been queued.
|
||||
* aTrackEvents can be any combination of TRACK_EVENT_CREATED and
|
||||
* TRACK_EVENT_ENDED. aQueuedMedia is the data being added to the track
|
||||
* at aTrackOffset (relative to the start of the stream).
|
||||
*/
|
||||
virtual void NotifyQueuedTrackChanges(
|
||||
mozilla::MediaStreamGraph* aGraph,
|
||||
mozilla::TrackID aID,
|
||||
mozilla::TrackRate aTrackRate,
|
||||
mozilla::TrackTicks aTrackOffset,
|
||||
PRUint32 aTrackEvents,
|
||||
const mozilla::MediaSegment& aQueuedMedia
|
||||
);
|
||||
|
||||
virtual void NotifyPull(mozilla::MediaStreamGraph* aGraph,
|
||||
mozilla::StreamTime aDesiredTime) {}
|
||||
|
||||
nsDOMMediaStream* GetMediaStream() {
|
||||
return mMediaStream;
|
||||
}
|
||||
void StorePipeline(int aTrack, mozilla::RefPtr<mozilla::MediaPipeline> aPipeline);
|
||||
|
||||
void ExpectAudio(const mozilla::TrackID);
|
||||
void ExpectVideo(const mozilla::TrackID);
|
||||
unsigned AudioTrackCount();
|
||||
unsigned VideoTrackCount();
|
||||
|
||||
void Detach() {
|
||||
// Disconnect my own listener
|
||||
GetMediaStream()->GetStream()->RemoveListener(this);
|
||||
|
||||
// walk through all the MediaPipelines and disconnect them.
|
||||
for (std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> >::iterator it =
|
||||
mPipelines.begin(); it != mPipelines.end();
|
||||
++it) {
|
||||
it->second->DetachMediaStream();
|
||||
}
|
||||
mMediaStream = NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> > mPipelines;
|
||||
nsRefPtr<nsDOMMediaStream> mMediaStream;
|
||||
nsTArray<mozilla::TrackID> mAudioTracks;
|
||||
nsTArray<mozilla::TrackID> mVideoTracks;
|
||||
};
|
||||
|
||||
class RemoteSourceStreamInfo {
|
||||
public:
|
||||
RemoteSourceStreamInfo(nsDOMMediaStream* aMediaStream) :
|
||||
mMediaStream(aMediaStream),
|
||||
mPipelines() {}
|
||||
|
||||
nsDOMMediaStream* GetMediaStream() {
|
||||
return mMediaStream;
|
||||
}
|
||||
void StorePipeline(int aTrack, mozilla::RefPtr<mozilla::MediaPipeline> aPipeline);
|
||||
|
||||
void Detach() {
|
||||
// walk through all the MediaPipelines and disconnect them.
|
||||
for (std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> >::iterator it =
|
||||
mPipelines.begin(); it != mPipelines.end();
|
||||
++it) {
|
||||
it->second->DetachMediaStream();
|
||||
}
|
||||
mMediaStream = NULL;
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteSourceStreamInfo)
|
||||
private:
|
||||
nsRefPtr<nsDOMMediaStream> mMediaStream;
|
||||
std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> > mPipelines;
|
||||
};
|
||||
|
||||
class PeerConnectionWrapper;
|
||||
|
||||
class PeerConnectionImpl MOZ_FINAL : public IPeerConnection,
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
public mozilla::DataChannelConnection::DataConnectionListener,
|
||||
#endif
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
PeerConnectionImpl();
|
||||
~PeerConnectionImpl();
|
||||
|
||||
enum ReadyState {
|
||||
kNew,
|
||||
kNegotiating,
|
||||
kActive,
|
||||
kClosing,
|
||||
kClosed
|
||||
};
|
||||
|
||||
enum SipccState {
|
||||
kIdle,
|
||||
kStarting,
|
||||
kStarted
|
||||
};
|
||||
|
||||
// TODO(ekr@rtfm.com): make this conform to the specifications
|
||||
enum IceState {
|
||||
kIceGathering,
|
||||
kIceWaiting,
|
||||
kIceChecking,
|
||||
kIceConnected,
|
||||
kIceFailed
|
||||
};
|
||||
|
||||
enum Role {
|
||||
kRoleUnknown,
|
||||
kRoleOfferer,
|
||||
kRoleAnswerer
|
||||
};
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_IPEERCONNECTION
|
||||
|
||||
static PeerConnectionImpl* CreatePeerConnection();
|
||||
static void Shutdown();
|
||||
|
||||
Role GetRole() const { return mRole; }
|
||||
nsresult CreateRemoteSourceStreamInfo(PRUint32 aHint, RemoteSourceStreamInfo** aInfo);
|
||||
|
||||
// Implementation of the only observer we need
|
||||
virtual void onCallEvent(
|
||||
ccapi_call_event_e aCallEvent,
|
||||
CSF::CC_CallPtr aCall,
|
||||
CSF::CC_CallInfoPtr aInfo
|
||||
);
|
||||
|
||||
// DataConnection observers
|
||||
void NotifyConnection();
|
||||
void NotifyClosedConnection();
|
||||
void NotifyDataChannel(mozilla::DataChannel *aChannel);
|
||||
|
||||
// Handle system to allow weak references to be passed through C code
|
||||
static PeerConnectionWrapper *AcquireInstance(const std::string& aHandle);
|
||||
virtual void ReleaseInstance();
|
||||
virtual const std::string& GetHandle();
|
||||
|
||||
// ICE events
|
||||
void IceGatheringCompleted(NrIceCtx *aCtx);
|
||||
void IceCompleted(NrIceCtx *aCtx);
|
||||
void IceStreamReady(NrIceMediaStream *aStream);
|
||||
|
||||
mozilla::RefPtr<NrIceCtx> ice_ctx() const { return mIceCtx; }
|
||||
mozilla::RefPtr<NrIceMediaStream> ice_media_stream(size_t i) const {
|
||||
// TODO(ekr@rtfm.com): If someone asks for a value that doesn't exist,
|
||||
// make one.
|
||||
if (i >= mIceStreams.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return mIceStreams[i];
|
||||
}
|
||||
|
||||
// Get a specific local stream
|
||||
nsRefPtr<LocalSourceStreamInfo> GetLocalStream(int aIndex);
|
||||
|
||||
// Get a specific remote stream
|
||||
nsRefPtr<RemoteSourceStreamInfo> GetRemoteStream(int aIndex);
|
||||
|
||||
// Add a remote stream. Returns the index in index
|
||||
nsresult AddRemoteStream(nsRefPtr<RemoteSourceStreamInfo> aInfo, int *aIndex);
|
||||
|
||||
// Get a transport flow either RTP/RTCP for a particular stream
|
||||
// A stream can be of audio/video/datachannel/budled(?) types
|
||||
mozilla::RefPtr<TransportFlow> GetTransportFlow(int aStreamIndex, bool aIsRtcp) {
|
||||
int index_inner = aStreamIndex * 2 + (aIsRtcp ? 1 : 0);
|
||||
|
||||
if (mTransportFlows.find(index_inner) == mTransportFlows.end())
|
||||
return NULL;
|
||||
|
||||
return mTransportFlows[index_inner];
|
||||
}
|
||||
|
||||
// Add a transport flow
|
||||
void AddTransportFlow(int aIndex, bool aRtcp, mozilla::RefPtr<TransportFlow> aFlow) {
|
||||
int index_inner = aIndex * 2 + (aRtcp ? 1 : 0);
|
||||
|
||||
mTransportFlows[index_inner] = aFlow;
|
||||
}
|
||||
|
||||
static void ListenThread(void *aData);
|
||||
static void ConnectThread(void *aData);
|
||||
|
||||
// Get the main thread
|
||||
nsCOMPtr<nsIThread> GetMainThread() { return mThread; }
|
||||
|
||||
// Get the STS thread
|
||||
nsCOMPtr<nsIEventTarget> GetSTSThread() { return mSTSThread; }
|
||||
|
||||
// Get the DTLS identity
|
||||
mozilla::RefPtr<DtlsIdentity> const GetIdentity() { return mIdentity; }
|
||||
|
||||
private:
|
||||
PeerConnectionImpl(const PeerConnectionImpl&rhs);
|
||||
PeerConnectionImpl& operator=(PeerConnectionImpl);
|
||||
|
||||
void ChangeReadyState(ReadyState aReadyState);
|
||||
void CheckIceState() {
|
||||
PR_ASSERT(mIceState != kIceGathering);
|
||||
}
|
||||
|
||||
// Shut down media. Called on any thread.
|
||||
void ShutdownMedia();
|
||||
|
||||
// Disconnect the media streams. Must be called on the
|
||||
// main thread.
|
||||
void DisconnectMediaStreams();
|
||||
|
||||
// Shutdown media transport. Must be called on STS thread.
|
||||
void ShutdownMediaTransport();
|
||||
|
||||
nsresult MakeMediaStream(PRUint32 aHint, nsIDOMMediaStream** aStream);
|
||||
nsresult MakeRemoteSource(nsDOMMediaStream* aStream, RemoteSourceStreamInfo** aInfo);
|
||||
|
||||
// The role we are adopting
|
||||
Role mRole;
|
||||
|
||||
// The call
|
||||
CSF::CC_CallPtr mCall;
|
||||
ReadyState mReadyState;
|
||||
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
nsCOMPtr<IPeerConnectionObserver> mPCObserver;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
// The SDP sent in from JS - here for debugging.
|
||||
std::string mLocalRequestedSDP;
|
||||
std::string mRemoteRequestedSDP;
|
||||
// The SDP we are using.
|
||||
std::string mLocalSDP;
|
||||
std::string mRemoteSDP;
|
||||
|
||||
// DTLS fingerprint
|
||||
std::string mFingerprint;
|
||||
std::string mRemoteFingerprint;
|
||||
|
||||
// A list of streams returned from GetUserMedia
|
||||
PRLock *mLocalSourceStreamsLock;
|
||||
nsTArray<nsRefPtr<LocalSourceStreamInfo> > mLocalSourceStreams;
|
||||
|
||||
// A list of streams provided by the other side
|
||||
PRLock *mRemoteSourceStreamsLock;
|
||||
nsTArray<nsRefPtr<RemoteSourceStreamInfo> > mRemoteSourceStreams;
|
||||
|
||||
// A handle to refer to this PC with
|
||||
std::string mHandle;
|
||||
|
||||
// ICE objects
|
||||
mozilla::RefPtr<NrIceCtx> mIceCtx;
|
||||
std::vector<mozilla::RefPtr<NrIceMediaStream> > mIceStreams;
|
||||
IceState mIceState;
|
||||
|
||||
// Transport flows: even is RTP, odd is RTCP
|
||||
std::map<int, mozilla::RefPtr<TransportFlow> > mTransportFlows;
|
||||
|
||||
// The DTLS identity
|
||||
mozilla::RefPtr<DtlsIdentity> mIdentity;
|
||||
|
||||
// The target to run stuff on
|
||||
nsCOMPtr<nsIEventTarget> mSTSThread;
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// DataConnection that's used to get all the DataChannels
|
||||
nsRefPtr<mozilla::DataChannelConnection> mDataConnection;
|
||||
#endif
|
||||
|
||||
// Singleton list of all the PeerConnections
|
||||
static std::map<const std::string, PeerConnectionImpl *> peerconnections;
|
||||
|
||||
public:
|
||||
//these are temporary until the DataChannel Listen/Connect API is removed
|
||||
unsigned short listenPort;
|
||||
unsigned short connectPort;
|
||||
char *connectStr; // XXX ownership/free
|
||||
};
|
||||
|
||||
// This is what is returned when you acquire on a handle
|
||||
class PeerConnectionWrapper {
|
||||
public:
|
||||
PeerConnectionWrapper(PeerConnectionImpl *impl) : impl_(impl) {}
|
||||
|
||||
~PeerConnectionWrapper() {
|
||||
if (impl_)
|
||||
impl_->ReleaseInstance();
|
||||
}
|
||||
|
||||
PeerConnectionImpl *impl() { return impl_; }
|
||||
|
||||
private:
|
||||
PeerConnectionImpl *impl_;
|
||||
};
|
||||
|
||||
} // end sipcc namespace
|
||||
|
||||
#endif // _PEER_CONNECTION_IMPL_H_
|
|
@ -130,6 +130,10 @@ typedef struct cc_call_info_t_{
|
|||
cc_boolean audio_mute;
|
||||
cc_boolean video_mute;
|
||||
cc_call_conference_Info_t call_conference;
|
||||
cc_string_t sdp;
|
||||
unsigned int media_stream_track_id;
|
||||
unsigned int media_stream_id;
|
||||
|
||||
} session_data_t;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -143,13 +143,13 @@ cc_boolean partyInfoPassedTheNumberFilter (cc_string_t partyString)
|
|||
// check if partyString is something we should not be logging at this point
|
||||
// Uris: CfwdALL 105
|
||||
// Conference 152
|
||||
if (partyString[1] == 17 ||
|
||||
partyString[1] == 91 ||
|
||||
// partyString[1] == 698 ||
|
||||
partyString[1] == 05 ||
|
||||
partyString[1] == 18 ||
|
||||
partyString[1] == 16 ||
|
||||
partyString[1] == 52 ) {
|
||||
if (partyString && strlen(partyString) > 1 &&
|
||||
(partyString[1] == 17 ||
|
||||
partyString[1] == 91 ||
|
||||
partyString[1] == 05 ||
|
||||
partyString[1] == 18 ||
|
||||
partyString[1] == 16 ||
|
||||
partyString[1] == 52 )) {
|
||||
|
||||
CCLOG_DEBUG(DEB_F_PREFIX"Filtering out the partyName=%s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), partyString);
|
||||
return FALSE;
|
||||
|
@ -168,7 +168,8 @@ cc_boolean partyInfoPassedTheNameFilter(cc_string_t partyString) {
|
|||
|
||||
CCLOG_DEBUG(DEB_F_PREFIX"Entering...\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
||||
// If the name String has Conference, filter it out
|
||||
if (partyString[1] == 52 || partyString[1] == 53) {
|
||||
if (partyString && strlen(partyString) > 1 &&
|
||||
(partyString[1] == 52 || partyString[1] == 53)) {
|
||||
CCLOG_DEBUG(DEB_F_PREFIX"Filtering out the partyName=%s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), partyString);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -36,9 +36,6 @@
|
|||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
|
||||
#include "capability_set.h"
|
||||
#include "CCProvider.h"
|
||||
|
@ -295,140 +292,7 @@ static void fcp_init()
|
|||
capset_init();
|
||||
|
||||
// initialize the version
|
||||
strcpy (g_fp_version_stamp, "");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* config_parse_fcp_feature - parse info associated with a given feature
|
||||
*
|
||||
*/
|
||||
static void config_parse_fcp_feature (char* featureName, xmlNode* fcp_node, xmlDocPtr doc)
|
||||
{
|
||||
xmlChar* xmlValue;
|
||||
xmlNode* cur_node;
|
||||
|
||||
// obtain a new feature index
|
||||
if ((fcp_index+1) >= FCP_FEATURE_MAX)
|
||||
{
|
||||
CONFIG_ERROR(CFG_F_PREFIX "Received more than the maximum supported features [%d] in FCP \n", "config_parse_fcp_feature", FCP_FEATURE_MAX);
|
||||
return;
|
||||
}
|
||||
fcp_index++;
|
||||
|
||||
// initialize the element
|
||||
strcpy (cc_feat_control_policy[fcp_index].featureName, "");
|
||||
cc_feat_control_policy[fcp_index].featureEnabled = FALSE;
|
||||
cc_feat_control_policy[fcp_index].featureId = 0;
|
||||
|
||||
// set the name of the feature
|
||||
strncpy (cc_feat_control_policy[fcp_index].featureName, featureName, FCP_FEATURE_NAME_MAX);
|
||||
|
||||
// parse the id and enabled state of the feature, and save in structure
|
||||
for (cur_node = fcp_node; cur_node; cur_node = cur_node->next)
|
||||
{
|
||||
if (cur_node->type == XML_ELEMENT_NODE)
|
||||
{
|
||||
xmlValue = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
|
||||
if (xmlValue != NULL)
|
||||
{
|
||||
|
||||
if (!xmlStrcmp(cur_node->name, (const xmlChar *) "id"))
|
||||
{
|
||||
unsigned int featureId = atoi((char*)xmlValue);
|
||||
if (featureId > FCP_FEATURE_MAX)
|
||||
{
|
||||
CONFIG_ERROR(CFG_F_PREFIX "Feature Id [%d] in FCP file Out Of Range [%d] \n", "config_parse_fcp_feature", featureId, FCP_FEATURE_MAX);
|
||||
featureId = 0;
|
||||
}
|
||||
|
||||
cc_feat_control_policy[fcp_index].featureId = featureId;
|
||||
|
||||
} else if (!xmlStrcmp(cur_node->name, (const xmlChar *) "enable"))
|
||||
{
|
||||
cc_feat_control_policy[fcp_index].featureEnabled = (cc_boolean)(strcmp((char*)xmlValue, "true") == 0);
|
||||
}
|
||||
|
||||
xmlFree(xmlValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* config_parse_fcp_element
|
||||
*
|
||||
* Parse the elements in the XML document and call the
|
||||
* corressponding set functions
|
||||
*/
|
||||
static void config_parse_fcp_element (xmlNode* fcp_node, char* value, xmlDocPtr doc )
|
||||
{
|
||||
int versionStampSize = 0;
|
||||
|
||||
if (!xmlStrcmp(fcp_node->name, (const xmlChar *) "versionStamp"))
|
||||
{
|
||||
versionStampSize = strlen(value);
|
||||
|
||||
// ensure version stamp size is not unexpectedly large...
|
||||
if (versionStampSize > MAX_FP_VERSION_STAMP_LEN) {
|
||||
CONFIG_ERROR(CFG_F_PREFIX "FCP Version Length [%d] is crazy large!\n", "config_parse_fcp_element", versionStampSize);
|
||||
return;
|
||||
}
|
||||
|
||||
// trusting nothing, ensure we don't copy more bytes than we can handle...
|
||||
sstrncpy(g_fp_version_stamp, value, MAX_FP_VERSION_STAMP_LEN);
|
||||
|
||||
} else if (!xmlStrcmp(fcp_node->name, (const xmlChar *) "featureDef"))
|
||||
{
|
||||
xmlChar* featureName = NULL;
|
||||
|
||||
featureName = xmlGetProp(fcp_node, (const xmlChar *) "name");
|
||||
if (featureName == NULL)
|
||||
{
|
||||
CONFIG_ERROR(CFG_F_PREFIX "FCP Couldnt get feature name element!\n", "config_parse_fcp_element");
|
||||
return;
|
||||
}
|
||||
|
||||
// pass the name below to store
|
||||
CONFIG_DEBUG(CFG_F_PREFIX "FCP Parsing FeatureName=[%s] \n", "config_parse_fcp_element", (char*)featureName);
|
||||
config_parse_fcp_feature ((char*)featureName, fcp_node->children, doc);
|
||||
|
||||
xmlFree(featureName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* fcp_parse_and_set:
|
||||
* @a_node: the initial xml node to consider.
|
||||
* @doc: The DOM tree of the xml file
|
||||
*
|
||||
* Get the names of the all the xml elements
|
||||
* that are siblings or children of a given xml node.
|
||||
*
|
||||
* Recursive call to traverse all the elements of the tree.
|
||||
*/
|
||||
static int fcp_parse_and_set (xmlNode* a_node, xmlDocPtr doc)
|
||||
{
|
||||
xmlNode* cur_node = NULL;
|
||||
xmlChar* data;
|
||||
|
||||
for (cur_node = a_node; cur_node; cur_node = cur_node->next)
|
||||
{
|
||||
if (cur_node->type == XML_ELEMENT_NODE)
|
||||
{
|
||||
data = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
|
||||
if (data != NULL)
|
||||
{
|
||||
config_parse_fcp_element(cur_node, (char *)data, doc);
|
||||
xmlFree(data);
|
||||
}
|
||||
}
|
||||
|
||||
fcp_parse_and_set(cur_node->children, doc);
|
||||
}
|
||||
|
||||
return (0);
|
||||
g_fp_version_stamp[0] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -437,11 +301,6 @@ static int fcp_parse_and_set (xmlNode* a_node, xmlDocPtr doc)
|
|||
*/
|
||||
int fcp_init_template (const char* fcp_plan_string)
|
||||
{
|
||||
static const char fname[] = "fcp_init_template";
|
||||
|
||||
xmlNode* fcp_xml_root_element;
|
||||
xmlDocPtr fcp_xml_doc;
|
||||
|
||||
fcp_init();
|
||||
|
||||
if (fcp_plan_string == NULL)
|
||||
|
@ -449,31 +308,6 @@ int fcp_init_template (const char* fcp_plan_string)
|
|||
return (0);
|
||||
}
|
||||
|
||||
fcp_xml_doc = xmlReadFile(fcp_plan_string, NULL, 0);
|
||||
if (fcp_xml_doc == NULL)
|
||||
{
|
||||
CONFIG_ERROR(CFG_F_PREFIX "FCP - Unable to xmlReadFile = [%s]", fname, fcp_plan_string);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// get the root element
|
||||
fcp_xml_root_element = xmlDocGetRootElement(fcp_xml_doc);
|
||||
if (fcp_xml_root_element == NULL)
|
||||
{
|
||||
CONFIG_ERROR(CFG_F_PREFIX "FCP - Unable to get root element for FCP file = [%s]", fname, fcp_plan_string);
|
||||
xmlFreeDoc(fcp_xml_doc);
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
fcp_parse_and_set (fcp_xml_root_element, fcp_xml_doc);
|
||||
|
||||
// free the document */
|
||||
xmlFreeDoc(fcp_xml_doc);
|
||||
|
||||
// Now set the capability bools, based on the parsed FCP values
|
||||
CONFIG_DEBUG(DEB_F_PREFIX"FCP Post FCP Parse Setting Capabilities\n", DEB_F_PREFIX_ARGS(JNI, "fcp_display"));
|
||||
|
||||
// update the fcp capabilities structure, based on the parsed feature information
|
||||
fcp_set_capabilities();
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ cc_return_t cc_invokeFeature(cc_call_handle_t call_handle, group_cc_feature_t fe
|
|||
callFeature.session_id = (SESSIONTYPE_CALLCONTROL << CC_SID_TYPE_SHIFT) + call_handle;
|
||||
callFeature.featureID = featureId;
|
||||
callFeature.featData.ccData.state = video_pref;
|
||||
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"cc_invokeFeature:sid=%d, line=%d, cid=%d, fid=%d, video_pref=%s data=%s\n",
|
||||
DEB_F_PREFIX_ARGS("cc_call_feature", "cc_invokeFeature"),
|
||||
callFeature.session_id,
|
||||
|
@ -108,9 +109,69 @@ cc_return_t cc_invokeFeature(cc_call_handle_t call_handle, group_cc_feature_t fe
|
|||
case CC_FEATURE_CONF:
|
||||
case CC_FEATURE_XFER:
|
||||
case CC_FEATURE_HOLD:
|
||||
callFeature.featData.ccData.info = strlib_malloc(data, strlen(data));
|
||||
callFeature.featData.ccData.info1 = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
callFeature.featData.ccData.info = NULL;
|
||||
callFeature.featData.ccData.info1 = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ccappTaskPostMsg(CCAPP_INVOKE_FEATURE, &callFeature, sizeof(session_feature_t), CCAPP_CCPROVIER) == CPR_FAILURE) {
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"ccappTaskSendMsg failed\n",
|
||||
DEB_F_PREFIX_ARGS("cc_call_feature", "cc_invokeFeature"));
|
||||
return CC_FAILURE;
|
||||
}
|
||||
return CC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke a call feature.
|
||||
*/
|
||||
cc_return_t cc_invokeFeatureSDPMode(cc_call_handle_t call_handle, group_cc_feature_t featureId, cc_sdp_direction_t video_pref,
|
||||
cc_jsep_action_t action, cc_media_stream_id_t stream_id, cc_media_track_id_t track_id,
|
||||
cc_media_type_t media_type, uint16_t level, string_t data, string_t data1) {
|
||||
session_feature_t callFeature;
|
||||
callFeature.session_id = (SESSIONTYPE_CALLCONTROL << CC_SID_TYPE_SHIFT) + call_handle;
|
||||
callFeature.featureID = featureId;
|
||||
callFeature.featData.ccData.state = video_pref;
|
||||
callFeature.featData.ccData.action = action;
|
||||
callFeature.featData.ccData.media_type = media_type;
|
||||
callFeature.featData.ccData.stream_id = stream_id;
|
||||
callFeature.featData.ccData.track_id = track_id;
|
||||
callFeature.featData.ccData.level = level;
|
||||
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"cc_invokeFeatureSDPMode:sid=%d, line=%d, cid=%d, fid=%d, video_pref=%s data=%s\n",
|
||||
DEB_F_PREFIX_ARGS("cc_call_feature", "cc_invokeFeatureSDPMode"),
|
||||
callFeature.session_id,
|
||||
GET_LINE_ID(call_handle),
|
||||
GET_CALL_ID(call_handle),
|
||||
featureId, SDP_DIRECTION_PRINT(video_pref),
|
||||
((featureId == CC_FEATURE_KEYPRESS) ? "...": data));
|
||||
|
||||
switch (featureId) {
|
||||
case CC_FEATURE_KEYPRESS:
|
||||
case CC_FEATURE_DIALSTR:
|
||||
case CC_FEATURE_SPEEDDIAL:
|
||||
case CC_FEATURE_BLIND_XFER_WITH_DIALSTRING:
|
||||
case CC_FEATURE_END_CALL:
|
||||
case CC_FEATURE_B2BCONF:
|
||||
case CC_FEATURE_CONF:
|
||||
case CC_FEATURE_XFER:
|
||||
case CC_FEATURE_HOLD:
|
||||
case CC_FEATURE_CREATEANSWER:
|
||||
case CC_FEATURE_SETLOCALDESC:
|
||||
case CC_FEATURE_SETREMOTEDESC:
|
||||
case CC_FEATURE_SETPEERCONNECTION:
|
||||
callFeature.featData.ccData.info = strlib_malloc(data, strlen(data));
|
||||
callFeature.featData.ccData.info1 = NULL;
|
||||
break;
|
||||
case CC_FEATURE_ADDICECANDIDATE:
|
||||
callFeature.featData.ccData.info = strlib_malloc(data, strlen(data));
|
||||
callFeature.featData.ccData.info1 = strlib_malloc(data1, strlen(data1));
|
||||
break;
|
||||
|
||||
default:
|
||||
callFeature.featData.ccData.info = NULL;
|
||||
|
@ -120,11 +181,12 @@ cc_return_t cc_invokeFeature(cc_call_handle_t call_handle, group_cc_feature_t fe
|
|||
|
||||
if (ccappTaskPostMsg(CCAPP_INVOKE_FEATURE, &callFeature, sizeof(session_feature_t), CCAPP_CCPROVIER) == CPR_FAILURE) {
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"ccappTaskSendMsg failed\n",
|
||||
DEB_F_PREFIX_ARGS("cc_call_feature", "cc_invokeFeature"));
|
||||
DEB_F_PREFIX_ARGS("cc_call_feature", "cc_invokeFeatureSDPMode"));
|
||||
return CC_FAILURE;
|
||||
}
|
||||
return CC_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************Basic Call Feature Control Methods************************************
|
||||
* This section defines all the call related methods that an upper layer can use to control
|
||||
* a call in progress.
|
||||
|
@ -140,7 +202,6 @@ cc_return_t cc_invokeFeature(cc_call_handle_t call_handle, group_cc_feature_t fe
|
|||
cc_call_handle_t CC_createCall(cc_lineid_t line) {
|
||||
static const char fname[] = "CC_CreateCall";
|
||||
//Create call handle to initialize the memory.
|
||||
//call handle
|
||||
cc_call_handle_t call_handle = CC_EMPTY_CALL_HANDLE;
|
||||
cc_lineid_t lineid = line;
|
||||
cc_callid_t callid = CC_NO_CALL_ID;
|
||||
|
@ -249,6 +310,66 @@ cc_return_t CC_CallFeature_dial(cc_call_handle_t call_handle, cc_sdp_direction_t
|
|||
return cc_invokeFeature(call_handle, CC_FEATURE_DIALSTR, video_pref, numbers);
|
||||
}
|
||||
|
||||
cc_return_t CC_CallFeature_CreateOffer(cc_call_handle_t call_handle) {
|
||||
CCAPP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, GET_CALL_ID(call_handle),
|
||||
GET_LINE_ID(call_handle), __FUNCTION__));
|
||||
|
||||
return cc_invokeFeatureSDPMode(call_handle, CC_FEATURE_CREATEOFFER, CC_SDP_DIRECTION_SENDRECV, JSEP_NO_ACTION, 0, 0, NO_STREAM, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
cc_return_t CC_CallFeature_CreateAnswer(cc_call_handle_t call_handle, string_t sdp) {
|
||||
CCAPP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, GET_CALL_ID(call_handle),
|
||||
GET_LINE_ID(call_handle), __FUNCTION__));
|
||||
|
||||
return cc_invokeFeatureSDPMode(call_handle, CC_FEATURE_CREATEANSWER, CC_SDP_DIRECTION_SENDRECV, JSEP_NO_ACTION, 0, 0, NO_STREAM, 0, sdp, NULL);
|
||||
}
|
||||
|
||||
cc_return_t CC_CallFeature_SetLocalDescription(cc_call_handle_t call_handle, cc_jsep_action_t action, string_t sdp) {
|
||||
CCAPP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, GET_CALL_ID(call_handle),
|
||||
GET_LINE_ID(call_handle), __FUNCTION__));
|
||||
|
||||
return cc_invokeFeatureSDPMode(call_handle, CC_FEATURE_SETLOCALDESC, CC_SDP_DIRECTION_SENDRECV, action, 0, 0, NO_STREAM, 0, sdp, NULL);
|
||||
}
|
||||
|
||||
cc_return_t CC_CallFeature_SetRemoteDescription(cc_call_handle_t call_handle, cc_jsep_action_t action, string_t sdp) {
|
||||
CCAPP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, GET_CALL_ID(call_handle),
|
||||
GET_LINE_ID(call_handle), __FUNCTION__));
|
||||
|
||||
return cc_invokeFeatureSDPMode(call_handle, CC_FEATURE_SETREMOTEDESC, CC_SDP_DIRECTION_SENDRECV, action, 0, 0, NO_STREAM, 0, sdp, NULL);
|
||||
}
|
||||
|
||||
cc_return_t CC_CallFeature_SetPeerConnection(cc_call_handle_t call_handle, cc_peerconnection_t pc) {
|
||||
CCAPP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, GET_CALL_ID(call_handle),
|
||||
GET_LINE_ID(call_handle), __FUNCTION__));
|
||||
|
||||
return cc_invokeFeatureSDPMode(call_handle, CC_FEATURE_SETPEERCONNECTION,
|
||||
CC_SDP_DIRECTION_SENDRECV, JSEP_NO_ACTION, 0, 0, NO_STREAM, 0, pc, NULL);
|
||||
}
|
||||
|
||||
cc_return_t CC_CallFeature_AddStream(cc_call_handle_t call_handle, cc_media_stream_id_t stream_id, cc_media_track_id_t track_id, cc_media_type_t media_type) {
|
||||
CCAPP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, GET_CALL_ID(call_handle),
|
||||
GET_LINE_ID(call_handle), __FUNCTION__));
|
||||
|
||||
return cc_invokeFeatureSDPMode(call_handle, CC_FEATURE_ADDSTREAM,
|
||||
CC_SDP_DIRECTION_SENDRECV, JSEP_NO_ACTION, stream_id, track_id, media_type, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
cc_return_t CC_CallFeature_RemoveStream(cc_call_handle_t call_handle, cc_media_stream_id_t stream_id, cc_media_track_id_t track_id, cc_media_type_t media_type) {
|
||||
CCAPP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, GET_CALL_ID(call_handle),
|
||||
GET_LINE_ID(call_handle), __FUNCTION__));
|
||||
|
||||
return cc_invokeFeatureSDPMode(call_handle, CC_FEATURE_REMOVESTREAM,
|
||||
CC_SDP_DIRECTION_SENDRECV, JSEP_NO_ACTION, stream_id, track_id, media_type, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
cc_return_t CC_CallFeature_AddICECandidate(cc_call_handle_t call_handle, const char* candidate, const char *mid, cc_level_t level) {
|
||||
CCAPP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, GET_CALL_ID(call_handle),
|
||||
GET_LINE_ID(call_handle), __FUNCTION__));
|
||||
|
||||
return cc_invokeFeatureSDPMode(call_handle, CC_FEATURE_ADDICECANDIDATE,
|
||||
CC_SDP_DIRECTION_SENDRECV, JSEP_NO_ACTION, 0, 0, NO_STREAM, (uint16_t)level, candidate, mid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a speed dial.
|
||||
* @param call handle
|
||||
|
|
|
@ -65,14 +65,9 @@
|
|||
|
||||
|
||||
mgmt_state_t mgmtState = MGMT_STATE_IDLE;
|
||||
int parse_config_properties (int device_handle, const char *device_name, const char *cfg, int from_memory);
|
||||
//int parse_config_properties (int device_handle, const char *device_name, const char *cfg, int from_memory);
|
||||
static boolean isStartRequestPending = FALSE;
|
||||
static boolean isServiceStopped = TRUE;
|
||||
extern int g_dev_hdl;
|
||||
extern char g_dev_name[];
|
||||
extern char g_cfg_p[];
|
||||
extern int g_compl_cfg;
|
||||
|
||||
|
||||
extern cc_boolean is_action_to_be_deferred(cc_action_t action);
|
||||
|
||||
|
@ -526,6 +521,7 @@ void registration_processEvent(int event) {
|
|||
isServiceStopped = TRUE;
|
||||
switch ( mgmtState) {
|
||||
case MGMT_STATE_REGISTERED:
|
||||
CC_Service_destroy();
|
||||
processInsToOos();
|
||||
case MGMT_STATE_REGISTERING:
|
||||
case MGMT_STATE_OOS:
|
||||
|
@ -537,10 +533,9 @@ void registration_processEvent(int event) {
|
|||
case MGMT_STATE_OOS_AWAIT_SHUTDOWN_ACK:
|
||||
case MGMT_STATE_OOS_AWAIT_UN_REG_ACK:
|
||||
//setState(MGMT_STATE_DESTROY_AWAIT_SHUTDOWN_ACK);
|
||||
//Suhas
|
||||
setState(MGMT_STATE_IDLE);
|
||||
CC_Service_destroy();
|
||||
break;
|
||||
setState(MGMT_STATE_IDLE);
|
||||
CC_Service_destroy();
|
||||
break;
|
||||
case MGMT_STATE_CREATED:
|
||||
CC_Service_destroy();
|
||||
break;
|
||||
|
@ -548,8 +543,6 @@ void registration_processEvent(int event) {
|
|||
CC_Service_destroy();
|
||||
break;
|
||||
case MGMT_STATE_DESTROY_AWAIT_SHUTDOWN_ACK:
|
||||
|
||||
// Suhas: Adding state change
|
||||
setState(MGMT_STATE_IDLE);
|
||||
|
||||
default:
|
||||
|
@ -578,8 +571,9 @@ void registration_processEvent(int event) {
|
|||
case MGMT_STATE_CREATED:
|
||||
case MGMT_STATE_IDLE:
|
||||
case MGMT_STATE_DESTROY_AWAIT_SHUTDOWN_ACK:
|
||||
// Suhas: Adding state change
|
||||
setState(MGMT_STATE_IDLE);
|
||||
//action(CMD_SHUTDOWN);
|
||||
CC_Service_destroy();
|
||||
|
||||
default:
|
||||
ignored = 1;
|
||||
|
@ -590,13 +584,11 @@ void registration_processEvent(int event) {
|
|||
switch ( mgmtState) {
|
||||
case MGMT_STATE_OOS_AWAIT_UN_REG_ACK:
|
||||
setState(MGMT_STATE_REGISTERING);
|
||||
parse_config_properties(g_dev_hdl, g_dev_name, g_cfg_p, g_compl_cfg);
|
||||
action(CMD_RESTART);
|
||||
break;
|
||||
case MGMT_STATE_OOS_AWAIT_SHUTDOWN_ACK:
|
||||
setState(MGMT_STATE_WAITING_FOR_CONFIG_FILE);
|
||||
configFetchReq(0);
|
||||
// Suhas: Adding state change
|
||||
setState(MGMT_STATE_IDLE);
|
||||
break;
|
||||
case MGMT_STATE_STOP_AWAIT_SHUTDOWN_ACK:
|
||||
|
@ -605,7 +597,6 @@ void registration_processEvent(int event) {
|
|||
isStartRequestPending = FALSE;
|
||||
configFetchReq(0);
|
||||
}
|
||||
// Suhas: Adding state change
|
||||
setState(MGMT_STATE_IDLE);
|
||||
break;
|
||||
case MGMT_STATE_DESTROY_AWAIT_SHUTDOWN_ACK:
|
||||
|
|
|
@ -121,23 +121,42 @@ cc_lineid_t CCAPI_Call_getLine(cc_call_handle_t call_handle){
|
|||
* @param [in] digits - digits to be dialed
|
||||
* @return SUCCESS or FAILURE
|
||||
*/
|
||||
cc_return_t CCAPI_Call_originateCall(cc_call_handle_t handle, cc_sdp_direction_t video_pref, cc_string_t digits, char* ipaddress, int audioPort, int videoPort){
|
||||
|
||||
int roapproxy = 0;
|
||||
config_get_value(CFGID_ROAPPROXY, &roapproxy, sizeof(roapproxy));
|
||||
|
||||
if (roapproxy == TRUE) {
|
||||
init_empty_str(gROAPSDP.offerAddress);
|
||||
init_empty_str(gROAPSDP.answerSDP);
|
||||
init_empty_str(gROAPSDP.offerSDP);
|
||||
strcpy(gROAPSDP.offerAddress, ipaddress);
|
||||
gROAPSDP.audioPort = audioPort;
|
||||
gROAPSDP.videoPort = videoPort;
|
||||
}
|
||||
|
||||
cc_return_t CCAPI_Call_originateCall(cc_call_handle_t handle, cc_sdp_direction_t video_pref, cc_string_t digits){
|
||||
return CC_CallFeature_dial(handle, video_pref, digits);
|
||||
}
|
||||
|
||||
cc_return_t CCAPI_CreateOffer(cc_call_handle_t handle) {
|
||||
return CC_CallFeature_CreateOffer(handle);
|
||||
}
|
||||
|
||||
cc_return_t CCAPI_CreateAnswer(cc_call_handle_t handle, cc_string_t offersdp) {
|
||||
return CC_CallFeature_CreateAnswer(handle, offersdp);
|
||||
}
|
||||
|
||||
cc_return_t CCAPI_SetLocalDescription(cc_call_handle_t handle, cc_jsep_action_t action, cc_string_t sdp) {
|
||||
return CC_CallFeature_SetLocalDescription(handle, action, sdp);
|
||||
}
|
||||
|
||||
cc_return_t CCAPI_SetRemoteDescription(cc_call_handle_t handle, cc_jsep_action_t action, cc_string_t sdp) {
|
||||
return CC_CallFeature_SetRemoteDescription(handle, action, sdp);
|
||||
}
|
||||
|
||||
cc_return_t CCAPI_SetPeerConnection(cc_call_handle_t handle, cc_peerconnection_t pc) {
|
||||
return CC_CallFeature_SetPeerConnection(handle, pc);
|
||||
}
|
||||
|
||||
cc_return_t CCAPI_AddStream(cc_call_handle_t handle, cc_media_stream_id_t stream_id, cc_media_track_id_t track_id, cc_media_type_t media_type) {
|
||||
return CC_CallFeature_AddStream(handle, stream_id, track_id, media_type);
|
||||
}
|
||||
|
||||
cc_return_t CCAPI_RemoveStream(cc_call_handle_t handle, cc_media_stream_id_t stream_id, cc_media_track_id_t track_id, cc_media_type_t media_type) {
|
||||
return CC_CallFeature_RemoveStream(handle, stream_id, track_id, media_type);
|
||||
}
|
||||
|
||||
cc_return_t CCAPI_AddICECandidate(cc_call_handle_t handle, cc_string_t candidate, cc_string_t mid, cc_level_t level) {
|
||||
return CC_CallFeature_AddICECandidate(handle, candidate, mid, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dial digits on the call
|
||||
* @param [in] handle - call handle
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "CCProvider.h"
|
||||
#include "text_strings.h"
|
||||
#include "phone_debug.h"
|
||||
|
||||
#include "peer_connection_types.h"
|
||||
|
||||
/**
|
||||
* get Line on which this call is
|
||||
|
@ -507,14 +507,14 @@ cc_int32_t CCAPI_CallInfo_getOnhookReason(cc_callinfo_ref_t handle){
|
|||
* @return boolean - is Conference
|
||||
*/
|
||||
cc_boolean CCAPI_CallInfo_getIsConference(cc_callinfo_ref_t handle){
|
||||
static const char *fname="CCAPI_CallInfo_getIsConference";
|
||||
session_data_t *data = (session_data_t *)handle;
|
||||
char isConf_buf[32];
|
||||
char* isConf = &isConf_buf[0];
|
||||
char isConf[32];
|
||||
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"Entering\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"Entering\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, __FUNCTION__));
|
||||
|
||||
if(platGetPhraseText(CONFERENCE_LOCALE_CODE, isConf, 32) == CC_FAILURE){
|
||||
memset(isConf, 0, sizeof(isConf));
|
||||
|
||||
if(platGetPhraseText(CONFERENCE_LOCALE_CODE, isConf, sizeof(isConf)) == CC_FAILURE){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -745,4 +745,74 @@ cc_boolean CCAPI_CallInfo_isVideoMuted (cc_callinfo_ref_t handle){
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* get SDP for CreateOffer\Create answer success callback
|
||||
* @param handle - call handle
|
||||
* @return sdp
|
||||
*/
|
||||
cc_string_t CCAPI_CallInfo_getSDP(cc_callinfo_ref_t handle){
|
||||
static const char *fname="CCAPI_CallInfo_getSDP";
|
||||
session_data_t *data = (session_data_t *)handle;
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"Entering\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
||||
|
||||
if (data != NULL){
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"returned %s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), data->sdp);
|
||||
return data->sdp;
|
||||
}
|
||||
|
||||
return strlib_empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* get status code from internal JSEP functions
|
||||
* @param handle - call handle
|
||||
* @return status code
|
||||
*/
|
||||
cc_int32_t CCAPI_CallInfo_getStatusCode(cc_callinfo_ref_t handle){
|
||||
static const char *fname="CCAPI_CallInfo_getStatusCode";
|
||||
session_data_t *data = (session_data_t *)handle;
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"Entering\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
||||
|
||||
if ( data != NULL){
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"returned %d\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), data->cause);
|
||||
return data->cause;
|
||||
}
|
||||
|
||||
return CC_CAUSE_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get media stream table
|
||||
* @param handle - call handle
|
||||
* @return status MediaStreamTable
|
||||
*/
|
||||
MediaStreamTable* CCAPI_CallInfo_getMediaStreams(cc_callinfo_ref_t handle) {
|
||||
static const char *fname="CCAPI_CallInfo_getMediaStreams";
|
||||
session_data_t *data = (session_data_t *)handle;
|
||||
MediaTrack track;
|
||||
MediaStreamTable* table = cpr_malloc(sizeof(MediaStreamTable));
|
||||
if (!table)
|
||||
return NULL;
|
||||
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"Entering\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
||||
|
||||
if (data != NULL) {
|
||||
table->media_stream_id = data->media_stream_id;
|
||||
table->num_tracks = 1; /* this will change when we have multiple tracks per stream */
|
||||
track.media_stream_track_id = data->media_stream_track_id;
|
||||
table->track[0] = track;
|
||||
|
||||
/*
|
||||
* Partly implemented multi-track handling
|
||||
cc_table = data->media_tracks;
|
||||
table->stream_id = (unsigned int)cc_table->stream_id;
|
||||
table->num_tracks = (unsigned int)cc_table->num_tracks;
|
||||
track.track_id = cc_table->track[0].ref_id;
|
||||
table->track[0] = track;
|
||||
*/
|
||||
return table;
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
|
|
@ -51,50 +51,14 @@
|
|||
#include "ccapi_service.h"
|
||||
#include "util_string.h"
|
||||
|
||||
extern int g_dev_hdl;
|
||||
extern char g_dev_name[];
|
||||
extern char g_cfg_p[];
|
||||
extern int g_compl_cfg;
|
||||
extern boolean apply_config;
|
||||
extern cc_apply_config_result_t apply_config_result;
|
||||
cc_boolean parse_config_properties (int device_handle, const char *device_name, const char *cfg, int from_memory);
|
||||
cc_boolean parse_setup_properties (int device_handle, const char *device_name, const char *sipUser, const char *sipPassword, const char *sipDomain);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
void CCAPI_Config_response(int device_handle, const char *device_name, const char *cfg, int from_memory) {
|
||||
static const char fname[] = "CCAPI_Config_response";
|
||||
cc_apply_config_result_t config_compare_result;
|
||||
|
||||
if (is_empty_str((char*)cfg)) {
|
||||
CCAPP_ERROR(DEB_F_PREFIX" invalid config file=%x\n", DEB_F_PREFIX_ARGS(CC_API, fname),cfg);
|
||||
return;
|
||||
}
|
||||
|
||||
g_dev_hdl = device_handle;
|
||||
strncpy(g_dev_name, device_name, 64);
|
||||
strncpy(g_cfg_p, cfg, 256);
|
||||
g_compl_cfg = from_memory;
|
||||
|
||||
if (is_phone_registered() == FALSE) {
|
||||
DEF_DEBUG(DEB_F_PREFIX" Phone not registered. do parse and register.\n", DEB_F_PREFIX_ARGS(CC_API, fname));
|
||||
if (parse_config_properties(device_handle, device_name, cfg, from_memory) == TRUE) {
|
||||
registration_processEvent(EV_CC_CONFIG_RECEIVED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
config_compare_result = CCAPI_Config_compareProperties(device_handle, cfg, from_memory);
|
||||
if (config_compare_result == APPLY_DYNAMICALLY) {
|
||||
DEF_DEBUG(DEB_F_PREFIX" Phone is registered. Changes can be applied dynamically.\n", DEB_F_PREFIX_ARGS(CC_API, fname));
|
||||
parse_config_properties(device_handle, device_name, cfg, from_memory);
|
||||
} else {
|
||||
DEF_DEBUG(DEB_F_PREFIX" Phone is registered. config changes need re-register.\n", DEB_F_PREFIX_ARGS(CC_API, fname));
|
||||
CCAPI_Service_reregister(device_handle, device_name, cfg, from_memory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CCAPI_Start_response(int device_handle, const char *device_name, const char *sipUser, const char *sipPassword, const char *sipDomain) {
|
||||
static const char fname[] = "CCAPI_Start_response";
|
||||
|
@ -105,7 +69,7 @@ void CCAPI_Start_response(int device_handle, const char *device_name, const char
|
|||
}
|
||||
|
||||
g_dev_hdl = device_handle;
|
||||
strncpy(g_dev_name, device_name, 64);
|
||||
sstrncpy(g_dev_name, device_name, sizeof(g_dev_name));
|
||||
|
||||
if (is_phone_registered() == FALSE) {
|
||||
|
||||
|
@ -117,20 +81,6 @@ void CCAPI_Start_response(int device_handle, const char *device_name, const char
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
cc_boolean parse_config_properties (int device_handle, const char *device_name, const char *cfg, int from_memory) {
|
||||
CC_Config_setStringValue(CFGID_DEVICE_NAME, device_name);
|
||||
if (config_parser_main((char *) cfg, from_memory) != 0) {
|
||||
configParserError();
|
||||
return FALSE;
|
||||
}
|
||||
ccsnap_device_init();
|
||||
ccsnap_line_init();
|
||||
ccsnap_gen_deviceEvent(CCAPI_DEVICE_EV_CONFIG_CHANGED, CC_DEVICE_ID);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* New Function
|
||||
Register without using config file downloaded from cucm
|
||||
*/
|
||||
|
@ -177,49 +127,17 @@ const char* CCAPI_Config_get_version() {
|
|||
return config_get_version();
|
||||
}
|
||||
|
||||
cc_boolean CCAPI_Config_checkValidity (int device_handle, const char *cfg_file_name, int from_memory) {
|
||||
CCAPP_ERROR("CCAPI_Config_checkValidity - check config file validity \n");
|
||||
return is_config_valid((char *)cfg_file_name, from_memory);
|
||||
}
|
||||
|
||||
cc_boolean CCAPI_Config_set_p2p_mode(const cc_boolean is_p2p) {
|
||||
config_setup_p2p_mode(is_p2p);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cc_boolean CCAPI_Config_set_roap_proxy_mode(const cc_boolean is_roap_proxy) {
|
||||
config_setup_roap_proxy_mode(is_roap_proxy);
|
||||
cc_boolean CCAPI_Config_set_sdp_mode(const cc_boolean is_sdp) {
|
||||
config_setup_sdp_mode(is_sdp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cc_boolean CCAPI_Config_set_roap_client_mode(const cc_boolean is_roap_client) {
|
||||
config_setup_roap_client_mode(is_roap_client);
|
||||
cc_boolean CCAPI_Config_set_avp_mode(const cc_boolean is_rtpsavpf) {
|
||||
config_setup_avp_mode(is_rtpsavpf);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int CCAPI_Config_compareProperties (int device_handle, const char *cfg_file_name, int from_memory) {
|
||||
cc_apply_config_result_t result;
|
||||
int val;
|
||||
|
||||
DEF_DEBUG("CCAPI_Config_compareProperties - compare config files\n");
|
||||
apply_config = TRUE;
|
||||
apply_config_result = APPLY_DYNAMICALLY; // initialization
|
||||
|
||||
val = config_parser_main((char *)cfg_file_name, from_memory);
|
||||
|
||||
if (val != 0) {
|
||||
configParserError();
|
||||
result = APPLY_CONFIG_NONE;
|
||||
} else {
|
||||
result = apply_config_result;
|
||||
}
|
||||
|
||||
DEF_DEBUG("apply_config_flag=%d apply_config_result(0-dynamic, 1-restart)=%d", apply_config, apply_config_result);
|
||||
apply_config_result = APPLY_CONFIG_NONE;
|
||||
apply_config = FALSE;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -57,8 +57,8 @@ int sendResetUpdates = 0; // default is not to send updates
|
|||
|
||||
// Global Variables
|
||||
int g_dev_hdl;
|
||||
char g_dev_name[64];
|
||||
char g_cfg_p[256];
|
||||
char g_dev_name[G_DEV_NAME_SIZE];
|
||||
char g_cfg_p[G_CFG_P_SIZE];
|
||||
int g_compl_cfg;
|
||||
|
||||
// Externs
|
||||
|
@ -72,7 +72,7 @@ extern cc_srv_ctrl_cmd_t reset_type;
|
|||
boolean isServiceStartRequestPending = FALSE;
|
||||
cc_boolean is_action_to_be_deferred(cc_action_t action);
|
||||
extern cc_action_t pending_action_type;
|
||||
cc_boolean parse_config_properties (int device_handle, const char *device_name, const char *cfg, int from_memory);
|
||||
//cc_boolean parse_config_properties (int device_handle, const char *device_name, const char *cfg, int from_memory);
|
||||
|
||||
|
||||
|
||||
|
@ -99,9 +99,9 @@ cc_return_t CCAPI_Service_create() {
|
|||
cc_return_t CCAPI_Service_destroy() {
|
||||
CCAPP_ERROR("CCAPI_Service_destroy - calling CC_Service_destroy \n");
|
||||
|
||||
if (is_action_to_be_deferred(STOP_ACTION) == TRUE) {
|
||||
return CC_SUCCESS;
|
||||
}
|
||||
// if (is_action_to_be_deferred(STOP_ACTION) == TRUE) {
|
||||
// return CC_SUCCESS;
|
||||
// }
|
||||
// initialize the config to empty
|
||||
init_empty_str(g_cfg_p);
|
||||
isServiceStartRequestPending = FALSE;
|
||||
|
@ -134,9 +134,15 @@ cc_return_t CCAPI_Service_start() {
|
|||
*/
|
||||
cc_return_t CCAPI_Service_stop() {
|
||||
|
||||
int sdpmode = 0;
|
||||
|
||||
CCAPP_ERROR("CCAPI_Service_stop - calling registration stop \n");
|
||||
if (is_action_to_be_deferred(STOP_ACTION) == TRUE) {
|
||||
return CC_SUCCESS;
|
||||
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
if (!sdpmode) {
|
||||
if (is_action_to_be_deferred(STOP_ACTION) == TRUE) {
|
||||
return CC_SUCCESS;
|
||||
}
|
||||
}
|
||||
sendResetUpdates = 0; // reset to default is not to send updates
|
||||
isServiceStartRequestPending = FALSE;
|
||||
|
@ -169,14 +175,12 @@ cc_return_t CCAPI_Service_reregister(int device_handle, const char *device_name,
|
|||
}
|
||||
|
||||
g_dev_hdl = device_handle;
|
||||
strncpy(g_dev_name, device_name, 64);
|
||||
strncpy(g_cfg_p, cfg, 256);
|
||||
sstrncpy(g_dev_name, device_name, sizeof(g_dev_name));
|
||||
sstrncpy(g_cfg_p, cfg, sizeof(g_cfg_p));
|
||||
CCAPP_DEBUG("CCAPI_Service_reregister - devce name [%s], cfg [%s] \n", g_dev_name, g_cfg_p);
|
||||
g_compl_cfg = complete_config;
|
||||
|
||||
if (parse_config_properties(g_dev_hdl, g_dev_name, g_cfg_p, g_compl_cfg) == TRUE) {
|
||||
registration_processEvent(EV_CC_RE_REGISTER);
|
||||
}
|
||||
|
||||
return (CC_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -486,7 +486,7 @@ void ccsnap_gen_callEvent(ccapi_call_event_e event, cc_call_handle_t handle){
|
|||
printCallInfo(call_info, "ccsnap_gen_callEvent");
|
||||
}
|
||||
|
||||
CCAPI_CallListener_onCallEvent(event, handle, call_info, gROAPSDP.answerSDP);
|
||||
CCAPI_CallListener_onCallEvent(event, handle, call_info);
|
||||
CCAPI_Call_releaseCallInfo(call_info);
|
||||
}
|
||||
|
||||
|
@ -541,7 +541,7 @@ void ccsnap_handle_mnc_reached (cc_line_info_t *line_info, cc_boolean mnc_reache
|
|||
if (g_CCAppDebug) {
|
||||
printCallInfo(cinfo, "ccsnap_handle_mnc_reached");
|
||||
}
|
||||
CCAPI_CallListener_onCallEvent(CCAPI_CALL_EV_CAPABILITY, handles[i], cinfo, "");
|
||||
CCAPI_CallListener_onCallEvent(CCAPI_CALL_EV_CAPABILITY, handles[i], cinfo);
|
||||
}
|
||||
}
|
||||
// update RIU call caps on this line
|
||||
|
@ -554,7 +554,7 @@ void ccsnap_handle_mnc_reached (cc_line_info_t *line_info, cc_boolean mnc_reache
|
|||
if (g_CCAppDebug) {
|
||||
printCallInfo(cinfo, "ccsnap_handle_mnc_reached");
|
||||
}
|
||||
CCAPI_CallListener_onCallEvent(CCAPI_CALL_EV_CAPABILITY, handles[i], cinfo, "");
|
||||
CCAPI_CallListener_onCallEvent(CCAPI_CALL_EV_CAPABILITY, handles[i], cinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "ccapp_task.h"
|
||||
#include "phone.h"
|
||||
#include "CCProvider.h"
|
||||
#include "platform_api.h"
|
||||
|
||||
extern cprMsgQueue_t ccapp_msgq;
|
||||
extern void CCAppInit();
|
||||
|
@ -117,7 +118,7 @@ cpr_status_e ccappTaskPostMsg(unsigned int msgId, void * data, uint16_t len, int
|
|||
static const char fname[] = "ccappPostMsg";
|
||||
cpr_status_e retval = CPR_SUCCESS;
|
||||
|
||||
msg = (cprBuffer_t *) cprGetBuffer(len);
|
||||
msg = (cprBuffer_t *) cpr_malloc(len);
|
||||
if (msg == NULL) {
|
||||
CCAPP_ERROR(DEB_F_PREFIX"failed to allocate message.\n",
|
||||
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
||||
|
@ -127,7 +128,7 @@ cpr_status_e ccappTaskPostMsg(unsigned int msgId, void * data, uint16_t len, int
|
|||
memcpy(msg, data, len);
|
||||
|
||||
if ((retval=ccappTaskSendMsg(msgId, msg, len, appId)) == CPR_FAILURE) {
|
||||
cprReleaseBuffer(msg);
|
||||
cpr_free(msg);
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -202,7 +203,7 @@ void CCApp_task(void * arg)
|
|||
syshdr->Usr.UsrInfo);
|
||||
}
|
||||
cprReleaseSysHeader(syshdr);
|
||||
cprReleaseBuffer(msg);
|
||||
cpr_free(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "CCProvider.h"
|
||||
#include "ccSession.h"
|
||||
#include "ccsip_task.h"
|
||||
|
@ -82,6 +84,7 @@
|
|||
#include "ccapi_device_info.h"
|
||||
#include "conf_roster.h"
|
||||
#include "reset_api.h"
|
||||
#include "prlog.h"
|
||||
|
||||
/*---------------------------------------------------------
|
||||
*
|
||||
|
@ -170,15 +173,7 @@ extern boolean apply_config;
|
|||
|
||||
extern char g_new_signaling_ip[];
|
||||
|
||||
extern char g_applyConfigFcpVersion[];
|
||||
extern char g_applyConfigDialPlanVersion[];
|
||||
|
||||
extern int configFileDownloadNeeded;
|
||||
cc_boolean parse_config_properties (int device_handle, const char *device_name, const char *cfg, int from_memory);
|
||||
extern int g_dev_hdl;
|
||||
extern char g_dev_name[];
|
||||
extern char g_cfg_p[];
|
||||
extern int g_compl_cfg;
|
||||
cc_action_t pending_action_type = NO_ACTION;
|
||||
|
||||
|
||||
|
@ -604,6 +599,9 @@ processSessionEvent (line_t line_id, callid_t call_id, unsigned int event, sdp_d
|
|||
session_data_t * sess_data_p;
|
||||
char digits[CC_MAX_DIALSTRING_LEN];
|
||||
char* data = (char*)ccData.info;
|
||||
char* data1 =(char*)ccData.info1;
|
||||
long strtol_result;
|
||||
char *strtol_end;
|
||||
|
||||
CCAPP_DEBUG(DEB_L_C_F_PREFIX"event=%d data=%s",
|
||||
DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, call_id, line_id, fname), event,
|
||||
|
@ -625,6 +623,47 @@ processSessionEvent (line_t line_id, callid_t call_id, unsigned int event, sdp_d
|
|||
case CC_FEATURE_BKSPACE:
|
||||
dp_int_update_keypress(line_id, call_id, BKSP_KEY);
|
||||
break;
|
||||
case CC_FEATURE_CREATEOFFER:
|
||||
cc_createoffer (CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_CREATEOFFER, &featdata);
|
||||
break;
|
||||
case CC_FEATURE_CREATEANSWER:
|
||||
cc_createanswer (CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_CREATEANSWER, data, &featdata);
|
||||
break;
|
||||
case CC_FEATURE_SETLOCALDESC:
|
||||
cc_setlocaldesc (CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_SETLOCALDESC, ccData.action, data, &featdata);
|
||||
break;
|
||||
case CC_FEATURE_SETREMOTEDESC:
|
||||
cc_setremotedesc (CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_SETREMOTEDESC, ccData.action, data, &featdata);
|
||||
break;
|
||||
case CC_FEATURE_SETPEERCONNECTION:
|
||||
PR_ASSERT(strlen(data) < PC_HANDLE_SIZE);
|
||||
if (strlen(data) >= PC_HANDLE_SIZE)
|
||||
return;
|
||||
|
||||
sstrncpy(featdata.pc.pc_handle, data, sizeof(featdata.pc.pc_handle));
|
||||
|
||||
cc_int_feature2(CC_MSG_SETPEERCONNECTION, CC_SRC_UI, CC_SRC_GSM,
|
||||
call_id, (line_t)instance,
|
||||
CC_FEATURE_SETPEERCONNECTION, &featdata);
|
||||
break;
|
||||
case CC_FEATURE_ADDSTREAM:
|
||||
featdata.track.stream_id = ccData.stream_id;
|
||||
featdata.track.track_id = ccData.track_id;
|
||||
featdata.track.media_type = ccData.media_type;
|
||||
cc_int_feature2(CC_MSG_ADDSTREAM, CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_ADDSTREAM, &featdata);
|
||||
break;
|
||||
case CC_FEATURE_REMOVESTREAM:
|
||||
featdata.track.stream_id = ccData.stream_id;
|
||||
featdata.track.track_id = ccData.track_id;
|
||||
featdata.track.media_type = ccData.media_type;
|
||||
cc_int_feature2(CC_MSG_REMOVESTREAM, CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_REMOVESTREAM, &featdata);
|
||||
break;
|
||||
case CC_FEATURE_ADDICECANDIDATE:
|
||||
featdata.candidate.level = ccData.level;
|
||||
sstrncpy(featdata.candidate.candidate, data, sizeof(featdata.candidate.candidate)-1);
|
||||
sstrncpy(featdata.candidate.mid, data1, sizeof(featdata.candidate.mid)-1);
|
||||
cc_int_feature2(CC_MSG_ADDCANDIDATE, CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_ADDICECANDIDATE, &featdata);
|
||||
break;
|
||||
case CC_FEATURE_DIALSTR:
|
||||
if (CheckAndGetAvailableLine(&line_id, &call_id) == TRUE) {
|
||||
getDigits(data, digits);
|
||||
|
@ -840,7 +879,15 @@ processSessionEvent (line_t line_id, callid_t call_id, unsigned int event, sdp_d
|
|||
//Legacy local conference.
|
||||
ftr_data.cnf.target_call_id = call_id;
|
||||
}
|
||||
cc_feature(CC_SRC_UI, GET_CALLID(atoi(digits)), line_id, event, &ftr_data);
|
||||
|
||||
errno = 0;
|
||||
strtol_result = strtol(digits, &strtol_end, 10);
|
||||
|
||||
if (errno || digits == strtol_end || strtol_result < INT_MIN || strtol_result > INT_MAX) {
|
||||
CCAPP_ERROR(DEB_F_PREFIX"digits parse error %s.\n",DEB_F_PREFIX_ARGS(SIP_CC_PROV, __FUNCTION__), digits);
|
||||
} else {
|
||||
cc_feature(CC_SRC_UI, GET_CALLID((int) strtol_result), line_id, event, &ftr_data);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"conf: no sid.\n",DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
||||
|
@ -950,9 +997,11 @@ session_data_t * getDeepCopyOfSessionData(session_data_t *data)
|
|||
session_data_t *newData = (session_data_t *) cpr_malloc(sizeof(session_data_t));
|
||||
|
||||
if ( newData != NULL ) {
|
||||
memset(newData, 0, sizeof(session_data_t));
|
||||
|
||||
if ( data != NULL ) {
|
||||
*newData = *data;
|
||||
newData->ref_count = 1;
|
||||
newData->ref_count = 1;
|
||||
newData->clg_name = strlib_copy(data->clg_name);
|
||||
newData->clg_number = strlib_copy(data->clg_number);
|
||||
newData->cld_name = strlib_copy(data->cld_name);
|
||||
|
@ -966,10 +1015,8 @@ session_data_t * getDeepCopyOfSessionData(session_data_t *data)
|
|||
newData->plcd_number = strlib_copy(data->plcd_number);
|
||||
newData->status = strlib_copy(data->status);
|
||||
calllogger_copy_call_log(&newData->call_log, &data->call_log);
|
||||
conf_roster_copy_call_conferance(&newData->call_conference, &data->call_conference);
|
||||
} else {
|
||||
memset(newData, 0, sizeof(session_data_t));
|
||||
newData->ref_count = 1;
|
||||
newData->ref_count = 1;
|
||||
newData->state = ONHOOK;
|
||||
newData->security = CC_SECURITY_NONE;
|
||||
newData->policy = CC_POLICY_NONE;
|
||||
|
@ -986,7 +1033,6 @@ session_data_t * getDeepCopyOfSessionData(session_data_t *data)
|
|||
newData->plcd_number = strlib_empty();
|
||||
newData->status = strlib_empty();
|
||||
calllogger_init_call_log(&newData->call_log);
|
||||
conf_roster_init_call_conference(&newData->call_conference);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1031,7 +1077,6 @@ void cleanSessionData(session_data_t *data)
|
|||
strlib_free(data->status);
|
||||
data->status = strlib_empty();
|
||||
calllogger_free_call_log(&data->call_log);
|
||||
conf_roster_free_call_conference(&data->call_conference);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1289,9 +1334,12 @@ static void ccappUpdateSessionData (session_update_t *sessUpd)
|
|||
|
||||
if ( data == NULL ) {
|
||||
cc_call_state_t call_state = sessUpd->update.ccSessionUpd.data.state_data.state;
|
||||
// TODO: Think how can this be handled better
|
||||
|
||||
if ( ( sessUpd->eventID == CALL_INFORMATION ) ||
|
||||
( sessUpd->eventID == CALL_STATE || sessUpd->eventID == CALL_NEWCALL)) {
|
||||
( sessUpd->eventID == CALL_STATE || sessUpd->eventID == CALL_NEWCALL
|
||||
|| sessUpd->eventID == CREATE_OFFER || sessUpd->eventID == CREATE_ANSWER
|
||||
|| sessUpd->eventID == SET_LOCAL_DESC || sessUpd->eventID == SET_REMOTE_DESC
|
||||
|| sessUpd->eventID == REMOTE_STREAM_ADD)) {
|
||||
|
||||
CCAPP_DEBUG(DEB_F_PREFIX"CALL_SESSION_CREATED for session id 0x%x event is 0x%x \n",
|
||||
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), sessUpd->sessionID,
|
||||
|
@ -1326,7 +1374,9 @@ static void ccappUpdateSessionData (session_update_t *sessUpd)
|
|||
data->sess_id = sessUpd->sessionID;
|
||||
data->state = call_state;
|
||||
data->line = sessUpd->update.ccSessionUpd.data.state_data.line_id;
|
||||
if (sessUpd->eventID == CALL_NEWCALL) {
|
||||
if (sessUpd->eventID == CALL_NEWCALL || sessUpd->eventID == CREATE_OFFER ||
|
||||
sessUpd->eventID == CREATE_ANSWER || sessUpd->eventID == SET_LOCAL_DESC ||
|
||||
sessUpd->eventID == SET_REMOTE_DESC || sessUpd->eventID == REMOTE_STREAM_ADD ) {
|
||||
data->attr = sessUpd->update.ccSessionUpd.data.state_data.attr;
|
||||
data->inst = sessUpd->update.ccSessionUpd.data.state_data.inst;
|
||||
}
|
||||
|
@ -1347,7 +1397,16 @@ static void ccappUpdateSessionData (session_update_t *sessUpd)
|
|||
data->vid_dir = SDP_DIRECTION_INACTIVE;
|
||||
data->callref = 0;
|
||||
calllogger_init_call_log(&data->call_log);
|
||||
conf_roster_init_call_conference(&data->call_conference);
|
||||
|
||||
if ( sessUpd->eventID == CREATE_OFFER || sessUpd->eventID == CREATE_ANSWER
|
||||
|| sessUpd->eventID == SET_LOCAL_DESC || sessUpd->eventID == SET_REMOTE_DESC
|
||||
|| sessUpd->eventID == REMOTE_STREAM_ADD) {
|
||||
data->sdp = sessUpd->update.ccSessionUpd.data.state_data.sdp;
|
||||
data->cause = sessUpd->update.ccSessionUpd.data.state_data.cause;
|
||||
data->media_stream_track_id = sessUpd->update.ccSessionUpd.data.state_data.media_stream_track_id;
|
||||
data->media_stream_id = sessUpd->update.ccSessionUpd.data.state_data.media_stream_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* If phone was idle, we not going to active state
|
||||
* send notification to resetmanager that we
|
||||
|
@ -1665,6 +1724,19 @@ static void ccappUpdateSessionData (session_update_t *sessUpd)
|
|||
ccsnap_gen_callEvent(CCAPI_CALL_EV_MEDIA_INTERFACE_UPDATE_FAIL,
|
||||
CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
||||
break;
|
||||
case CREATE_OFFER:
|
||||
case CREATE_ANSWER:
|
||||
case SET_LOCAL_DESC:
|
||||
case SET_REMOTE_DESC:
|
||||
case REMOTE_STREAM_ADD:
|
||||
data->sdp = sessUpd->update.ccSessionUpd.data.state_data.sdp;
|
||||
data->cause = sessUpd->update.ccSessionUpd.data.state_data.cause;
|
||||
data->state = sessUpd->update.ccSessionUpd.data.state_data.state;
|
||||
data->media_stream_track_id = sessUpd->update.ccSessionUpd.data.state_data.media_stream_track_id;
|
||||
data->media_stream_id = sessUpd->update.ccSessionUpd.data.state_data.media_stream_id;
|
||||
capset_get_allowed_features(gCCApp.mode, data->state, data->allowed_features);
|
||||
ccsnap_gen_callEvent(CCAPI_CALL_EV_STATE, CREATE_CALL_HANDLE_FROM_SESSION_ID(data->sess_id));
|
||||
break;
|
||||
default:
|
||||
DEF_DEBUG(DEB_F_PREFIX"Unknown event, id = %d\n",
|
||||
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), sessUpd->eventID);
|
||||
|
@ -1914,13 +1986,6 @@ void ccp_handler(void* msg, int type) {
|
|||
data->info_type = rcvdInfo->info.generic_raw.content_type;
|
||||
data->info_body = rcvdInfo->info.generic_raw.message_body;
|
||||
|
||||
// We are freeing the existing conference information, and
|
||||
// re-parsing the new XML received in the INFO. A future possible
|
||||
// optimization is to find the difference and only update the
|
||||
// changed/removed/added participants
|
||||
conf_roster_free_call_conference(&data->call_conference);
|
||||
decodeInfoXML(rcvdInfo->info.generic_raw.message_body, length, &data->call_conference);
|
||||
|
||||
ccsnap_gen_callEvent(CCAPI_CALL_EV_RECEIVED_INFO, CREATE_CALL_HANDLE_FROM_SESSION_ID(rcvdInfo->sessionID));
|
||||
|
||||
// most of the time isConference will be true at this point, we can notify the app of
|
||||
|
@ -2141,9 +2206,6 @@ void ccappSyncSessionMgmt(session_mgmt_t *sessMgmt)
|
|||
case SESSION_MGMT_APPLY_CONFIG:
|
||||
// save the proposed versions of fcp and dialplan to apply. Will check against
|
||||
// current versions and redownload if necessary
|
||||
|
||||
strcpy (g_applyConfigFcpVersion, sessMgmt->data.config.fcp_version_stamp);
|
||||
strcpy (g_applyConfigDialPlanVersion, sessMgmt->data.config.dialplan_version_stamp);
|
||||
|
||||
if (pending_action_type == NO_ACTION) {
|
||||
configApplyConfigNotify(sessMgmt->data.config.config_version_stamp,
|
||||
|
|
|
@ -38,15 +38,12 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
#include "sll_lite.h"
|
||||
#include "cc_constants.h"
|
||||
#include "cc_types.h"
|
||||
#include "cc_config.h"
|
||||
#include "phone_debug.h"
|
||||
#include "debug.h"
|
||||
#include <string.h> /* for strncpy */
|
||||
#include "CCProvider.h"
|
||||
#include "ccapi_call_info.h"
|
||||
#include "conf_roster.h"
|
||||
|
@ -87,324 +84,6 @@ convertStringToParticipantSecurity(const char *data)
|
|||
return CC_SECURITY_NONE;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* parse_call_info_node
|
||||
*
|
||||
* Parse call-info node.
|
||||
*
|
||||
* Assumes a_node, participant are not null.
|
||||
*/
|
||||
static void
|
||||
parse_call_info_node (xmlNode * a_node, cc_call_conferenceParticipant_Info_t *participant) {
|
||||
xmlChar *data;
|
||||
xmlNode *cur_node;
|
||||
xmlNode *walker_node;
|
||||
|
||||
for (cur_node = a_node->children; cur_node != NULL; cur_node = cur_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
if (xmlStrcmp(cur_node->name, (const xmlChar *) "security") == 0) {
|
||||
data = xmlNodeGetContent(cur_node);
|
||||
if (data != NULL) {
|
||||
participant->participantSecurity = convertStringToParticipantSecurity((const char*)data);
|
||||
xmlFree(data);
|
||||
}
|
||||
} else if (xmlStrcmp(cur_node->name, (const xmlChar *) "sip") == 0) {
|
||||
for (walker_node = cur_node->children; walker_node != NULL; walker_node = walker_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
if (xmlStrcmp(walker_node->name, (const xmlChar *) "call-id") == 0) {
|
||||
data = xmlNodeGetContent(walker_node);
|
||||
if (data != NULL) {
|
||||
participant->callid = strlib_update(participant->callid, (const char*)data);
|
||||
xmlFree(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_self_node
|
||||
*
|
||||
* Parse self node.
|
||||
*
|
||||
* Assumes a_node, participant are not null.
|
||||
*/
|
||||
|
||||
static void
|
||||
parse_self_node (xmlNode * a_node, cc_call_conferenceParticipant_Info_t *participant)
|
||||
{
|
||||
xmlChar* data;
|
||||
xmlNode* cur_node;
|
||||
xmlNode* walker_node;
|
||||
|
||||
for (cur_node = a_node->children; cur_node != NULL; cur_node = cur_node->next)
|
||||
{
|
||||
if (xmlStrcmp(cur_node->name, (const xmlChar *) "user-capabilities") == 0)
|
||||
{
|
||||
for (walker_node = cur_node->children; walker_node != NULL; walker_node = walker_node->next)
|
||||
{
|
||||
if (cur_node->type == XML_ELEMENT_NODE)
|
||||
{
|
||||
if (xmlStrcmp(walker_node->name, (const xmlChar *) "remove-participant") == 0)
|
||||
{
|
||||
data = xmlNodeGetContent(walker_node);
|
||||
if (data != NULL)
|
||||
{ // set field to indicate this participant can remove other participants
|
||||
participant->canRemoveOtherParticipants = TRUE;
|
||||
xmlFree(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_user_endpoint_node
|
||||
*
|
||||
* Do endpoint specific parsing.
|
||||
*
|
||||
* Assumes a_node, participant is not null.
|
||||
*/
|
||||
static void
|
||||
parse_user_endpoint_node (xmlNode * a_node, cc_call_conferenceParticipant_Info_t *participant, cc_call_conference_Info_t *info) {
|
||||
xmlChar *data;
|
||||
xmlNode *cur_node;
|
||||
|
||||
for (cur_node = a_node->children; cur_node != NULL; cur_node = cur_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
if (xmlStrcmp(cur_node->name, (const xmlChar *) "status") == 0) {
|
||||
data = xmlNodeGetContent(cur_node);
|
||||
if (data != NULL) {
|
||||
participant->participantStatus = convertStringToParticipantStatus((const char*)data);
|
||||
xmlFree(data);
|
||||
} else {
|
||||
//continue parsing other elements
|
||||
CCAPP_ERROR(DEB_F_PREFIX" Error while getting the data for node: status\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAPI-CONFPARSE"));
|
||||
}
|
||||
} else if (xmlStrcmp(cur_node->name, (const xmlChar *) "call-info") == 0) {
|
||||
parse_call_info_node(cur_node, participant);
|
||||
} else if (xmlStrcmp(cur_node->name, (const xmlChar *) "self") == 0) {
|
||||
parse_self_node(cur_node, participant);
|
||||
info->myParticipantId = strlib_update(info->myParticipantId, participant->callid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_user_node
|
||||
*
|
||||
* Do user node specific parsing.
|
||||
*
|
||||
* Assumes a_node, info are not null.
|
||||
*/
|
||||
static void
|
||||
parse_user_node (xmlNode * a_node, cc_call_conference_Info_t *info)
|
||||
{
|
||||
xmlChar *data;
|
||||
xmlNode *cur_node;
|
||||
cc_call_conferenceParticipant_Info_t *participant;
|
||||
sll_lite_return_e sll_ret_val;
|
||||
|
||||
//allocate a new participant
|
||||
participant = cpr_malloc(sizeof(cc_call_conferenceParticipant_Info_t));
|
||||
if (participant == NULL) {
|
||||
CCAPP_ERROR(DEB_F_PREFIX" Malloc failure for participant\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAPI-CONFPARSE"));
|
||||
return;
|
||||
} else {
|
||||
participant->participantName = strlib_empty();
|
||||
participant->endpointUri = strlib_empty();
|
||||
participant->callid = strlib_empty();
|
||||
participant->participantNumber = strlib_empty();
|
||||
participant->participantSecurity = CC_SECURITY_NONE;
|
||||
participant->participantStatus = CCAPI_CONFPARTICIPANT_UNKNOWN;
|
||||
participant->canRemoveOtherParticipants = FALSE;
|
||||
}
|
||||
|
||||
sll_ret_val = sll_lite_link_tail(&info->currentParticipantsList, (sll_lite_node_t *)participant);
|
||||
if (sll_ret_val != SLL_LITE_RET_SUCCESS) {
|
||||
CCAPP_ERROR(DEB_F_PREFIX" Error while trying to insert in the linked list\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAPI-CONFPARSE"));
|
||||
cpr_free(participant);
|
||||
return;
|
||||
}
|
||||
|
||||
data = xmlGetProp(a_node, (const xmlChar *) "entity");
|
||||
if (data != NULL) {
|
||||
char *tmp2;
|
||||
char *tmp1;
|
||||
participant->endpointUri = strlib_update(participant->endpointUri, (const char*)data);
|
||||
|
||||
// Parse the endpoint URI, to get the Participant number
|
||||
|
||||
tmp1 = (char *) strstr((const char*)data, "sip:");
|
||||
if (tmp1) {
|
||||
tmp1 += 4;
|
||||
tmp2 = (char *) strchr(tmp1, '@');
|
||||
if (tmp2) {
|
||||
*tmp2 = 0;
|
||||
participant->participantNumber = strlib_update(participant->participantNumber, (const char*)tmp1);
|
||||
}
|
||||
}
|
||||
xmlFree(data);
|
||||
} else {
|
||||
//continue parsing other elements
|
||||
CCAPP_ERROR(DEB_F_PREFIX" Error while trying to find the endpoint URI\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAPI-CONFPARSE"));
|
||||
}
|
||||
|
||||
for (cur_node = a_node->children; cur_node != NULL; cur_node = cur_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
if (xmlStrcmp(cur_node->name, (const xmlChar *) "endpoint") == 0) {
|
||||
parse_user_endpoint_node(cur_node, participant, info);
|
||||
} else if (xmlStrcmp(cur_node->name, (const xmlChar *) "display-text") == 0) {
|
||||
data = xmlNodeGetContent(cur_node);
|
||||
if (data != NULL) {
|
||||
participant->participantName = strlib_update(participant->participantName, (const char*)data);
|
||||
xmlFree(data);
|
||||
} else {
|
||||
//No display text - continue parsing other elements -
|
||||
CCAPP_ERROR(DEB_F_PREFIX" Error while trying to get the display text\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAPI-CONFPARSE"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_conference_state_node
|
||||
*
|
||||
* Do conference-state specific parsing.
|
||||
*
|
||||
* Assumes a_node, info are not null.
|
||||
*/
|
||||
static void
|
||||
parse_conference_state_node (xmlNode * a_node, cc_call_conference_Info_t *info)
|
||||
{
|
||||
xmlNode *cur_node;
|
||||
xmlChar *data;
|
||||
|
||||
for (cur_node = a_node->children; cur_node != NULL; cur_node = cur_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
if (xmlStrcmp(cur_node->name, (const xmlChar *) "user-count") == 0) {
|
||||
data = xmlNodeGetContent(cur_node);
|
||||
if (data != NULL) {
|
||||
info->participantCount = atoi((const char*)data);
|
||||
xmlFree(data);
|
||||
} else {
|
||||
//No user-count - continue parsing other elements -
|
||||
CCAPP_ERROR(DEB_F_PREFIX" Error while trying to get the user-count\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAPI-CONFPARSE"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_conference_description_node
|
||||
*
|
||||
* Do conference-description specific parsing.
|
||||
*
|
||||
* Assumes a_node, info are not null.
|
||||
*/
|
||||
static void
|
||||
parse_conference_description_node (xmlNode * a_node, cc_call_conference_Info_t *info)
|
||||
{
|
||||
xmlNode *cur_node;
|
||||
xmlChar *data;
|
||||
|
||||
for (cur_node = a_node->children; cur_node != NULL; cur_node = cur_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
if (xmlStrcmp(cur_node->name, (const xmlChar *) "maximum-user-count") == 0) {
|
||||
data = xmlNodeGetContent(cur_node);
|
||||
if (data != NULL) {
|
||||
info->participantMax = atoi((const char*)data);
|
||||
xmlFree(data);
|
||||
} else {
|
||||
//No max-user-count - continue parsing other elements -
|
||||
CCAPP_ERROR(DEB_F_PREFIX" Error while trying to get the max-user-count\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAPI-CONFPARSE"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_conference_info_node
|
||||
*
|
||||
* Do conference-info specific parsing.
|
||||
*
|
||||
* Assumes a_node, doc, info are not null.
|
||||
*/
|
||||
static void
|
||||
parse_conference_info_node (xmlNode * a_node, xmlDocPtr doc, cc_call_conference_Info_t *info)
|
||||
{
|
||||
xmlNode *cur_node;
|
||||
xmlNode *nodeLevel1;
|
||||
xmlNode *nodeLevel2;
|
||||
|
||||
for (cur_node = a_node; cur_node != NULL; cur_node = cur_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
|
||||
for (nodeLevel1 = cur_node->children; nodeLevel1 != NULL; nodeLevel1 = nodeLevel1->next) {
|
||||
if (nodeLevel1->type == XML_ELEMENT_NODE) {
|
||||
|
||||
if (xmlStrcmp(nodeLevel1->name, (const xmlChar *) "conference-description") == 0) {
|
||||
parse_conference_description_node(nodeLevel1, info);
|
||||
}
|
||||
if (xmlStrcmp(nodeLevel1->name, (const xmlChar *) "conference-state") == 0) {
|
||||
parse_conference_state_node(nodeLevel1, info);
|
||||
}
|
||||
|
||||
if (xmlStrcmp(nodeLevel1->name, (const xmlChar *) "users") == 0) {
|
||||
for (nodeLevel2 = nodeLevel1->children; nodeLevel2 != NULL; nodeLevel2 = nodeLevel2->next) {
|
||||
if (nodeLevel2->type == XML_ELEMENT_NODE) {
|
||||
if (xmlStrcmp(nodeLevel2->name, (const xmlChar *) "user") == 0) {
|
||||
parse_user_node(nodeLevel2, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @content: the content of the document
|
||||
* @length: the length in bytes
|
||||
*
|
||||
* Parse the in memory document and free the resulting tree
|
||||
*/
|
||||
void
|
||||
decodeInfoXML(const char *content, int length, cc_call_conference_Info_t *info) {
|
||||
xmlDocPtr doc; /* the resulting document tree */
|
||||
xmlNode *root_element = NULL;
|
||||
|
||||
doc = xmlReadMemory(content, length, "noname.xml", NULL, 0);
|
||||
if (doc == NULL) {
|
||||
CCAPP_ERROR(DEB_F_PREFIX" Failed to parse document\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAPI-CONFPARSE"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the root element node */
|
||||
root_element = xmlDocGetRootElement(doc);
|
||||
if (root_element == NULL) {
|
||||
CCAPP_ERROR(DEB_F_PREFIX" Failed to get the root element\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAPI-CONFPARSE"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (xmlStrcmp(root_element->name, (const xmlChar *)"conference-info") == 0) {
|
||||
parse_conference_info_node(root_element, doc, info);
|
||||
}
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
}
|
||||
|
||||
|
||||
void conf_roster_init_call_conference (cc_call_conference_Info_t *info)
|
||||
|
|
|
@ -77,7 +77,6 @@ cc_call_conference_ref_t getCallConferenceRef(cc_callinfo_ref_t hand
|
|||
cc_call_conference_participant_ref_t getConferenceParticipantRef(cc_callinfo_ref_t handle, cc_participant_ref_t participantHandle);
|
||||
void conf_roster_free_call_conference (cc_call_conference_Info_t *confInfo);
|
||||
void conf_roster_copy_call_conferance (cc_call_conference_Info_t *dest, cc_call_conference_Info_t * src);
|
||||
void decodeInfoXML(const char *content, int length, cc_call_conference_Info_t *info);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ cfgfile_parse_str (const var_t *entry, const char *value)
|
|||
/*
|
||||
* Copy string into config block
|
||||
*/
|
||||
strncpy((char *)entry->addr, value, entry->length);
|
||||
sstrncpy((char *)entry->addr, value, entry->length);
|
||||
return (0);
|
||||
|
||||
|
||||
|
|
|
@ -291,13 +291,13 @@ get_printable_cfg(unsigned int indx, char *buf, unsigned int len)
|
|||
// real password
|
||||
if (indx>=CFGID_LINE_PASSWORD && indx < CFGID_LINE_PASSWORD+MAX_CONFIG_LINES) {
|
||||
// and add an invisible one
|
||||
strncpy(buf, "**********", MAX_CONFIG_VAL_PRINT_LEN);
|
||||
sstrncpy(buf, "**********", MAX_CONFIG_VAL_PRINT_LEN);
|
||||
} else if ( table->print_func ) {
|
||||
table->print_func(table, buf, len);
|
||||
}
|
||||
|
||||
if ( buf[0] == 0 ) {
|
||||
strcpy(buf,"EMPTY");
|
||||
sstrncpy(buf,"EMPTY", len);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ show_config_cmd (cc_int32_t argc, const char *argv[])
|
|||
// real password
|
||||
if (strstr(table->name, "Password") != 0) {
|
||||
// and add an invisible one
|
||||
strncpy(buf, "**********", MAX_CONFIG_VAL_PRINT_LEN);
|
||||
sstrncpy(buf, "**********", sizeof(buf));
|
||||
}
|
||||
debugif_printf("%s : %s\n", table->name, buf);
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -40,8 +40,6 @@
|
|||
#ifndef CONFIG_PARSER_H_
|
||||
#define CONFIG_PARSER_H_
|
||||
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
#include "cc_constants.h"
|
||||
#include "cc_types.h"
|
||||
#include "cc_config.h"
|
||||
|
@ -55,8 +53,6 @@
|
|||
|
||||
#define MAX_CFG_VERSION_STAMP_LEN 80
|
||||
|
||||
extern char g_cfg_version_stamp[];
|
||||
|
||||
/*
|
||||
* This function determine whether the passed config parameter should be used
|
||||
* in comparing the new and old config value for apply-config purpose. Only
|
||||
|
@ -91,14 +87,6 @@ void compare_or_set_int_value(int cfgid, int value, const unsigned char * config
|
|||
*/
|
||||
void compare_or_set_string_value (int cfgid, const char* value, const unsigned char * config_name);
|
||||
|
||||
void update_sipline_properties(xmlNode *sipline_node, xmlDocPtr doc);
|
||||
|
||||
/*
|
||||
* config_set_sipline_properties
|
||||
*
|
||||
*/
|
||||
void config_set_sipline_properties (xmlNode *sipline_node, xmlDocPtr doc, boolean button_configured[] );
|
||||
|
||||
/*
|
||||
* config_fetch_dialplan() called to retrieve the dialplan
|
||||
*
|
||||
|
@ -123,18 +111,6 @@ void config_set_autoreg_properties ();
|
|||
*/
|
||||
void update_security_mode_and_ports(void);
|
||||
|
||||
//void process_ccm_config(xmlNode *ccm_node, xmlDocPtr doc, char **ccm_name, int * sip_port, int *iteration);
|
||||
void process_ccm_config(xmlNode *ccm_node, xmlDocPtr doc,
|
||||
char ccm_name[][MAX_SIP_URL_LENGTH],
|
||||
int * sip_port, int * secured_sip_port,
|
||||
int *iteration);
|
||||
|
||||
/*
|
||||
* config_set_ccm_properties
|
||||
*
|
||||
*/
|
||||
void config_process_ccm_properties (xmlNode *ccm_node, xmlDocPtr doc);
|
||||
|
||||
/*
|
||||
* config_get_mac_addr
|
||||
*
|
||||
|
@ -148,14 +124,6 @@ void config_get_mac_addr (char *maddr);
|
|||
*/
|
||||
void config_set_ccm_ip_mac ();
|
||||
|
||||
/*
|
||||
* config_parse_element
|
||||
*
|
||||
* Parse the elements in the XML document and call the
|
||||
* corressponding set functions
|
||||
*/
|
||||
void config_parse_element (xmlNode *cur_node, char * value, xmlDocPtr doc );
|
||||
|
||||
|
||||
/*
|
||||
* Set up configuration without XML config file.
|
||||
|
@ -203,17 +171,15 @@ const char* config_get_version();
|
|||
*/
|
||||
void config_setup_p2p_mode(const cc_boolean is_p2p);
|
||||
|
||||
/*
|
||||
* set sdp mode on or off
|
||||
*/
|
||||
void config_setup_sdp_mode(const cc_boolean is_sdp);
|
||||
|
||||
/*
|
||||
* set ROAP proxy mode on or off
|
||||
* set avp mode (true == RTP/SAVPF, false = RTP/SAVP)
|
||||
*/
|
||||
void config_setup_roap_proxy_mode(const cc_boolean is_roap_proxy);
|
||||
|
||||
/*
|
||||
* set ROAP client mode on or off
|
||||
*/
|
||||
void config_setup_roap_client_mode(const cc_boolean is_roap_client);
|
||||
|
||||
void config_setup_avp_mode(const cc_boolean is_rtpsavpf);
|
||||
|
||||
/**
|
||||
* config_minimum_check:
|
||||
|
@ -225,11 +191,6 @@ void config_setup_roap_client_mode(const cc_boolean is_roap_client);
|
|||
* have values that can be used by sipstack
|
||||
*
|
||||
*/
|
||||
void config_minimum_check_siplines(xmlNode * a_node, xmlDocPtr doc);
|
||||
|
||||
boolean is_config_valid(char * config, int from_memory);
|
||||
|
||||
void config_minimum_check(xmlNode * a_node, xmlDocPtr doc);
|
||||
|
||||
/**
|
||||
* Parse the file that is passed in,
|
||||
|
|
|
@ -74,18 +74,9 @@
|
|||
#define MEM_PER_CALL_BLK 20 //20 block, ~20k
|
||||
#define PRIVATE_SYS_MEM_SIZE ((MEM_BASE_BLK + MEM_MISC_BLK + (MEM_PER_CALL_BLK) * MAX_CALLS) * BLK_SZ)
|
||||
|
||||
extern boolean cpr_memory_mgmt_pre_init(size_t size);
|
||||
extern boolean cpr_memory_mgmt_post_init(void);
|
||||
extern void cpr_memory_mgmt_destroy(void);
|
||||
|
||||
/**
|
||||
* Force a crash dump which will allow a stack trace to be generated
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @note crash dump is created by an illegal write to memory
|
||||
*/
|
||||
extern void cpr_crashdump(void);
|
||||
// used in early init code where config has not been setup
|
||||
const boolean gHardCodeSDPMode = TRUE;
|
||||
boolean gStopTickTask = FALSE;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
|
@ -218,16 +209,6 @@ void send_protocol_config_msg(void);
|
|||
*/
|
||||
extern
|
||||
int ccMemInit(size_t size) {
|
||||
/*
|
||||
* Do not move memory pre init below.
|
||||
* This initializes the memory sandbox
|
||||
* and must be first thing done here to make sure
|
||||
* allocations succeed.
|
||||
*/
|
||||
if (cpr_memory_mgmt_pre_init(size) != TRUE)
|
||||
{
|
||||
return CPR_FAILURE;
|
||||
}
|
||||
return CPR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -283,6 +264,7 @@ ccInit ()
|
|||
static int
|
||||
thread_init ()
|
||||
{
|
||||
gStopTickTask = FALSE;
|
||||
/*
|
||||
* This will have already been called for CPR CNU code,
|
||||
* but may be called here for Windows emulation.
|
||||
|
@ -295,7 +277,10 @@ thread_init ()
|
|||
/* initialize message queues */
|
||||
sip_msgq = cprCreateMessageQueue("SIPQ", SIPQSZ);
|
||||
gsm_msgq = cprCreateMessageQueue("GSMQ", GSMQSZ);
|
||||
misc_app_msgq = cprCreateMessageQueue("MISCAPPQ", DEFQSZ);
|
||||
|
||||
if (FALSE == gHardCodeSDPMode) {
|
||||
misc_app_msgq = cprCreateMessageQueue("MISCAPPQ", DEFQSZ);
|
||||
}
|
||||
ccapp_msgq = cprCreateMessageQueue("CCAPPQ", DEFQSZ);
|
||||
#ifdef JINDO_DEBUG_SUPPORTED
|
||||
debug_msgq = cprCreateMessageQueue("DEBUGAPPQ", DEFQSZ);
|
||||
|
@ -310,10 +295,6 @@ thread_init ()
|
|||
*/
|
||||
debugInit();
|
||||
|
||||
/* initialize adapter level debugs */
|
||||
//debug_bind_keyword("sip-adapter", &TNPDebug);
|
||||
// bind_clear_keyword("mwi", &ui_clear_mwi);
|
||||
|
||||
/* create threads */
|
||||
ccapp_thread = cprCreateThread("CCAPP Task",
|
||||
(cprThreadStartRoutine) CCApp_task,
|
||||
|
@ -333,7 +314,7 @@ thread_init ()
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* SIP main thread */
|
||||
sip_thread = cprCreateThread("SIPStack task",
|
||||
(cprThreadStartRoutine) sip_platform_task_loop,
|
||||
|
@ -359,11 +340,14 @@ thread_init ()
|
|||
if (gsm_thread == NULL) {
|
||||
err_msg("failed to create gsm task \n");
|
||||
}
|
||||
misc_app_thread = cprCreateThread("MiscApp Task",
|
||||
(cprThreadStartRoutine) MiscAppTask,
|
||||
STKSZ, 0 /* pri */, misc_app_msgq);
|
||||
if (misc_app_thread == NULL) {
|
||||
err_msg("failed to create MiscApp task \n");
|
||||
|
||||
if (FALSE == gHardCodeSDPMode) {
|
||||
misc_app_thread = cprCreateThread("MiscApp Task",
|
||||
(cprThreadStartRoutine) MiscAppTask,
|
||||
STKSZ, 0 /* pri */, misc_app_msgq);
|
||||
if (misc_app_thread == NULL) {
|
||||
err_msg("failed to create MiscApp task \n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_TICK_REQUIRED
|
||||
|
@ -376,9 +360,13 @@ thread_init ()
|
|||
#endif
|
||||
|
||||
/* Associate the threads with the message queues */
|
||||
(void) cprSetMessageQueueThread(sip_msgq, sip_thread);
|
||||
(void) cprSetMessageQueueThread(sip_msgq, sip_thread);
|
||||
(void) cprSetMessageQueueThread(gsm_msgq, gsm_thread);
|
||||
(void) cprSetMessageQueueThread(misc_app_msgq, misc_app_thread);
|
||||
|
||||
if (FALSE == gHardCodeSDPMode) {
|
||||
(void) cprSetMessageQueueThread(misc_app_msgq, misc_app_thread);
|
||||
}
|
||||
|
||||
(void) cprSetMessageQueueThread(ccapp_msgq, ccapp_thread);
|
||||
#ifdef JINDO_DEBUG_SUPPORTED
|
||||
(void) cprSetMessageQueueThread(debug_msgq, debug_thread);
|
||||
|
@ -442,7 +430,7 @@ int
|
|||
TickerTask (void *a)
|
||||
{
|
||||
TNP_DEBUG(DEB_F_PREFIX"Ticker Task initialized..\n", DEB_F_PREFIX_ARGS(SIP_CC_INIT, "TickerTask"));
|
||||
while (1) {
|
||||
while (FALSE == gStopTickTask) {
|
||||
cprSleep(20);
|
||||
MAIN0Timer();
|
||||
}
|
||||
|
@ -466,7 +454,7 @@ send_protocol_config_msg (void)
|
|||
/* send a config done message to the SIP Task */
|
||||
if (SIPTaskSendMsg(TCP_PHN_CFG_TCP_DONE, msg, 0, NULL) == CPR_FAILURE) {
|
||||
err_msg("%s: notify SIP stack ready failed", fname);
|
||||
cprReleaseBuffer(msg);
|
||||
cpr_free(msg);
|
||||
}
|
||||
gsm_set_initialized();
|
||||
PHNChangeState(STATE_CONNECTED);
|
||||
|
@ -493,6 +481,9 @@ send_task_unload_msg(cc_srcs_t dest_id)
|
|||
const char *fname = "send_task_unload_msg";
|
||||
uint16_t len = 4;
|
||||
cprBuffer_t msg = gsm_get_buffer(len);
|
||||
int sdpmode = 0;
|
||||
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
|
||||
if (msg == NULL) {
|
||||
err_msg("%s: failed to allocate msg cprBuffer_t\n", fname);
|
||||
|
@ -512,7 +503,10 @@ send_task_unload_msg(cc_srcs_t dest_id)
|
|||
/* send this msg so phone can send unRegister msg */
|
||||
SIPTaskPostShutdown(SIP_EXTERNAL, CC_CAUSE_SHUTDOWN, "");
|
||||
/* allow unRegister msg to sent out and shutdown to complete */
|
||||
cprSleep(2000);
|
||||
|
||||
if (!sdpmode) {
|
||||
cprSleep(2000);
|
||||
}
|
||||
/* send a unload message to the SIP Task to kill sip thread*/
|
||||
msg = SIPTaskGetBuffer(len);
|
||||
if (msg == NULL) {
|
||||
|
@ -522,7 +516,7 @@ send_task_unload_msg(cc_srcs_t dest_id)
|
|||
|
||||
if (SIPTaskSendMsg(THREAD_UNLOAD, (cprBuffer_t)msg, len, NULL) == CPR_FAILURE)
|
||||
{
|
||||
cprReleaseBuffer(msg);
|
||||
cpr_free(msg);
|
||||
err_msg("%s: Unable to send THREAD_UNLOAD msg to sip thread", fname);
|
||||
}
|
||||
}
|
||||
|
@ -541,7 +535,7 @@ send_task_unload_msg(cc_srcs_t dest_id)
|
|||
break;
|
||||
case CC_SRC_MISC_APP:
|
||||
{
|
||||
msg = cprGetBuffer(len);
|
||||
msg = cpr_malloc(len);
|
||||
if (msg == NULL) {
|
||||
err_msg("%s: failed to allocate misc msg cprBuffer_t\n", fname);
|
||||
return;
|
||||
|
@ -553,7 +547,7 @@ send_task_unload_msg(cc_srcs_t dest_id)
|
|||
break;
|
||||
case CC_SRC_CCAPP:
|
||||
{
|
||||
msg = cprGetBuffer(len);
|
||||
msg = cpr_malloc(len);
|
||||
if (msg == NULL) {
|
||||
err_msg("%s: failed to allocate ccapp msg cprBuffer_t\n", fname);
|
||||
return;
|
||||
|
@ -601,7 +595,15 @@ ccUnload (void)
|
|||
*/
|
||||
send_task_unload_msg(CC_SRC_SIP);
|
||||
send_task_unload_msg(CC_SRC_GSM);
|
||||
send_task_unload_msg(CC_SRC_MISC_APP);
|
||||
|
||||
if (FALSE == gHardCodeSDPMode) {
|
||||
send_task_unload_msg(CC_SRC_MISC_APP);
|
||||
}
|
||||
|
||||
send_task_unload_msg(CC_SRC_CCAPP);
|
||||
|
||||
cprSleep(200);
|
||||
|
||||
gStopTickTask = TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,14 +41,18 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "cpr.h"
|
||||
#include "phone_debug.h"
|
||||
#include "cc_debug.h"
|
||||
#include "phone.h"
|
||||
#include "cpr_socket.h"
|
||||
//#include "cc_config.h"
|
||||
#include "prot_configmgr.h"
|
||||
#include "debug.h"
|
||||
#include "cpr_string.h"
|
||||
#include "cpr_stdlib.h"
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Local definitions
|
||||
*--------------------------------------------------------------------------
|
||||
|
@ -70,116 +74,6 @@ static const char *month_ar[MAX_NTP_MONTH_ARRAY_SIZE] = {
|
|||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
extern boolean ccsip_get_ccm_date(char *date_value);
|
||||
|
||||
/** The debug Bind table. Contains all the different debug categories used in
|
||||
* the core. Each row has the debug category, the name used in the RT/TNP
|
||||
* implementation (Jindo) and the variable that is used to start/stop this
|
||||
* debug.
|
||||
*/
|
||||
debugStruct_t debugBindTable[] = {
|
||||
{CC_DEBUG_CCAPP, "ccapp", &g_CCAppDebug},
|
||||
{CC_DEBUG_CONFIG_CACHE, "config-cache", &ConfigDebug},
|
||||
{CC_DEBUG_SIP_ADAPTER, "sip-adapter", &TNPDebug},
|
||||
{CC_DEBUG_CCAPI, "cc", &CCDebug},
|
||||
{CC_DEBUG_CC_MSG, "cc-msg", &CCDebugMsg},
|
||||
{CC_DEBUG_FIM, "fim", &FIMDebug},
|
||||
{CC_DEBUG_FSM, "fsm", &FSMDebugSM},
|
||||
{CC_DEBUG_AUTH, "auth", &AuthDebug},
|
||||
{CC_DEBUG_GSM, "gsm", &GSMDebug},
|
||||
{CC_DEBUG_LSM, "lsm", &LSMDebug},
|
||||
{CC_DEBUG_FSM_CAC, "fsm-cac", &g_cacDebug},
|
||||
{CC_DEBUG_DCSM, "dcsm", &g_dcsmDebug},
|
||||
{CC_DEBUG_SIP_TASK, "sip-task", &SipDebugTask},
|
||||
{CC_DEBUG_SIP_STATE, "sip-state", &SipDebugState},
|
||||
{CC_DEBUG_SIP_MSG, "sip-messages", &SipDebugMessage},
|
||||
{CC_DEBUG_SIP_REG_STATE, "sip-reg-state", &SipDebugRegState},
|
||||
{CC_DEBUG_SIP_TRX, "sip-trx", &SipDebugTrx},
|
||||
{CC_DEBUG_TIMERS, "timers", &TMRDebug},
|
||||
{CC_DEBUG_CCDEFAULT, "ccdefault", &g_DEFDebug},
|
||||
{CC_DEBUG_DIALPLAN, "dialplan", &DpintDebug},
|
||||
{CC_DEBUG_KPML, "kpml", &KpmlDebug},
|
||||
{CC_DEBUG_SIP_PRESENCE, "sip-presence", &g_blfDebug},
|
||||
{CC_DEBUG_CONFIG_APP, "config-app", &g_configappDebug},
|
||||
{CC_DEBUG_CALL_EVENT, "call-event", &CCEVENTDebug},
|
||||
{CC_DEBUG_PLAT, "plat", &PLATDebug},
|
||||
{CC_DEBUG_NOTIFY, "cc-notify", NULL},
|
||||
{CC_DEBUG_CPR_MEMORY, "cpr-memory", NULL}, /* cpr-memory has a func callback*/
|
||||
{CC_DEBUG_MAX, "not-used", NULL} /* MUST BE THE LAST ELEMENT */
|
||||
};
|
||||
|
||||
/* A list of the external functions that are used as callback functions in the
|
||||
* show command. These functions are invoked whenever a show command is called
|
||||
* either by the vendor or the plat code.
|
||||
*/
|
||||
extern cc_int32_t fsmcnf_show_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t fsmdef_show_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t fsmxfr_show_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t fsmb2bcnf_show_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t dcsm_show_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t fim_show_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t fsm_show_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t lsm_show_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t show_kpmlmap_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t show_config_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t show_subsmanager_stats(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t show_publish_stats(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t show_register_cmd(cc_int32_t argc, const char *argv[]);
|
||||
extern cc_int32_t show_dialplan_cmd(cc_int32_t argc, const char *argv[]);
|
||||
/* CPR MEMORY ARCHIVE DECLARATIONS. These are considered to be part of core */
|
||||
extern int32_t cpr_show_memory(int32_t argc, const char *argv[]);
|
||||
extern int32_t cpr_clear_memory (int32_t argc, const char *argv[]);
|
||||
extern void debugCprMem(cc_debug_cpr_mem_options_e category, cc_debug_flag_e flag);
|
||||
extern void debugClearCprMem(cc_debug_clear_cpr_options_e category);
|
||||
void debugShowCprMem(cc_debug_show_cpr_options_e category);
|
||||
|
||||
|
||||
/** The debug Show table. Contains all the different show categories used in
|
||||
* the core. Each row has the show category, the name used in the RT/TNP
|
||||
* implementation (Jindo), the callback function assoicated with the show
|
||||
* and a boolean. The boolean indicates if this show is tied with the "tech"
|
||||
* keyword. A TRUE means this show is also part of the "show tech-sip" command.
|
||||
*/
|
||||
debugShowStruct_t debugShowTable[] = {
|
||||
{CC_DEBUG_SHOW_FSMCNF, "fsmcnf", fsmcnf_show_cmd, FALSE},
|
||||
{CC_DEBUG_SHOW_FSMDEF, "fsmdef", fsmdef_show_cmd, FALSE},
|
||||
{CC_DEBUG_SHOW_FSMXFR, "fsmxfr", fsmxfr_show_cmd, FALSE},
|
||||
{CC_DEBUG_SHOW_FSMB2BCNF, "fsmb2bcnf", fsmb2bcnf_show_cmd, FALSE},
|
||||
{CC_DEBUG_SHOW_DCSM, "dcsm", dcsm_show_cmd, FALSE},
|
||||
{CC_DEBUG_SHOW_FIM, "fim", fim_show_cmd, FALSE},
|
||||
{CC_DEBUG_SHOW_FSM, "fsm", fsm_show_cmd, FALSE},
|
||||
{CC_DEBUG_SHOW_LSM, "lsm", lsm_show_cmd, FALSE},
|
||||
{CC_DEBUG_SHOW_KPML, "kpml", show_kpmlmap_cmd, FALSE},
|
||||
{CC_DEBUG_SHOW_CONFIG_CACHE, "config-cache", show_config_cmd, TRUE},
|
||||
{CC_DEBUG_SHOW_SUBS_STATS, "sip-subscription-statistics", show_subsmanager_stats, TRUE},
|
||||
{CC_DEBUG_SHOW_PUBLISH_STATS, "sip-publish-statistics", show_publish_stats, TRUE},
|
||||
{CC_DEBUG_SHOW_REGISTER, "register", show_register_cmd, TRUE},
|
||||
{CC_DEBUG_SHOW_DIALPLAN, "dialplan", show_dialplan_cmd, TRUE},
|
||||
{CC_DEBUG_SHOW_CPR_MEMORY, "cpr-memory", cpr_show_memory, FALSE},
|
||||
{CC_DEBUG_SHOW_MAX, "not-used", NULL, FALSE} /* MUST BE THE LAST ELEMENT */
|
||||
};
|
||||
|
||||
/** The debug Clear table. Contains all the different clear categories used in
|
||||
* the core/cpr archives. Currently we have only CPR memory. Added table for
|
||||
* expansion purposes.
|
||||
*/
|
||||
debugClearStruct_t debugClearTable[] = {
|
||||
{CC_DEBUG_CLEAR_CPR_MEMORY, "cpr-memory", cpr_clear_memory},
|
||||
{CC_DEBUG_CLEAR_MAX, "not-used", NULL} /* MUST BE THE LAST ELEMENT */
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Global data
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* External data references
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* External function prototypes
|
||||
*--------------------------------------------------------------------------
|
||||
|
@ -211,7 +105,7 @@ set_month_from_str (char *month_str)
|
|||
if (strncmp(month_str, last_month_str, 3) != 0) {
|
||||
for (i = 0; i < 12; i++) {
|
||||
if (strncmp(month_str, month_ar[i], 3) == 0) {
|
||||
strncpy(last_month_str, month_str, 3);
|
||||
sstrncpy(last_month_str, month_str, sizeof(last_month_str));
|
||||
last_month = i;
|
||||
ret_val = TRUE;
|
||||
break;
|
||||
|
@ -226,109 +120,6 @@ set_month_from_str (char *month_str)
|
|||
return (ret_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called from SIP stack when it receives
|
||||
* REGISTER response that contains a valid date header.
|
||||
* It reads the date header string and converts it into
|
||||
* local epoch; then sends it to platform to adjust the
|
||||
* date and time. If NTP server is used and in-sync then
|
||||
* the time derived from CCM is not used.
|
||||
* Date header format: "Wed, 22 Jun 2005 18:26:53 GMT"
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void
|
||||
SipNtpUpdateClockFromCCM (void)
|
||||
{
|
||||
const char *fname = "SipNtpUpdateClockFromCCM";
|
||||
struct tm tm_s, *tm_tmp_ptr;
|
||||
time_t epoch = 0;
|
||||
time_t epoch_tmp = 0;
|
||||
time_t tz_diff_sec = 0;
|
||||
char date_hdr_str[MAX_NTP_DATE_HDR_STR_LEN];
|
||||
char *token[MAX_NTP_TOKEN_BUF_LEN];
|
||||
char *curr_token;
|
||||
int count = 0;
|
||||
#ifndef _WIN32
|
||||
char *last;
|
||||
#endif
|
||||
|
||||
if (ccsip_get_ccm_date(date_hdr_str) == TRUE) {
|
||||
|
||||
/* windows does not support strtok_r() but it is needed
|
||||
* for CNU multi thread
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
curr_token = (char *) strtok_r(date_hdr_str, " ,:\t\r\n", &last);
|
||||
#else
|
||||
curr_token = (char *) strtok(date_hdr_str, " ,:\t\r\n");
|
||||
#endif
|
||||
|
||||
while (curr_token) {
|
||||
token[count++] = curr_token;
|
||||
if (count > 8) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* windows does not support strtok_r() but it is needed
|
||||
* for CNU multi thread
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
curr_token = (char *) strtok_r(NULL, " ,:\t\r\n", &last);
|
||||
#else
|
||||
curr_token = (char *) strtok(NULL, " ,:\t\r\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
/* we must have exactly 8 tokens and last token must be "GMT" */
|
||||
if ((count == 8) && (strcmp(token[7], "GMT") == 0)) {
|
||||
if (set_month_from_str(token[2])) {
|
||||
tm_s.tm_mon = last_month;
|
||||
(void) sscanf(token[6], "%d", &tm_s.tm_sec);
|
||||
(void) sscanf(token[5], "%d", &tm_s.tm_min);
|
||||
(void) sscanf(token[4], "%d", &tm_s.tm_hour);
|
||||
(void) sscanf(token[1], "%d", &tm_s.tm_mday);
|
||||
(void) sscanf(token[3], "%d", &tm_s.tm_year);
|
||||
|
||||
// subtract 1900 from the current year
|
||||
tm_s.tm_year = tm_s.tm_year - 1900;
|
||||
|
||||
// no knowledge of DST
|
||||
tm_s.tm_isdst = -1;
|
||||
|
||||
// convert tm to epoch. note that we are still GMT
|
||||
epoch = (time_t) mktime(&tm_s);
|
||||
if (epoch == (time_t) - 1) {
|
||||
TNP_DEBUG(DEB_F_PREFIX "mktime() returned -1... Not Good\n", DEB_F_PREFIX_ARGS(PLAT_API, fname));
|
||||
} else {
|
||||
// pass current (GMT) epoch to gmtime() so it will
|
||||
// give us forward corrected (for timezone) tm data struct
|
||||
tm_tmp_ptr = gmtime(&epoch);
|
||||
tm_tmp_ptr->tm_isdst = -1;
|
||||
|
||||
// now use the forward corrected tm data struct to get
|
||||
// epoch that will have number of sec added to it equal
|
||||
// to the local timezone and GMT difference
|
||||
epoch_tmp = (time_t) mktime(tm_tmp_ptr);
|
||||
if (epoch == (time_t) - 1) {
|
||||
TNP_DEBUG(DEB_F_PREFIX "mktime() returned -1... Not Good\n",
|
||||
DEB_F_PREFIX_ARGS(PLAT_API, fname));
|
||||
} else {
|
||||
// get the GMT and local tz sec difference
|
||||
tz_diff_sec = epoch_tmp - epoch;
|
||||
// subtract the difference from the original GMT epoch
|
||||
epoch -= tz_diff_sec;
|
||||
|
||||
// call platform function to set time
|
||||
platform_set_time((long) (epoch));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -497,6 +288,8 @@ IPNameCk (char *name, char *addr_error)
|
|||
int i = 0;
|
||||
uint32_t temp, ip_addr = 0;
|
||||
char ip_addr_out[MAX_IPADDR_STR_LEN];
|
||||
unsigned long strtoul_result;
|
||||
char *strtoul_end;
|
||||
|
||||
/* Check if valid IPv6 address */
|
||||
if (cpr_inet_pton(AF_INET6, name, ip_addr_out)) {
|
||||
|
@ -515,8 +308,16 @@ IPNameCk (char *name, char *addr_error)
|
|||
return (0);
|
||||
namePtr++;
|
||||
x = 0;
|
||||
if ((temp = atoi(string)) > 255)
|
||||
return (0);
|
||||
|
||||
errno = 0;
|
||||
strtoul_result = strtoul(string, &strtoul_end, 10);
|
||||
|
||||
if (errno || string == strtoul_end || strtoul_result > 255) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
temp = (uint32_t) strtoul_result;
|
||||
|
||||
ip_addr |= temp << (24 - (i * 8));
|
||||
string[0] = 0;
|
||||
string[1] = 0;
|
||||
|
@ -528,8 +329,15 @@ IPNameCk (char *name, char *addr_error)
|
|||
}
|
||||
|
||||
if (i == 3) {
|
||||
if ((temp = atoi(string)) > 255)
|
||||
return (0);
|
||||
errno = 0;
|
||||
strtoul_result = strtoul(string, &strtoul_end, 10);
|
||||
|
||||
if (errno || string == strtoul_end || strtoul_result > 255) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
temp = (uint32_t) strtoul_result;
|
||||
|
||||
ip_addr |= temp;
|
||||
*addr_error = FALSE;
|
||||
return (ntohl(ip_addr));
|
||||
|
@ -539,181 +347,78 @@ IPNameCk (char *name, char *addr_error)
|
|||
}
|
||||
|
||||
/**
|
||||
* Set/Unset a pSIPCC Debug Category
|
||||
* @brief Given a msg buffer, returns a pointer to the buffer's header
|
||||
*
|
||||
* The pSIPCC implements this function. The platform code i.e. vendor code
|
||||
* calls this function in order to set or unset a debug category
|
||||
* The cprGetSysHeader function retrieves the system header buffer for the
|
||||
* passed in message buffer.
|
||||
*
|
||||
* @param[in] category - The Debug category
|
||||
* @param[in] flag - To enable or disable the debug
|
||||
* @param[in] buffer pointer to the buffer whose sysHdr to return
|
||||
*
|
||||
* @return Abstract pointer to the msg buffer's system header
|
||||
* or #NULL if failure
|
||||
*/
|
||||
void debugSet (cc_debug_category_e category, cc_debug_flag_e flag, ...)
|
||||
void *
|
||||
cprGetSysHeader (void *buffer)
|
||||
{
|
||||
int i = 0; //, sub_cat;
|
||||
va_list ap;
|
||||
int32_t data = -1;
|
||||
phn_syshdr_t *syshdr;
|
||||
|
||||
va_start(ap, flag);
|
||||
|
||||
while (debugBindTable[i].category != CC_DEBUG_MAX) {
|
||||
if (debugBindTable[i].category == category) {
|
||||
if (debugBindTable[i].category == CC_DEBUG_CPR_MEMORY) {
|
||||
data = va_arg(ap, int32_t);
|
||||
if (data != -1) {
|
||||
//sub_cat = atoi(data);
|
||||
switch(data) {
|
||||
case CC_DEBUG_CPR_MEM_TRACKING:
|
||||
case CC_DEBUG_CPR_MEM_POISON:
|
||||
debugCprMem(data, flag);
|
||||
break;
|
||||
default:
|
||||
debugif_printf("Error: Unknown CPR debug sub-category passed in\n");
|
||||
}
|
||||
} else {
|
||||
debugif_printf("Error: CPR debug sub-category NOT passed in\n");
|
||||
}
|
||||
} else {
|
||||
*(debugBindTable[i].key) = flag;
|
||||
}
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
/*
|
||||
* Stinks that an external structure is necessary,
|
||||
* but this is a side-effect of porting from IRX.
|
||||
*/
|
||||
syshdr = cpr_calloc(1, sizeof(phn_syshdr_t));
|
||||
if (syshdr) {
|
||||
syshdr->Data = buffer;
|
||||
}
|
||||
debugif_printf("Error: Unknown debug category passed in\n");
|
||||
va_end(ap);
|
||||
return (void *)syshdr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when the application is done with this system header
|
||||
*
|
||||
* The cprReleaseSysHeader function returns the system header buffer to the
|
||||
* system.
|
||||
* @param[in] syshdr pointer to the sysHdr to be released
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void
|
||||
cprReleaseSysHeader (void *syshdr)
|
||||
{
|
||||
if (syshdr == NULL) {
|
||||
CPR_ERROR("cprReleaseSysHeader: Sys header pointer is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cpr_free(syshdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief An internal function to update the system header
|
||||
*
|
||||
* A CPR-only function. Given a sysHeader and data, this function fills
|
||||
* in the data. The purpose for this function is to help prevent CPR
|
||||
* code from having to know about the phn_syshdr_t layout.
|
||||
*
|
||||
* @param[in] buffer pointer to a syshdr from a successful call to
|
||||
* cprGetSysHeader
|
||||
* @param[in] cmd command to place in the syshdr buffer
|
||||
* @param[in] len length to place in the syshdr buffer
|
||||
* @param[in] timerMsg msg being sent to the calling thread
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* @pre (buffer != NULL)
|
||||
*/
|
||||
void
|
||||
fillInSysHeader (void *buffer, uint16_t cmd, uint16_t len, void *timerMsg)
|
||||
{
|
||||
phn_syshdr_t *syshdr;
|
||||
|
||||
syshdr = (phn_syshdr_t *) buffer;
|
||||
syshdr->Cmd = cmd;
|
||||
syshdr->Len = len;
|
||||
syshdr->Usr.UsrPtr = timerMsg;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a pSIPCC Show Category
|
||||
*
|
||||
* The pSIPCC implements this function. The platform code i.e. vendor code
|
||||
* calls this function in order to use a show command
|
||||
*
|
||||
* @param[in] category - The Show category
|
||||
*
|
||||
* @return 0 if succesfull
|
||||
*/
|
||||
int debugShow(cc_debug_show_options_e category, ...)
|
||||
{
|
||||
const char *showArgc[NUM_OF_SHOW_ARGUMENTS];
|
||||
int i = 0, returnCode = 0;
|
||||
va_list ap;
|
||||
int32_t data = -1;
|
||||
|
||||
va_start(ap, category);
|
||||
|
||||
while (debugShowTable[i].category != CC_DEBUG_SHOW_MAX) {
|
||||
if (debugShowTable[i].category == category) {
|
||||
if (category == CC_DEBUG_SHOW_FSMDEF) {
|
||||
/* Special category for FSMDEF - Show "all" fsm's for vendor */
|
||||
showArgc[0] = "all";
|
||||
returnCode = debugShowTable[i].callbackFunc(NUM_OF_SHOW_ARGUMENTS-1, showArgc);
|
||||
} else if (category == CC_DEBUG_SHOW_CPR_MEMORY) {
|
||||
data = va_arg(ap, int32_t);
|
||||
if (data != -1) {
|
||||
switch (data) {
|
||||
case CC_DEBUG_SHOW_CPR_CONFIG:
|
||||
case CC_DEBUG_SHOW_CPR_HEAP_GUARD:
|
||||
case CC_DEBUG_SHOW_CPR_STATISTICS:
|
||||
case CC_DEBUG_SHOW_CPR_TRACKING:
|
||||
debugShowCprMem((cc_debug_show_cpr_options_e) data);
|
||||
break;
|
||||
|
||||
default:
|
||||
debugif_printf("Error: Unknown CPR show sub-category passed in\n");
|
||||
}
|
||||
} else {
|
||||
debugif_printf("Error: CPR show sub-category NOT passed in\n");
|
||||
}
|
||||
} else {
|
||||
showArgc[0] = "show";
|
||||
showArgc[1] = debugShowTable[i].showName;
|
||||
returnCode = debugShowTable[i].callbackFunc(NUM_OF_SHOW_ARGUMENTS, showArgc);
|
||||
}
|
||||
debugif_printf("\n<EOT>\n");
|
||||
va_end(ap);
|
||||
return returnCode;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
debugif_printf("Error: Unknown show category passed in\n");
|
||||
|
||||
va_end(ap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the show tech command
|
||||
*
|
||||
* The pSIPCC implements this function. The platform code i.e. vendor code
|
||||
* calls this function in order to do the equivalent of the "show tech-sip"
|
||||
*
|
||||
*/
|
||||
void debugShowTech()
|
||||
{
|
||||
const char *showArgc[NUM_OF_SHOW_ARGUMENTS];
|
||||
int i = 0;
|
||||
|
||||
showArgc[0] = "show";
|
||||
|
||||
while (debugShowTable[i].category != CC_DEBUG_SHOW_MAX) {
|
||||
if (debugShowTable[i].showTech == TRUE) {
|
||||
showArgc[0] = debugShowTable[i].showName;
|
||||
debugShowTable[i].callbackFunc(NUM_OF_SHOW_ARGUMENTS, showArgc);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
debugif_printf("\n<EOT>\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a pSIPCC Clear Category
|
||||
*
|
||||
* The pSIPCC implements this function. Vendors need to
|
||||
* call this function in order to clear certain information stored in pSIPCC.
|
||||
*
|
||||
* @param[in] category - The Clear category
|
||||
* @param[in] ... variable arg list
|
||||
*
|
||||
* @note - The variable parameter list actually consists of only one additional
|
||||
* formal argument. This is the second parameter specifying any sub category for
|
||||
* clearing information.
|
||||
* Currently only CC_DEBUG_CLEAR_CPR_MEMORY has sub-categories. The sub-categories are
|
||||
* defined in cc_debug_clear_cpr_options_e.
|
||||
* @return 0 if succesfull
|
||||
*/
|
||||
int debugClear(cc_debug_clear_options_e category, ...)
|
||||
{
|
||||
int i = 0, returnCode = 0 ;
|
||||
va_list ap;
|
||||
int32_t data = -1;
|
||||
|
||||
va_start(ap, category);
|
||||
|
||||
/* Only the clear "cpr-memory" is present right now */
|
||||
if (debugClearTable[i].category == category) {
|
||||
data = va_arg(ap, int32_t);
|
||||
if (data != -1) {
|
||||
switch (data) {
|
||||
case CC_DEBUG_CLEAR_CPR_TRACKING:
|
||||
case CC_DEBUG_CLEAR_CPR_STATISTICS:
|
||||
debugClearCprMem((cc_debug_clear_cpr_options_e) data);
|
||||
break;
|
||||
default:
|
||||
debugif_printf("Error: Unknown CPR clear sub-category passed in\n");
|
||||
}
|
||||
debugif_printf("\n<EOT>\n");
|
||||
} else {
|
||||
debugif_printf("Error: CPR clear sub-category NOT passed in\n");
|
||||
}
|
||||
} else {
|
||||
debugif_printf("Error: Unknown show category passed in\n");
|
||||
returnCode = -1;
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
return returnCode;
|
||||
}
|
||||
|
|
|
@ -226,9 +226,19 @@ typedef struct
|
|||
char external_number_mask[MAX_EXTERNAL_NUMBER_MASK_SIZE];
|
||||
char media_ip_addr[MAX_IPADDR_STR_LEN];
|
||||
int p2psip;
|
||||
int roapproxy;
|
||||
int roapclient;
|
||||
int sdpmode;
|
||||
char version[4];
|
||||
int rtcpmux;
|
||||
int rtpsavpf;
|
||||
int maxavbitrate;
|
||||
int maxcodedaudiobw;
|
||||
int usedtx;
|
||||
int stereo;
|
||||
int useinbandfec;
|
||||
int cbr;
|
||||
int maxptime;
|
||||
int sctp_port;
|
||||
int num_data_streams;
|
||||
} prot_cfg_t;
|
||||
|
||||
static prot_cfg_t prot_cfg_block;
|
||||
|
@ -261,6 +271,7 @@ static const key_table_entry_t codec_table[] = {
|
|||
{"g722", RTP_G722},
|
||||
{"iLBC", RTP_ILBC},
|
||||
{"iSAC", RTP_ISAC},
|
||||
{"opus", RTP_OPUS},
|
||||
{"none", RTP_NONE},
|
||||
{0, RTP_NONE}
|
||||
};
|
||||
|
@ -436,9 +447,19 @@ var_t prot_cfg_table[CFGID_PROTOCOL_MAX+1] = {
|
|||
{"externalNumberMask", CFGVAR(external_number_mask), PA_STR, PR_STR, 0},
|
||||
{"mediaIpAddr", CFGVAR(media_ip_addr), PA_STR, PR_STR, 0},
|
||||
{"p2psip", CFGVAR(p2psip), PA_INT, PR_INT, 0},
|
||||
{"roapproxy", CFGVAR(roapproxy), PA_INT, PR_INT, 0},
|
||||
{"roapclient", CFGVAR(roapclient), PA_INT, PR_INT, 0},
|
||||
{"version", CFGVAR(version), PA_STR, PR_STR, 0},
|
||||
{"sdpmode", CFGVAR(sdpmode), PA_INT, PR_INT, 0},
|
||||
{"rtcpmux", CFGVAR(rtcpmux), PA_INT, PR_INT, 0},
|
||||
{"rtpsavpf", CFGVAR(rtpsavpf), PA_INT, PR_INT, 0},
|
||||
{"maxavbitrate", CFGVAR(maxavbitrate), PA_INT, PR_INT, 0},
|
||||
{"maxcodedaudiobw", CFGVAR(maxcodedaudiobw), PA_INT, PR_INT, 0},
|
||||
{"usedtx", CFGVAR(usedtx), PA_INT, PR_INT, 0},
|
||||
{"stereo", CFGVAR(stereo), PA_INT, PR_INT, 0},
|
||||
{"useinbandfec", CFGVAR(useinbandfec), PA_INT, PR_INT, 0},
|
||||
{"cbr", CFGVAR(cbr), PA_INT, PR_INT, 0},
|
||||
{"maxptime", CFGVAR(maxptime), PA_INT, PR_INT, 0},
|
||||
{"sctp_port", CFGVAR(sctp_port), PA_INT, PR_INT, 0},
|
||||
{"num_data_streams", CFGVAR(num_data_streams), PA_INT, PR_INT, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
|
|
@ -544,7 +544,7 @@ sip_config_local_supported_codecs_get (rtp_ptype aSupportedCodecs[],
|
|||
codec_mask = vcmGetAudioCodecList(VCM_DSP_FULLDUPLEX);
|
||||
|
||||
if (!codec_mask) {
|
||||
codec_mask = VCM_CODEC_RESOURCE_G711;
|
||||
codec_mask = VCM_CODEC_RESOURCE_G711 | VCM_CODEC_RESOURCE_OPUS;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -629,6 +629,10 @@ sip_config_video_supported_codecs_get (rtp_ptype aSupportedCodecs[],
|
|||
//codec_mask = vcmGetVideoCodecList(DSP_ENCODEONLY);
|
||||
codec_mask = vcmGetVideoCodecList(VCM_DSP_IGNORE);
|
||||
}
|
||||
if ( codec_mask & VCM_CODEC_RESOURCE_VP8) {
|
||||
aSupportedCodecs[count] = RTP_VP8;
|
||||
count++;
|
||||
}
|
||||
if ( codec_mask & VCM_CODEC_RESOURCE_H264) {
|
||||
/*
|
||||
* include payload type for packetization mode 1 only if ucm sis version
|
||||
|
@ -676,6 +680,11 @@ config_set_current_codec_table (int codec_mask, rtp_ptype *codecs)
|
|||
{
|
||||
int idx = 0;
|
||||
|
||||
if (codec_mask & VCM_CODEC_RESOURCE_OPUS) {
|
||||
codecs[idx] = RTP_OPUS;
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (codec_mask & VCM_CODEC_RESOURCE_G711) {
|
||||
codecs[idx] = RTP_PCMU;
|
||||
idx++;
|
||||
|
|
|
@ -268,9 +268,19 @@
|
|||
#define CFGID_LINE_FWD_DIALED_NUMBER_DIPLAY CFGID_LINE_FWD_DIALED_NUMBER_DIPLAY_BOOL
|
||||
#define CFGID_LINE_FEATURE_OPTION_MASK CFGID_LINE_FEATURE_OPTION_MASK_INT
|
||||
#define CFGID_P2PSIP CFGID_P2PSIP_BOOL
|
||||
#define CFGID_ROAPPROXY CFGID_ROAPPROXY_BOOL
|
||||
#define CFGID_ROAPCLIENT CFGID_ROAPCLIENT_BOOL
|
||||
#define CFGID_VERSION CFGID_VERSION_STRING
|
||||
#define CFGID_SDPMODE CFGID_SDPMODE_BOOL
|
||||
#define CFGID_RTCPMUX CFGID_RTCPMUX_BOOL
|
||||
#define CFGID_RTPSAVPF CFGID_RTPSAVPF_BOOL
|
||||
#define CFGID_MAXAVBITRATE CFGID_MAXAVBITRATE_BOOL
|
||||
#define CFGID_MAXCODEDAUDIOBW CFGID_MAXCODEDAUDIOBW_BOOL
|
||||
#define CFGID_USEDTX CFGID_USEDTX_BOOL
|
||||
#define CFGID_STEREO CFGID_STEREO_BOOL
|
||||
#define CFGID_USEINBANDFEC CFGID_USEINBANDFEC_BOOL
|
||||
#define CFGID_CBR CFGID_CBR_BOOL
|
||||
#define CFGID_MAXPTIME CFGID_MAXPTIME_BOOL
|
||||
#define CFGID_SCTP_PORT CFGID_SCTP_PORT_INT
|
||||
#define CFGID_NUM_DATA_STREAMS CFGID_NUM_DATA_STREAMS_INT
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
|
|
|
@ -67,11 +67,11 @@ sipSocketSend (cpr_socket_t soc,
|
|||
int32_t flags,
|
||||
boolean secure)
|
||||
{
|
||||
if (secure) {
|
||||
return platSecSocSend (soc, buf, len);
|
||||
} else {
|
||||
// if (secure) {
|
||||
// return platSecSocSend (soc, buf, len);
|
||||
// } else {
|
||||
return cprSend(soc, buf, len, flags);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,11 +97,11 @@ sipSocketRecv (cpr_socket_t soc,
|
|||
int32_t flags,
|
||||
boolean secure)
|
||||
{
|
||||
if (secure) {
|
||||
return platSecSocRecv (soc, buf, len);
|
||||
} else {
|
||||
// if (secure) {
|
||||
// return platSecSocRecv (soc, buf, len);
|
||||
// } else {
|
||||
return cprRecv(soc, buf, len, flags);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,10 +126,10 @@ cpr_status_e
|
|||
sipSocketClose (cpr_socket_t soc,
|
||||
boolean secure)
|
||||
{
|
||||
if (secure) {
|
||||
return platSecSocClose (soc);
|
||||
} else {
|
||||
// if (secure) {
|
||||
// return platSecSocClose (soc);
|
||||
// } else {
|
||||
return cprCloseSocket(soc);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
|
|
|
@ -369,7 +369,7 @@ void sub_hndlr_NotifyBLFStatus(int requestId, cc_blf_state_t status, int appId)
|
|||
if (displayBLFState == FALSE) {
|
||||
return; // ignore the notify
|
||||
}
|
||||
if ((lineFeature == cfgLineFeatureSpeedDialBLF)) {
|
||||
if (lineFeature == cfgLineFeatureSpeedDialBLF) {
|
||||
ccsnap_gen_blfFeatureEvent(status, appId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
* Local definitions
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
#define CCAPP_F_PREFIX "CCAPP : %s : " // requires 1 arg: fname
|
||||
#define CCAPP_F_PREFIX "CCAPP : %s : " // requires 1 arg: __FUNCTION__
|
||||
// Why don't we modify strlib_malloc to handle NULL?
|
||||
#define STRLIB_CREATE(str) (str)?strlib_malloc((str), strlen((str))):strlib_empty()
|
||||
// Define default display timeout and priority
|
||||
|
@ -129,10 +129,9 @@ extern session_id_t createSessionId(line_t line, callid_t call);
|
|||
void
|
||||
ui_call_state (call_events event, line_t nLine, callid_t nCallID, cc_causes_t cause)
|
||||
{
|
||||
static const char fname[] = "ui_call_state";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"event=%d \n", DEB_L_C_F_PREFIX_ARGS(UI_API, nLine, nCallID, fname),
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"event=%d \n", DEB_L_C_F_PREFIX_ARGS(UI_API, nLine, nCallID, __FUNCTION__),
|
||||
event);
|
||||
|
||||
if (nCallID == CC_NO_CALL_ID) {
|
||||
|
@ -147,7 +146,7 @@ ui_call_state (call_events event, line_t nLine, callid_t nCallID, cc_causes_t ca
|
|||
msg.update.ccSessionUpd.data.state_data.cause = cause;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATE(%d) msg \n", fname, event);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATE(%d) msg \n", __FUNCTION__, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,11 +165,10 @@ void
|
|||
ui_new_call (call_events event, line_t nLine, callid_t nCallID,
|
||||
int call_attr, uint16_t call_instance_id, boolean dialed_digits)
|
||||
{
|
||||
static const char fname[] = "ui_new_call";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"state=%d attr=%d call_instance=%d, dialed_digits=%s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, nLine, nCallID, fname), event, call_attr, call_instance_id, (dialed_digits)? "true" : "false");
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, nLine, nCallID, __FUNCTION__), event, call_attr, call_instance_id, (dialed_digits)? "true" : "false");
|
||||
|
||||
if (nCallID == CC_NO_CALL_ID) {
|
||||
/* no operation when no call ID */
|
||||
|
@ -186,7 +184,7 @@ ui_new_call (call_events event, line_t nLine, callid_t nCallID,
|
|||
msg.update.ccSessionUpd.data.state_data.line_id = nLine;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATE(%d) msg \n", fname, event);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATE(%d) msg \n", __FUNCTION__, event);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -208,10 +206,9 @@ ui_new_call (call_events event, line_t nLine, callid_t nCallID,
|
|||
void
|
||||
ui_set_call_attr (line_t line_id, callid_t call_id, call_attr_t attr)
|
||||
{
|
||||
static const char fname[] = "ui_set_call_attr";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"attr=%d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, fname), attr);
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"attr=%d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, __FUNCTION__), attr);
|
||||
|
||||
if (call_id == CC_NO_CALL_ID) {
|
||||
/* no operation when no call ID */
|
||||
|
@ -223,7 +220,7 @@ ui_set_call_attr (line_t line_id, callid_t call_id, call_attr_t attr)
|
|||
msg.update.ccSessionUpd.data.state_data.attr = attr;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_ATTR(%d) msg \n", fname, attr);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_ATTR(%d) msg \n", __FUNCTION__, attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,10 +236,9 @@ ui_set_call_attr (line_t line_id, callid_t call_id, call_attr_t attr)
|
|||
void
|
||||
ui_update_callref (line_t line, callid_t call_id, unsigned int callref)
|
||||
{
|
||||
static const char fname[] = "ui_update_callref";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"callref = %d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname), callref);
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"callref = %d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__), callref);
|
||||
|
||||
if ( callref == 0 ) return;
|
||||
|
||||
|
@ -256,7 +252,7 @@ ui_update_callref (line_t line, callid_t call_id, unsigned int callref)
|
|||
msg.update.ccSessionUpd.data.callref = callref;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_REF() msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_REF() msg \n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -275,10 +271,9 @@ ui_update_callref (line_t line, callid_t call_id, unsigned int callref)
|
|||
void
|
||||
ui_update_gcid (line_t line, callid_t call_id, char *gcid)
|
||||
{
|
||||
static const char fname[] = "ui_update_gcid";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"gcid = %s\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname), gcid);
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"gcid = %s\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__), gcid);
|
||||
|
||||
if ( *gcid == '\0' ) return;
|
||||
|
||||
|
@ -292,7 +287,7 @@ ui_update_gcid (line_t line, callid_t call_id, char *gcid)
|
|||
sstrncpy(msg.update.ccSessionUpd.data.gcid, gcid, CC_MAX_GCID);
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_GCID() msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_GCID() msg \n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -309,10 +304,9 @@ ui_update_gcid (line_t line, callid_t call_id, char *gcid)
|
|||
void
|
||||
ui_update_video_avail (line_t line, callid_t call_id, int avail)
|
||||
{
|
||||
static const char fname[] = "ui_update_video_avail";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname));
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__));
|
||||
|
||||
if (call_id == CC_NO_CALL_ID) {
|
||||
/* no operation when no call ID */
|
||||
|
@ -324,14 +318,13 @@ ui_update_video_avail (line_t line, callid_t call_id, int avail)
|
|||
msg.update.ccSessionUpd.data.action = avail;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send VIDEO_AVAIL() msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send VIDEO_AVAIL() msg \n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ui_update_media_interface_change(line_t line, callid_t call_id, group_call_event_t event) {
|
||||
static const char fname[] = "ui_update_media_interface_changes";
|
||||
session_update_t msg;
|
||||
|
||||
if (event != MEDIA_INTERFACE_UPDATE_BEGIN &&
|
||||
|
@ -346,7 +339,7 @@ void ui_update_media_interface_change(line_t line, callid_t call_id, group_call_
|
|||
g_dock_undock_event = MEDIA_INTERFACE_UPDATE_NOT_REQUIRED;
|
||||
}
|
||||
|
||||
DEF_DEBUG(DEB_L_C_F_PREFIX "event=%s", DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname),
|
||||
DEF_DEBUG(DEB_L_C_F_PREFIX "event=%s", DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__),
|
||||
event == MEDIA_INTERFACE_UPDATE_BEGIN ? "MEDIA_INTERFACE_UPDATE_BEGIN" :
|
||||
event == MEDIA_INTERFACE_UPDATE_SUCCESSFUL ? "MEDIA_INTERFACE_UPDATE_SUCCESSFUL" :
|
||||
event == MEDIA_INTERFACE_UPDATE_FAIL ? "MEDIA_INTERFACE_UPDATE_FAIL" : "unknown");
|
||||
|
@ -358,17 +351,16 @@ void ui_update_media_interface_change(line_t line, callid_t call_id, group_call_
|
|||
msg.eventID = event;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send media update () msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send media update () msg \n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ui_call_stop_ringer (line_t line, callid_t call_id)
|
||||
{
|
||||
static const char fname[] = "ui_call_stop_ringer";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname));
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__));
|
||||
|
||||
if (call_id == CC_NO_CALL_ID) {
|
||||
/* no operation when no call ID */
|
||||
|
@ -381,7 +373,7 @@ ui_call_stop_ringer (line_t line, callid_t call_id)
|
|||
msg.update.ccSessionUpd.data.ringer.mode = VCM_RING_OFF;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send RINGER_STATE() msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send RINGER_STATE() msg \n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -390,10 +382,9 @@ ui_call_stop_ringer (line_t line, callid_t call_id)
|
|||
void
|
||||
ui_call_start_ringer (vcm_ring_mode_t ringMode, short once, line_t line, callid_t call_id)
|
||||
{
|
||||
static const char fname[] = "ui_call_start_ringer";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname));
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__));
|
||||
|
||||
if (call_id == CC_NO_CALL_ID) {
|
||||
/* no operation when no call ID */
|
||||
|
@ -407,7 +398,7 @@ ui_call_start_ringer (vcm_ring_mode_t ringMode, short once, line_t line, callid_
|
|||
msg.update.ccSessionUpd.data.ringer.once = (cc_boolean) once;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send RINGER_STATE() msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send RINGER_STATE() msg \n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -424,10 +415,9 @@ ui_call_start_ringer (vcm_ring_mode_t ringMode, short once, line_t line, callid_
|
|||
void
|
||||
ui_update_video_offered (line_t line, callid_t call_id, int avail)
|
||||
{
|
||||
static const char fname[] = "ui_update_video_offered";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname));
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__));
|
||||
|
||||
if (call_id == CC_NO_CALL_ID) {
|
||||
/* no operation when no call ID */
|
||||
|
@ -439,7 +429,7 @@ ui_update_video_offered (line_t line, callid_t call_id, int avail)
|
|||
msg.update.ccSessionUpd.data.action = avail;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send VIDEO_OFFERED() msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send VIDEO_OFFERED() msg \n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -483,7 +473,6 @@ ui_call_info (string_t pCallingPartyNameStr,
|
|||
cc_security_e call_security,
|
||||
cc_policy_e call_policy)
|
||||
{
|
||||
static const char fname[] = "ui_call_info";
|
||||
session_update_t msg;
|
||||
const char *uiCalledName;
|
||||
const char *uiCalledNumber;
|
||||
|
@ -495,10 +484,10 @@ ui_call_info (string_t pCallingPartyNameStr,
|
|||
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"call instance=%d callednum=%s calledname=%s clngnum=%s clngname = %s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname), call_instance_id, pCalledPartyNumberStr,
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__), call_instance_id, pCalledPartyNumberStr,
|
||||
pCalledPartyNameStr, pCallingPartyNumberStr, pCallingPartyNameStr);
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"calltype=%d displayClng=%d displayCld=%d\n", DEB_F_PREFIX_ARGS(UI_API, fname), call_type,
|
||||
TNP_DEBUG(DEB_F_PREFIX"calltype=%d displayClng=%d displayCld=%d\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__), call_type,
|
||||
displayCallingNumber, displayCalledNumber);
|
||||
|
||||
|
||||
|
@ -558,7 +547,7 @@ ui_call_info (string_t pCallingPartyNameStr,
|
|||
msg.update.ccSessionUpd.data.call_info.policy = call_policy;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_INFO() msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_INFO() msg \n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -576,11 +565,10 @@ ui_call_info (string_t pCallingPartyNameStr,
|
|||
void
|
||||
ui_cc_capability (line_t line, callid_t call_id, string_t recv_info_list)
|
||||
{
|
||||
static const char fname[] = "ui_cc_capability";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"recv_info_list:%s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname),
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__),
|
||||
recv_info_list);
|
||||
|
||||
msg.sessionID = createSessionId(line, call_id);
|
||||
|
@ -588,7 +576,7 @@ ui_cc_capability (line_t line, callid_t call_id, string_t recv_info_list)
|
|||
msg.update.ccSessionUpd.data.recv_info_list = strlib_copy(recv_info_list);
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_RECV_INFO_LIST msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_RECV_INFO_LIST msg \n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -607,11 +595,10 @@ void
|
|||
ui_info_received (line_t line, callid_t call_id, const char *info_package,
|
||||
const char *content_type, const char *message_body)
|
||||
{
|
||||
static const char fname[] = "ui_info_received";
|
||||
session_rcvd_info_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"info_package:%s content_type:%s message_body:%s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname),
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__),
|
||||
info_package, content_type, message_body);
|
||||
|
||||
msg.sessionID = createSessionId(line, call_id);
|
||||
|
@ -621,7 +608,7 @@ ui_info_received (line_t line, callid_t call_id, const char *info_package,
|
|||
msg.info.generic_raw.message_body = message_body?strlib_malloc(message_body, strlen(message_body)):strlib_empty();
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_RCVD_INFO, &msg, sizeof(session_rcvd_info_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_INFO_RECEIVED msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_INFO_RECEIVED msg \n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -639,10 +626,9 @@ ui_info_received (line_t line, callid_t call_id, const char *info_package,
|
|||
static void
|
||||
ui_set_call_status_display (string_t status, line_t line, callid_t callID, int timeout, char priority)
|
||||
{
|
||||
static const char fname[] = "ui_set_call_status";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"the stat string =%s, timeout= %d, priority=%d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, callID, fname),
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"the stat string =%s, timeout= %d, priority=%d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, callID, __FUNCTION__),
|
||||
status,
|
||||
timeout,
|
||||
priority);
|
||||
|
@ -663,7 +649,7 @@ ui_set_call_status_display (string_t status, line_t line, callid_t callID, int t
|
|||
}
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATUS(%s) msg \n", fname, status);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATUS(%s) msg \n", __FUNCTION__, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -681,9 +667,8 @@ ui_set_call_status_display (string_t status, line_t line, callid_t callID, int t
|
|||
void
|
||||
ui_set_call_status (string_t status, line_t line, callid_t callID)
|
||||
{
|
||||
static const char fname[] = "ui_set_call_status";
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"the stat string =%s\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, callID, fname),
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"the stat string =%s\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, callID, __FUNCTION__),
|
||||
status);
|
||||
|
||||
if (callID == CC_NO_CALL_ID) {
|
||||
|
@ -711,10 +696,9 @@ void
|
|||
ui_set_notification (line_t line, callid_t call_id, char *promptString, int timeout,
|
||||
boolean notifyProgress, char priority)
|
||||
{
|
||||
static const char fname[] = "ui_set_notification";
|
||||
feature_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"line=%d callid=%d str=%s tout=%d notifyProgress=%d pri=%d\n", DEB_F_PREFIX_ARGS(UI_API, fname),
|
||||
TNP_DEBUG(DEB_F_PREFIX"line=%d callid=%d str=%s tout=%d notifyProgress=%d pri=%d\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__),
|
||||
line, call_id, promptString, timeout, notifyProgress, priority);
|
||||
|
||||
if (line > 0 && call_id > 0) {
|
||||
|
@ -733,7 +717,7 @@ ui_set_notification (line_t line, callid_t call_id, char *promptString, int time
|
|||
}
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_FEATURE_UPDATE, &msg, sizeof(feature_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_NOTIFICATION(%s) msg \n", fname, promptString);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_NOTIFICATION(%s) msg \n", __FUNCTION__, promptString);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -748,9 +732,7 @@ ui_set_notification (line_t line, callid_t call_id, char *promptString, int time
|
|||
void
|
||||
ui_clear_notification ()
|
||||
{
|
||||
static const char fname[] = "ui_clear_notification";
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"called..\n", DEB_F_PREFIX_ARGS(UI_API, fname));
|
||||
TNP_DEBUG(DEB_F_PREFIX"called..\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__));
|
||||
|
||||
// A promptString of NULL shall act as a clear
|
||||
ui_set_notification(CC_NO_LINE, CC_NO_CALL_ID, NULL, 0, FALSE, 1);
|
||||
|
@ -767,18 +749,17 @@ ui_clear_notification ()
|
|||
void
|
||||
ui_change_mwi_lamp (int status)
|
||||
{
|
||||
static const char fname[] = "ui_change_mwi_lamp";
|
||||
feature_update_t msg;
|
||||
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"status=%d \n", DEB_F_PREFIX_ARGS(UI_API, fname), status);
|
||||
TNP_DEBUG(DEB_F_PREFIX"status=%d \n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__), status);
|
||||
|
||||
msg.sessionType = SESSIONTYPE_CALLCONTROL;
|
||||
msg.featureID = DEVICE_FEATURE_MWILAMP;
|
||||
msg.update.ccFeatUpd.data.state_data.state = status;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_FEATURE_UPDATE, &msg, sizeof(feature_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_FEATURE_MWILAMP(%d) msg \n", fname, status);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_FEATURE_MWILAMP(%d) msg \n", __FUNCTION__, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -794,10 +775,9 @@ ui_change_mwi_lamp (int status)
|
|||
void
|
||||
ui_set_mwi (line_t line, boolean status, int type, int newCount, int oldCount, int hpNewCount, int hpOldCount)
|
||||
{
|
||||
static const char fname[] = "ui_set_mwi";
|
||||
feature_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"line=%d count=%d \n", DEB_F_PREFIX_ARGS(UI_API, fname), line, status);
|
||||
TNP_DEBUG(DEB_F_PREFIX"line=%d count=%d \n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__), line, status);
|
||||
|
||||
msg.sessionType = SESSIONTYPE_CALLCONTROL;
|
||||
msg.featureID = DEVICE_FEATURE_MWI;
|
||||
|
@ -810,7 +790,7 @@ ui_set_mwi (line_t line, boolean status, int type, int newCount, int oldCount, i
|
|||
msg.update.ccFeatUpd.data.mwi_status.hpOldCount = hpOldCount;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_FEATURE_UPDATE, &msg, sizeof(feature_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_FEATURE_MWI(%d,%d) msg \n", fname, line, status);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_FEATURE_MWI(%d,%d) msg \n", __FUNCTION__, line, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -828,11 +808,10 @@ ui_set_mwi (line_t line, boolean status, int type, int newCount, int oldCount, i
|
|||
*/
|
||||
void ui_mnc_reached (line_t line, boolean mnc_reached)
|
||||
{
|
||||
static const char fname[] = "ui_mnc_reached";
|
||||
feature_update_t msg;
|
||||
|
||||
DEF_DEBUG(DEB_F_PREFIX"line %d: Max number of calls reached =%d \n",
|
||||
DEB_F_PREFIX_ARGS(UI_API, fname),
|
||||
DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__),
|
||||
line, mnc_reached);
|
||||
|
||||
msg.sessionType = SESSIONTYPE_CALLCONTROL;
|
||||
|
@ -841,7 +820,7 @@ void ui_mnc_reached (line_t line, boolean mnc_reached)
|
|||
msg.update.ccFeatUpd.data.line_info.info = mnc_reached;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_FEATURE_UPDATE, &msg, sizeof(feature_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_FEATURE_MNC_REACHED(%d,%d) msg \n", fname,
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_FEATURE_MNC_REACHED(%d,%d) msg \n", __FUNCTION__,
|
||||
line, mnc_reached);
|
||||
}
|
||||
|
||||
|
@ -858,10 +837,9 @@ void ui_mnc_reached (line_t line, boolean mnc_reached)
|
|||
boolean
|
||||
ui_line_has_mwi_active (line_t line)
|
||||
{
|
||||
static const char fname[] = "ui_line_has_mwi_active";
|
||||
session_mgmt_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"line=%d\n", DEB_F_PREFIX_ARGS(UI_API, fname), line);
|
||||
TNP_DEBUG(DEB_F_PREFIX"line=%d\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__), line);
|
||||
|
||||
msg.func_id = SESSION_MGMT_LINE_HAS_MWI_ACTIVE;
|
||||
msg.data.line_mwi_active.line = line;
|
||||
|
@ -884,10 +862,9 @@ ui_line_has_mwi_active (line_t line)
|
|||
void
|
||||
ui_update_label_n_speeddial (line_t line, line_t button_no, string_t speed_dial, string_t label)
|
||||
{
|
||||
static const char fname[] = "ui_update_label_n_speeddial";
|
||||
feature_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"line=%d speeddial=%s displayname=%s\n", DEB_F_PREFIX_ARGS(UI_API, fname), line,
|
||||
TNP_DEBUG(DEB_F_PREFIX"line=%d speeddial=%s displayname=%s\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__), line,
|
||||
speed_dial, label);
|
||||
|
||||
msg.sessionType = SESSIONTYPE_CALLCONTROL;
|
||||
|
@ -898,7 +875,7 @@ ui_update_label_n_speeddial (line_t line, line_t button_no, string_t speed_dial,
|
|||
msg.update.ccFeatUpd.data.cfg_lbl_n_spd.label = strlib_malloc(label, sizeof(label));
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_FEATURE_UPDATE, &msg, sizeof(feature_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_LABEL_N_SPEED(%d) msg \n", fname, button_no);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_LABEL_N_SPEED(%d) msg \n", __FUNCTION__, button_no);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -913,11 +890,10 @@ ui_update_label_n_speeddial (line_t line, line_t button_no, string_t speed_dial,
|
|||
void
|
||||
ui_set_sip_registration_state (line_t line, boolean registered)
|
||||
{
|
||||
static const char fname[] = "ui_set_sip_registration_state";
|
||||
feature_update_t msg;
|
||||
int value;
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"%s %d: %s\n", DEB_F_PREFIX_ARGS(UI_API, fname),
|
||||
TNP_DEBUG(DEB_F_PREFIX"%s %d: %s\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__),
|
||||
(line==CC_ALL_LINES) ? "ALL LINES":"LINE" ,line,
|
||||
(registered)? "REGISTERED":"UN-REGISTERED");
|
||||
|
||||
|
@ -931,7 +907,7 @@ ui_set_sip_registration_state (line_t line, boolean registered)
|
|||
}
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_FEATURE_UPDATE, &msg, sizeof(feature_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATE(%d, %d) msg \n", fname, line, registered);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATE(%d, %d) msg \n", __FUNCTION__, line, registered);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -945,10 +921,8 @@ ui_set_sip_registration_state (line_t line, boolean registered)
|
|||
void
|
||||
ui_update_registration_state_all_lines (boolean registered)
|
||||
{
|
||||
static const char fname[] = "ui_update_registration_state_all_lines";
|
||||
|
||||
DEF_DEBUG(DEB_F_PREFIX"***********ALL LINES %s****************\n",
|
||||
DEB_F_PREFIX_ARGS(UI_API, fname),
|
||||
DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__),
|
||||
(registered)? "REGISTERED":"UN-REGISTERED");
|
||||
|
||||
ui_set_sip_registration_state(CC_ALL_LINES, registered);
|
||||
|
@ -966,11 +940,10 @@ ui_update_registration_state_all_lines (boolean registered)
|
|||
void
|
||||
ui_reg_all_failed (void)
|
||||
{
|
||||
static const char fname[] = "ui_reg_all_failed";
|
||||
feature_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"***********Registration to all CUCMs failed.***********\n",
|
||||
DEB_F_PREFIX_ARGS(UI_API, fname));
|
||||
DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__));
|
||||
|
||||
msg.sessionType = SESSIONTYPE_CALLCONTROL;
|
||||
msg.featureID = CCAPP_REG_ALL_FAIL;
|
||||
|
@ -978,7 +951,7 @@ ui_reg_all_failed (void)
|
|||
msg.update.ccFeatUpd.data.line_info.info = FALSE;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_REG_ALL_FAIL, &msg, sizeof(feature_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATE() msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATE() msg \n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -994,11 +967,10 @@ ui_reg_all_failed (void)
|
|||
void
|
||||
ui_set_ccm_conn_status (char * ccm_addr, int status)
|
||||
{
|
||||
static const char fname[] = "ui_set_ccm_conn_status";
|
||||
feature_update_t msg;
|
||||
|
||||
DEF_DEBUG(DEB_F_PREFIX"***********CUCM %s %s***********\n",
|
||||
DEB_F_PREFIX_ARGS(UI_API, fname), ccm_addr,
|
||||
DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__), ccm_addr,
|
||||
((status == 0) ?"Not connected":((status == 1)?"STAND BY":
|
||||
((status == 2)?"ACTIVE":"UNKNOWN"))));
|
||||
|
||||
|
@ -1008,7 +980,7 @@ ui_set_ccm_conn_status (char * ccm_addr, int status)
|
|||
msg.update.ccFeatUpd.data.ccm_conn.status = status;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_FEATURE_UPDATE, &msg, sizeof(feature_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_CCM_CONN_STATUS(%d) msg \n", fname, status);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_CCM_CONN_STATUS(%d) msg \n", __FUNCTION__, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1041,10 +1013,9 @@ ui_set_local_hold (line_t line, callid_t call_id)
|
|||
void
|
||||
ui_cfwd_status (line_t line, boolean cfa, char *cfa_number, boolean lcl_fwd)
|
||||
{
|
||||
static const char fname[] = "ui_cfwd_status";
|
||||
feature_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"line=%d cfa=%d cfa_number=%s lcl_fwd=%d", DEB_F_PREFIX_ARGS(UI_API, fname),
|
||||
TNP_DEBUG(DEB_F_PREFIX"line=%d cfa=%d cfa_number=%s lcl_fwd=%d", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__),
|
||||
line, cfa, cfa_number, lcl_fwd);
|
||||
|
||||
msg.sessionType = SESSIONTYPE_CALLCONTROL;
|
||||
|
@ -1055,7 +1026,7 @@ ui_cfwd_status (line_t line, boolean cfa, char *cfa_number, boolean lcl_fwd)
|
|||
msg.update.ccFeatUpd.data.cfwd.cfa_num = cfa_number?strlib_malloc(cfa_number, strlen(cfa_number)):strlib_empty();
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_FEATURE_UPDATE, &msg, sizeof(feature_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_FEATURE_CFWD(%d) msg \n", fname, cfa);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_FEATURE_CFWD(%d) msg \n", __FUNCTION__, cfa);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1082,9 +1053,7 @@ ui_get_idle_prompt_string (void)
|
|||
void
|
||||
ui_set_idle_prompt_string (string_t pString, int prompt)
|
||||
{
|
||||
static const char fname[] = "ui_set_idle_prompt_string";
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"Prompt=%d, Prompt string=%s NOP operation\n", DEB_F_PREFIX_ARGS(UI_API, fname), prompt, pString);
|
||||
TNP_DEBUG(DEB_F_PREFIX"Prompt=%d, Prompt string=%s NOP operation\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__), prompt, pString);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1101,15 +1070,14 @@ void
|
|||
ui_update_placed_call_info (line_t line, callid_t call_id, string_t cldName,
|
||||
string_t cldNumber)
|
||||
{
|
||||
static const char fname[] = "ui_update_placed_call_info";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"calledName:calledNumber %s:%s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname), cldName, cldNumber);
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__), cldName, cldNumber);
|
||||
|
||||
if (call_id == CC_NO_CALL_ID) {
|
||||
/* no operation when no call ID */
|
||||
TNP_DEBUG(DEB_F_PREFIX"invalid callid\n", DEB_F_PREFIX_ARGS(UI_API, fname));
|
||||
TNP_DEBUG(DEB_F_PREFIX"invalid callid\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__));
|
||||
return;
|
||||
}
|
||||
msg.sessionID = createSessionId(line, call_id);
|
||||
|
@ -1127,7 +1095,7 @@ ui_update_placed_call_info (line_t line, callid_t call_id, string_t cldName,
|
|||
}
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_PLACED_INFO(%s) msg \n", fname, cldNumber);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_PLACED_INFO(%s) msg \n", __FUNCTION__, cldNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1143,10 +1111,9 @@ ui_update_placed_call_info (line_t line, callid_t call_id, string_t cldName,
|
|||
void
|
||||
ui_delete_last_digit (line_t line_id, callid_t call_id)
|
||||
{
|
||||
static const char fname[] = "ui_delete_last_digit";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"called\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, fname));
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"called\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, __FUNCTION__));
|
||||
|
||||
if (call_id == CC_NO_CALL_ID) {
|
||||
/* no operation when no call ID */
|
||||
|
@ -1157,7 +1124,7 @@ ui_delete_last_digit (line_t line_id, callid_t call_id)
|
|||
msg.eventID = CALL_DELETE_LAST_DIGIT;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_DELETE_LAST_DIGIT() msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_DELETE_LAST_DIGIT() msg \n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1173,17 +1140,16 @@ ui_delete_last_digit (line_t line_id, callid_t call_id)
|
|||
void
|
||||
ui_control_featurekey_bksp (line_t line_id, callid_t call_id, boolean enable)
|
||||
{
|
||||
static const char fname[] = "ui_control_featurekey_bksp";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"enable=%d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, fname),
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"enable=%d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, __FUNCTION__),
|
||||
enable);
|
||||
|
||||
msg.sessionID = createSessionId(line_id, call_id);
|
||||
msg.eventID = CALL_ENABLE_BKSP;
|
||||
msg.update.ccSessionUpd.data.action = enable;
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_ENABLE_BKSP(%d) msg \n", fname, enable);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_ENABLE_BKSP(%d) msg \n", __FUNCTION__, enable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1202,18 +1168,17 @@ ui_control_featurekey_bksp (line_t line_id, callid_t call_id, boolean enable)
|
|||
void
|
||||
ui_call_selected (line_t line_id, callid_t call_id, int selected)
|
||||
{
|
||||
static const char fname[] = "ui_call_selected";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"selected=%d\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, fname), selected);
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, __FUNCTION__), selected);
|
||||
|
||||
msg.sessionID = createSessionId(line_id, call_id);
|
||||
msg.eventID = CALL_SELECTED;
|
||||
msg.update.ccSessionUpd.data.action = selected;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_SELECTED(%d) msg \n", fname, selected);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_SELECTED(%d) msg \n", __FUNCTION__, selected);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1226,10 +1191,9 @@ ui_call_selected (line_t line_id, callid_t call_id, int selected)
|
|||
*/
|
||||
void ui_BLF_notification (int request_id, cc_blf_state_t blf_state, int app_id)
|
||||
{
|
||||
static const char fname[] = "ui_BLF_notification";
|
||||
feature_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"state=%d app_id=%d\n", DEB_F_PREFIX_ARGS(UI_API, fname), blf_state, app_id);
|
||||
TNP_DEBUG(DEB_F_PREFIX"state=%d app_id=%d\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__), blf_state, app_id);
|
||||
|
||||
msg.sessionType = SESSIONTYPE_CALLCONTROL;
|
||||
msg.featureID = DEVICE_FEATURE_BLF;
|
||||
|
@ -1239,7 +1203,7 @@ void ui_BLF_notification (int request_id, cc_blf_state_t blf_state, int app_id)
|
|||
|
||||
if ( ccappTaskPostMsg(CCAPP_FEATURE_UPDATE, &msg, sizeof(feature_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send DEVICE_FEATURE_BLF(state=%d, app_id=%d) msg \n",
|
||||
fname, blf_state, app_id);
|
||||
__FUNCTION__, blf_state, app_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1260,9 +1224,7 @@ void ui_BLF_notification (int request_id, cc_blf_state_t blf_state, int app_id)
|
|||
void
|
||||
ui_call_in_preservation (line_t line_id, callid_t call_id)
|
||||
{
|
||||
static const char fname[] = "ui_call_in_preservation";
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"called\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, fname));
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"called\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, __FUNCTION__));
|
||||
|
||||
/* simply update the state . A Preservation event from
|
||||
CUCM is just for the session */
|
||||
|
@ -1292,11 +1254,10 @@ void
|
|||
ui_select_feature_key_set (line_t line_id, callid_t call_id, char *set_name,
|
||||
int sk_mask_list[], int len)
|
||||
{
|
||||
static const char fname[] = "ui_select_feature_key_set";
|
||||
int i;
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"called\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, fname));
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"called\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line_id, call_id, __FUNCTION__));
|
||||
|
||||
if (call_id == CC_NO_CALL_ID) {
|
||||
/* no operation when no call ID */
|
||||
|
@ -1304,7 +1265,7 @@ ui_select_feature_key_set (line_t line_id, callid_t call_id, char *set_name,
|
|||
}
|
||||
|
||||
if (len <= 0 || len > MAX_SOFT_KEYS) {
|
||||
TNP_DEBUG(DEB_F_PREFIX"Incorrect softkey array length passed in : %d\n", DEB_F_PREFIX_ARGS(UI_API, fname), len);
|
||||
TNP_DEBUG(DEB_F_PREFIX"Incorrect softkey array length passed in : %d\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__), len);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1324,7 +1285,7 @@ ui_select_feature_key_set (line_t line_id, callid_t call_id, char *set_name,
|
|||
}
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_SELECT_FEATURE_SET() msg \n", fname);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_SELECT_FEATURE_SET() msg \n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1341,16 +1302,15 @@ ui_select_feature_key_set (line_t line_id, callid_t call_id, char *set_name,
|
|||
void
|
||||
ui_execute_uri (char *uri)
|
||||
{
|
||||
static const char fname[] = "ui_execute_uri";
|
||||
session_mgmt_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_F_PREFIX"uri=%s\n", DEB_F_PREFIX_ARGS(UI_API, fname), uri);
|
||||
TNP_DEBUG(DEB_F_PREFIX"uri=%s\n", DEB_F_PREFIX_ARGS(UI_API, __FUNCTION__), uri);
|
||||
|
||||
msg.func_id = SESSION_MGMT_EXECUTE_URI;
|
||||
msg.data.uri.uri = STRLIB_CREATE(uri);
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_MGMT, &msg, sizeof(session_mgmt_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(DEB_F_PREFIX"failed to send EXECUTE_URI() msg\n", DEB_F_PREFIX_ARGS(PLAT_API, fname));
|
||||
CCAPP_ERROR(DEB_F_PREFIX"failed to send EXECUTE_URI() msg\n", DEB_F_PREFIX_ARGS(PLAT_API, __FUNCTION__));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1373,10 +1333,9 @@ void
|
|||
ui_update_call_security (line_t line, callid_t call_id,
|
||||
cc_security_e call_security)
|
||||
{
|
||||
static const char fname[] = "ui_update_call_security";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"security=%d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname),
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"security=%d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__),
|
||||
call_security);
|
||||
|
||||
msg.sessionID = createSessionId(line, call_id);
|
||||
|
@ -1384,7 +1343,7 @@ ui_update_call_security (line_t line, callid_t call_id,
|
|||
msg.update.ccSessionUpd.data.security = call_security;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_SECURITY(%d) msg \n", fname, call_security);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_SECURITY(%d) msg \n", __FUNCTION__, call_security);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1413,10 +1372,9 @@ void
|
|||
ui_terminate_feature (line_t line, callid_t call_id,
|
||||
callid_t target_call_id)
|
||||
{
|
||||
static const char fname[] = "ui_terminate_feature";
|
||||
session_update_t msg;
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"target_call_id=%d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, fname),
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"target_call_id=%d\n", DEB_L_C_F_PREFIX_ARGS(UI_API, line, call_id, __FUNCTION__),
|
||||
target_call_id);
|
||||
|
||||
msg.sessionID = createSessionId(line, call_id);
|
||||
|
@ -1428,7 +1386,7 @@ ui_terminate_feature (line_t line, callid_t call_id,
|
|||
}
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_FEATURE_CANCEL(%d) msg \n", fname, target_call_id);
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_FEATURE_CANCEL(%d) msg \n", __FUNCTION__, target_call_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1561,7 +1519,6 @@ ui_log_status_msg (char *msg)
|
|||
|
||||
void ui_log_disposition (callid_t call_id, int logdisp)
|
||||
{
|
||||
static const char fname[] = "ui_log_disposition";
|
||||
session_update_t msg;
|
||||
fsmdef_dcb_t *dcb = fsmdef_get_dcb_by_call_id(call_id);
|
||||
|
||||
|
@ -1571,14 +1528,14 @@ void ui_log_disposition (callid_t call_id, int logdisp)
|
|||
return;
|
||||
}
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"called\n", DEB_L_C_F_PREFIX_ARGS(UI_API, dcb->line, call_id, fname));
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"called\n", DEB_L_C_F_PREFIX_ARGS(UI_API, dcb->line, call_id, __FUNCTION__));
|
||||
|
||||
msg.sessionID = createSessionId(dcb->line, call_id);
|
||||
msg.eventID = CALL_LOGDISP;
|
||||
msg.update.ccSessionUpd.data.action = logdisp;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR("%s: failed to send CALL_PRESERVATION_ACTIVE(%d) msg \n", fname, call_id);
|
||||
CCAPP_ERROR("%s: failed to send CALL_PRESERVATION_ACTIVE(%d) msg \n", __FUNCTION__, call_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1598,3 +1555,147 @@ ui_control_feature (line_t line_id, callid_t call_id,
|
|||
{
|
||||
// do nothing.
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper for the following four functions which all load up a
|
||||
* session_update message and post it.
|
||||
*
|
||||
*/
|
||||
static void post_message_helper(
|
||||
group_call_event_t eventId,
|
||||
call_events event,
|
||||
line_t nLine,
|
||||
callid_t nCallId,
|
||||
uint16_t call_instance_id,
|
||||
char *sdp,
|
||||
cc_int32_t status)
|
||||
{
|
||||
session_update_t msg;
|
||||
|
||||
if (nCallId == CC_NO_CALL_ID) {
|
||||
/* no operation when no call ID */
|
||||
return;
|
||||
}
|
||||
|
||||
msg.sessionID = createSessionId(nLine, nCallId);
|
||||
|
||||
msg.eventID = eventId;
|
||||
msg.update.ccSessionUpd.data.state_data.state = event;
|
||||
msg.update.ccSessionUpd.data.state_data.inst = call_instance_id;
|
||||
msg.update.ccSessionUpd.data.state_data.line_id = nLine;
|
||||
msg.update.ccSessionUpd.data.state_data.sdp = sdp;
|
||||
if (eventId == SET_LOCAL_DESC || eventId == SET_REMOTE_DESC) {
|
||||
msg.update.ccSessionUpd.data.state_data.cause = status;
|
||||
}
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATE(%d) msg \n", __FUNCTION__, event);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data from createOffer to the UI, can send success with SDP string
|
||||
* or can send error
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ui_create_offer(call_events event, line_t nLine, callid_t nCallID,
|
||||
uint16_t call_instance_id, char* sdp)
|
||||
{
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"state=%d attr=%d call_instance=%d\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, nLine, nCallID, __FUNCTION__), event, call_instance_id);
|
||||
|
||||
post_message_helper(CREATE_OFFER, event, nLine, nCallID, call_instance_id, sdp, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data from createAnswer to the UI, can send success with SDP string
|
||||
* or can send error
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ui_create_answer(call_events event, line_t nLine, callid_t nCallID,
|
||||
uint16_t call_instance_id, char* sdp)
|
||||
{
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"state=%d call_instance=%d\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, nLine, nCallID, __FUNCTION__), event, call_instance_id);
|
||||
|
||||
post_message_helper(CREATE_ANSWER, event, nLine, nCallID, call_instance_id, sdp, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data from setLocalDescription to the UI
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
|
||||
void ui_set_local_description(call_events event, line_t nLine, callid_t nCallID,
|
||||
uint16_t call_instance_id, char* sdp, cc_int32_t status)
|
||||
{
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"state=%d call_instance=%d\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, nLine, nCallID, __FUNCTION__), event, call_instance_id);
|
||||
|
||||
post_message_helper(SET_LOCAL_DESC, event, nLine, nCallID, call_instance_id, sdp, status);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data from setRemoteDescription to the UI
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
|
||||
void ui_set_remote_description(call_events event, line_t nLine, callid_t nCallID,
|
||||
uint16_t call_instance_id, char* sdp, cc_int32_t status)
|
||||
{
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"state=%d call_instance=%d\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, nLine, nCallID, __FUNCTION__), event, call_instance_id);
|
||||
|
||||
post_message_helper(SET_REMOTE_DESC, event, nLine, nCallID, call_instance_id, sdp, status);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send Remote Stream data to the UI
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
|
||||
void ui_on_remote_stream_added(call_events event, line_t nLine, callid_t nCallID, uint16_t call_instance_id, cc_media_remote_track_table_t media_track)
|
||||
{
|
||||
session_update_t msg;
|
||||
fsmdef_dcb_t *dcb = fsmdef_get_dcb_by_call_id(nCallID);
|
||||
|
||||
if (nCallID == CC_NO_CALL_ID || dcb == NULL) {
|
||||
/* no operation when no call ID */
|
||||
return;
|
||||
}
|
||||
|
||||
TNP_DEBUG(DEB_L_C_F_PREFIX"state=%d call_instance=%d\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(UI_API, nLine, nCallID, __FUNCTION__), event, call_instance_id);
|
||||
|
||||
|
||||
msg.sessionID = createSessionId(nLine, nCallID);
|
||||
|
||||
msg.eventID = REMOTE_STREAM_ADD;
|
||||
msg.update.ccSessionUpd.data.state_data.state = event;
|
||||
msg.update.ccSessionUpd.data.state_data.inst = call_instance_id;
|
||||
msg.update.ccSessionUpd.data.state_data.line_id = nLine;
|
||||
msg.update.ccSessionUpd.data.state_data.media_stream_track_id = media_track.track[0].media_stream_track_id;
|
||||
msg.update.ccSessionUpd.data.state_data.media_stream_id = (unsigned int)media_track.media_stream_id;
|
||||
|
||||
if ( ccappTaskPostMsg(CCAPP_SESSION_UPDATE, &msg, sizeof(session_update_t), CCAPP_CCPROVIER) != CPR_SUCCESS ) {
|
||||
CCAPP_ERROR(CCAPP_F_PREFIX"failed to send CALL_STATE(%d) msg \n", __FUNCTION__, event);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -102,6 +102,13 @@ vcm_media_payload_type_t vcmRtpToMediaPayload (int32_t ptype,
|
|||
case RTP_H264_P1:
|
||||
type = CREATE_MT_MAP(dynamic_ptype_value, VCM_Media_Payload_H264);
|
||||
break;
|
||||
case RTP_VP8:
|
||||
type = CREATE_MT_MAP(dynamic_ptype_value, VCM_Media_Payload_VP8);
|
||||
break;
|
||||
|
||||
case RTP_OPUS:
|
||||
type = CREATE_MT_MAP(dynamic_ptype_value, VCM_Media_Payload_OPUS);
|
||||
break;
|
||||
|
||||
default:
|
||||
type = VCM_Media_Payload_NonStandard;
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cisco Systems SIP Stack.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Cisco Systems (CSCO).
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Enda Mannion <emannion@cisco.com>
|
||||
* Suhas Nandakumar <snandaku@cisco.com>
|
||||
* Ethan Hugg <ehugg@cisco.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "xml_parser.h"
|
||||
#include "cpr_stdlib.h"
|
||||
#include "phone_debug.h"
|
||||
#include "xml_util.h"
|
||||
|
||||
static void *xml_parser_handle = NULL;
|
||||
|
||||
int xmlInit() {
|
||||
if (ccxmlInitialize(&xml_parser_handle) == CC_FAILURE) {
|
||||
return CC_FAILURE;
|
||||
}
|
||||
return CC_SUCCESS;
|
||||
}
|
||||
|
||||
void xmlDeInit() {
|
||||
ccxmlDeInitialize(&xml_parser_handle);
|
||||
}
|
||||
|
||||
char * xmlEncodeEventData(ccsip_event_data_t *event_datap) {
|
||||
const char *fname = "xmlEncodeEventData";
|
||||
char *buffer;
|
||||
uint32_t nbytes = 0;
|
||||
|
||||
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Encode event data: entered,\n",
|
||||
DEB_F_PREFIX_ARGS(SIP_SUB, fname));
|
||||
//For RAW data, no encoding is needed, just copy back.
|
||||
if (event_datap->type == EVENT_DATA_RAW) {
|
||||
nbytes = event_datap->u.raw_data.length;
|
||||
buffer = (char *) ccAllocXML(nbytes + 1);
|
||||
if (buffer) {
|
||||
memcpy(buffer, event_datap->u.raw_data.data, nbytes);
|
||||
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Framed raw buffer: length = %d,\n",
|
||||
DEB_F_PREFIX_ARGS(SIP_SUB, fname), nbytes);
|
||||
}
|
||||
return (buffer);
|
||||
|
||||
}
|
||||
buffer = ccxmlEncodeEventData(xml_parser_handle, event_datap);
|
||||
DEF_DEBUG(DEB_F_PREFIX"returned content after encoding:\n%s\n", DEB_F_PREFIX_ARGS(SIP_REG, fname), buffer);
|
||||
return (buffer);
|
||||
|
||||
//return ccxmlEncodeEventData(xml_parser_handle, event_datap);
|
||||
}
|
||||
|
||||
int xmlDecodeEventData (cc_subscriptions_ext_t msg_type, const char *msg_body, int msg_length, ccsip_event_data_t ** event_datap) {
|
||||
const char *fname = "xmlDecodeEventData";
|
||||
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Decode event data: entered,\n",
|
||||
DEB_F_PREFIX_ARGS(SIP_SUB, fname));
|
||||
|
||||
return ccxmlDecodeEventData(xml_parser_handle, msg_type, msg_body, msg_length, event_datap );
|
||||
}
|
||||
|
||||
void *ccAllocXML(cc_size_t size) {
|
||||
return cpr_calloc(1, size);
|
||||
}
|
||||
|
||||
void ccFreeXML(void *mem) {
|
||||
cpr_free(mem);
|
||||
}
|
||||
|
|
@ -53,6 +53,7 @@
|
|||
#include "gsm.h"
|
||||
#include "vcm.h"
|
||||
#include "sip_common_regmgr.h"
|
||||
#include "util_string.h"
|
||||
|
||||
static const char *cc_src_names[] = {
|
||||
"GSM",
|
||||
|
@ -62,9 +63,9 @@ static const char *cc_src_names[] = {
|
|||
"CCAPP"
|
||||
};
|
||||
|
||||
#define CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, msg) \
|
||||
#define CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, msg) \
|
||||
DEF_DEBUG(DEB_L_C_F_PREFIX"%s -> %s: %-20s\n",\
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname),\
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__),\
|
||||
cc_src_name(src_id), cc_src_name(dst_id), msg)
|
||||
|
||||
|
||||
|
@ -96,9 +97,8 @@ cc_print_msg (char *pData, int len)
|
|||
{
|
||||
int ix;
|
||||
int msg_id = *((int *) pData);
|
||||
static const char fname[] = "cc_print_msg";
|
||||
|
||||
buginf("\n" CCA_F_PREFIX "cc_msg= %s, 0x=", fname,
|
||||
buginf("\n" CCA_F_PREFIX "cc_msg= %s, 0x=", __FUNCTION__,
|
||||
cc_msg_name((cc_msgs_t) msg_id));
|
||||
for (ix = 0; ix < len; ix++) {
|
||||
if ((ix % 8 == 0) && ix) {
|
||||
|
@ -121,26 +121,25 @@ cc_print_msg (char *pData, int len)
|
|||
cprBuffer_t
|
||||
cc_get_msg_buf (int min_size)
|
||||
{
|
||||
static const char fname[] = "cc_get_msg_buf";
|
||||
cprBuffer_t buf;
|
||||
|
||||
if (min_size > CPR_MAX_MSG_SIZE) {
|
||||
/* Size requested exceeds maximum ethernet buffer */
|
||||
GSM_ERR_MSG(get_debug_string(DEBUG_MSG_BUFFER_TOO_BIG),
|
||||
fname, min_size);
|
||||
__FUNCTION__, min_size);
|
||||
return (cprBuffer_t)NULL;
|
||||
}
|
||||
|
||||
buf = gsm_get_buffer((uint16_t) min_size);
|
||||
if (!buf) {
|
||||
GSM_ERR_MSG(get_debug_string(DEBUG_SYSBUF_UNAVAILABLE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(DEBUG_SYSBUF_UNAVAILABLE), __FUNCTION__);
|
||||
return (cprBuffer_t)NULL;
|
||||
}
|
||||
|
||||
/* Clean out the data region of the message */
|
||||
memset(buf, 0, min_size);
|
||||
|
||||
CC_DEBUG(DEB_F_PREFIX "Msg id = 0x%0x\n", DEB_F_PREFIX_ARGS(CC_API, fname), buf);
|
||||
CC_DEBUG(DEB_F_PREFIX "Msg id = 0x%0x\n", DEB_F_PREFIX_ARGS(CC_API, __FUNCTION__), buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -157,14 +156,14 @@ cc_send_cmd_msg (uint32_t cmd, cprBuffer_t buf, uint16_t len, cc_srcs_t dst_id)
|
|||
rc = gsm_send_msg(cmd, buf, len);
|
||||
if (rc == CPR_FAILURE) {
|
||||
cc_free_msg_data((cc_msg_t *) buf);
|
||||
cprReleaseBuffer(buf);
|
||||
cpr_free(buf);
|
||||
}
|
||||
break;
|
||||
case CC_SRC_SIP:
|
||||
rc = SIPTaskSendMsg(cmd, buf, len, NULL);
|
||||
if (rc == CPR_FAILURE) {
|
||||
cc_free_msg_data((cc_msg_t *) buf);
|
||||
cprReleaseBuffer(buf);
|
||||
cpr_free(buf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -187,14 +186,14 @@ cc_send_msg (cprBuffer_t buf, uint16_t len, cc_srcs_t dst_id)
|
|||
rc = gsm_send_msg(GSM_SIP, buf, len);
|
||||
if (rc == CPR_FAILURE) {
|
||||
cc_free_msg_data((cc_msg_t *) buf);
|
||||
cprReleaseBuffer(buf);
|
||||
cpr_free(buf);
|
||||
}
|
||||
break;
|
||||
case CC_SRC_SIP:
|
||||
rc = SIPTaskSendMsg(SIP_GSM, buf, len, NULL);
|
||||
if (rc == CPR_FAILURE) {
|
||||
cc_free_msg_data((cc_msg_t *) buf);
|
||||
cprReleaseBuffer(buf);
|
||||
cpr_free(buf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -253,11 +252,9 @@ cc_initialize_msg_body_parts_info (cc_msgbody_info_t *msg_body)
|
|||
*/
|
||||
void
|
||||
cc_mv_msg_body_parts (cc_msgbody_info_t *dst_msg, cc_msgbody_info_t *src_msg)
|
||||
{
|
||||
static const char fname[] = "cc_mv_msg_body_parts";
|
||||
|
||||
{
|
||||
if (dst_msg == NULL) {
|
||||
GSM_ERR_MSG(CCA_F_PREFIX "dst is NULL\n", fname);
|
||||
GSM_ERR_MSG(CCA_F_PREFIX "dst is NULL\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -814,24 +811,23 @@ cc_int_setup (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
cc_call_info_t *call_info_p, boolean replaces,
|
||||
string_t recv_info_list, cc_msgbody_info_t *msg_body)
|
||||
{
|
||||
static const char fname[] = "cc_int_setup";
|
||||
cc_setup_t *pmsg;
|
||||
|
||||
if (caller_id == NULL) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG("%s: caller id is NULL\n", fname);
|
||||
GSM_ERR_MSG("%s: caller id is NULL\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX " CGPD= %s, CGPN= %s,\n CDPD= %s, CDPN= %s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname),
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__),
|
||||
caller_id->calling_name, caller_id->calling_number,
|
||||
caller_id->called_name, caller_id->called_number);
|
||||
|
||||
pmsg = (cc_setup_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -866,11 +862,11 @@ cc_int_setup (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
pmsg->msg_body.num_parts = 0;
|
||||
cc_mv_msg_body_parts(&pmsg->msg_body, msg_body);
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -881,13 +877,12 @@ cc_int_setup_ack (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
line_t line, cc_caller_id_t *caller_id,
|
||||
cc_msgbody_info_t *msg_body)
|
||||
{
|
||||
static const char fname[] = "cc_int_setup_ack";
|
||||
cc_setup_ack_t *pmsg;
|
||||
|
||||
pmsg = (cc_setup_ack_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -902,11 +897,11 @@ cc_int_setup_ack (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
pmsg->msg_body.num_parts = 0;
|
||||
cc_mv_msg_body_parts(&pmsg->msg_body, msg_body);
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -915,13 +910,12 @@ void
|
|||
cc_int_proceeding (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, cc_caller_id_t *caller_id)
|
||||
{
|
||||
static const char fname[] = "cc_int_proceeding";
|
||||
cc_proceeding_t *pmsg;
|
||||
|
||||
pmsg = (cc_proceeding_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -933,11 +927,11 @@ cc_int_proceeding (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
cc_cp_caller(&pmsg->caller_id, caller_id);
|
||||
}
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg(pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -948,14 +942,13 @@ cc_int_alerting (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
line_t line, cc_caller_id_t *caller_id,
|
||||
cc_msgbody_info_t *msg_body, boolean inband)
|
||||
{
|
||||
static const char fname[] = "cc_int_alerting";
|
||||
cc_alerting_t *pmsg;
|
||||
|
||||
|
||||
pmsg = (cc_alerting_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -972,13 +965,13 @@ cc_int_alerting (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
|
||||
pmsg->inband = inband;
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX " inband= %d\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname), inband);
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__), inband);
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -989,13 +982,12 @@ cc_int_connected (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
line_t line, cc_caller_id_t *caller_id,
|
||||
string_t recv_info_list, cc_msgbody_info_t *msg_body)
|
||||
{
|
||||
static const char fname[] = "cc_int_connected";
|
||||
cc_connected_t *pmsg;
|
||||
|
||||
pmsg = (cc_connected_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1018,11 +1010,11 @@ cc_int_connected (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
pmsg->msg_body.num_parts = 0;
|
||||
cc_mv_msg_body_parts(&pmsg->msg_body, msg_body);
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1033,13 +1025,12 @@ cc_int_connected_ack (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
line_t line, cc_caller_id_t *caller_id,
|
||||
cc_msgbody_info_t *msg_body)
|
||||
{
|
||||
static const char fname[] = "cc_int_connected_ack";
|
||||
cc_connected_ack_t *pmsg;
|
||||
|
||||
pmsg = (cc_connected_ack_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1054,11 +1045,11 @@ cc_int_connected_ack (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
pmsg->msg_body.num_parts = 0;
|
||||
cc_mv_msg_body_parts(&pmsg->msg_body, msg_body);
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1069,21 +1060,20 @@ cc_int_release (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
line_t line, cc_causes_t cause, const char *dialstring,
|
||||
cc_kfact_t *kfactor)
|
||||
{
|
||||
static const char fname[] = "cc_int_release";
|
||||
cc_release_t *pmsg;
|
||||
|
||||
if ((dialstring == NULL)) {
|
||||
if (dialstring == NULL) {
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX " cause= %s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname), cc_cause_name(cause));
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__), cc_cause_name(cause));
|
||||
} else {
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX " cause= %s, dialstring= %s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname), cc_cause_name(cause), dialstring);
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__), cc_cause_name(cause), dialstring);
|
||||
}
|
||||
|
||||
pmsg = (cc_release_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1101,11 +1091,11 @@ cc_int_release (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
sstrncpy(pmsg->kfactor.txstats, kfactor->txstats, CC_KFACTOR_STAT_LEN);
|
||||
}
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1116,14 +1106,13 @@ cc_int_release_complete (cc_srcs_t src_id, cc_srcs_t dst_id,
|
|||
callid_t call_id, line_t line, cc_causes_t cause,
|
||||
cc_kfact_t *kfactor)
|
||||
{
|
||||
static const char fname[] = "cc_int_release_complete";
|
||||
cc_release_complete_t *pmsg;
|
||||
|
||||
|
||||
pmsg = (cc_release_complete_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1137,35 +1126,35 @@ cc_int_release_complete (cc_srcs_t src_id, cc_srcs_t dst_id,
|
|||
sstrncpy(pmsg->kfactor.txstats, kfactor->txstats, CC_KFACTOR_STAT_LEN);
|
||||
}
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX " cause= %s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname), cc_cause_name(cause));
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__), cc_cause_name(cause));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cc_int_feature (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, cc_features_t feature_id, cc_feature_data_t *data)
|
||||
cc_int_feature2 (cc_msgs_t msg_id, cc_srcs_t src_id, cc_srcs_t dst_id,
|
||||
callid_t call_id, line_t line, cc_features_t feature_id,
|
||||
cc_feature_data_t *data)
|
||||
{
|
||||
static const char fname[] = "cc_int_feature";
|
||||
cc_feature_t *pmsg;
|
||||
cc_msgbody_info_t *msg_body;
|
||||
|
||||
pmsg = (cc_feature_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG("%s: no buffer available for feat=%s\n", fname,
|
||||
GSM_ERR_MSG("%s: no buffer available for feat=%s\n", __FUNCTION__,
|
||||
cc_feature_name(feature_id));
|
||||
return;
|
||||
}
|
||||
|
||||
pmsg->msg_id = CC_MSG_FEATURE;
|
||||
pmsg->msg_id = msg_id;
|
||||
pmsg->src_id = src_id;
|
||||
pmsg->call_id = call_id;
|
||||
pmsg->line = line;
|
||||
|
@ -1195,36 +1184,164 @@ cc_int_feature (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
if (data != NULL) {
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX
|
||||
"method= %d, call_id= %d, cause= %s dialstring= %s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname),
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__),
|
||||
data->xfer.method, data->xfer.target_call_id,
|
||||
cc_cause_name(data->xfer.cause), data->xfer.dialstring);
|
||||
}
|
||||
}
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_feature_name(feature_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_feature_name(feature_id));
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX "feature= %s, data= %p\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname), cc_feature_name(feature_id), data);
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__), cc_feature_name(feature_id), data);
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG("%s: unable to send msg for feat=%s\n", fname,
|
||||
GSM_ERR_MSG("%s: unable to send msg for feat=%s\n", __FUNCTION__,
|
||||
cc_feature_name(feature_id));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for the next six functions that populates and sends
|
||||
* a feature message
|
||||
*
|
||||
*/
|
||||
static void send_message_helper(
|
||||
cc_msgs_t msg_id,
|
||||
cc_srcs_t src_id,
|
||||
cc_srcs_t dst_id,
|
||||
callid_t call_id,
|
||||
line_t line,
|
||||
cc_features_t feature_id,
|
||||
cc_feature_data_t *data,
|
||||
string_t sdp,
|
||||
cc_jsep_action_t action)
|
||||
{
|
||||
cc_feature_t *pmsg;
|
||||
cc_msgbody_info_t *msg_body;
|
||||
|
||||
pmsg = (cc_feature_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
GSM_ERR_MSG("%s: no buffer available for feat=%s\n", __FUNCTION__,
|
||||
cc_feature_name(feature_id));
|
||||
return;
|
||||
}
|
||||
|
||||
pmsg->msg_id = msg_id;
|
||||
pmsg->src_id = src_id;
|
||||
pmsg->call_id = call_id;
|
||||
pmsg->line = line;
|
||||
pmsg->feature_id = feature_id;
|
||||
pmsg->data_valid = (data == NULL) ? (FALSE) : (TRUE);
|
||||
|
||||
if (msg_id == CC_MSG_SETLOCALDESC || msg_id == CC_MSG_SETREMOTEDESC) {
|
||||
pmsg->action = action;
|
||||
}
|
||||
|
||||
if (msg_id == CC_MSG_CREATEANSWER || msg_id == CC_MSG_SETLOCALDESC || msg_id == CC_MSG_SETREMOTEDESC) {
|
||||
sstrncpy(pmsg->sdp, sdp, sizeof(pmsg->sdp));
|
||||
}
|
||||
|
||||
if (pmsg->data_valid == TRUE) {
|
||||
pmsg->data = *data;
|
||||
/*
|
||||
* For call Info feature, need to copy the caller ID
|
||||
*/
|
||||
if (feature_id == CC_FEATURE_CALLINFO) {
|
||||
/* Copy the caller ID */
|
||||
cc_cp_caller(&pmsg->data.call_info.caller_id,
|
||||
&data->call_info.caller_id);
|
||||
}
|
||||
/*
|
||||
* Clear the msg body from the source now since the msg. bodies
|
||||
* has been transferred to to the CCAPI msg.
|
||||
*/
|
||||
msg_body = cc_get_msg_body_info_ptr_from_feature_data(feature_id, data);
|
||||
cc_initialize_msg_body_parts_info(msg_body);
|
||||
}
|
||||
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_feature_name(feature_id));
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX "feature= %s, data= %p\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__), cc_feature_name(feature_id), data);
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG("%s: unable to send msg for feat=%s\n", __FUNCTION__,
|
||||
cc_feature_name(feature_id));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
cc_createoffer (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, cc_features_t feature_id, cc_feature_data_t *data)
|
||||
{
|
||||
send_message_helper(CC_MSG_CREATEOFFER, src_id, dst_id, call_id, line,
|
||||
feature_id, data, NULL, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cc_createanswer (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, cc_features_t feature_id, string_t sdp, cc_feature_data_t *data)
|
||||
{
|
||||
send_message_helper(CC_MSG_CREATEANSWER, src_id, dst_id, call_id, line,
|
||||
feature_id, data, sdp, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void cc_setlocaldesc (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line,
|
||||
cc_features_t feature_id, cc_jsep_action_t action, string_t sdp, cc_feature_data_t *data)
|
||||
{
|
||||
send_message_helper(CC_MSG_SETLOCALDESC, src_id, dst_id, call_id, line,
|
||||
feature_id, data, sdp, action);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void cc_setremotedesc (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line,
|
||||
cc_features_t feature_id, cc_jsep_action_t action, string_t sdp, cc_feature_data_t *data)
|
||||
{
|
||||
send_message_helper(CC_MSG_SETREMOTEDESC, src_id, dst_id, call_id, line,
|
||||
feature_id, data, sdp, action);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void cc_localdesc (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line,
|
||||
cc_features_t feature_id, cc_feature_data_t *data)
|
||||
{
|
||||
send_message_helper(CC_MSG_LOCALDESC, src_id, dst_id, call_id, line,
|
||||
feature_id, data, NULL, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void cc_remotedesc (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line,
|
||||
cc_features_t feature_id, cc_feature_data_t *data)
|
||||
{
|
||||
send_message_helper(CC_MSG_REMOTEDESC, src_id, dst_id, call_id, line,
|
||||
feature_id, data, NULL, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cc_int_feature_ack (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, cc_features_t feature_id,
|
||||
cc_feature_data_t *data, cc_causes_t cause)
|
||||
{
|
||||
static const char fname[] = "cc_int_feature_ack";
|
||||
cc_feature_ack_t *pmsg;
|
||||
cc_msgbody_info_t *msg_body;
|
||||
|
||||
pmsg = (cc_feature_ack_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1251,20 +1368,20 @@ cc_int_feature_ack (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
if (data != NULL) {
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX
|
||||
"method= %d, call_id= %d, cause= %s dialstring= %s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname),
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__),
|
||||
data->xfer.method, data->xfer.target_call_id,
|
||||
cc_cause_name(data->xfer.cause), data->xfer.dialstring);
|
||||
}
|
||||
}
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX "feature= %s, data= %p, cause= %s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname), cc_feature_name(feature_id), data,
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__), cc_feature_name(feature_id), data,
|
||||
cc_cause_name(cause));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1276,13 +1393,12 @@ cc_int_offhook (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t prim_call_id,
|
|||
line_t line, char *global_call_id, monitor_mode_t monitor_mode,
|
||||
cfwdall_mode_t cfwdall_mode)
|
||||
{
|
||||
static const char fname[] = "cc_int_offhook";
|
||||
cc_offhook_t *pmsg;
|
||||
|
||||
pmsg = (cc_offhook_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1298,11 +1414,11 @@ cc_int_offhook (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t prim_call_id,
|
|||
pmsg->monitor_mode = monitor_mode;
|
||||
pmsg->cfwdall_mode = cfwdall_mode;
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1311,13 +1427,12 @@ cc_int_offhook (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t prim_call_id,
|
|||
void
|
||||
cc_int_line (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line)
|
||||
{
|
||||
static const char fname[] = "cc_int_line";
|
||||
cc_line_t *pmsg;
|
||||
|
||||
pmsg = (cc_line_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1326,11 +1441,11 @@ cc_int_line (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line)
|
|||
pmsg->call_id = call_id;
|
||||
pmsg->line = line;
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1341,13 +1456,12 @@ cc_int_onhook (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t prim_call_id,
|
|||
cc_hold_resume_reason_e consult_reason, callid_t call_id,
|
||||
line_t line, boolean softkey, cc_onhook_reason_e active_list)
|
||||
{
|
||||
static const char fname[] = "cc_int_onhook";
|
||||
cc_onhook_t *pmsg;
|
||||
|
||||
pmsg = (cc_onhook_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1360,11 +1474,11 @@ cc_int_onhook (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t prim_call_id,
|
|||
pmsg->hold_resume_reason = consult_reason;
|
||||
pmsg->active_list = active_list;
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1374,13 +1488,12 @@ void
|
|||
cc_int_digit_begin (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, int digit)
|
||||
{
|
||||
static const char fname[] = "cc_int_digit_begin";
|
||||
cc_digit_begin_t *pmsg;
|
||||
|
||||
pmsg = (cc_digit_begin_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1389,11 +1502,11 @@ cc_int_digit_begin (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
pmsg->call_id = call_id;
|
||||
pmsg->digit = digit;
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1404,22 +1517,21 @@ cc_int_dialstring (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
line_t line, const char *dialstring, const char *g_call_id,
|
||||
monitor_mode_t monitor_mode)
|
||||
{
|
||||
static const char fname[] = "cc_int_dialstring";
|
||||
cc_dialstring_t *pmsg;
|
||||
|
||||
if (dialstring == NULL) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG("%s: no dialstring\n", fname);
|
||||
GSM_ERR_MSG("%s: no dialstring\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX "dialstring= %s\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname),dialstring);
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__),dialstring);
|
||||
|
||||
pmsg = (cc_dialstring_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1431,11 +1543,11 @@ cc_int_dialstring (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
sstrncpy(pmsg->g_call_id, g_call_id, CC_GCID_LEN);
|
||||
pmsg->monitor_mode = monitor_mode;
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1445,13 +1557,12 @@ void
|
|||
cc_int_mwi (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line,
|
||||
boolean on, int type, int newCount, int oldCount, int hpNewCount, int hpOldCount)
|
||||
{
|
||||
static const char fname[] = "cc_int_mwi";
|
||||
cc_mwi_t *pmsg;
|
||||
|
||||
pmsg = (cc_mwi_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1466,13 +1577,13 @@ cc_int_mwi (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line,
|
|||
pmsg->msgSummary.hpNewCount = hpNewCount;
|
||||
pmsg->msgSummary.hpOldCount = hpOldCount;
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX " mwi status= %d\n new count= %d old count= %d",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname), on, newCount, oldCount);
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__), on, newCount, oldCount);
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1481,13 +1592,12 @@ void
|
|||
cc_int_options_sdp_req (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, void *pMessage)
|
||||
{
|
||||
static const char fname[] = "cc_int_options_sdp_req";
|
||||
cc_options_sdp_req_t *pmsg;
|
||||
|
||||
pmsg = (cc_options_sdp_req_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1497,13 +1607,13 @@ cc_int_options_sdp_req (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
pmsg->line = line;
|
||||
pmsg->pMessage = pMessage;
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX " message ptr=%p\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname), pMessage);
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__), pMessage);
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1512,13 +1622,12 @@ void
|
|||
cc_int_options_sdp_ack (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, void *pMessage, cc_msgbody_info_t *msg_body)
|
||||
{
|
||||
static const char fname[] = "cc_int_options_sdp_ack";
|
||||
cc_options_sdp_ack_t *pmsg;
|
||||
|
||||
pmsg = (cc_options_sdp_ack_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1531,13 +1640,13 @@ cc_int_options_sdp_ack (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
pmsg->msg_body.num_parts = 0;
|
||||
cc_mv_msg_body_parts(&pmsg->msg_body, msg_body);
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX " message ptr=%p\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname), pMessage);
|
||||
DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__), pMessage);
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1546,13 +1655,12 @@ void
|
|||
cc_int_audit_sdp_req (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, boolean apply_ringout)
|
||||
{
|
||||
static const char fname[] = "cc_int_audit_sdp_req";
|
||||
cc_audit_sdp_req_t *pmsg;
|
||||
|
||||
pmsg = (cc_audit_sdp_req_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1562,12 +1670,12 @@ cc_int_audit_sdp_req (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
pmsg->line = line;
|
||||
pmsg->apply_ringout = apply_ringout;
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX "\n", DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, fname));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG(DEB_L_C_F_PREFIX "\n", DEB_L_C_F_PREFIX_ARGS(CC_API, line, call_id, __FUNCTION__));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1576,13 +1684,12 @@ void
|
|||
cc_int_audit_sdp_ack (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, cc_msgbody_info_t *msg_body)
|
||||
{
|
||||
static const char fname[] = "cc_int_audit_sdp_ack";
|
||||
cc_audit_sdp_ack_t *pmsg;
|
||||
|
||||
pmsg = (cc_audit_sdp_ack_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1594,11 +1701,11 @@ cc_int_audit_sdp_ack (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
pmsg->msg_body.num_parts = 0;
|
||||
cc_mv_msg_body_parts(&pmsg->msg_body, msg_body);
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1607,14 +1714,13 @@ void
|
|||
cc_int_fail_fallback (cc_srcs_t src_id, cc_srcs_t dst_id, int rsp_type,
|
||||
cc_regmgr_rsp_e rsp_id, boolean waited)
|
||||
{
|
||||
static const char fname[] = "cc_int_fail_fallback";
|
||||
cc_regmgr_t *pmsg;
|
||||
|
||||
|
||||
pmsg = (cc_regmgr_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1624,9 +1730,9 @@ cc_int_fail_fallback (cc_srcs_t src_id, cc_srcs_t dst_id, int rsp_type,
|
|||
pmsg->rsp_id = rsp_id;
|
||||
pmsg->wait_flag = waited;
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, 0, 0, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, 0, 0, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG(DEB_F_PREFIX "rsp_type= %s rsp_id= %s waited = %d\n",
|
||||
DEB_F_PREFIX_ARGS(CC_API, fname),
|
||||
DEB_F_PREFIX_ARGS(CC_API, __FUNCTION__),
|
||||
rsp_type == RSP_START ? "RSP_START" : "RSP_COMPLETE",
|
||||
rsp_id == CC_REG_FAILOVER_RSP ? "REG_FAILOVER_RSP" : "REG_FALLBACK_RSP",
|
||||
waited);
|
||||
|
@ -1634,7 +1740,7 @@ cc_int_fail_fallback (cc_srcs_t src_id, cc_srcs_t dst_id, int rsp_type,
|
|||
if (cc_send_cmd_msg(REG_MGR_STATE_CHANGE, (cprBuffer_t) pmsg,
|
||||
sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1644,14 +1750,13 @@ cc_int_info (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
line_t line, string_t info_package, string_t content_type,
|
||||
string_t message_body)
|
||||
{
|
||||
static const char fname[] = "cc_int_info";
|
||||
cc_info_t *pmsg;
|
||||
|
||||
|
||||
pmsg = (cc_info_t *) cc_get_msg_buf(sizeof(*pmsg));
|
||||
if (!pmsg) {
|
||||
// nobody checks, CC_RC_ERROR, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_NO_MSG_BUFFER), __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1662,11 +1767,11 @@ cc_int_info (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
|||
pmsg->content_type = strlib_copy(content_type);
|
||||
pmsg->message_body = strlib_copy(message_body);
|
||||
|
||||
CC_DEBUG_ENTRY(fname, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
CC_DEBUG_ENTRY(__FUNCTION__, src_id, dst_id, call_id, line, cc_msg_name(pmsg->msg_id));
|
||||
|
||||
if (cc_send_msg((cprBuffer_t) pmsg, sizeof(*pmsg), dst_id) != CC_RC_SUCCESS) {
|
||||
// nobody checks the return code, so generate error message
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), fname);
|
||||
GSM_ERR_MSG(get_debug_string(CC_SEND_FAILURE), __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -218,7 +218,7 @@ static void dcsm_process_event_to_gsm (void *msg_ptr)
|
|||
fim_free_event(msg_ptr);
|
||||
|
||||
/* Release buffer too */
|
||||
cprReleaseBuffer(msg_ptr);
|
||||
cpr_free(msg_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -748,7 +748,7 @@ dcsm_shutdown (void)
|
|||
fim_free_event(msg_ptr);
|
||||
|
||||
/* Release buffer too */
|
||||
cprReleaseBuffer(msg_ptr);
|
||||
cpr_free(msg_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -435,7 +435,7 @@ fim_process_event (void *data, boolean cac_passed)
|
|||
callid_t bw_call_id;
|
||||
|
||||
FIM_DEBUG(DEB_L_C_F_PREFIX"Msg name = %s\n", DEB_L_C_F_PREFIX_ARGS(FIM, line, call_id, fname),
|
||||
cc_msg_name(msg_id));
|
||||
cc_msg_name(msg_id));
|
||||
|
||||
/*
|
||||
* Validate the incoming event.
|
||||
|
@ -465,6 +465,7 @@ fim_process_event (void *data, boolean cac_passed)
|
|||
fim_process_options_msg(data);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
if (platWlanISActive() && cac_passed == FALSE) {
|
||||
/* The WLAN will request for bandwidth only for the events received from
|
||||
|
@ -519,10 +520,12 @@ fim_process_event (void *data, boolean cac_passed)
|
|||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the call chain associated with this call_id.
|
||||
*/
|
||||
* Get the call chain associated with this call_id.
|
||||
*/
|
||||
call_chn = fim_get_call_chn_by_call_id(call_id);
|
||||
|
||||
if (call_chn == NULL) {
|
||||
/*
|
||||
* No call chain, so get a new call chain,
|
||||
|
@ -532,6 +535,14 @@ fim_process_event (void *data, boolean cac_passed)
|
|||
(event_id == CC_MSG_OFFHOOK) ||
|
||||
(event_id == CC_MSG_DIALSTRING) ||
|
||||
(event_id == CC_MSG_LINE) ||
|
||||
(event_id == CC_MSG_CREATEOFFER) ||
|
||||
(event_id == CC_MSG_CREATEANSWER) ||
|
||||
(event_id == CC_MSG_SETLOCALDESC) ||
|
||||
(event_id == CC_MSG_SETREMOTEDESC) ||
|
||||
(event_id == CC_MSG_SETPEERCONNECTION) ||
|
||||
(event_id == CC_MSG_ADDSTREAM) ||
|
||||
(event_id == CC_MSG_REMOVESTREAM) ||
|
||||
(event_id == CC_MSG_ADDCANDIDATE) ||
|
||||
((event_id == CC_MSG_FEATURE) &&
|
||||
((((cc_feature_t *) msg)->feature_id == CC_FEATURE_NEW_CALL)))) {
|
||||
call_chn = fim_get_new_call_chn(call_id);
|
||||
|
@ -607,7 +618,7 @@ fim_process_event (void *data, boolean cac_passed)
|
|||
if (fsm_event_filtered_by_ui_lock(event_id,
|
||||
((cc_feature_t *)msg)->feature_id)) {
|
||||
FIM_DEBUG(DEB_L_C_F_PREFIX" %s filtered by UI lock\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(FIM, line, call_id, fname),
|
||||
DEB_L_C_F_PREFIX_ARGS(FIM, line, call_id, fname),
|
||||
cc_feature_name(((cc_feature_t *)msg)->feature_id));
|
||||
return(TRUE);
|
||||
}
|
||||
|
@ -653,7 +664,7 @@ fim_process_event (void *data, boolean cac_passed)
|
|||
}
|
||||
|
||||
FIM_DEBUG(DEB_L_C_F_PREFIX" %s(%s:%s)\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(FIM, line, call_id, fname), fsm_type_name(icb->scb->type),
|
||||
DEB_L_C_F_PREFIX_ARGS(FIM, line, call_id, fname), fsm_type_name(icb->scb->type),
|
||||
fsm_state_name(fcb->fsm_type, event.state),
|
||||
cc_msg_name((cc_msgs_t) (event.event)));
|
||||
|
||||
|
@ -672,7 +683,7 @@ fim_process_event (void *data, boolean cac_passed)
|
|||
|
||||
case SM_RC_ERROR:
|
||||
FIM_DEBUG(DEB_L_C_F_PREFIX" fsm sm error(%d:%d)\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(FIM, line, call_id, fname), event.state, event.event);
|
||||
DEB_L_C_F_PREFIX_ARGS(FIM, line, call_id, fname), event.state, event.event);
|
||||
done = TRUE;
|
||||
cc_call_state(call_id, line, CC_STATE_UNKNOWN, NULL);
|
||||
break;
|
||||
|
|
|
@ -160,7 +160,7 @@ fsm_clear_cac_data (cac_data_t *cac_data)
|
|||
fim_free_event(cac_data->msg_ptr);
|
||||
|
||||
/* Release buffer too */
|
||||
cprReleaseBuffer(cac_data->msg_ptr);
|
||||
cpr_free(cac_data->msg_ptr);
|
||||
|
||||
cpr_free(cac_data);
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -61,6 +61,7 @@
|
|||
#include "dialplanint.h"
|
||||
#include "kpmlmap.h"
|
||||
#include "subapi.h"
|
||||
#include "platform_api.h"
|
||||
|
||||
static void sub_process_feature_msg(uint32_t cmd, void *msg);
|
||||
static void sub_process_feature_notify(ccsip_sub_not_data_t *msg, callid_t call_id,
|
||||
|
@ -104,7 +105,7 @@ gsm_get_initialize_state (void)
|
|||
cprBuffer_t
|
||||
gsm_get_buffer (uint16_t size)
|
||||
{
|
||||
return cprGetBuffer(size);
|
||||
return cpr_malloc(size);
|
||||
}
|
||||
|
||||
|
||||
|
@ -261,7 +262,7 @@ gsm_process_timer_expiration (void *msg)
|
|||
if (timeout_msg != NULL) {
|
||||
/* Let state machine handle glare timer expiration */
|
||||
gsm_process_msg(GSM_GSM, timeout_msg);
|
||||
cprReleaseBuffer(timeout_msg);
|
||||
cpr_free(timeout_msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -312,7 +313,6 @@ GSMTask (void *arg)
|
|||
if (platThreadInit("GSMTask") != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust relative priority of GSM thread.
|
||||
*/
|
||||
|
@ -407,7 +407,7 @@ GSMTask (void *arg)
|
|||
|
||||
cprReleaseSysHeader(syshdr);
|
||||
if (release_msg == TRUE) {
|
||||
cprReleaseBuffer(msg);
|
||||
cpr_free(msg);
|
||||
}
|
||||
|
||||
/* Check if there are pending messages for dcsm
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -37,6 +37,9 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "cpr_types.h"
|
||||
#include "cpr_rand.h"
|
||||
#include "sdp.h"
|
||||
|
@ -435,6 +438,8 @@ gsmsdp_is_supported_session_parm (const char *session_parms)
|
|||
{
|
||||
int len, wsh;
|
||||
const char *parm_ptr;
|
||||
long strtol_result;
|
||||
char *strtol_end;
|
||||
|
||||
if (session_parms == NULL) {
|
||||
/* No session parameters, this is acceptable */
|
||||
|
@ -447,11 +452,16 @@ gsmsdp_is_supported_session_parm (const char *session_parms)
|
|||
len = strlen(session_parms);
|
||||
if (strcmp(session_parms, "WSH=") && (len == 6)) {
|
||||
parm_ptr = &session_parms[sizeof("WSH=") - 1]; /* point the wsh value */
|
||||
wsh = atoi(parm_ptr);
|
||||
|
||||
errno = 0;
|
||||
strtol_result = strtol(parm_ptr, &strtol_end, 10);
|
||||
|
||||
/* minimum value of WSH is 64 */
|
||||
if (wsh >= 64) {
|
||||
return (TRUE);
|
||||
if (errno || parm_ptr == strtol_end || strtol_result < 64 || strtol_result > INT_MAX) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
/* Other parameters are not supported */
|
||||
return (FALSE);
|
||||
|
@ -980,7 +990,9 @@ gsmsdp_negotiate_offer_crypto (fsmdef_dcb_t *dcb_p, cc_sdp_t *cc_sdp_p,
|
|||
sdp_transport_e negotiated_transport = SDP_TRANSPORT_INVALID;
|
||||
void *sdp_p = cc_sdp_p->dest_sdp;
|
||||
uint16_t level;
|
||||
int sdpmode = 0;
|
||||
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
level = media->level;
|
||||
*crypto_inst = 0;
|
||||
remote_transport = sdp_get_media_transport(sdp_p, level);
|
||||
|
@ -993,9 +1005,10 @@ gsmsdp_negotiate_offer_crypto (fsmdef_dcb_t *dcb_p, cc_sdp_t *cc_sdp_p,
|
|||
break;
|
||||
|
||||
case SDP_TRANSPORT_RTPSAVP:
|
||||
|
||||
/* Remote offer SRTP for media transport */
|
||||
if ((sip_regmgr_get_sec_level(dcb_p->line) == ENCRYPTED) &&
|
||||
FSM_CHK_FLAGS(media->flags, FSM_MEDIA_F_SUPPORT_SECURITY)) {
|
||||
if (((sip_regmgr_get_sec_level(dcb_p->line) == ENCRYPTED) &&
|
||||
FSM_CHK_FLAGS(media->flags, FSM_MEDIA_F_SUPPORT_SECURITY)) || sdpmode) {
|
||||
/* The signalling with this line is encrypted, try to use SRTP */
|
||||
if (gsmsdp_select_offer_crypto(dcb_p, sdp_p, level, crypto_inst)) {
|
||||
/* Found a suitable crypto line from the remote offer */
|
||||
|
@ -1014,6 +1027,15 @@ gsmsdp_negotiate_offer_crypto (fsmdef_dcb_t *dcb_p, cc_sdp_t *cc_sdp_p,
|
|||
}
|
||||
break;
|
||||
|
||||
case SDP_TRANSPORT_RTPSAVPF:
|
||||
/* Remote offers Extended SRTP for media transport */
|
||||
negotiated_transport = SDP_TRANSPORT_RTPSAVPF;
|
||||
break;
|
||||
|
||||
case SDP_TRANSPORT_SCTPDTLS:
|
||||
negotiated_transport = SDP_TRANSPORT_SCTPDTLS;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown */
|
||||
break;
|
||||
|
@ -1087,6 +1109,14 @@ gsmsdp_negotiate_answer_crypto (fsmdef_dcb_t *dcb_p, cc_sdp_t *cc_sdp_p,
|
|||
}
|
||||
break;
|
||||
|
||||
case SDP_TRANSPORT_RTPSAVPF:
|
||||
negotiated_transport = SDP_TRANSPORT_RTPSAVPF;
|
||||
break;
|
||||
|
||||
case SDP_TRANSPORT_SCTPDTLS:
|
||||
negotiated_transport = SDP_TRANSPORT_SCTPDTLS;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown */
|
||||
break;
|
||||
|
@ -1312,20 +1342,31 @@ void
|
|||
gsmsdp_init_sdp_media_transport (fsmdef_dcb_t *dcb_p, void *sdp_p,
|
||||
fsmdef_media_t *media)
|
||||
{
|
||||
int rtpsavpf = 0;
|
||||
int sdpmode = 0;
|
||||
|
||||
/* Initialize crypto context */
|
||||
gsmsdp_init_crypto_context(media);
|
||||
|
||||
if ((sip_regmgr_get_sec_level(dcb_p->line) != ENCRYPTED) ||
|
||||
config_get_value(CFGID_RTPSAVPF, &rtpsavpf, sizeof(rtpsavpf));
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
|
||||
if (SDP_MEDIA_APPLICATION == media->type) {
|
||||
media->transport = SDP_TRANSPORT_SCTPDTLS;
|
||||
} else if (rtpsavpf) {
|
||||
media->transport = SDP_TRANSPORT_RTPSAVPF;
|
||||
} else if (sdpmode) {
|
||||
media->transport = SDP_TRANSPORT_RTPSAVP;
|
||||
} else if ((sip_regmgr_get_sec_level(dcb_p->line) != ENCRYPTED) ||
|
||||
(!FSM_CHK_FLAGS(media->flags, FSM_MEDIA_F_SUPPORT_SECURITY))) {
|
||||
/*
|
||||
* The signaling is not encrypted or this media can not support
|
||||
* security.
|
||||
* security.
|
||||
*/
|
||||
media->transport = SDP_TRANSPORT_RTPAVP;
|
||||
return;
|
||||
} else {
|
||||
media->transport = SDP_TRANSPORT_RTPSAVP;
|
||||
}
|
||||
|
||||
media->transport = SDP_TRANSPORT_RTPSAVP;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1446,7 +1487,7 @@ gsmsdp_update_local_sdp_media_transport (fsmdef_dcb_t *dcb_p, void *sdp_p,
|
|||
{
|
||||
const char *fname = "gsmsdp_update_local_sdp_media_transport";
|
||||
sdp_srtp_crypto_suite_t crypto_suite;
|
||||
uint16_t level;
|
||||
uint16_t level;
|
||||
|
||||
level = media->level;
|
||||
/* Get the current transport before delete the media line */
|
||||
|
@ -1794,10 +1835,7 @@ gsmsdp_is_crypto_ready (fsmdef_media_t *media, boolean rx)
|
|||
* allowing the Rx/Tx to be opened. If we did not offer (we received
|
||||
* an offered SDP instead then we should have key negotiated).
|
||||
*/
|
||||
if (media->transport == SDP_TRANSPORT_RTPAVP) {
|
||||
/*
|
||||
* The local did not offer SRTP.
|
||||
*/
|
||||
if (media->transport == SDP_TRANSPORT_RTPAVP || media->transport == SDP_TRANSPORT_RTPSAVPF) {
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
@ -1848,7 +1886,7 @@ gsmsdp_is_media_encrypted (fsmdef_dcb_t *dcb_p)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (media->transport == SDP_TRANSPORT_RTPSAVP) {
|
||||
if (media->transport == SDP_TRANSPORT_RTPSAVP || media->transport == SDP_TRANSPORT_RTPSAVPF) {
|
||||
num_encrypted++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,9 @@ typedef enum {
|
|||
#define FSMDEF_NO_DCB (NULL)
|
||||
#define FSMDEF_ERR_ONHOOK_TMR_SECS (20)
|
||||
|
||||
#define FSMDEF_MAX_DIGEST_ALG_LEN 10
|
||||
#define FSMDEF_MAX_DIGEST_LEN 32 * 3
|
||||
|
||||
// Should match define for SIP stack MAX_SIP_URL_LENGTH
|
||||
#define FSMDEF_MAX_CALLER_ID_LEN (256)
|
||||
|
||||
|
@ -148,6 +151,8 @@ typedef struct fsmdef_negotiated_crypto_t_ {
|
|||
vcm_crypto_key_t tx_key; /* tx key */
|
||||
vcm_crypto_key_t rx_key; /* rx key */
|
||||
uint32_t flags; /* misc. flags. */
|
||||
char algorithm[FSMDEF_MAX_DIGEST_ALG_LEN];
|
||||
char digest[FSMDEF_MAX_DIGEST_LEN];
|
||||
} fsmdef_negotiated_crypto_t;
|
||||
|
||||
/*
|
||||
|
@ -160,6 +165,7 @@ typedef struct fsmdef_previous_sdp_ {
|
|||
int32_t payload_type;
|
||||
int32_t local_payload_type;
|
||||
uint16_t packetization_period;
|
||||
uint16_t max_packetization_period;
|
||||
sdp_direction_e direction;
|
||||
int32_t tias_bw;
|
||||
int32_t profile_level;
|
||||
|
@ -181,6 +187,7 @@ typedef struct fsmdef_media_t_ {
|
|||
int32_t avt_payload_type;
|
||||
vcm_vad_t vad;
|
||||
uint16_t packetization_period;
|
||||
uint16_t max_packetization_period;
|
||||
uint16_t mode;
|
||||
uint16_t level;
|
||||
boolean direction_set;
|
||||
|
@ -245,6 +252,31 @@ typedef struct fsmdef_media_t_ {
|
|||
int32_t profile_level;
|
||||
|
||||
void *video;
|
||||
|
||||
char **candidatesp;
|
||||
int candidate_ct;
|
||||
|
||||
/*
|
||||
* rtcp-mux indicates media stream is muxed for RTP and RTCP
|
||||
*/
|
||||
boolean rtcp_mux;
|
||||
|
||||
/*
|
||||
* port number used in m= data channel line
|
||||
*/
|
||||
uint16_t sctp_port;
|
||||
|
||||
/*
|
||||
* Data Channel properties
|
||||
*/
|
||||
uint32 streams;
|
||||
char *protocol;
|
||||
|
||||
/*
|
||||
* List of active lists of payloads negotiated
|
||||
*/
|
||||
vcm_media_payload_type_t* payloads;
|
||||
int32_t num_payloads;
|
||||
} fsmdef_media_t;
|
||||
|
||||
struct fsm_fcb_t_;
|
||||
|
@ -408,6 +440,16 @@ typedef struct {
|
|||
*/
|
||||
cc_media_cap_table_t *media_cap_tbl;
|
||||
|
||||
/*
|
||||
* Holds the remote stream track information to be passed to UI
|
||||
*/
|
||||
cc_media_remote_stream_table_t *remote_media_stream_tbl;
|
||||
|
||||
/*
|
||||
* Holds the local stream track information passed in from the UI
|
||||
*/
|
||||
cc_media_local_track_table_t *local_media_track_tbl;
|
||||
|
||||
#define FSMDEF_F_HOLD_REQ_PENDING (1 << 0)/* hold feature pending */
|
||||
#define FSMDEF_F_XFER_COMPLETE (1 << 1)/* hold feature pending */
|
||||
uint32_t flags; /* misc. flags. */
|
||||
|
@ -418,6 +460,16 @@ typedef struct {
|
|||
sdp_direction_e video_pref;
|
||||
unsigned int callref; /* Callref (CI) from CUCM */
|
||||
|
||||
char peerconnection[PC_HANDLE_SIZE]; /* A handle to the peerconnection */
|
||||
boolean peerconnection_set;
|
||||
|
||||
char *ice_ufrag;
|
||||
char *ice_pwd;
|
||||
char ice_default_candidate_addr[MAX_IPADDR_STR_LEN];
|
||||
|
||||
char digest_alg[FSMDEF_MAX_DIGEST_ALG_LEN];
|
||||
char digest[FSMDEF_MAX_DIGEST_LEN];
|
||||
|
||||
} fsmdef_dcb_t;
|
||||
|
||||
typedef enum fsm_types_t_ {
|
||||
|
@ -600,6 +652,7 @@ void fsmdef_init_dcb(fsmdef_dcb_t *dcb, callid_t call_id,
|
|||
fsmdef_call_types_t call_type,
|
||||
const char *called_number, line_t line,
|
||||
fsm_fcb_t *fcb);
|
||||
cc_causes_t fsm_set_fcb_dcbs (fsmdef_dcb_t *dcb);
|
||||
fsmdef_dcb_t *fsmdef_get_new_dcb(callid_t call_id);
|
||||
void fsmdef_init(void);
|
||||
int fsmdef_get_active_call_cnt(callid_t callId);
|
||||
|
@ -684,13 +737,20 @@ void fsmdef_call_cc_state_dialing(fsmdef_dcb_t *dcb, boolean suppressStutter);
|
|||
#define FSM_GET_CACHED_ORIENTATION(dcb) (dcb->orientation)
|
||||
#define FSM_SET_CACHED_ORIENTATION(dcb, value) (dcb->orientation = value)
|
||||
#define FSM_NEGOTIATED_CRYPTO_ALGORITHM_ID(media) \
|
||||
((media->transport == SDP_TRANSPORT_RTPSAVP) ? \
|
||||
((media->transport == SDP_TRANSPORT_RTPSAVP || \
|
||||
media->transport == SDP_TRANSPORT_RTPSAVPF) ? \
|
||||
media->negotiated_crypto.algorithmID : VCM_NO_ENCRYPTION)
|
||||
#define FSM_NEGOTIATED_CRYPTO_RX_KEY(media) \
|
||||
&media->negotiated_crypto.rx_key
|
||||
#define FSM_NEGOTIATED_CRYPTO_TX_KEY(media) \
|
||||
&media->negotiated_crypto.tx_key
|
||||
|
||||
#define FSM_NEGOTIATED_CRYPTO_DIGEST_ALGORITHM(media) \
|
||||
media->negotiated_crypto.algorithm
|
||||
|
||||
#define FSM_NEGOTIATED_CRYPTO_DIGEST(media) \
|
||||
media->negotiated_crypto.digest
|
||||
|
||||
int fsmutil_get_call_attr(fsmdef_dcb_t *dcb, line_t line, callid_t call_id);
|
||||
uint16_t fsmutil_get_ci_id(line_t line);
|
||||
void fsmutil_init_ci_map(void);
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
for (media = GSMSDP_FIRST_MEDIA_ENTRY(dcb); (media != NULL); \
|
||||
media = GSMSDP_NEXT_MEDIA_ENTRY(media))
|
||||
|
||||
cc_causes_t gsmsdp_create_local_sdp(fsmdef_dcb_t *dcb_p);
|
||||
cc_causes_t gsmsdp_create_local_sdp(fsmdef_dcb_t *dcb_p, boolean force_streams_enabled);
|
||||
void gsmsdp_create_options_sdp(cc_sdp_t **sdp_pp);
|
||||
void gsmsdp_reset_local_sdp_media(fsmdef_dcb_t *dcb, fsmdef_media_t *media,
|
||||
boolean hold);
|
||||
|
@ -80,6 +80,13 @@ cc_causes_t gsmsdp_negotiate_answer_sdp(fsm_fcb_t *fcb,
|
|||
cc_causes_t gsmsdp_negotiate_offer_sdp(fsm_fcb_t *fcb,
|
||||
cc_msgbody_info_t *msg_body,
|
||||
boolean init);
|
||||
cc_causes_t gsmsdp_process_offer_sdp(fsm_fcb_t *fcb,
|
||||
cc_msgbody_info_t *msg_body,
|
||||
boolean init);
|
||||
cc_causes_t
|
||||
gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p,
|
||||
boolean initial_offer, boolean offer, boolean notify_stream_added);
|
||||
|
||||
boolean gsmsdp_sdp_differs_from_previous_sdp(boolean rcv_only,
|
||||
fsmdef_media_t *media);
|
||||
cc_causes_t gsmsdp_encode_sdp(cc_sdp_t *sdp_p, cc_msgbody_info_t *msg_body);
|
||||
|
@ -134,5 +141,11 @@ extern boolean gsmsdp_handle_media_cap_change(fsmdef_dcb_t *dcb_p,
|
|||
extern boolean gsmsdp_update_local_sdp_media_capability(fsmdef_dcb_t *dcb_p,
|
||||
boolean refresh, boolean hold);
|
||||
boolean is_gsmsdp_media_ip_updated_to_latest( fsmdef_dcb_t * dcb );
|
||||
|
||||
void gsmsdp_add_remote_stream(uint16_t idx, int pc_stream_id, fsmdef_dcb_t * dcb, fsmdef_media_t *media);
|
||||
cc_causes_t gsmsdp_install_peer_ice_attributes(fsm_fcb_t *fcb_p);
|
||||
cc_causes_t gsmsdp_configure_dtls_data_attributes(fsm_fcb_t *fcb_p);
|
||||
cc_causes_t gsmsdp_find_level_from_mid(fsmdef_dcb_t * dcb, const char * mid, uint16_t *level);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "cpr_types.h"
|
||||
#include "ccapi.h"
|
||||
#include "uiapi.h"
|
||||
#include "fsm.h"
|
||||
|
||||
|
||||
#define LSM_NO_LINE (0)
|
||||
|
@ -140,6 +141,7 @@ void lsm_ui_display_status(const char *pStatusStr, line_t line,
|
|||
callid_t call_id);
|
||||
string_t lsm_parse_displaystr(string_t displaystr);
|
||||
void lsm_speaker_mode(short mode);
|
||||
void lsm_add_remote_stream (line_t line, callid_t call_id, fsmdef_media_t *media, int *pc_stream_id);
|
||||
|
||||
#ifdef _WIN32
|
||||
void terminate_active_calls(void);
|
||||
|
@ -206,5 +208,8 @@ void
|
|||
lsm_util_tone_start_with_speaker_as_backup (vcm_tones_t tone, short alert_info,
|
||||
cc_call_handle_t call_handle, groupid_t group_id,
|
||||
streamid_t stream_id, uint16_t direction);
|
||||
|
||||
void lsm_data_channel_negotiated (line_t line, callid_t call_id, fsmdef_media_t *media, int *pc_stream_id);
|
||||
|
||||
#endif //_LSM_H_
|
||||
|
||||
|
|
|
@ -394,8 +394,8 @@ void lsm_update_gcid (callid_t call_id, char * gcid)
|
|||
sstrncpy(lcb->gcid, gcid, CC_GCID_LEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* This function will be invoked by DEF SM.
|
||||
* it will check if there is a RINGIN call
|
||||
|
@ -612,7 +612,7 @@ lsm_open_rx (lsm_lcb_t *lcb, cc_action_data_open_rcv_t *data,
|
|||
int port_allocated = 0;
|
||||
cc_rcs_t rc = CC_RC_ERROR;
|
||||
fsmdef_dcb_t *dcb;
|
||||
int roapproxy;
|
||||
int sdpmode = 0;
|
||||
|
||||
dcb = lcb->dcb;
|
||||
if (dcb == NULL) {
|
||||
|
@ -642,52 +642,61 @@ lsm_open_rx (lsm_lcb_t *lcb, cc_action_data_open_rcv_t *data,
|
|||
LSM_DEBUG(get_debug_string(LSM_DBG_INT1), lcb->call_id, lcb->line, fname,
|
||||
"requested port", data->port);
|
||||
|
||||
|
||||
sdpmode = 0;
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
|
||||
if (data->keep == TRUE) {
|
||||
|
||||
roapproxy = 0;
|
||||
config_get_value(CFGID_ROAPPROXY, &roapproxy, sizeof(roapproxy));
|
||||
if (roapproxy == FALSE) {
|
||||
|
||||
//Todo IPv6: Add interface call for IPv6
|
||||
(void) vcmRxOpen(media->cap_index, dcb->group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(lcb->line, lcb->call_id, lcb->ui_id), data->port,
|
||||
media->is_multicast ? &media->dest_addr:&media->src_addr, data->is_multicast,
|
||||
&port_allocated);
|
||||
if (port_allocated != -1) {
|
||||
data->port = (uint16_t)port_allocated;
|
||||
rc = CC_RC_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (CC_AUDIO_1 == media->cap_index )
|
||||
data->port = gROAPSDP.audioPort;
|
||||
if (CC_VIDEO_1 == media->cap_index )
|
||||
data->port = gROAPSDP.videoPort;
|
||||
|
||||
rc = CC_RC_SUCCESS;
|
||||
}
|
||||
if (sdpmode && strlen(dcb->peerconnection)) {
|
||||
/* If we are doing ICE, don't try to re-open */
|
||||
port_allocated = data->port;
|
||||
}
|
||||
else {
|
||||
//Todo IPv6: Add interface call for IPv6
|
||||
(void) vcmRxOpen(media->cap_index, dcb->group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(lcb->line, lcb->call_id, lcb->ui_id), data->port,
|
||||
media->is_multicast ? &media->dest_addr:&media->src_addr, data->is_multicast,
|
||||
&port_allocated);
|
||||
}
|
||||
if (port_allocated != -1) {
|
||||
data->port = (uint16_t)port_allocated;
|
||||
rc = CC_RC_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
|
||||
roapproxy = 0;
|
||||
config_get_value(CFGID_ROAPPROXY, &roapproxy, sizeof(roapproxy));
|
||||
if (sdpmode) {
|
||||
if (!strlen(dcb->peerconnection)) {
|
||||
vcmRxAllocPort(media->cap_index, dcb->group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(lcb->line, lcb->call_id, lcb->ui_id),
|
||||
data->port,
|
||||
&port_allocated);
|
||||
if (port_allocated != -1) {
|
||||
data->port = (uint16_t)port_allocated;
|
||||
rc = CC_RC_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
char **candidates;
|
||||
int candidate_ct;
|
||||
char *default_addr;
|
||||
|
||||
if (roapproxy == FALSE) {
|
||||
vcmRxAllocICE(media->cap_index, dcb->group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(lcb->line, lcb->call_id, lcb->ui_id),
|
||||
dcb->peerconnection,
|
||||
media->level,
|
||||
&default_addr, &port_allocated,
|
||||
&candidates, &candidate_ct);
|
||||
|
||||
vcmRxAllocPort(media->cap_index, dcb->group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(lcb->line, lcb->call_id, lcb->ui_id), data->port,
|
||||
&port_allocated);
|
||||
if (port_allocated != -1) {
|
||||
data->port = (uint16_t)port_allocated;
|
||||
rc = CC_RC_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
if (CC_AUDIO_1 == media->cap_index )
|
||||
data->port = gROAPSDP.audioPort;
|
||||
if (CC_VIDEO_1 == media->cap_index )
|
||||
data->port = gROAPSDP.videoPort;
|
||||
// Check that we got a valid address and port
|
||||
if (default_addr && (strlen(default_addr) > 0) && (port_allocated != -1)) {
|
||||
sstrncpy(dcb->ice_default_candidate_addr, default_addr, sizeof(dcb->ice_default_candidate_addr));
|
||||
|
||||
rc = CC_RC_SUCCESS;
|
||||
}
|
||||
data->port = (uint16_t)port_allocated;
|
||||
media->candidate_ct = candidate_ct;
|
||||
media->candidatesp = candidates;
|
||||
rc = CC_RC_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LSM_DEBUG(get_debug_string(LSM_DBG_INT1), lcb->call_id, lcb->line, fname,
|
||||
|
@ -745,7 +754,7 @@ lsm_close_rx (lsm_lcb_t *lcb, boolean refresh, fsmdef_media_t *media)
|
|||
static const char fname[] = "lsm_close_rx";
|
||||
fsmdef_media_t *start_media, *end_media;
|
||||
fsmdef_dcb_t *dcb;
|
||||
int roapproxy;
|
||||
int sdpmode = 0;
|
||||
|
||||
dcb = lcb->dcb;
|
||||
if (dcb == NULL) {
|
||||
|
@ -781,13 +790,12 @@ lsm_close_rx (lsm_lcb_t *lcb, boolean refresh, fsmdef_media_t *media)
|
|||
dcb->line, fname, "port closed",
|
||||
media->src_port);
|
||||
|
||||
roapproxy = 0;
|
||||
config_get_value(CFGID_ROAPPROXY, &roapproxy, sizeof(roapproxy));
|
||||
if (roapproxy == FALSE) {
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
if (!sdpmode) {
|
||||
|
||||
vcmRxClose(media->cap_index, dcb->group_id, media->refid,
|
||||
vcmRxClose(media->cap_index, dcb->group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(lcb->line, lcb->call_id, lcb->ui_id));
|
||||
}
|
||||
}
|
||||
media->rcv_chan = FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -820,7 +828,7 @@ lsm_close_tx (lsm_lcb_t *lcb, boolean refresh, fsmdef_media_t *media)
|
|||
fsmdef_media_t *start_media, *end_media;
|
||||
fsmdef_dcb_t *dcb;
|
||||
static const char fname[] = "lsm_close_tx";
|
||||
int roapproxy;
|
||||
int sdpmode = 0;
|
||||
|
||||
dcb = lcb->dcb;
|
||||
if (dcb == NULL) {
|
||||
|
@ -830,6 +838,8 @@ lsm_close_tx (lsm_lcb_t *lcb, boolean refresh, fsmdef_media_t *media)
|
|||
LSM_DEBUG(DEB_L_C_F_PREFIX"called with refresh set to %d\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(LSM, dcb->line, dcb->call_id, fname), refresh);
|
||||
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
|
||||
if (media == NULL) {
|
||||
/* NULL value of the given media indicates for all media */
|
||||
start_media = GSMSDP_FIRST_MEDIA_ENTRY(dcb);
|
||||
|
@ -851,23 +861,20 @@ lsm_close_tx (lsm_lcb_t *lcb, boolean refresh, fsmdef_media_t *media)
|
|||
(refresh &&
|
||||
gsmsdp_sdp_differs_from_previous_sdp(FALSE, media))) {
|
||||
|
||||
roapproxy = 0;
|
||||
config_get_value(CFGID_ROAPPROXY, &roapproxy, sizeof(roapproxy));
|
||||
if (roapproxy == FALSE) {
|
||||
|
||||
if (!sdpmode) {
|
||||
vcmTxClose(media->cap_index, dcb->group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(lcb->line, lcb->call_id, lcb->ui_id));
|
||||
}
|
||||
}
|
||||
|
||||
if (dcb->active_tone == VCM_MONITORWARNING_TONE || dcb->active_tone == VCM_RECORDERWARNING_TONE) {
|
||||
LSM_DEBUG(DEB_L_C_F_PREFIX"%s: Found active_tone: %d being played, current monrec_tone_action: %d. Need stop tone. \n",
|
||||
LSM_DEBUG(DEB_L_C_F_PREFIX"%s: Found active_tone: %d being played, current monrec_tone_action: %d. Need stop tone. \n",
|
||||
DEB_L_C_F_PREFIX_ARGS(LSM, dcb->line, dcb->call_id, fname), fname,
|
||||
dcb->active_tone, dcb->monrec_tone_action);
|
||||
(void) lsm_stop_tone(lcb, NULL);
|
||||
}
|
||||
}
|
||||
media->xmit_chan = FALSE;
|
||||
LSM_DEBUG(DEB_L_C_F_PREFIX"closed",
|
||||
DEB_L_C_F_PREFIX_ARGS(LSM, dcb->line, dcb->call_id, fname));
|
||||
DEB_L_C_F_PREFIX_ARGS(LSM, dcb->line, dcb->call_id, fname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -905,8 +912,9 @@ lsm_rx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||
boolean has_checked_conference = FALSE;
|
||||
fsmdef_dcb_t *dcb, *grp_id_dcb;
|
||||
vcm_mediaAttrs_t attrs;
|
||||
int roapproxy;
|
||||
|
||||
int sdpmode = 0;
|
||||
int pc_stream_id = 0;
|
||||
int pc_track_id = 0;
|
||||
attrs.video.opaque = NULL;
|
||||
|
||||
dcb = lcb->dcb;
|
||||
|
@ -924,7 +932,7 @@ lsm_rx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||
start_media = media;
|
||||
end_media = media;
|
||||
}
|
||||
|
||||
|
||||
/* Start receive channel for the media(s) */
|
||||
GSMSDP_FOR_MEDIA_LIST(media, start_media, end_media, dcb) {
|
||||
if (!GSMSDP_MEDIA_ENABLED(media)) {
|
||||
|
@ -976,7 +984,7 @@ lsm_rx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||
group_id = grp_id_dcb->group_id;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case MONITOR:
|
||||
case LOCAL_CONF:
|
||||
//AgentGreeting is MIX RXBOTH, SilentMonitoring is MIX TXBOTH
|
||||
|
@ -1007,41 +1015,55 @@ lsm_rx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||
media->src_port = open_rcv.port;
|
||||
}
|
||||
|
||||
/* TODO(ekr@rtfm.com): Needs changing for when we have > 2 streams */
|
||||
if ( media->cap_index == CC_VIDEO_1 ) {
|
||||
attrs.video.opaque = media->video;
|
||||
pc_stream_id = 1;
|
||||
} else {
|
||||
attrs.audio.packetization_period = media->packetization_period;
|
||||
attrs.audio.max_packetization_period = media->max_packetization_period;
|
||||
attrs.audio.avt_payload_type = media->avt_payload_type;
|
||||
attrs.audio.mixing_mode = mix_mode;
|
||||
attrs.audio.mixing_party = mix_party;
|
||||
pc_stream_id = 0;
|
||||
}
|
||||
pc_track_id = 0;
|
||||
dcb->cur_video_avail &= ~CC_ATTRIB_CAST;
|
||||
if (media->local_dynamic_payload_type_value == RTP_NONE) {
|
||||
media->local_dynamic_payload_type_value = media->payload;
|
||||
}
|
||||
|
||||
dcb->cur_video_avail &= ~CC_ATTRIB_CAST;
|
||||
if (media->local_dynamic_payload_type_value == RTP_NONE) {
|
||||
media->local_dynamic_payload_type_value = media->payload;
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
if (dcb->peerconnection) {
|
||||
ret_val = vcmRxStartICE(media->cap_index, group_id, media->refid,
|
||||
media->level,
|
||||
pc_stream_id,
|
||||
pc_track_id,
|
||||
lsm_get_ms_ui_call_handle(dcb->line, call_id, CC_NO_CALL_ID),
|
||||
dcb->peerconnection,
|
||||
media->num_payloads,
|
||||
media->payloads,
|
||||
FSM_NEGOTIATED_CRYPTO_DIGEST_ALGORITHM(media),
|
||||
FSM_NEGOTIATED_CRYPTO_DIGEST(media),
|
||||
&attrs);
|
||||
} else if (!sdpmode) {
|
||||
ret_val = vcmRxStart(media->cap_index, group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(dcb->line, call_id, CC_NO_CALL_ID),
|
||||
vcmRtpToMediaPayload(media->payload,
|
||||
media->local_dynamic_payload_type_value,
|
||||
media->mode),
|
||||
media->is_multicast ? &media->dest_addr:&media->src_addr,
|
||||
port,
|
||||
FSM_NEGOTIATED_CRYPTO_ALGORITHM_ID(media),
|
||||
FSM_NEGOTIATED_CRYPTO_RX_KEY(media),
|
||||
&attrs);
|
||||
if (ret_val == -1) {
|
||||
dcb->dsp_out_of_resources = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
roapproxy = 0;
|
||||
config_get_value(CFGID_ROAPPROXY, &roapproxy, sizeof(roapproxy));
|
||||
if (roapproxy == FALSE) {
|
||||
|
||||
ret_val = vcmRxStart(media->cap_index, group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(dcb->line, call_id, CC_NO_CALL_ID),
|
||||
vcmRtpToMediaPayload(media->payload,
|
||||
media->local_dynamic_payload_type_value,
|
||||
media->mode),
|
||||
media->is_multicast ? &media->dest_addr:&media->src_addr,
|
||||
port,
|
||||
FSM_NEGOTIATED_CRYPTO_ALGORITHM_ID(media),
|
||||
FSM_NEGOTIATED_CRYPTO_RX_KEY(media),
|
||||
&attrs);
|
||||
if (ret_val == -1) {
|
||||
dcb->dsp_out_of_resources = TRUE;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ret_val = CC_RC_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret_val = CC_RC_ERROR;
|
||||
}
|
||||
|
||||
lsm_update_dscp_value(dcb);
|
||||
|
||||
|
@ -1103,7 +1125,9 @@ lsm_tx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||
boolean has_checked_conference = FALSE;
|
||||
fsmdef_dcb_t *dcb;
|
||||
vcm_mediaAttrs_t attrs;
|
||||
int roapproxy;
|
||||
int sdpmode;
|
||||
long strtol_result;
|
||||
char *strtol_end;
|
||||
|
||||
attrs.video.opaque = NULL;
|
||||
|
||||
|
@ -1191,7 +1215,18 @@ lsm_tx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||
media->vad = VCM_VAD_OFF;
|
||||
} else {
|
||||
config_get_string(CFGID_ENABLE_VAD, tmp, sizeof(tmp));
|
||||
media->vad = (vcm_vad_t) atoi(tmp);
|
||||
|
||||
errno = 0;
|
||||
|
||||
strtol_result = strtol(tmp, &strtol_end, 10);
|
||||
|
||||
if (errno || tmp == strtol_end ||
|
||||
strtol_result < VCM_VAD_OFF || strtol_result > VCM_VAD_ON) {
|
||||
LSM_ERR_MSG("%s parse error of vad: %s", __FUNCTION__, tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
media->vad = (vcm_vad_t) strtol_result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1199,9 +1234,9 @@ lsm_tx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||
* the SDP for the remote end.
|
||||
*/
|
||||
|
||||
roapproxy = 0;
|
||||
config_get_value(CFGID_ROAPPROXY, &roapproxy, sizeof(roapproxy));
|
||||
if (roapproxy == FALSE) {
|
||||
sdpmode = 0;
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
if (!sdpmode) {
|
||||
|
||||
if (vcmTxOpen(media->cap_index, dcb->group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(lcb->line, lcb->call_id, lcb->ui_id)) != 0) {
|
||||
|
@ -1222,6 +1257,7 @@ lsm_tx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||
|
||||
} else if ( CC_IS_AUDIO(media->cap_index)){
|
||||
attrs.audio.packetization_period = media->packetization_period;
|
||||
attrs.audio.max_packetization_period = media->max_packetization_period;
|
||||
attrs.audio.avt_payload_type = media->avt_payload_type;
|
||||
attrs.audio.vad = media->vad;
|
||||
attrs.audio.mixing_mode = mix_mode;
|
||||
|
@ -1230,31 +1266,52 @@ lsm_tx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||
|
||||
dcb->cur_video_avail &= ~CC_ATTRIB_CAST;
|
||||
|
||||
roapproxy = 0;
|
||||
config_get_value(CFGID_ROAPPROXY, &roapproxy, sizeof(roapproxy));
|
||||
if (roapproxy == FALSE) {
|
||||
|
||||
if (vcmTxStart(media->cap_index, group_id,
|
||||
media->refid,
|
||||
lsm_get_ms_ui_call_handle(dcb->line, call_id, CC_NO_CALL_ID),
|
||||
vcmRtpToMediaPayload(media->payload,
|
||||
media->remote_dynamic_payload_type_value,
|
||||
media->mode),
|
||||
(short)dscp,
|
||||
&media->src_addr,
|
||||
media->src_port,
|
||||
&media->dest_addr,
|
||||
media->dest_port,
|
||||
FSM_NEGOTIATED_CRYPTO_ALGORITHM_ID(media),
|
||||
FSM_NEGOTIATED_CRYPTO_TX_KEY(media),
|
||||
&attrs) == -1)
|
||||
{
|
||||
LSM_DEBUG(DEB_L_C_F_PREFIX"%s: vcmTxStart failed\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(LSM, dcb->line, dcb->call_id, fname1), fname);
|
||||
dcb->dsp_out_of_resources = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!strlen(dcb->peerconnection)){
|
||||
if (vcmTxStart(media->cap_index, group_id,
|
||||
media->refid,
|
||||
lsm_get_ms_ui_call_handle(dcb->line, call_id, CC_NO_CALL_ID),
|
||||
vcmRtpToMediaPayload(media->payload,
|
||||
media->remote_dynamic_payload_type_value,
|
||||
media->mode),
|
||||
(short)dscp,
|
||||
&media->src_addr,
|
||||
media->src_port,
|
||||
&media->dest_addr,
|
||||
media->dest_port,
|
||||
FSM_NEGOTIATED_CRYPTO_ALGORITHM_ID(media),
|
||||
FSM_NEGOTIATED_CRYPTO_TX_KEY(media),
|
||||
&attrs) == -1)
|
||||
{
|
||||
LSM_DEBUG(DEB_L_C_F_PREFIX"%s: vcmTxStart failed\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(LSM, dcb->line, dcb->call_id, fname1), fname);
|
||||
dcb->dsp_out_of_resources = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (vcmTxStartICE(media->cap_index, group_id,
|
||||
media->refid,
|
||||
media->level,
|
||||
/* TODO(emannion): his perhaps needs some error checking for validity.
|
||||
See gsmsdp_get_media_cap_entry_by_index. */
|
||||
dcb->media_cap_tbl->cap[media->cap_index].pc_stream,
|
||||
dcb->media_cap_tbl->cap[media->cap_index].pc_track,
|
||||
lsm_get_ms_ui_call_handle(dcb->line, call_id, CC_NO_CALL_ID),
|
||||
dcb->peerconnection,
|
||||
vcmRtpToMediaPayload(media->payload,
|
||||
media->remote_dynamic_payload_type_value,
|
||||
media->mode),
|
||||
(short)dscp,
|
||||
FSM_NEGOTIATED_CRYPTO_DIGEST_ALGORITHM(media),
|
||||
FSM_NEGOTIATED_CRYPTO_DIGEST(media),
|
||||
&attrs) == -1)
|
||||
{
|
||||
LSM_DEBUG(DEB_L_C_F_PREFIX"%s: vcmTxStartICE failed\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(LSM, dcb->line, dcb->call_id, fname1), fname);
|
||||
dcb->dsp_out_of_resources = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lsm_update_dscp_value(dcb);
|
||||
|
||||
|
@ -1847,7 +1904,7 @@ static void lsm_release_port (lsm_lcb_t *lcb)
|
|||
fsmdef_media_t *start_media, *end_media;
|
||||
fsmdef_dcb_t *dcb;
|
||||
fsmdef_media_t *media;
|
||||
int roapproxy;
|
||||
int sdpmode = 0;
|
||||
|
||||
dcb = lcb->dcb;
|
||||
if (dcb == NULL) {
|
||||
|
@ -1855,6 +1912,8 @@ static void lsm_release_port (lsm_lcb_t *lcb)
|
|||
return;
|
||||
}
|
||||
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
|
||||
LSM_DEBUG(DEB_L_C_F_PREFIX,
|
||||
DEB_L_C_F_PREFIX_ARGS(LSM, dcb->line, dcb->call_id, fname));
|
||||
|
||||
|
@ -1862,14 +1921,10 @@ static void lsm_release_port (lsm_lcb_t *lcb)
|
|||
end_media = NULL; /* NULL means till the end of the list */
|
||||
|
||||
GSMSDP_FOR_MEDIA_LIST(media, start_media, end_media, dcb) {
|
||||
|
||||
roapproxy = 0;
|
||||
config_get_value(CFGID_ROAPPROXY, &roapproxy, sizeof(roapproxy));
|
||||
if (roapproxy == FALSE) {
|
||||
|
||||
vcmRxReleasePort(media->cap_index, dcb->group_id, media->refid,
|
||||
if (!sdpmode) {
|
||||
vcmRxReleasePort(media->cap_index, dcb->group_id, media->refid,
|
||||
lsm_get_ms_ui_call_handle(lcb->line, lcb->call_id, lcb->ui_id), media->src_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2148,7 +2203,8 @@ lsm_get_facility_by_called_number (callid_t call_id,
|
|||
lsm_debug_entry(call_id, 0, fname);
|
||||
LSM_DEBUG(DEB_F_PREFIX"called_number= %s\n", DEB_F_PREFIX_ARGS(LSM, fname), called_number);
|
||||
|
||||
line = sip_config_get_line_by_called_number(1, called_number);
|
||||
//line = sip_config_get_line_by_called_number(1, called_number);
|
||||
line = 1;
|
||||
if (line == 0) {
|
||||
return (CC_CAUSE_UNASSIGNED_NUM);
|
||||
}
|
||||
|
@ -2878,10 +2934,14 @@ lsm_set_ringer (lsm_lcb_t *lcb, callid_t call_id, line_t line, int alerting)
|
|||
vcm_tones_t toneMode = VCM_CALL_WAITING_TONE;
|
||||
fsmdef_media_t *media;
|
||||
boolean isDusting = FSM_CHK_FLAGS(lcb->flags, LSM_FLAGS_DUSTING) ? TRUE : FALSE;
|
||||
int sdpmode = 0;
|
||||
|
||||
|
||||
LSM_DEBUG(DEB_L_C_F_PREFIX"Entered, state=%d.\n",
|
||||
DEB_L_C_F_PREFIX_ARGS(LSM, line, call_id, fname), lcb->state);
|
||||
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
|
||||
/*
|
||||
* The ringer (or call-waiting tone) should be on if these
|
||||
* conditions are met:
|
||||
|
@ -3238,7 +3298,9 @@ lsm_set_ringer (lsm_lcb_t *lcb, callid_t call_id, line_t line, int alerting)
|
|||
DEB_L_C_F_PREFIX_ARGS(LSM, line, call_id, fname));
|
||||
|
||||
|
||||
vcmControlRinger(VCM_RING_OFF, NO, NO, line, call_id);
|
||||
if (!sdpmode) {
|
||||
vcmControlRinger(VCM_RING_OFF, NO, NO, line, call_id);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3924,6 +3986,10 @@ lsm_connected (lsm_lcb_t *lcb, cc_state_data_connected_t *data)
|
|||
call_events original_call_event;
|
||||
int ringSettingBusyStationPolicy;
|
||||
boolean tone_stop_bool = TRUE;
|
||||
int sdpmode = 0;
|
||||
boolean start_ice = FALSE;
|
||||
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
|
||||
dcb = lcb->dcb;
|
||||
if (dcb == NULL) {
|
||||
|
@ -3951,19 +4017,38 @@ lsm_connected (lsm_lcb_t *lcb, cc_state_data_connected_t *data)
|
|||
tone_stop_bool = FALSE;
|
||||
}
|
||||
|
||||
/* Don't try to start ICE unless this is the first time connecting.
|
||||
* TODO(ekr@rtfm.com): Is this the right ICE start logic? What about restarts
|
||||
*/
|
||||
if (strlen(dcb->peerconnection) && lcb->state != LSM_S_CONNECTED)
|
||||
start_ice = TRUE;
|
||||
|
||||
lsm_change_state(lcb, __LINE__, LSM_S_CONNECTED);
|
||||
|
||||
if (tone_stop_bool == TRUE)
|
||||
(void) lsm_stop_tone(lcb, NULL);
|
||||
|
||||
|
||||
if (!sdpmode) {
|
||||
if (tone_stop_bool == TRUE)
|
||||
(void) lsm_stop_tone(lcb, NULL);
|
||||
}
|
||||
|
||||
/* Start ICE */
|
||||
if (start_ice) {
|
||||
short res = vcmStartIceChecks(dcb->peerconnection);
|
||||
/* TODO(emannion): Set state to dead here. */
|
||||
if (res)
|
||||
return CC_RC_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the RTP receive channel.
|
||||
*/
|
||||
lsm_call_state_media(lcb, line, cc_state_name(CC_STATE_CONNECTED));
|
||||
|
||||
vcmEnableSidetone(YES);
|
||||
|
||||
if (!sdpmode) {
|
||||
vcmEnableSidetone(YES);
|
||||
|
||||
lsm_set_ringer(lcb, call_id, line, alerting);
|
||||
lsm_set_ringer(lcb, call_id, line, alerting);
|
||||
}
|
||||
|
||||
FSM_RESET_FLAGS(lcb->flags, LSM_FLAGS_ANSWER_PENDING);
|
||||
FSM_RESET_FLAGS(lcb->flags, LSM_FLAGS_DUSTING);
|
||||
|
@ -4284,6 +4369,10 @@ lsm_onhook (lsm_lcb_t *lcb, cc_state_data_onhook_t *data)
|
|||
line_t line = lcb->line;
|
||||
fsmdef_dcb_t *dcb;
|
||||
cc_causes_t cause;
|
||||
int sdpmode = 0;
|
||||
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
|
||||
|
||||
dcb = lcb->dcb;
|
||||
if (dcb == NULL) {
|
||||
|
@ -4307,8 +4396,9 @@ lsm_onhook (lsm_lcb_t *lcb, cc_state_data_onhook_t *data)
|
|||
|
||||
(void) lsm_stop_tone(lcb, NULL);
|
||||
|
||||
vcmControlRinger(VCM_RING_OFF, NO, NO, line, dcb->call_id);
|
||||
|
||||
if (!sdpmode) {
|
||||
vcmControlRinger(VCM_RING_OFF, NO, NO, line, dcb->call_id);
|
||||
}
|
||||
|
||||
lsm_set_ringer(lcb, call_id, line, YES);
|
||||
|
||||
|
@ -5205,6 +5295,79 @@ lsm_stop_media (lsm_lcb_t *lcb, callid_t call_id, line_t line,
|
|||
lsm_set_ringer(lcb, call_id, line, YES);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lsm_add_remote_stream
|
||||
*
|
||||
* Description:
|
||||
* The function adds a remote stream to the media subsystem
|
||||
*
|
||||
* Parameters:
|
||||
* [in] line - line
|
||||
* [in] call_id - GSM call ID
|
||||
* [in] media - media line to add as remote stream
|
||||
* [out] pc_stream_id
|
||||
* Returns: None
|
||||
*/
|
||||
void lsm_add_remote_stream (line_t line, callid_t call_id, fsmdef_media_t *media, int *pc_stream_id)
|
||||
{
|
||||
static const char fname[] = "lsm_add_remote_stream";
|
||||
fsmdef_dcb_t *dcb;
|
||||
lsm_lcb_t *lcb;
|
||||
|
||||
lcb = lsm_get_lcb_by_call_id(call_id);
|
||||
if (lcb != NULL) {
|
||||
dcb = lcb->dcb;
|
||||
if (dcb == NULL) {
|
||||
LSM_ERR_MSG(get_debug_string(DEBUG_INPUT_NULL), fname);
|
||||
return;
|
||||
}
|
||||
|
||||
vcmCreateRemoteStream(media->cap_index, dcb->peerconnection, pc_stream_id,
|
||||
vcmRtpToMediaPayload(media->payload,
|
||||
media->local_dynamic_payload_type_value,media->mode));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* lsm_data_channel_negotiated
|
||||
*
|
||||
* Description:
|
||||
* The function informs the API of a negotiated data channel m= line
|
||||
*
|
||||
* Parameters:
|
||||
* [in] line - line
|
||||
* [in] call_id - GSM call ID
|
||||
* [in] media - media line to add as remote stream
|
||||
* [out] pc_stream_id
|
||||
* Returns: None
|
||||
*/
|
||||
void lsm_data_channel_negotiated (line_t line, callid_t call_id, fsmdef_media_t *media, int *pc_stream_id)
|
||||
{
|
||||
static const char fname[] = "lsm_data_channel_negotiated";
|
||||
fsmdef_dcb_t *dcb;
|
||||
lsm_lcb_t *lcb;
|
||||
|
||||
lcb = lsm_get_lcb_by_call_id(call_id);
|
||||
if (lcb) {
|
||||
dcb = lcb->dcb;
|
||||
if (dcb == NULL) {
|
||||
LSM_ERR_MSG(get_debug_string(DEBUG_INPUT_NULL), fname);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* have access to media->streams, media->protocol, media->sctp_port
|
||||
* vcmSetDataChannelParameters may need renaming TODO: jesup
|
||||
*/
|
||||
|
||||
vcmSetDataChannelParameters(dcb->peerconnection, media->streams, media->sctp_port, media->protocol);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Peform non call related action
|
||||
|
@ -5852,10 +6015,10 @@ lsm_update_inalert_status (line_t line, callid_t call_id,
|
|||
(data->caller_id.calling_number[0] != '\0') &&
|
||||
data->caller_id.display_calling_number) {
|
||||
|
||||
strncat(disp_str, data->caller_id.calling_number,
|
||||
sstrncat(disp_str, data->caller_id.calling_number,
|
||||
sizeof(disp_str) - strlen(disp_str));
|
||||
} else {
|
||||
strncat(disp_str, platform_get_phrase_index_str(UI_UNKNOWN),
|
||||
sstrncat(disp_str, platform_get_phrase_index_str(UI_UNKNOWN),
|
||||
sizeof(disp_str) - strlen(disp_str));
|
||||
}
|
||||
|
||||
|
@ -6388,19 +6551,17 @@ static void lsm_util_start_tone(vcm_tones_t tone, short alert_info,
|
|||
cc_call_handle_t call_handle, groupid_t group_id,
|
||||
streamid_t stream_id, uint16_t direction) {
|
||||
|
||||
int roapproxy;
|
||||
int sdpmode = 0;
|
||||
static const char fname[] = "lsm_util_start_tone";
|
||||
line_t line = GET_LINE_ID(call_handle);
|
||||
callid_t call_id = GET_CALL_ID(call_handle);
|
||||
DEF_DEBUG(DEB_F_PREFIX"Enter, line=%d, call_id=%d.\n",
|
||||
DEB_F_PREFIX_ARGS(MED_API, fname), line, call_id);
|
||||
|
||||
roapproxy = 0;
|
||||
config_get_value(CFGID_ROAPPROXY, &roapproxy, sizeof(roapproxy));
|
||||
if (roapproxy == FALSE) {
|
||||
|
||||
//vcmToneStart
|
||||
vcmToneStart(tone, alert_info, call_handle, group_id, stream_id, direction);
|
||||
sdpmode = 0;
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
if (!sdpmode) {
|
||||
vcmToneStart(tone, alert_info, call_handle, group_id, stream_id, direction);
|
||||
}
|
||||
/*
|
||||
* Set delay value for multi-part tones and repeated tones.
|
||||
|
|
|
@ -54,7 +54,8 @@ cc_media_cap_table_t g_media_table = {
|
|||
1,
|
||||
{
|
||||
{CC_AUDIO_1,SDP_MEDIA_AUDIO,TRUE,TRUE,SDP_DIRECTION_SENDRECV},
|
||||
{CC_VIDEO_1,SDP_MEDIA_VIDEO,FALSE,FALSE,SDP_DIRECTION_SENDRECV},
|
||||
{CC_VIDEO_1,SDP_MEDIA_VIDEO,FALSE,TRUE,SDP_DIRECTION_SENDRECV},
|
||||
{CC_DATACHANNEL_1,SDP_MEDIA_APPLICATION,FALSE,TRUE,SDP_DIRECTION_SENDRECV},
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -86,19 +86,19 @@ sub_send_msg (cprBuffer_t buf, uint32_t cmd, uint16_t len, cc_srcs_t dst_id)
|
|||
case CC_SRC_GSM:
|
||||
rc = gsm_send_msg(cmd, buf, len);
|
||||
if (rc == CPR_FAILURE) {
|
||||
cprReleaseBuffer(buf);
|
||||
cpr_free(buf);
|
||||
}
|
||||
break;
|
||||
case CC_SRC_SIP:
|
||||
rc = SIPTaskSendMsg(cmd, buf, len, NULL);
|
||||
if (rc == CPR_FAILURE) {
|
||||
cprReleaseBuffer(buf);
|
||||
cpr_free(buf);
|
||||
}
|
||||
break;
|
||||
case CC_SRC_MISC_APP:
|
||||
rc = MiscAppTaskSendMsg(cmd, buf, len);
|
||||
if (rc == CPR_FAILURE) {
|
||||
cprReleaseBuffer(buf);
|
||||
cpr_free(buf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#ifndef _CCAPI_H_
|
||||
#define _CCAPI_H_
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "cpr_types.h"
|
||||
#include "cpr_memory.h"
|
||||
#include "phone_types.h"
|
||||
|
@ -57,6 +58,10 @@ typedef int cc_causes_t;
|
|||
#define CC_CALL_FORWARDED CC_CALL_TYPE_FORWARDED
|
||||
#define CC_CALL_NONE CC_CALL_TYPE_NONE
|
||||
#define CC_CALL_INCOMING CC_CALL_TYPE_INCOMING
|
||||
#define SDP_SIZE 4096 /* must increase this */
|
||||
#define PC_HANDLE_SIZE 17 /* 8 random bytes in hex plus null */
|
||||
#define CANDIDATE_SIZE 150
|
||||
#define MID_SIZE 150
|
||||
|
||||
#include "sessionConstants.h"
|
||||
|
||||
|
@ -65,18 +70,8 @@ typedef unsigned int softkey_events;
|
|||
typedef unsigned int cc_call_priority_e;
|
||||
extern cc_reg_state_t ccapp_get_state();
|
||||
|
||||
|
||||
// global sdp structure
|
||||
typedef struct cc_global_sdp_ {
|
||||
char offerSDP[1020];
|
||||
char answerSDP[1024];
|
||||
char offerAddress[MAX_IPADDR_STR_LEN];
|
||||
int audioPort;
|
||||
int videoPort;
|
||||
} cc_global_sdp_t;
|
||||
|
||||
extern cc_global_sdp_t gROAPSDP;
|
||||
|
||||
/* Session FEATURES */
|
||||
/* please update cc_feature_names whenever this enum list is changed */
|
||||
|
||||
typedef enum {
|
||||
CC_FEATURE_MIN = -1L,
|
||||
|
@ -128,9 +123,93 @@ typedef enum {
|
|||
CC_FEATURE_CAC_RESP_FAIL,
|
||||
CC_FEATURE_FAST_PIC_UPD,
|
||||
CC_FEATURE_UNDEFINED,
|
||||
CC_FEATURE_CREATEOFFER,
|
||||
CC_FEATURE_CREATEANSWER,
|
||||
CC_FEATURE_SETLOCALDESC,
|
||||
CC_FEATURE_SETREMOTEDESC,
|
||||
CC_FEATURE_LOCALDESC,
|
||||
CC_FEATURE_REMOTEDESC,
|
||||
CC_FEATURE_SETPEERCONNECTION,
|
||||
CC_FEATURE_ADDSTREAM,
|
||||
CC_FEATURE_REMOVESTREAM,
|
||||
CC_FEATURE_ADDICECANDIDATE,
|
||||
CC_FEATURE_MAX
|
||||
} group_cc_feature_t;
|
||||
|
||||
#define skNewCall CC_FEATURE_NEW_CALL
|
||||
#define skConfrn CC_FEATURE_CONF
|
||||
|
||||
/* please update the following cc_feature_names whenever this feature list is changed */
|
||||
|
||||
#ifdef __CC_FEATURE_STRINGS__
|
||||
static const char *cc_feature_names[] = {
|
||||
"NONE",
|
||||
"HOLD",
|
||||
"RESUME",
|
||||
"OFFHOOK",
|
||||
"NEW_CALL",
|
||||
"REDIAL",
|
||||
"ONHOOK",
|
||||
"KEYPRESS",
|
||||
"DIAL",
|
||||
"XFER",
|
||||
"CFWD_ALL", //10
|
||||
"END_CALL",
|
||||
"ANSWER",
|
||||
"INFO",
|
||||
"CONF",
|
||||
"JOIN",
|
||||
"DIR_XFER",
|
||||
"SELECT",
|
||||
"SPEEDDIAL",
|
||||
"SWAP",
|
||||
"SDBLF", //45
|
||||
"BLIND_XFER_WITH_DIALSTRING",
|
||||
"BSPACE",
|
||||
"CANCEL",
|
||||
"DIALSTR",
|
||||
"UPD_SESSION_MEDIA_CAP",
|
||||
"NEW_MEDIA",
|
||||
"UPDATE",
|
||||
"CALLINFO",
|
||||
"BLIND_XFER",
|
||||
"NOTIFY",
|
||||
"SUBSCRIBE",
|
||||
"B2BCONF",
|
||||
"B2BJOIN",
|
||||
"HOLD_REVERSION", //jni_max + 10
|
||||
"BLF_ALERT_TONE",
|
||||
"REQPENDTMREXP",
|
||||
"NUMBER",
|
||||
"URL",
|
||||
"REDIRECT", //jni_max + 20
|
||||
"RINGBACKDELAYTMREXP",
|
||||
"CALL_PRESERVATION",
|
||||
"UPD_MEDIA_CAP",
|
||||
"CAC PASSED",
|
||||
"CAC FAILED",
|
||||
"FAST_PIC_UPD",
|
||||
"UNDEFINED",
|
||||
"CREATEOFFER",
|
||||
"CREATEANSWER",
|
||||
"SETLOCALDESC",
|
||||
"SETREMOTEDESC",
|
||||
"LOCALDESC",
|
||||
"REMOTEDESC",
|
||||
"SETPEERCONNECTION",
|
||||
"ADDSTREAM",
|
||||
"REMOVESTREAM",
|
||||
"ADDICECANDIDATE",
|
||||
"MAX"
|
||||
};
|
||||
|
||||
/* This checks at compile-time that the cc_feature_names list
|
||||
* is the same size as the cc_group_feature_t enum
|
||||
*/
|
||||
PR_STATIC_ASSERT(PR_ARRAY_SIZE(cc_feature_names) == CC_FEATURE_MAX + 1);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
@ -149,6 +228,9 @@ typedef enum {
|
|||
#define CC_CISCO_PLAR_STRING "x-cisco-serviceuri-offhook"
|
||||
#define CISCO_BLFPICKUP_STRING "x-cisco-serviceuri-blfpickup"
|
||||
#define JOIN_ACROSS_LINES_DISABLED 0
|
||||
#define CC_MAX_TRACKS 8 // <EM> query this figure
|
||||
#define CC_MAX_STREAMS 2 // TODO: expand signaling to handle more than one of each a/v.
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -182,6 +264,16 @@ typedef enum cc_msgs_t_ {
|
|||
CC_MSG_DIALSTRING,
|
||||
CC_MSG_MWI,
|
||||
CC_MSG_AUDIT,
|
||||
CC_MSG_CREATEOFFER,
|
||||
CC_MSG_CREATEANSWER,
|
||||
CC_MSG_SETLOCALDESC,
|
||||
CC_MSG_SETREMOTEDESC,
|
||||
CC_MSG_REMOTEDESC,
|
||||
CC_MSG_LOCALDESC,
|
||||
CC_MSG_SETPEERCONNECTION,
|
||||
CC_MSG_ADDSTREAM,
|
||||
CC_MSG_REMOVESTREAM,
|
||||
CC_MSG_ADDCANDIDATE,
|
||||
CC_MSG_AUDIT_ACK,
|
||||
CC_MSG_OPTIONS,
|
||||
CC_MSG_OPTIONS_ACK,
|
||||
|
@ -213,6 +305,16 @@ static const char *cc_msg_names[] = {
|
|||
"DIALSTRING",
|
||||
"MWI",
|
||||
"AUDIT",
|
||||
"CREATEOFFER",
|
||||
"CREATEANSWER",
|
||||
"SETLOCALDESC",
|
||||
"SETREMOTEDESC",
|
||||
"REMOTEDESC",
|
||||
"LOCALDESC",
|
||||
"SETPEERCONNECTION",
|
||||
"ADDSTREAM",
|
||||
"REMOVESTREAM",
|
||||
"ADDCANDIDATE",
|
||||
"AUDIT_ACK",
|
||||
"OPTIONS",
|
||||
"OPTIONS_ACK",
|
||||
|
@ -222,6 +324,12 @@ static const char *cc_msg_names[] = {
|
|||
"INFO",
|
||||
"INVALID",
|
||||
};
|
||||
|
||||
/* This checks at compile-time that the cc_msg_names list
|
||||
* is the same size as the cc_msgs_t enum
|
||||
*/
|
||||
PR_STATIC_ASSERT(PR_ARRAY_SIZE(cc_msg_names) == CC_MSG_MAX + 1);
|
||||
|
||||
#endif //__CC_MESSAGES_STRINGS__
|
||||
|
||||
typedef enum cc_srcs_t_ {
|
||||
|
@ -297,7 +405,8 @@ typedef enum {
|
|||
/* media name with media capability table */
|
||||
typedef enum {
|
||||
CC_AUDIO_1,
|
||||
CC_VIDEO_1
|
||||
CC_VIDEO_1,
|
||||
CC_DATACHANNEL_1,
|
||||
} cc_media_cap_name;
|
||||
|
||||
typedef struct cc_sdp_addr_t_ {
|
||||
|
@ -698,6 +807,8 @@ typedef struct cc_media_cap_t_ {
|
|||
boolean enabled; /* this media is enabled or disabled */
|
||||
boolean support_security; /* security is supported */
|
||||
sdp_direction_e support_direction;/* supported direction */
|
||||
cc_media_stream_id_t pc_stream; /* The media stream in the PC */
|
||||
cc_media_track_id_t pc_track; /* The track ID in the media stream */
|
||||
} cc_media_cap_t;
|
||||
|
||||
typedef struct cc_media_cap_table_t_ {
|
||||
|
@ -705,6 +816,26 @@ typedef struct cc_media_cap_table_t_ {
|
|||
cc_media_cap_t cap[CC_MAX_MEDIA_CAP];/* capability table. */
|
||||
} cc_media_cap_table_t;
|
||||
|
||||
typedef struct cc_media_track_t_ {
|
||||
unsigned int media_stream_track_id;
|
||||
boolean video;
|
||||
} cc_media_track_t;
|
||||
|
||||
typedef struct cc_media_remote_track_table_t_ {
|
||||
uint32_t num_tracks;
|
||||
uint32_t media_stream_id;
|
||||
cc_media_track_t track[CC_MAX_TRACKS];
|
||||
} cc_media_remote_track_table_t;
|
||||
|
||||
typedef struct cc_media_remote_stream_table_t_ {
|
||||
cc_media_remote_track_table_t streams[CC_MAX_STREAMS];
|
||||
} cc_media_remote_stream_table_t;
|
||||
|
||||
typedef struct cc_media_local_track_table_t_ {
|
||||
uint32_t media_stream_id;
|
||||
cc_media_track_t track[CC_MAX_TRACKS];
|
||||
} cc_media_local_track_table_t;
|
||||
|
||||
typedef struct cc_feature_data_generic_t {
|
||||
boolean subref_flag;
|
||||
uint32_t eventid;
|
||||
|
@ -722,6 +853,25 @@ typedef struct cc_feature_data_cancel_t_ {
|
|||
callid_t target_call_id;
|
||||
} cc_feature_data_cancel_t;
|
||||
|
||||
typedef struct cc_feature_data_pc_t_ {
|
||||
char pc_handle[PC_HANDLE_SIZE];
|
||||
} cc_feature_data_pc_t;
|
||||
|
||||
typedef struct cc_feature_data_track_t_ {
|
||||
cc_media_stream_id_t stream_id;
|
||||
cc_media_track_id_t track_id;
|
||||
cc_media_type_t media_type;
|
||||
} cc_feature_data_track_t;
|
||||
|
||||
|
||||
typedef struct cc_feature_candidate_t_ {
|
||||
uint16_t level;
|
||||
char candidate[CANDIDATE_SIZE];
|
||||
char mid[MID_SIZE];
|
||||
} cc_feature_candidate_t;
|
||||
|
||||
|
||||
|
||||
typedef union cc_feature_data_t {
|
||||
cc_feature_data_newcall_t newcall;
|
||||
cc_feature_data_xfer_t xfer;
|
||||
|
@ -743,6 +893,9 @@ typedef union cc_feature_data_t {
|
|||
cc_feature_data_cnf_t cnf;
|
||||
cc_feature_data_b2bcnf_t cancel;
|
||||
cc_media_cap_t caps;
|
||||
cc_feature_data_pc_t pc;
|
||||
cc_feature_data_track_t track;
|
||||
cc_feature_candidate_t candidate;
|
||||
} cc_feature_data_t;
|
||||
|
||||
typedef struct cc_setup_t_ {
|
||||
|
@ -827,13 +980,15 @@ typedef struct cc_release_complete_t_ {
|
|||
} cc_release_complete_t;
|
||||
|
||||
typedef struct cc_feature_t_ {
|
||||
cc_msgs_t msg_id;
|
||||
cc_srcs_t src_id;
|
||||
callid_t call_id;
|
||||
line_t line;
|
||||
cc_features_t feature_id;
|
||||
cc_feature_data_t data;
|
||||
boolean data_valid;
|
||||
cc_msgs_t msg_id;
|
||||
cc_srcs_t src_id;
|
||||
callid_t call_id;
|
||||
line_t line;
|
||||
cc_features_t feature_id;
|
||||
cc_feature_data_t data;
|
||||
boolean data_valid;
|
||||
cc_jsep_action_t action;
|
||||
char sdp[SDP_SIZE];
|
||||
} cc_feature_t;
|
||||
|
||||
typedef struct cc_feature_ack_t_ {
|
||||
|
@ -1051,10 +1206,28 @@ void cc_int_release_complete(cc_srcs_t src_id, cc_srcs_t dst_id,
|
|||
callid_t call_id, line_t line, cc_causes_t cause,
|
||||
cc_kfact_t *kfactor);
|
||||
|
||||
void cc_int_feature(cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, cc_features_t feature_id,
|
||||
void cc_int_feature2(cc_msgs_t msg_id, cc_srcs_t src_id, cc_srcs_t dst_id,
|
||||
callid_t call_id, line_t line, cc_features_t feature_id,
|
||||
cc_feature_data_t *data);
|
||||
|
||||
void cc_createoffer(cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, cc_features_t feature_id, cc_feature_data_t *data);
|
||||
|
||||
void cc_createanswer (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, cc_features_t feature_id, string_t sdp, cc_feature_data_t *data);
|
||||
|
||||
void cc_setlocaldesc (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line,
|
||||
cc_features_t feature_id, cc_jsep_action_t action, string_t sdp, cc_feature_data_t *data);
|
||||
|
||||
void cc_setremotedesc (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line,
|
||||
cc_features_t feature_id, cc_jsep_action_t action, string_t sdp, cc_feature_data_t *data);
|
||||
|
||||
void cc_localdesc (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line,
|
||||
cc_features_t feature_id, cc_feature_data_t *data);
|
||||
|
||||
void cc_remotedesc (cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id, line_t line,
|
||||
cc_features_t feature_id, cc_feature_data_t *data);
|
||||
|
||||
void cc_int_feature_ack(cc_srcs_t src_id, cc_srcs_t dst_id, callid_t call_id,
|
||||
line_t line, cc_features_t feature_id,
|
||||
cc_feature_data_t *data, cc_causes_t cause);
|
||||
|
@ -1121,7 +1294,8 @@ void cc_int_fail_fallback(cc_srcs_t src_id, cc_srcs_t dst_id, int rsp_type,
|
|||
#define cc_release(a, b, c, d, e, f) cc_int_release(a, CC_SRC_GSM, b, c, d, e, f)
|
||||
#define cc_release_complete(a, b, c, d, e) \
|
||||
cc_int_release_complete(a, CC_SRC_GSM, b, c, d, e)
|
||||
#define cc_feature(a, b, c, d, e) cc_int_feature(a, CC_SRC_GSM, b, c, d, e)
|
||||
#define cc_feature(a, b, c, d, e) cc_int_feature2(CC_MSG_FEATURE, a, CC_SRC_GSM, b, c, d, e)
|
||||
#define cc_int_feature(a, b, c, d, e, f) cc_int_feature2(CC_MSG_FEATURE, a, b, c, d, e, f)
|
||||
#define cc_feature_ack(a, b, c, d, e, f) \
|
||||
cc_int_feature_ack(a, CC_SRC_GSM, b, c, d, e, f)
|
||||
#define cc_offhook(a, b, c) cc_int_offhook(a, CC_SRC_GSM, CC_NO_CALL_ID, CC_REASON_NONE, b, c, NULL, CC_MONITOR_NONE,CFWDALL_NONE)
|
||||
|
|
|
@ -216,6 +216,16 @@ static const int gDscpCallControl = 1;
|
|||
static const int gSpeakerEnabled = 1;
|
||||
static const char gExternalNumberMask[] = "";
|
||||
static const char gVersion[] = "0.1";
|
||||
|
||||
static const boolean gRTCPMUX = FALSE;
|
||||
static boolean gRTPSAVPF = TRUE; /* TRUE = RTP/SAVPF , FALSE = RTP/SAVP */
|
||||
static const boolean gMAXAVBITRATE = FALSE; /* Following six are OPUS fmtp options */
|
||||
static const boolean gMAXCODEDAUDIOBW = FALSE;
|
||||
static const boolean gUSEDTX = FALSE;
|
||||
static const boolean gSTEREO = FALSE;
|
||||
static const boolean gUSEINBANDFEC = FALSE;
|
||||
static const boolean gCBR = FALSE;
|
||||
static const boolean gMAXPTIME = FALSE;
|
||||
static const int gSCTPPort = 5000;
|
||||
static const int gNumDataStreams = 16;
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
||||
|
|
|
@ -127,26 +127,6 @@ typedef struct {
|
|||
#define MAX_SHOW_NAME 50
|
||||
#define MAX_CLEAR_NAME 50
|
||||
|
||||
|
||||
typedef struct {
|
||||
cc_debug_category_e category;
|
||||
char debugName[MAX_DEBUG_NAME];
|
||||
cc_int32_t *key; /* The variable associated with this debug category */
|
||||
} debugStruct_t;
|
||||
|
||||
typedef struct {
|
||||
cc_debug_show_options_e category;
|
||||
char showName[MAX_SHOW_NAME];
|
||||
show_callback callbackFunc; /* The callback function for the show cmd */
|
||||
boolean showTech; /* TRUE indicates this show is also tied with tech cmd */
|
||||
} debugShowStruct_t;
|
||||
|
||||
typedef struct {
|
||||
cc_debug_clear_options_e category;
|
||||
char clearName[MAX_CLEAR_NAME];
|
||||
clear_callback callbackFunc; /* The callback function for the clear cmd */
|
||||
} debugClearStruct_t;
|
||||
|
||||
/*
|
||||
* Prototypes for public functions
|
||||
*/
|
||||
|
|
|
@ -226,9 +226,10 @@
|
|||
#define CCSIP_SIP_USER_AGENT "CP9971"
|
||||
|
||||
#define MAX_PHONE_LINES 8
|
||||
#define MAX_REG_LINES 8
|
||||
#define MAX_REG_LINES 51
|
||||
#define MAX_CALLS 51
|
||||
#define MAX_CALLS_PER_LINE 51
|
||||
|
||||
/*
|
||||
* MAX_INSTANCES (call_instances) should equal to maximum number of calls
|
||||
* allowed by the phone but MAX_CALLS is defined to be 1 more than the
|
||||
|
@ -236,9 +237,9 @@
|
|||
*/
|
||||
#define MAX_INSTANCES (MAX_CALLS - 1) /* max number of instance ID */
|
||||
|
||||
/* MAX_CONFIG_LINES - java side defined fixed number to 36 for non-Guinness TNP
|
||||
/* MAX_CONFIG_LINES - java side defined fixed number to 36 for non-Buckfast TNP
|
||||
* models so use 36 in call cases. Changing this needs java side change
|
||||
*/
|
||||
#define MAX_CONFIG_LINES 36
|
||||
#define MAX_CONFIG_LINES 51
|
||||
|
||||
#endif
|
||||
|
|
|
@ -58,5 +58,30 @@ void platform_apply_config (char * configVersionStamp, char * dialplanVersionSta
|
|||
*/
|
||||
cpr_ip_mode_e platGetIpAddressMode();
|
||||
|
||||
/**
|
||||
* @brief Given a msg buffer, returns a pointer to the buffer's header
|
||||
*
|
||||
* The cprGetSysHeader function retrieves the system header buffer for the
|
||||
* passed in message buffer.
|
||||
*
|
||||
* @param[in] buffer pointer to the buffer whose sysHdr to return
|
||||
*
|
||||
* @return Abstract pointer to the msg buffer's system header
|
||||
* or #NULL if failure
|
||||
*/
|
||||
void *
|
||||
cprGetSysHeader (void *buffer);
|
||||
|
||||
/**
|
||||
* @brief Called when the application is done with this system header
|
||||
*
|
||||
* The cprReleaseSysHeader function returns the system header buffer to the
|
||||
* system.
|
||||
* @param[in] syshdr pointer to the sysHdr to be released
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void
|
||||
cprReleaseSysHeader (void *syshdr);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -186,66 +186,7 @@ typedef enum {
|
|||
|
||||
/* Other provider specific cmds can be defined beginning with STATE_PRO_BASE */
|
||||
|
||||
/* Session FEATURES */
|
||||
/* please update cc_feature_names whenever this enum list is changed */
|
||||
|
||||
#define skNewCall CC_FEATURE_NEW_CALL
|
||||
#define skConfrn CC_FEATURE_CONF
|
||||
|
||||
/* please update the following cc_feature_names whenever this feature list is changed */
|
||||
|
||||
#ifdef __CC_FEATURE_STRINGS__
|
||||
static const char *cc_feature_names[] = {
|
||||
"NONE",
|
||||
"HOLD",
|
||||
"RESUME",
|
||||
"OFFHOOK",
|
||||
"NEW_CALL",
|
||||
"REDIAL",
|
||||
"ONHOOK",
|
||||
"KEYPRESS",
|
||||
"DIAL",
|
||||
"XFER",
|
||||
"CFWD_ALL", //10
|
||||
"END_CALL",
|
||||
"ANSWER",
|
||||
"INFO",
|
||||
"CONF",
|
||||
"JOIN",
|
||||
"DIR_XFER",
|
||||
"SELECT",
|
||||
"SPEEDDIAL",
|
||||
"SWAP",
|
||||
"SDBLF", //45
|
||||
"BLIND_XFER_WITH_DIALSTRING",
|
||||
"BSPACE",
|
||||
"CANCEL",
|
||||
"DIALSTR",
|
||||
"UPD_SESSION_MEDIA_CAP",
|
||||
"NEW_MEDIA",
|
||||
"UPDATE",
|
||||
"CALLINFO",
|
||||
"BLIND_XFER",
|
||||
"NOTIFY",
|
||||
"SUBSCRIBE",
|
||||
"B2BCONF",
|
||||
"B2BJOIN",
|
||||
"HOLD_REVERSION", //jni_max + 10
|
||||
"BLF_ALERT_TONE",
|
||||
"REQPENDTMREXP",
|
||||
"NUMBER",
|
||||
"URL",
|
||||
"REDIRECT", //jni_max + 20
|
||||
"RINGBACKDELAYTMREXP",
|
||||
"CALL_PRESERVATION",
|
||||
"UPD_MEDIA_CAP",
|
||||
"CAC PASSED",
|
||||
"CAC FAILED",
|
||||
"FAST_PIC_UPD",
|
||||
"UNDEFINED",
|
||||
"MAX"
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Device specific feature update IDs */
|
||||
typedef enum {
|
||||
|
@ -309,7 +250,12 @@ typedef enum {
|
|||
CALL_CALLREF,
|
||||
MEDIA_INTERFACE_UPDATE_BEGIN,
|
||||
MEDIA_INTERFACE_UPDATE_SUCCESSFUL,
|
||||
MEDIA_INTERFACE_UPDATE_FAIL
|
||||
MEDIA_INTERFACE_UPDATE_FAIL,
|
||||
CREATE_OFFER,
|
||||
CREATE_ANSWER,
|
||||
SET_LOCAL_DESC,
|
||||
SET_REMOTE_DESC,
|
||||
REMOTE_STREAM_ADD
|
||||
} group_call_event_t;
|
||||
|
||||
/* File Player Session Events */
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче