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:
Randell Jesup 2012-10-07 01:34:29 -04:00
Родитель 1995a1f5d1
Коммит f769554f67
225 изменённых файлов: 17191 добавлений и 21686 удалений

Просмотреть файл

@ -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 */

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше