diff options
author | samelian <samelian@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-05-22 20:12:04 +0000 |
---|---|---|
committer | samelian <samelian@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-05-22 20:12:04 +0000 |
commit | ac87680632b4fb6582d1391b042eff7f0305c0a2 (patch) | |
tree | bfeee57d104a1bbc7c387d35190fa55d692115b7 /kopete/protocols/jabber/jingle | |
parent | aca844682f86c04f6b67b23de2a820fb0c63a32e (diff) | |
download | tdenetwork-ac87680632b4fb6582d1391b042eff7f0305c0a2.tar.gz tdenetwork-ac87680632b4fb6582d1391b042eff7f0305c0a2.zip |
[kdenetwork/kopete] added cmake support
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdenetwork@1233119 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kopete/protocols/jabber/jingle')
69 files changed, 7487 insertions, 7 deletions
diff --git a/kopete/protocols/jabber/jingle/CMakeLists.txt b/kopete/protocols/jabber/jingle/CMakeLists.txt new file mode 100644 index 00000000..18bbf758 --- /dev/null +++ b/kopete/protocols/jabber/jingle/CMakeLists.txt @@ -0,0 +1,38 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( libjingle ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/libjingle + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/include + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/xmpp-im + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/jabber + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/cutestuff/util + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopetejabberjingle (static) ############### + +tde_moc( MOCS voicecaller.h ) + +tde_add_library( kopetejabberjingle STATIC_PIC AUTOMOC + SOURCES + jinglevoicecaller.cpp jinglevoicesessiondialogbase.ui + jinglevoicesessiondialog.cpp ${MOCS} +) diff --git a/kopete/protocols/jabber/jingle/jinglevoicecaller.cpp b/kopete/protocols/jabber/jingle/jinglevoicecaller.cpp index dd809cea..12e4b93d 100644 --- a/kopete/protocols/jabber/jingle/jinglevoicecaller.cpp +++ b/kopete/protocols/jabber/jingle/jinglevoicecaller.cpp @@ -374,3 +374,5 @@ cricket::Thread* JingleVoiceCaller::thread_ = NULL; cricket::NetworkManager* JingleVoiceCaller::network_manager_ = NULL; cricket::BasicPortAllocator* JingleVoiceCaller::port_allocator_ = NULL; cricket::SocketAddress* JingleVoiceCaller::stun_addr_ = NULL; + +#include "jinglevoicecaller.moc" diff --git a/kopete/protocols/jabber/jingle/libjingle/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/CMakeLists.txt new file mode 100644 index 00000000..0aa34648 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( talk ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/CMakeLists.txt new file mode 100644 index 00000000..1a1d0416 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/CMakeLists.txt @@ -0,0 +1,19 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include( ConfigureChecks.cmake ) + +add_subdirectory( base ) +add_subdirectory( p2p ) +add_subdirectory( xmllite ) +add_subdirectory( xmpp ) +add_subdirectory( session ) +add_subdirectory( third_party ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/ConfigureChecks.cmake b/kopete/protocols/jabber/jingle/libjingle/talk/ConfigureChecks.cmake new file mode 100644 index 00000000..396efa92 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/ConfigureChecks.cmake @@ -0,0 +1,48 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +# gthread-2.0 +pkg_search_module( GTHREAD2 gthread-2.0 ) +if( NOT GTHREAD2_FOUND ) + tde_message_fatal( "gthread-2.0 is required, but was not found on your system" ) +endif( ) + + +# gmodule-2.0 +pkg_search_module( GMODULE2 gmodule-2.0 ) +if( NOT GMODULE2_FOUND ) + tde_message_fatal( "gmodule-2.0 are required, but not found on your system" ) +endif( ) + + +# speex +if( WITH_SPEEX ) + pkg_search_module( SPEEX speex ) + if( SPEEX_FOUND ) + set( HAVE_SPEEX 1 CACHE INTERNAL "" FORCE ) + if( NOT SPEEX_INCLUDE_DIRS ) + set( SPEEX_INCLUDE_DIRS "/usr/include/speex" ) + endif( ) + else( ) + tde_message_fatal( "speex is required, but was not found on your system" ) + endif( ) +endif( ) + +# expat +check_include_file( expat.h HAVE_EXPAT_H ) +if( HAVE_EXPAT_H ) + check_library_exists( expat XML_ParserCreate "" HAVE_EXPAT ) +endif( ) +if( HAVE_EXPAT_H AND HAVE_EXPAT ) + set( EXPAT_LIBRARY expat CACHE INTERNAL "" FORCE ) +else( ) + tde_message_fatal( "expat is required, but was not found on your system" ) +endif( ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/base/CMakeLists.txt new file mode 100644 index 00000000..8f037a9a --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/CMakeLists.txt @@ -0,0 +1,32 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DPOSIX +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### cricketbase (static) ###################### + +tde_add_library( cricketbase STATIC_PIC + SOURCES + socketaddress.cc jtime.cc asyncudpsocket.cc messagequeue.cc + thread.cc physicalsocketserver.cc bytebuffer.cc asyncpacketsocket.cc + network.cc asynctcpsocket.cc socketadapters.cc md5c.c base64.cc + task.cc taskrunner.cc host.cc socketaddresspair.cc +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/asynctcpsocket.cc b/kopete/protocols/jabber/jingle/libjingle/talk/base/asynctcpsocket.cc index 6d4697a6..8bf66a38 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/asynctcpsocket.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/asynctcpsocket.cc @@ -32,6 +32,7 @@ #include "talk/base/byteorder.h" #include "talk/base/common.h" #include "talk/base/logging.h" +#include <cstring> #if defined(_MSC_VER) && _MSC_VER < 1300 namespace std { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/bytebuffer.cc b/kopete/protocols/jabber/jingle/libjingle/talk/base/bytebuffer.cc index 067f50ed..e3af08b7 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/bytebuffer.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/bytebuffer.cc @@ -30,6 +30,7 @@ #include "talk/base/byteorder.h" #include <algorithm> #include <cassert> +#include <cstring> #if defined(_MSC_VER) && _MSC_VER < 1300 namespace std { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/host.cc b/kopete/protocols/jabber/jingle/libjingle/talk/base/host.cc index 7b7490d9..f604050f 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/host.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/host.cc @@ -30,6 +30,8 @@ #include "talk/base/network.h" #include "talk/base/socket.h" #include <string> +#include <cstring> +#include <cstdlib> #include <iostream> #include <cassert> #include <errno.h> diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/messagequeue.h b/kopete/protocols/jabber/jingle/libjingle/talk/base/messagequeue.h index 2a9cbed6..9b35b9af 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/messagequeue.h +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/messagequeue.h @@ -32,6 +32,7 @@ #include "talk/base/criticalsection.h" #include "talk/base/socketserver.h" #include "talk/base/jtime.h" +#include <string.h> #include <vector> #include <queue> #include <algorithm> diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/physicalsocketserver.cc b/kopete/protocols/jabber/jingle/libjingle/talk/base/physicalsocketserver.cc index 91d2daad..37836302 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/physicalsocketserver.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/physicalsocketserver.cc @@ -30,6 +30,7 @@ #endif #include <cassert> +#include <algorithm> #ifdef POSIX extern "C" { @@ -37,6 +38,7 @@ extern "C" { #include <fcntl.h> #include <sys/time.h> #include <unistd.h> +#include <string.h> } #endif @@ -59,9 +61,6 @@ extern "C" { #include <windows.h> #undef SetPort -#include <algorithm> -#include <iostream> - class WinsockInitializer { public: WinsockInitializer() { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/socketadapters.cc b/kopete/protocols/jabber/jingle/libjingle/talk/base/socketadapters.cc index 049e923c..f57043e3 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/socketadapters.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/socketadapters.cc @@ -42,6 +42,7 @@ #endif #include <cassert> +#include <cstring> #include "talk/base/base64.h" #include "talk/base/basicdefs.h" diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/CMakeLists.txt new file mode 100644 index 00000000..1708f179 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/CMakeLists.txt @@ -0,0 +1,13 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( base ) +add_subdirectory( client ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/CMakeLists.txt new file mode 100644 index 00000000..ba05a061 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/CMakeLists.txt @@ -0,0 +1,52 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DPOSIX +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../../.. + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### cricketp2pbase (static) ################### + +tde_add_library( cricketp2pbase STATIC_PIC + SOURCES + stun.cc port.cc udpport.cc tcpport.cc helpers.cc sessionmanager.cc + session.cc p2psocket.cc relayport.cc stunrequest.cc stunport.cc + socketmanager.cc +) + + +##### relayserver (executable) ################## + +tde_add_executable( relayserver + SOURCES + relayserver.cc relayserver_main.cc + LINK + cricketbase-static cricketp2pbase-static pthread + DESTINATION ${BIN_INSTALL_DIR} +) + + +##### stunserver (executable) ################### + +tde_add_executable( stunserver + SOURCES + stunserver.cc stunserver_main.cc + LINK + cricketbase-static cricketp2pbase-static pthread + DESTINATION ${BIN_INSTALL_DIR} +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/relayserver_main.cc b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/relayserver_main.cc index 5f624f37..4dfae42c 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/relayserver_main.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/relayserver_main.cc @@ -30,6 +30,7 @@ #include "talk/p2p/base/relayserver.h" #include <iostream> #include <assert.h> +#include <cstring> #ifdef POSIX extern "C" { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stun.cc b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stun.cc index 6a22b238..2d6aa67c 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stun.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stun.cc @@ -29,6 +29,7 @@ #include "talk/p2p/base/stun.h" #include <iostream> #include <cassert> +#include <cstring> #if defined(_MSC_VER) && _MSC_VER < 1300 namespace std { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver.cc b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver.cc index 6e4f6b66..c6d9f9f8 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver.cc @@ -28,6 +28,7 @@ #include "talk/base/bytebuffer.h" #include "talk/p2p/base/stunserver.h" #include <iostream> +#include <cstring> #ifdef POSIX extern "C" { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver_main.cc b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver_main.cc index bd8a96e5..bac3e35f 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver_main.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver_main.cc @@ -29,6 +29,7 @@ #include "talk/base/thread.h" #include "talk/p2p/base/stunserver.h" #include <iostream> +#include <cstring> #ifdef POSIX extern "C" { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/client/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/client/CMakeLists.txt new file mode 100644 index 00000000..7ede9820 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/client/CMakeLists.txt @@ -0,0 +1,30 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DLINUX + -DPOSIX + -DINTERNAL_BUILD +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../../.. + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### cricketp2pclient (static) ################# + +tde_add_library( cricketp2pclient STATIC_PIC + SOURCES + sessionclient.cc basicportallocator.cc socketmonitor.cc +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/session/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/session/CMakeLists.txt new file mode 100644 index 00000000..0b78949f --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/session/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( phone ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/CMakeLists.txt new file mode 100644 index 00000000..3f22e535 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/CMakeLists.txt @@ -0,0 +1,34 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DPOSIX +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../../.. + ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/ortp + ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/mediastreamer + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${GLIB2_INCLUDE_DIRS} + ${SPEEX_INCLUDE_DIRS} +) + + +##### cricketsessionphone (static) ############## + +tde_add_library( cricketsessionphone STATIC_PIC + SOURCES + audiomonitor.cc channelmanager.cc voicechannel.cc call.cc + phonesessionclient.cc linphonemediaengine.cc +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/linphonemediaengine.cc b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/linphonemediaengine.cc index e363392c..f3244c54 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/linphonemediaengine.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/linphonemediaengine.cc @@ -27,7 +27,7 @@ extern "C" { #include "talk/third_party/mediastreamer/msspeexdec.h" #endif } -#include <ortp/ortp.h> +#include <ortp.h> #include <netdb.h> #include <unistd.h> #include <fcntl.h> diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/phonesessionclient.cc b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/phonesessionclient.cc index d8a31df2..7f2ff11f 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/phonesessionclient.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/phonesessionclient.cc @@ -25,6 +25,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <stdio.h> + #include "talk/base/logging.h" #include "talk/session/receiver.h" #include "talk/session/phone/phonesessionclient.h" diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/CMakeLists.txt new file mode 100644 index 00000000..da1647c0 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/CMakeLists.txt @@ -0,0 +1,13 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( mediastreamer ) +add_subdirectory( ortp ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/CMakeLists.txt new file mode 100644 index 00000000..8c5a923b --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/CMakeLists.txt @@ -0,0 +1,36 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DG_LOG_DOMAIN="MediaStreamer" +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../ortp + ${CMAKE_BINARY_DIR} + ${GLIB2_INCLUDE_DIRS} + ${SPEEX_INCLUDE_DIRS} +) + + +##### mediastreamer (static) #################### + +tde_add_library( mediastreamer STATIC_PIC + SOURCES + msfilter.c mscodec.c mssoundread.c mssoundwrite.c msbuffer.c + msqueue.c msfifo.c ms.c mssync.c msnosync.c msread.c mswrite.c + mscopy.c msosswrite.c msossread.c msringplayer.c msrtprecv.c + msrtpsend.c msAlawenc.c msAlawdec.c msMUlawenc.c msMUlawdec.c + mstimer.c msqdispatcher.c msfdispatcher.c sndcard.c osscard.c + hpuxsndcard.c alsacard.c jackcard.c audiostream.c msspeexenc.c + msspeexdec.c msilbcdec.c msilbcenc.c +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtprecv.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtprecv.h index 5c8b616c..0f36c379 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtprecv.h +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtprecv.h @@ -28,7 +28,7 @@ /* because of a conflict between config.h from oRTP and config.h from linphone:*/ #undef PACKAGE #undef VERSION -#include <ortp/ortp.h> +#include <ortp.h> /*this is the class that implements a copy filter*/ diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.c index b13dfe28..645a19cd 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.c +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.c @@ -19,7 +19,7 @@ */ #include "msrtpsend.h" -#include <ortp/telephonyevents.h> +#include <telephonyevents.h> #include "mssync.h" #include "mscodec.h" diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.h index 746e436d..96889964 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.h +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.h @@ -27,7 +27,7 @@ #undef PACKAGE #undef VERSION -#include <ortp/ortp.h> +#include <ortp.h> /*this is the class that implements a sending through rtp filter*/ diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/CMakeLists.txt new file mode 100644 index 00000000..92a73a36 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/CMakeLists.txt @@ -0,0 +1,32 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -D_ORTP_SOURCE + -DG_LOG_DOMAIN="oRTP" +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${GLIB2_INCLUDE_DIRS} +) + + +##### ortp (static) ############################# + +tde_add_library( ortp STATIC_PIC + SOURCES + port_fct.c rtpmod.c rtpparse.c rtpsession.c jitterctl.c + rtpsignaltable.c rtptimer.c posixtimer.c ortp.c scheduler.c + avprofile.c sessionset.c telephonyevents.c payloadtype.c rtcp.c + utils.c rtcpparse.c str_utils.c +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/avprofile.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/avprofile.c new file mode 100644 index 00000000..8917e21b --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/avprofile.c @@ -0,0 +1,281 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <payloadtype.h> + +char offset127=127; +char offset0xD5=0xD5; +char offset0=0; + +/* IMPORTANT */ +/* some compiler don't support the "field:" syntax. Those macros are there to trap the problem +This means that if you want to keep portability, payload types must be defined with their fields +in the right order. */ + +#if !defined(__hpux) && !defined(WIN32) + +#define TYPE(val) type: (val) +#define CLOCK_RATE(val) clock_rate: (val) +#define BITS_PER_SAMPLE(val) bits_per_sample: (val) +#define ZERO_PATTERN(val) zero_pattern: (val) +#define PATTERN_LENGTH(val) pattern_length: (val) +#define NORMAL_BITRATE(val) normal_bitrate: (val) +#define MIME_TYPE(val) mime_type: (val) +#define FMTP(val) FMTP : (val) + +#else + +#define TYPE(val) (val) +#define CLOCK_RATE(val) (val) +#define BITS_PER_SAMPLE(val) (val) +#define ZERO_PATTERN(val) (val) +#define PATTERN_LENGTH(val) (val) +#define NORMAL_BITRATE(val) (val) +#define MIME_TYPE(val) (val) +#define FMTP(val) (val) + +#endif + +PayloadType pcmu8000={ + TYPE( PAYLOAD_AUDIO_CONTINUOUS), + CLOCK_RATE( 8000), + BITS_PER_SAMPLE(8), + ZERO_PATTERN( &offset127), + PATTERN_LENGTH( 1), + NORMAL_BITRATE( 64000), + MIME_TYPE ("PCMU") +}; + +PayloadType pcma8000={ + TYPE( PAYLOAD_AUDIO_CONTINUOUS), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(8), + ZERO_PATTERN( &offset0xD5), + PATTERN_LENGTH( 1), + NORMAL_BITRATE( 64000), + MIME_TYPE ("PCMA") +}; + +PayloadType pcm8000={ + TYPE( PAYLOAD_AUDIO_CONTINUOUS), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(16), + ZERO_PATTERN( &offset0), + PATTERN_LENGTH(1), + NORMAL_BITRATE( 128000), + MIME_TYPE ("PCM") +}; + +PayloadType lpc1016={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE( 0), + ZERO_PATTERN( NULL), + PATTERN_LENGTH( 0), + NORMAL_BITRATE( 2400), + MIME_TYPE ("1016") +}; + + +PayloadType gsm= +{ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE( 0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH( 0), + NORMAL_BITRATE( 13500), + MIME_TYPE ("GSM") +}; + +PayloadType payload_type_g7231= +{ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE( 0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH( 0), + NORMAL_BITRATE( 6300), + MIME_TYPE ("G723") +}; + +PayloadType payload_type_g729={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE( 0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH( 0), + NORMAL_BITRATE( 8000), + MIME_TYPE ("G729") +}; + +PayloadType mpv= +{ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE( 256000), + MIME_TYPE ("MPV") +}; + + +PayloadType h261={ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("H261") +}; + +PayloadType h263={ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(256000), + MIME_TYPE ("H263") +}; + +PayloadType truespeech= +{ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE( 0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH( 0), + NORMAL_BITRATE(8536), + MIME_TYPE ("TSP0") +}; + + +RtpProfile av_profile; + + +void av_profile_init(RtpProfile *profile) +{ + rtp_profile_clear_all(profile); + rtp_profile_set_name(profile,"AV profile"); + rtp_profile_set_payload(profile,0,&pcmu8000); + rtp_profile_set_payload(profile,1,&lpc1016); + rtp_profile_set_payload(profile,3,&gsm); + rtp_profile_set_payload(profile,4,&payload_type_g7231); + rtp_profile_set_payload(profile,8,&pcma8000); + rtp_profile_set_payload(profile,18,&payload_type_g729); + rtp_profile_set_payload(profile,31,&h261); + rtp_profile_set_payload(profile,32,&mpv); + rtp_profile_set_payload(profile,34,&h263); +} + +/* these are extra payload types that can be used dynamically */ +PayloadType lpc1015={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(2400), + MIME_TYPE ("1015") +}; + +PayloadType speex_nb={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(8000), /*not true: 8000 is the minimum*/ + MIME_TYPE ("speex") +}; + +PayloadType speex_wb={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(16000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(28000), + MIME_TYPE ("speex") +}; + +PayloadType payload_type_ilbc={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(13300), /* the minimum, with 30ms frames */ + MIME_TYPE ("iLBC"), +}; + +PayloadType amr={ + TYPE(PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("AMR") +}; + +PayloadType amrwb={ + TYPE(PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(16000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("AMR-WB") +}; + +PayloadType mp4v={ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("MP4V-ES") +}; + + +PayloadType h263_1998={ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("H263-1998") +}; + +PayloadType h263_2000={ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("H263-2000") +}; diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.c new file mode 100644 index 00000000..0f061c36 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.c @@ -0,0 +1,25 @@ +/* + * file : export.c + * + * this file is used when building the oRTP stack as a dynamic loadable library + * on win32 OS. Indeed, structures cannot been exported 'as is' using the .def + * file. Since we want to use the av_profile and telephone_event instances as defined + * in the original source code, We have to implement those 2 functions to retrieve + * pointers on them. + * + */ + + +#include "export.h" + + +RtpProfile * get_av_profile( void ) +{ + return &av_profile; +} + +PayloadType * get_telephone_event( void ) +{ + return &telephone_event; +} + diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.h new file mode 100644 index 00000000..0f5a3992 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.h @@ -0,0 +1,38 @@ +/* + * file : export.h + * + * this file is used when building the oRTP stack as a dynamic loadable library + * on win32 OS. Indeed, structures cannot been exported 'as is' using the .def + * file. Since we want to use the av_profile and telephone_event instances as defined + * in the original source code, We have to implement those 2 functions to retrieve + * pointers on them. + * + */ + + + +#ifndef EXPORT_H +#define EXPORT_H + + +#if defined __cplusplus +extern "C" +{ +#endif + + +#include "payloadtype.h" +#include "telephonyevents.h" + + + RtpProfile * get_av_profile( void ); + PayloadType * get_telephone_event( void ); + + + +#if defined __cplusplus +} +#endif + + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.c new file mode 100644 index 00000000..5f236f71 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.c @@ -0,0 +1,141 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/*************************************************************************** + * jitterctl.c + * + * Mon Nov 8 11:53:21 2004 + * Copyright 2004 Simon MORLAT + * Email [email protected] + ****************************************************************************/ + +#include <rtpsession.h> +#include <payloadtype.h> +#include <math.h> +#include <stdlib.h> + +#define JC_BETA 0.03 /*allows a clock slide around 3% */ +#define JC_GAMMA (JC_BETA) + +#include "jitterctl.h" + +void jitter_control_init(JitterControl *ctl, int base_jiitt_time, PayloadType *payload){ + ctl->count=0; + ctl->slide=0; + ctl->jitter=0; + ctl->inter_jitter=0; + ctl->slide=0; + if (base_jiitt_time!=-1) ctl->jitt_comp = base_jiitt_time; + /* convert in timestamp unit: */ + if (payload!=NULL){ + jitter_control_set_payload(ctl,payload); + } + ctl->adapt_jitt_comp_ts=ctl->jitt_comp_ts; + ctl->corrective_slide=0; +} + +void jitter_control_enable_adaptive(JitterControl *ctl, gboolean val){ + ctl->adaptive=val; +} + +void jitter_control_set_payload(JitterControl *ctl, PayloadType *pt){ + ctl->jitt_comp_ts = + (gint) (((double) ctl->jitt_comp / 1000.0) * (pt->clock_rate)); + ctl->corrective_step=(160 * 8000 )/pt->clock_rate; /* This formula got to me after some beers */ + ctl->adapt_jitt_comp_ts=ctl->jitt_comp_ts; +} + + +void jitter_control_dump_stats(JitterControl *ctl){ + g_log("oRTP-stats",G_LOG_LEVEL_MESSAGE,"JitterControl:\n\tslide=%g,jitter=%g,count=%i", + ctl->slide,ctl->jitter, ctl->count); +} + + +/* + The algorithm computes two values: + slide: an average of difference between the expected and the socket-received timestamp + jitter: an average of the absolute value of the difference between socket-received timestamp and slide. + slide is used to make clock-slide detection and correction. + jitter is added to the initial jitt_comp_time value. It compensates bursty packets arrival (packets + not arriving at regular interval ). +*/ +void jitter_control_new_packet(JitterControl *ctl, guint32 packet_ts, guint32 cur_str_ts, gint32 * slide, gint32 *safe_delay){ + int diff=packet_ts - cur_str_ts; + float gap; + int d; + //printf("diff=%g\n",diff); + + ctl->count++; + ctl->slide= (ctl->slide*(1-JC_BETA)) + ((float)diff*JC_BETA); + gap=fabs((float)diff - ctl->slide); + ctl->jitter=(ctl->jitter*(1-JC_GAMMA)) + (gap*JC_GAMMA); + d=diff-ctl->olddiff; + ctl->inter_jitter=ctl->inter_jitter+ (( (float)abs(d) - ctl->inter_jitter)*(1/16.0)); + ctl->olddiff=diff; + if (ctl->adaptive){ + int tmp; + if (ctl->count%50==0) { + /*jitter_control_dump_stats(ctl);*/ + } + tmp=(int)(ctl->slide)-ctl->corrective_slide; + if (tmp>ctl->corrective_step) ctl->corrective_slide+=ctl->corrective_step; + else if (tmp<-ctl->corrective_step) ctl->corrective_slide-=ctl->corrective_step; + /* the following is nearly equivalent, but maybe it consumes more CPU: ?*/ + /*ctl->corrective_slide=(((gint)ctl->slide)/ctl->corrective_step)*ctl->corrective_step;*/ + + ctl->adapt_jitt_comp_ts=MAX(ctl->jitt_comp_ts,ctl->jitter); + + *slide=(gint32)ctl->slide; + *safe_delay=(gint32)ctl->adapt_jitt_comp_ts; + }else { + *slide=0; + *safe_delay=(gint32)ctl->jitt_comp_ts; + } + return ; +} + + +/** + *rtp_session_set_jitter_compensation: + *@session: a RtpSession + *@milisec: the time interval in milisec to be jitter compensed. + * + * Sets the time interval for which packet are buffered instead of being delivered to the + * application. + **/ +void +rtp_session_set_jitter_compensation (RtpSession * session, gint milisec) +{ + PayloadType *payload = rtp_profile_get_payload (session->profile, + session-> + payload_type); + if (payload==NULL){ + g_warning("rtp_session_set_jitter_compensation: cannot set because the payload type is unknown"); + return; + } + jitter_control_init(&session->rtp.jittctl,milisec,payload); +} + +void rtp_session_enable_adaptive_jitter_compensation(RtpSession *session, gboolean val){ + jitter_control_enable_adaptive(&session->rtp.jittctl,val); +} + +gboolean rtp_session_adaptive_jitter_compensation_enabled(RtpSession *session){ + return session->rtp.jittctl.adaptive; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.h new file mode 100644 index 00000000..8e6986a9 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.h @@ -0,0 +1,38 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/*************************************************************************** + * jitterctl.c + * + * Mon Nov 8 11:53:21 2004 + * Copyright 2004 Simon MORLAT + * Email [email protected] + ****************************************************************************/ + +#ifndef JITTERCTL_H +#define JITTERCTL_H + + +void jitter_control_init(JitterControl *ctl, int base_jiitt_time, PayloadType *pt); +void jitter_control_enable_adaptive(JitterControl *ctl, gboolean val); +void jitter_control_new_packet(JitterControl *ctl, guint32 packet_ts, guint32 cur_str_ts, + gint32 * slide, gint32 *safe_delay); +#define jitter_control_adaptive_enabled(ctl) ((ctl)->adaptive) +void jitter_control_set_payload(JitterControl *ctl, PayloadType *pt); + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp-config.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp-config.h new file mode 100644 index 00000000..049a76d8 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp-config.h @@ -0,0 +1,9 @@ +#include <config.h> + +#define ORTP_MAJOR_VERSION 0 +#define ORTP_MINOR_VERSION 7 +#define ORTP_MICRO_VERSION 1 +#define ORTP_EXTRA_VERSION +#define ORTP_VERSION "0.7.1" + +#define POSIXTIMER_INTERVAL 10000 diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.c new file mode 100644 index 00000000..80e07682 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.c @@ -0,0 +1,258 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <ortp.h> +#include "scheduler.h" +#include <stdlib.h> + +rtp_stats_t ortp_global_stats; + +#ifdef ENABLE_MEMCHECK +gint ortp_allocations=0; +#endif + + +RtpScheduler *__ortp_scheduler; + + +void dummy_log(const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + return; +} + +extern void av_profile_init(RtpProfile *profile); + +static void init_random_number_generator(){ + struct timeval t; + gettimeofday(&t,NULL); + srandom(t.tv_usec+t.tv_sec); +} + +/** + *ortp_init: + * + * Initialize the oRTP library. You should call this function first before using + * oRTP API. +**/ + +void ortp_init() +{ + static gboolean initialized=FALSE; + if (initialized) return; + initialized=TRUE; + +#ifdef _WIN32 + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD( 1, 0 ); + + if (WSAStartup(wVersionRequested,&wsaData)!=0) + { + g_error("Fail to initialise socket api"); + } +#endif + +#ifdef HAVE_GLIB + if (!g_thread_supported()) g_thread_init (NULL); +#endif + av_profile_init(&av_profile); + ortp_global_stats_reset(); + init_random_number_generator(); + g_message("oRTP-" ORTP_VERSION "initialized."); +} + + +/** + *ortp_scheduler_init: + * + * Initialize the oRTP scheduler. You only have to do that if you intend to use the + * scheduled mode of the #RtpSession in your application. + * +**/ +void ortp_scheduler_init() +{ + static gboolean initialized=FALSE; + if (initialized) return; + initialized=TRUE; +#ifdef __hpux + /* on hpux, we must block sigalrm on the main process, because signal delivery + is ?random?, well, sometimes the SIGALRM goes to both the main thread and the + scheduler thread */ + sigset_t set; + sigemptyset(&set); + sigaddset(&set,SIGALRM); + sigprocmask(SIG_BLOCK,&set,NULL); +#endif /* __hpux */ + if (!g_thread_supported()) g_thread_init(NULL); + __ortp_scheduler=rtp_scheduler_new(); + rtp_scheduler_start(__ortp_scheduler); + //sleep(1); +} + + +/** + *ortp_exit: + * + * Gracefully uninitialize the library, including shutdowning the scheduler if it was started. + * +**/ +void ortp_exit() +{ + if (__ortp_scheduler!=NULL) + { + rtp_scheduler_destroy(__ortp_scheduler); + __ortp_scheduler=NULL; + } +} + +/** + *ortp_get_scheduler: + * + * Returns a pointer to the scheduler, NULL if it was not running. + * The application developer should have to call this function. + * + *Returns: a pointer to the scheduler. +**/ +RtpScheduler * ortp_get_scheduler() +{ + if (__ortp_scheduler==NULL) g_error("Cannot use the scheduled mode: the scheduler is not " + "started. Call ortp_scheduler_init() at the begginning of the application."); + return __ortp_scheduler; +} + + +void ortp_log(const gchar *log_domain,GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + gchar *lev; + switch(log_level){ + case G_LOG_LEVEL_MESSAGE: + lev="message"; + break; + case G_LOG_LEVEL_WARNING: + lev="warning"; + break; + case G_LOG_LEVEL_ERROR: + lev="error"; + default: + lev="(unknown log type)"; + } + if (user_data==NULL){ + user_data=stdout; + } + fprintf((FILE*)user_data,"%s-%s:%s\n",log_domain,lev,message); +} + + +/** + *ortp_set_debug_file: + *@domain: one of "oRTP" or "oRTP-stats" logging domain. + *@file: a FILE pointer where to output the messages from the domain. + * + * Warning: domain is ignored when not compiling with glib support. +**/ +void ortp_set_debug_file(gchar *domain,FILE *file) +{ + if (file!=NULL) + g_log_set_handler (domain, G_LOG_LEVEL_MASK, ortp_log, (gpointer)file); + else g_log_set_handler (domain, G_LOG_LEVEL_MASK, dummy_log, NULL); +} +/** + *ortp_set_log_handler: + *@domain: one of the "oRTP" or "oRTP-stats" logging domain. + *@func: your logging function, compatible with the GLogFunc prototype. + * + * Warning: domain is ignored when not compiling with glib support. +**/ +void ortp_set_log_handler(const gchar *domain, GLogFunc func, gpointer userdata){ + g_log_set_handler(domain,G_LOG_LEVEL_MASK,func,userdata); +} + + + +void ortp_global_stats_display() +{ + rtp_stats_display(&ortp_global_stats,"Global statistics"); +#ifdef ENABLE_MEMCHECK + printf("Unfreed allocations: %i\n",ortp_allocations); +#endif +} + + +void rtp_stats_display(rtp_stats_t *stats, char *header) +{ + + g_log("oRTP-stats",G_LOG_LEVEL_MESSAGE, + "\n %s :\n" + " number of rtp packet sent=%lld\n" + " number of rtp bytes sent=%lld bytes\n" + " number of rtp packet received=%lld\n" + " number of rtp bytes received=%lld bytes\n" + " number of incoming rtp bytes successfully delivered to the application=%lld \n" + " number of times the application queried a packet that didn't exist=%lld \n" + " number of rtp packets received too late=%lld\n" + " number of rtp packets skipped=%lld\n" + " number of bad formatted rtp packets=%lld\n" + " number of packet discarded because of queue overflow=%lld\n", + header, + (long long)stats->packet_sent, + (long long)stats->sent, + (long long)stats->packet_recv, + (long long)stats->hw_recv, + (long long)stats->recv, + (long long)stats->unavaillable, + (long long)stats->outoftime, + (long long)stats->skipped, + (long long)stats->bad, + (long long)stats->discarded); +} + +void ortp_global_stats_reset(){ + memset(&ortp_global_stats,0,sizeof(rtp_stats_t)); +} + +rtp_stats_t *ortp_get_global_stats(){ + return &ortp_global_stats; +} + +void rtp_stats_reset(rtp_stats_t *stats){ + memset((void*)stats,0,sizeof(rtp_stats_t)); +} + + +/** + *ortp_min_version_required: + *@major: + *@minor: + *@micro: + * + * This function give the opportunity to programs to check if the libortp they link to + * has the minimum version number they need. + * + * Returns: true if ortp has a version number greater or equal than the required one. +**/ +gboolean ortp_min_version_required(int major, int minor, int micro){ + return ((major*1000000) + (minor*1000) + micro) <= + ((ORTP_MAJOR_VERSION*1000000) + (ORTP_MINOR_VERSION*1000) + ORTP_MICRO_VERSION); +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.h new file mode 100644 index 00000000..a3c8b01c --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.h @@ -0,0 +1,54 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef ORTP_H +#define ORTP_H + +#include <rtpsession.h> +#include <sessionset.h> + +#ifdef __cplusplus +extern "C" +{ +#endif +gboolean ortp_min_version_required(int major, int minor, int micro); +void ortp_init(); +void ortp_scheduler_init(); +void ortp_exit(); + + +void ortp_set_debug_file(gchar *domain, FILE *file); +/* domain is ignored when not compiling with glib support */ +void ortp_set_log_handler(const gchar *domain, GLogFunc func, gpointer ud); + +extern rtp_stats_t ortp_global_stats; + +void ortp_global_stats_reset(); +rtp_stats_t *ortp_get_global_stats(); + +void ortp_global_stats_display(); +void rtp_stats_display(rtp_stats_t *stats, char *header); +void rtp_stats_reset(rtp_stats_t *stats); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.c new file mode 100644 index 00000000..c4886208 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.c @@ -0,0 +1,268 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <payloadtype.h> + +#include <stdio.h> +#include <stdlib.h> + +#ifdef WIN32 +#define snprintf _snprintf +#define strcasecmp stricmp +#endif + +/** + *rtp_profile_clear_all: + *@profile: an RTP profile (#RtpProfile object) + * + * Initialize the profile to the empty profile (all payload type are unassigned). + * +**/ + +/** + *rtp_profile_set_name: + *@profile: a rtp profile object (#RtpProfile) + *@nm: a string + * + * Set a name to the rtp profile. (This is not required) + * +**/ + +/** + *rtp_profile_get_name: + *@profile: a rtp profile object (#RtpProfile) + * + *Returns: the name of the rtp profile. May be NULL. +**/ + +/** + *rtp_profile_set_payload: + *@profile: an RTP profile (a #RtpProfile object) + *@index: the payload type number + *@pt: the payload type description (a #PayloadType object ) + * + * Assign payload type number @index to payload type desribed in @pt for the RTP profile + * @profile. + * +**/ + +/** + *rtp_profile_get_payload: + *@profile: an RTP profile (a #RtpProfile object) + *@index: the payload type number + * + * Gets the payload description of the payload type @index in the profile @profile. + * + *Returns: the payload description (a #PayloadType object) +**/ + +/** + *rtp_profile_clear_payload: + *@profile: an RTP profile (a #RtpProfile object) + *@index: the payload type number + * + * Set payload type number @index unassigned in profile @profile. + * +**/ + +char *payload_type_get_rtpmap(PayloadType *pt) +{ + int len=strlen(pt->mime_type)+15; + char *rtpmap=g_malloc(len); + snprintf(rtpmap,len,"%s/%i/1",pt->mime_type,pt->clock_rate); + return rtpmap; +} + +PayloadType *payload_type_new() +{ + PayloadType *newpayload=g_new0(PayloadType,1); + newpayload->flags|=PAYLOAD_TYPE_ALLOCATED; + return newpayload; +} + + +PayloadType *payload_type_clone(PayloadType *payload) +{ + PayloadType *newpayload=g_new0(PayloadType,1); + memcpy(newpayload,payload,sizeof(PayloadType)); + newpayload->mime_type=g_strdup(payload->mime_type); + if (payload->fmtp!=NULL) newpayload->fmtp=g_strdup(payload->fmtp); + newpayload->flags|=PAYLOAD_TYPE_ALLOCATED; + return newpayload; +} + +void payload_type_destroy(PayloadType *pt) +{ + g_free(pt->mime_type); + g_free(pt->fmtp); + g_free(pt); +} + +gint rtp_profile_get_payload_number_from_mime(RtpProfile *profile,const char *mime) +{ + PayloadType *pt; + gint i; + for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++) + { + pt=rtp_profile_get_payload(profile,i); + if (pt!=NULL) + { + if (strcasecmp(pt->mime_type,mime)==0){ + return i; + } + } + } + return -1; +} + +gint rtp_profile_find_payload_number(RtpProfile*profile,const gchar *mime,int rate) +{ + int i; + PayloadType *pt; + for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++) + { + pt=rtp_profile_get_payload(profile,i); + if (pt!=NULL) + { + if (strcasecmp(pt->mime_type,mime)==0 && pt->clock_rate==rate){ + + return i; + } + } + } + return -1; +} + +gint rtp_profile_get_payload_number_from_rtpmap(RtpProfile *profile,const char *rtpmap) +{ + gint clock_rate,ret; + char *p,*mime,*tmp,*c; + + /* parse the rtpmap */ + tmp=g_strdup(rtpmap); + p=strchr(tmp,'/'); + if (p!=NULL){ + mime=tmp; + *p='\0'; + c=p+1; + p=strchr(c,'/'); + if (p!=NULL) *p='\0'; + clock_rate=atoi(c); + }else return -1; + + //printf("Searching for payload %s at freq %i",mime,clock_rate); + ret=rtp_profile_find_payload_number(profile,mime,clock_rate); + g_free(tmp); + return ret; +} + +PayloadType * rtp_profile_find_payload(RtpProfile *prof,const gchar *mime,int rate) +{ + int i; + i=rtp_profile_find_payload_number(prof,mime,rate); + if (i>=0) return rtp_profile_get_payload(prof,i); + return NULL; +} + + +PayloadType * rtp_profile_get_payload_from_mime(RtpProfile *profile,const char *mime) +{ + int pt; + pt=rtp_profile_get_payload_number_from_mime(profile,mime); + if (pt==-1) return NULL; + else return rtp_profile_get_payload(profile,pt); +} + + +PayloadType * rtp_profile_get_payload_from_rtpmap(RtpProfile *profile, const char *rtpmap) +{ + int pt; + pt=rtp_profile_get_payload_number_from_rtpmap(profile,rtpmap); + if (pt==-1) return NULL; + else return rtp_profile_get_payload(profile,pt); +} + +int rtp_profile_move_payload(RtpProfile *prof,int oldpos,int newpos){ + prof->payload[newpos]=prof->payload[oldpos]; + prof->payload[oldpos]=NULL; + return 0; +} + +RtpProfile * rtp_profile_new(const char *name) +{ + RtpProfile *prof=g_new0(RtpProfile,1); + rtp_profile_set_name(prof,name); + rtp_profile_clear_all(prof); + return prof; +} + +void rtp_profile_set_name(RtpProfile *obj, const char *name){ + if (obj->name!=NULL) g_free(obj->name); + obj->name=g_strdup(name); +} + +/* ! payload are not cloned*/ +RtpProfile * rtp_profile_clone(RtpProfile *prof) +{ + int i; + PayloadType *pt; + RtpProfile *newprof=rtp_profile_new(prof->name); + rtp_profile_clear_all(newprof); + for (i=0;i<128;i++){ + pt=rtp_profile_get_payload(prof,i); + if (pt!=NULL){ + rtp_profile_set_payload(newprof,i,pt); + } + } + return newprof; +} + +void rtp_profile_copy(const RtpProfile *orig, RtpProfile *dest){ + memcpy(dest,orig,sizeof(RtpProfile)); +} + + +/*clone a profile and its payloads */ +RtpProfile * rtp_profile_clone_full(RtpProfile *prof) +{ + int i; + PayloadType *pt; + RtpProfile *newprof=rtp_profile_new(prof->name); + rtp_profile_clear_all(newprof); + for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++){ + pt=rtp_profile_get_payload(prof,i); + if (pt!=NULL){ + rtp_profile_set_payload(newprof,i,payload_type_clone(pt)); + } + } + return newprof; +} + +void rtp_profile_destroy(RtpProfile *prof) +{ + int i; + PayloadType *payload; + for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++) + { + payload=rtp_profile_get_payload(prof,i); + if (payload!=NULL && (payload->flags & PAYLOAD_TYPE_ALLOCATED)) + payload_type_destroy(payload); + } + g_free(prof); +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.h new file mode 100644 index 00000000..e5efa797 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.h @@ -0,0 +1,136 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef PAYLOADTYPE_H +#define PAYLOADTYPE_H +#include <rtpport.h> + +typedef enum{ + PAYLOAD_TYPE_ALLOCATED = 1 +}PayloadTypeFlags; + +struct _PayloadType +{ + gint type; + #define PAYLOAD_AUDIO_CONTINUOUS 0 + #define PAYLOAD_AUDIO_PACKETIZED 1 + #define PAYLOAD_VIDEO 2 + #define PAYLOAD_OTHER 3 /* ?? */ + gint clock_rate; + char bits_per_sample; /* in case of continuous audio data */ + char *zero_pattern; + gint pattern_length; + /* other usefull information */ + gint normal_bitrate; /*in bit/s */ + char *mime_type; + char *fmtp; /*various parameters, as a string */ + PayloadTypeFlags flags; + void *user_data; +}; + +#ifndef PayloadType_defined +#define PayloadType_defined +typedef struct _PayloadType PayloadType; +#endif + +#ifdef __cplusplus +extern "C"{ +#endif +PayloadType *payload_type_new(); +PayloadType *payload_type_clone(PayloadType *payload); +void payload_type_destroy(PayloadType *pt); +#ifdef __cplusplus +} +#endif + +#define payload_type_set_flag(pt,flag) (pt)->flags|=(flag) +#define payload_type_unset_flag(pt,flag) (pt)->flags&=(~flag) + +#define RTP_PROFILE_MAX_PAYLOADS 128 + +struct _RtpProfile +{ + char *name; + PayloadType *payload[RTP_PROFILE_MAX_PAYLOADS]; +}; + + +typedef struct _RtpProfile RtpProfile; + + +extern RtpProfile av_profile; + +#define payload_type_set_user_data(pt,p) (pt)->user_data=(p) +#define payload_type_get_user_data(pt) ((pt)->user_data) + + + +#define rtp_profile_get_name(profile) (const char*)((profile)->name) +#define rtp_profile_set_payload(profile,index,pt) (profile)->payload[(index)]=(pt) +#define rtp_profile_clear_payload(profile,index) (profile)->payload[(index)]=NULL +#define rtp_profile_clear_all(profile) memset((void*)(profile),0,sizeof(RtpProfile)) +#define rtp_profile_get_payload(profile,index) ((profile)->payload[(index)]) +#ifdef __cplusplus +extern "C"{ +#endif +void rtp_profile_set_name(RtpProfile *prof, const char *name); +PayloadType * rtp_profile_get_payload_from_mime(RtpProfile *profile,const char *mime); +PayloadType * rtp_profile_get_payload_from_rtpmap(RtpProfile *profile, const char *rtpmap); +gint rtp_profile_get_payload_number_from_mime(RtpProfile *profile,const char *mime); +gint rtp_profile_get_payload_number_from_rtpmap(RtpProfile *profile, const char *rtpmap); +gint rtp_profile_find_payload_number(RtpProfile *prof,const gchar *mime,int rate); +PayloadType * rtp_profile_find_payload(RtpProfile *prof,const gchar *mime,int rate); +gint rtp_profile_move_payload(RtpProfile *prof,int oldpos,int newpos); + +RtpProfile * rtp_profile_new(const char *name); +/* clone a profile, payload are not cloned */ +RtpProfile * rtp_profile_clone(RtpProfile *prof); +/* copy a profile into another one; payload are not cloned */ +void rtp_profile_copy(const RtpProfile *orig, RtpProfile *dest); + +/*clone a profile and its payloads (ie payload type are newly allocated, not reusing payload types of the reference profile) */ +RtpProfile * rtp_profile_clone_full(RtpProfile *prof); +/* frees the profile and all its PayloadTypes*/ +void rtp_profile_destroy(RtpProfile *prof); +#ifdef __cplusplus +} +#endif + +/* some payload types */ +/* audio */ +extern PayloadType pcmu8000; +extern PayloadType pcma8000; +extern PayloadType pcm8000; +extern PayloadType lpc1016; +extern PayloadType gsm; +extern PayloadType lpc1015; +extern PayloadType speex_nb; +extern PayloadType speex_wb; +extern PayloadType payload_type_ilbc; +extern PayloadType truespeech; + +/* video */ +extern PayloadType mpv; +extern PayloadType h261; +extern PayloadType h263; + + + + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.c new file mode 100644 index 00000000..2ad6b4dc --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.c @@ -0,0 +1,183 @@ + +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* port_fct.h. define methods to help for portability between unix and win32 */ + +#include <unistd.h> + +#include <rtpport.h> +#include "port_fct.h" + + + +/* + * this method is an utility method that calls fnctl() on UNIX or + * ioctlsocket on Win32. + * int retrun the result of the system method + */ +int set_non_blocking_socket (gint sock) +{ + + +#ifndef _WIN32 + return fcntl (sock, F_SETFL, O_NONBLOCK); +#else + unsigned long nonBlock = 1; + return ioctlsocket(sock, FIONBIO , &nonBlock); +#endif +} + + +/* + * this method is an utility method that calls close() on UNIX or + * closesocket on Win32. + * int retrun the result of the system method + */ +#ifndef _WIN32 + int close_socket(gint sock) + { + return close (sock); + } +#else + int close_socket(SOCKET sock) + { + return closesocket(sock); + } +#endif + + + +/* + * getSocketError() return a string describing the error + */ +#ifdef _WIN32 +char *getSocketError() +{ + int error = WSAGetLastError (); + static char buf[80]; + + switch (error) + { + case WSANOTINITIALISED: return "Windows sockets not initialized : call WSAStartup"; + case WSAEADDRINUSE: return "Local Address already in use"; + case WSAEADDRNOTAVAIL: return "The specified address is not a valid address for this machine"; +// case WSAEFAULT: return ""; +// case WSAEINPROGRESS: return ""; + case WSAEINVAL: return "The socket is already bound to an address."; + case WSAENOBUFS: return "Not enough buffers available, too many connections."; + case WSAENOTSOCK: return "The descriptor is not a socket."; + case WSAECONNRESET: return "Connection reset by peer"; +/* + + case : return ""; + case : return ""; + case : return ""; + case : return ""; + case : return ""; + case : return ""; +*/ + default : + sprintf (buf,"Error code : %d", error); + return buf; + break; + } + + return buf; + +} +#endif + +#ifndef _WIN32 + /* Use UNIX inet_aton method */ +#else + int inet_aton (const char * cp, struct in_addr * addr) + { + unsigned long retval; + + retval = inet_addr (cp); + + if (retval == INADDR_NONE) + { + return -1; + } + else + { + addr->S_un.S_addr = retval; + return 1; + } + } +#endif + +#ifndef HAVE_GLIB + +char * g_strdup_vprintf(const char *fmt, va_list ap) +{ + /* Guess we need no more than 100 bytes. */ + int n, size = 100; + char *p; + if ((p = g_malloc (size)) == NULL) + return NULL; + while (1) + { + /* Try to print in the allocated space. */ + n = vsnprintf (p, size, fmt, ap); + /* If that worked, return the string. */ + if (n > -1 && n < size) + return p; + //printf("Reallocing space.\n"); + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n + 1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + if ((p = g_realloc (p, size)) == NULL) + return NULL; + } +} + + + +extern void ortp_log(const gchar *log_domain,GLogLevelFlags log_level, + const gchar *message, + gpointer user_data); + +static GLogFunc __log_func=ortp_log; +static gpointer __log_user_data=(gpointer)NULL; + +void g_log(const gchar *log_domain,GLogLevelFlags log_level,const gchar *format,...){ + va_list args; + va_start(args,format); + g_logv(log_domain,log_level,format,args); + va_end(args); +} + +void g_logv(const gchar *log_domain,GLogLevelFlags log_level,const gchar *format,va_list args){ + gchar *msg; + msg=g_strdup_vprintf(format,args); + __log_func(log_domain,log_level,msg,__log_user_data); + g_free(msg); +} + +void g_log_set_handler(const gchar *log_domain,GLogLevelFlags log_levels, GLogFunc log_func, gpointer user_data){ + __log_func=log_func; + __log_user_data=user_data; +} + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.h new file mode 100644 index 00000000..3b3abe31 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.h @@ -0,0 +1,48 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* fct-win32.h. define unix methods that are not defined in win32 env */ + +#ifndef PORT_FCT_H +#define PORT_FCT_H + +#ifdef _WIN32 +#include <Winsock2.h> +#else +#include <fcntl.h> +#endif + +#include <rtpport.h> + +#ifndef _WIN32 +/* use unix pthread_t... */ + extern int close_socket(gint sock); +#else + #define pthread_t HANDLE + extern int pthread_create(pthread_t *thread,const void *attr,void *(__cdecl *start)(void *),void* arg); + extern int pthread_join(pthread_t thread,void **); + + extern int close_socket(SOCKET sock); + extern int inet_aton (const char * cp, struct in_addr * addr); +#endif + +extern int set_non_blocking_socket (int sock); +extern int set_thread_priority(); + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/posixtimer.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/posixtimer.c new file mode 100644 index 00000000..9e20ead4 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/posixtimer.c @@ -0,0 +1,167 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <rtpport.h> +#include "rtptimer.h" + + +#ifndef _WIN32 + +#ifdef __linux__ +#include <sys/select.h> +#endif + +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + + +static struct timeval orig,cur; +static guint32 posix_timer_time=0; /*in milisecond */ + +void posix_timer_init() +{ + posix_timer.state=RTP_TIMER_RUNNING; + gettimeofday(&orig,NULL); + posix_timer_time=0; +} + + + + +void posix_timer_do() +{ + gint32 diff,time; + struct timeval tv; + + gettimeofday(&cur,NULL); + time=((cur.tv_usec-orig.tv_usec)/1000 ) + ((cur.tv_sec-orig.tv_sec)*1000 ); + if ( (diff=time-posix_timer_time)>50){ + g_warning("Must catchup %i miliseconds.",diff); + } + while((diff = posix_timer_time-time) > 0) + { + tv.tv_sec = diff/1000; + tv.tv_usec = (diff%1000)*1000; + select(0,NULL,NULL,NULL,&tv); + gettimeofday(&cur,NULL); + time=((cur.tv_usec-orig.tv_usec)/1000 ) + ((cur.tv_sec-orig.tv_sec)*1000 ); + } + posix_timer_time+=POSIXTIMER_INTERVAL/1000; + +} + +void posix_timer_uninit() +{ + posix_timer.state=RTP_TIMER_STOPPED; +} + +RtpTimer posix_timer={ 0, + posix_timer_init, + posix_timer_do, + posix_timer_uninit, + {0,POSIXTIMER_INTERVAL}}; + + +#else //WIN32 + +#include <windows.h> +#include <mmsystem.h> + + +MMRESULT timerId; +HANDLE TimeEvent; +int late_ticks; + + +static DWORD posix_timer_time; +static DWORD offset_time; + + +#define TIME_INTERVAL 50 +#define TIME_RESOLUTION 10 +#define TIME_TIMEOUT 100 + + + +void CALLBACK timerCb(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) +{ + // Check timerId + if (timerId == uID) + { + SetEvent(TimeEvent); + posix_timer_time += TIME_INTERVAL; + } +} + + +void win_timer_init(void) +{ + timerId = timeSetEvent(TIME_INTERVAL,10,timerCb,0,TIME_PERIODIC | TIME_CALLBACK_FUNCTION); + TimeEvent = CreateEvent(NULL,FALSE,FALSE,NULL); + + late_ticks = 0; + + offset_time = GetTickCount(); + posix_timer_time=0; +} + + +void win_timer_do(void) +{ + DWORD diff; + + // If timer have expired while we where out of this method + // Try to run after lost time. + if (late_ticks > 0) + { + late_ticks--; + posix_timer_time+=TIME_INTERVAL; + return; + } + + + diff = GetTickCount() - posix_timer_time - offset_time; + if( diff>TIME_INTERVAL && (diff<(1<<31))) + { + late_ticks = diff/TIME_INTERVAL; + g_warning("we must catchup %i ticks.",late_ticks); + return; + } + + WaitForSingleObject(TimeEvent,TIME_TIMEOUT); + return; +} + + +void win_timer_close(void) +{ + timeKillEvent(timerId); +} + +RtpTimer toto; + +RtpTimer posix_timer={ 0, + win_timer_init, + win_timer_do, + win_timer_close, + {0,TIME_INTERVAL * 1000}}; + + +#endif // _WIN32 diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.c new file mode 100644 index 00000000..78599ae5 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.c @@ -0,0 +1,294 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/*************************************************************************** + * rtcp.c + * + * Wed Dec 1 11:45:30 2004 + * Copyright 2004 Simon Morlat + * Email simon dot morlat at linphone dot org + ****************************************************************************/ + +#include <rtpsession.h> +#include <rtcp.h> + +extern gint ortp_rtcp_send (RtpSession * session, mblk_t * m); + + +void rtcp_common_header_init(rtcp_common_header_t *ch, RtpSession *s,int type, int rc, int bytes_len){ + rtcp_common_header_set_version(ch,2); + rtcp_common_header_set_padbit(ch,0); + rtcp_common_header_set_packet_type(ch,type); + rtcp_common_header_set_rc(ch,rc); /* as we don't yet support multi source receiving */ + rtcp_common_header_set_length(ch,(bytes_len/4)-1); +} + +mblk_t *sdes_chunk_new(guint32 ssrc){ + mblk_t *m=allocb(RTCP_SDES_CHUNK_DEFAULT_SIZE,0); + sdes_chunk_t *sc=(sdes_chunk_t*)m->b_rptr; + sc->csrc=htonl(ssrc); + m->b_wptr+=sizeof(sc->csrc); + return m; +} + + +mblk_t * sdes_chunk_append_item(mblk_t *m, rtcp_sdes_type_t sdes_type, const gchar *content) +{ + if ( content ) + { + sdes_item_t si; + si.item_type=sdes_type; + si.len=MIN(strlen(content),RTCP_SDES_MAX_STRING_SIZE); + m=appendb(m,(char*)&si,RTCP_SDES_ITEM_HEADER_SIZE,FALSE); + m=appendb(m,content,si.len,FALSE); + } + return m; +} + +void sdes_chunk_set_ssrc(mblk_t *m, guint32 ssrc){ + sdes_chunk_t *sc=(sdes_chunk_t*)m->b_rptr; + sc->csrc=htonl(ssrc); +} + +#define sdes_chunk_get_ssrc(m) ntohl(((sdes_chunk_t*)((m)->b_rptr))->csrc) + +mblk_t * sdes_chunk_pad(mblk_t *m){ + return appendb(m,NULL,0,TRUE); +} + +void rtp_session_set_source_description(RtpSession *session, + const gchar *cname, const gchar *name, const gchar *email, const gchar *phone, + const gchar *loc, const gchar *tool, const gchar *note){ + mblk_t *chunk = sdes_chunk_new(session->send_ssrc); + mblk_t *m=chunk; + const gchar *_cname=cname; + if (_cname==NULL) + { + _cname="Unknown"; + } + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_CNAME, _cname); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_NAME, name); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_EMAIL, email); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_PHONE, phone); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_LOC, loc); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_TOOL, tool); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_NOTE, note); + chunk=sdes_chunk_pad(chunk); + rtp_session_lock(session); + if (session->sd!=NULL) freemsg(session->sd); + session->sd=m; + rtp_session_unlock(session); +} + +void +rtp_session_add_contributing_source(RtpSession *session, guint32 csrc, + const gchar *cname, const gchar *name, const gchar *email, const gchar *phone, + const gchar *loc, const gchar *tool, const gchar *note) +{ + mblk_t *chunk = sdes_chunk_new(csrc); + mblk_t *m=chunk; + gchar *_cname=(gchar*)cname; + if (_cname==NULL) + { + _cname="toto"; + } + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_CNAME, cname); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_NAME, name); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_EMAIL, email); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_PHONE, phone); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_LOC, loc); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_TOOL, tool); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_NOTE, note); + chunk=sdes_chunk_pad(chunk); + rtp_session_lock(session); + putq(&session->contributing_sources,m); + rtp_session_unlock(session); +} + + + +mblk_t* rtp_session_create_rtcp_sdes_packet(RtpSession *session) +{ + mblk_t *mp=allocb(sizeof(rtcp_common_header_t),0); + rtcp_common_header_t *rtcp; + mblk_t *tmp,*m=mp; + queue_t *q; + int rc=0; + rtcp = (rtcp_common_header_t*)mp->b_wptr; + mp->b_wptr+=sizeof(rtcp_common_header_t); + + /* concatenate all sdes chunks */ + sdes_chunk_set_ssrc(session->sd,session->send_ssrc); + m=concatb(m,dupmsg(session->sd)); + rc++; + + q=&session->contributing_sources; + for (tmp=qbegin(q); !qend(q,tmp); tmp=qnext(q,mp)){ + m=concatb(m,dupmsg(tmp)); + rc++; + } + rtcp_common_header_init(rtcp,session,RTCP_SDES,rc,msgdsize(mp)); + return mp; +} + + +mblk_t *rtcp_create_simple_bye_packet(guint32 ssrc, const gchar *reason) +{ + gint strsize=0; + gint packet_size; + mblk_t *mp; + rtcp_bye_t *rtcp; + packet_size = RTCP_BYE_HEADER_SIZE + 1 + strsize; + if (reason!=NULL) + strsize=MIN(strlen(reason),RTCP_BYE_REASON_MAX_STRING_SIZE); + mp = allocb(packet_size, 0); + + rtcp = (rtcp_bye_t*)mp->b_rptr; + + rtcp_common_header_init(&rtcp->ch,NULL,RTCP_BYE,1,packet_size); + rtcp->ssrc[0] = htonl(ssrc); + mp->b_wptr += packet_size; + /* append the reason if any*/ + if (reason!=NULL) + appendb(mp,reason,strsize,FALSE); + return mp; +} + +void rtp_session_remove_contributing_sources(RtpSession *session, guint32 ssrc) +{ + queue_t *q=&session->contributing_sources; + mblk_t *tmp; + for (tmp=qbegin(q); !qend(q,tmp); tmp=qnext(q,tmp)){ + guint32 csrc=sdes_chunk_get_ssrc(tmp); + if (csrc==ssrc) { + remq(q,tmp); + break; + } + } + tmp=rtcp_create_simple_bye_packet(ssrc, NULL); + ortp_rtcp_send(session,tmp); +} + +void sender_info_init(sender_info_t *info, RtpSession *session){ + struct timeval tv; + guint32 tmp; + gettimeofday(&tv,NULL); + info->ntp_timestamp_msw=htonl(tv.tv_sec); + tmp=(guint32)((double)tv.tv_usec*(double)(1LL<<32)*1.0e-6); + info->ntp_timestamp_lsw=htonl(tmp); + info->rtp_timestamp=htonl(session->rtp.snd_last_ts); + info->senders_packet_count=htonl(session->rtp.stats.packet_sent); + info->senders_octet_count=htonl(session->rtp.stats.sent); +} + + + +void report_block_init(report_block_t *b, RtpSession *session){ + guint packet_loss=0; + guint8 loss_fraction=0; + RtpStream *stream=&session->rtp; + guint32 delay_snc_last_sr=0; + + /* compute the statistics */ + /*printf("hwrcv_extseq.one=%u, hwrcv_seq_at_last_SR=%u hwrcv_since_last_SR=%u\n", + stream->hwrcv_extseq.one, + stream->hwrcv_seq_at_last_SR, + stream->hwrcv_since_last_SR + );*/ + if (stream->hwrcv_seq_at_last_SR!=0){ + packet_loss=(stream->hwrcv_extseq.one - stream->hwrcv_seq_at_last_SR) - stream->hwrcv_since_last_SR; + stream->stats.cum_packet_loss+=packet_loss; + loss_fraction=(int)(256.0*(float)packet_loss/(float)stream->hwrcv_since_last_SR); + } + /* reset them */ + stream->hwrcv_since_last_SR=0; + stream->hwrcv_seq_at_last_SR=stream->hwrcv_extseq.one; + + if (stream->last_rcv_SR_time.tv_sec!=0){ + struct timeval now; + gfloat delay; + gettimeofday(&now,NULL); + delay=((now.tv_sec-stream->last_rcv_SR_time.tv_sec)*1e6 ) + (now.tv_usec-stream->last_rcv_SR_time.tv_usec); + delay=delay*65536*1e-6; + delay_snc_last_sr=(guint32) delay; + } + + b->ssrc=htonl(session->recv_ssrc); + b->fraction_lost=loss_fraction; + b->cum_num_packet_lost=hton24(stream->stats.cum_packet_loss); + b->interarrival_jitter=htonl((guint32) stream->jittctl.inter_jitter); + b->ext_high_seq_num_rec=htonl(stream->hwrcv_extseq.one); + b->lsr=htonl(stream->last_rcv_SR_ts); + b->delay_snc_last_sr=htonl(delay_snc_last_sr); +} + + + +int rtcp_sr_init(RtpSession *session, char *buf, int size){ + rtcp_sr_t *sr=(rtcp_sr_t*)buf; + if (size<sizeof(rtcp_sr_t)) return -1; + rtcp_common_header_init(&sr->ch,session,RTCP_SR,1,sizeof(rtcp_sr_t)); + sr->ssrc=htonl(session->send_ssrc); + sender_info_init(&sr->si,session); + report_block_init(&sr->rb[0],session); + return sizeof(rtcp_sr_t); +} + +int rtcp_rr_init(RtpSession *session, char *buf, int size){ + rtcp_rr_t *rr=(rtcp_rr_t*)buf; + if (size<sizeof(rtcp_rr_t)) return -1; + rtcp_common_header_init(&rr->ch,session,RTCP_RR,1,sizeof(rtcp_sr_t)); + rr->ssrc=htonl(session->send_ssrc); + report_block_init(&rr->rb[0],session); + return sizeof(rtcp_sr_t); +} + + +void __rtp_session_rtcp_process(RtpSession *session){ + mblk_t *cm=NULL; + mblk_t *sdes=NULL; + if (session->mode==RTP_SESSION_SENDONLY || session->mode==RTP_SESSION_SENDRECV){ + /* first make a SR packet */ + cm=allocb(sizeof(rtcp_sr_t),0); + cm->b_wptr+=rtcp_sr_init(session,cm->b_wptr,sizeof(rtcp_sr_t)); + /* make a SDES packet */ + sdes=rtp_session_create_rtcp_sdes_packet(session); + /* link them */ + cm->b_cont=sdes; + }else{ + /* make a RR packet */ + cm=allocb(sizeof(rtcp_rr_t),0); + cm->b_wptr+=rtcp_rr_init(session,cm->b_wptr,sizeof(rtcp_rr_t)); + /* if we are recv-only do we need to add SDES packet ? I don't think so + as we are not a source */ + } + /* send the compound packet */ + ortp_rtcp_send(session,cm); + ortp_debug("Rtcp compound message sent."); +} + +void rtp_session_rtcp_process(RtpSession *session){ + RtpStream *st=&session->rtp; + if (st->rcv_last_app_ts - st->last_rtcp_report_snt_r > st->rtcp_report_snt_interval + || st->snd_last_ts - st->last_rtcp_report_snt_s > st->rtcp_report_snt_interval){ + st->last_rtcp_report_snt_r=st->rcv_last_app_ts; + st->last_rtcp_report_snt_s=st->snd_last_ts; + __rtp_session_rtcp_process(session); + } +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.h new file mode 100644 index 00000000..574bcf91 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.h @@ -0,0 +1,167 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef RTCP_H +#define RTCP_H + +#include <rtpport.h> + +#define RTCP_MAX_RECV_BUFSIZE 1024 + +#define RTCP_SENDER_INFO_SIZE 20 +#define RTCP_REPORT_BLOCK_SIZE 24 +#define RTCP_COMMON_HEADER_SIZE 4 +#define RTCP_SSRC_FIELD_SIZE 4 + + +/* RTCP common header */ + +typedef enum { + RTCP_SR = 200, + RTCP_RR = 201, + RTCP_SDES = 202, + RTCP_BYE = 203, + RTCP_APP = 204 +} rtcp_type_t; + + +typedef struct rtcp_common_header +{ +#ifdef WORDS_BIGENDIAN + guint16 version:2; + guint16 padbit:1; + guint16 rc:5; + guint16 packet_type:8; +#else + guint16 rc:5; + guint16 padbit:1; + guint16 version:2; + guint16 packet_type:8; +#endif + guint16 length:16; +} rtcp_common_header_t; + +#define rtcp_common_header_set_version(ch,v) (ch)->version=v +#define rtcp_common_header_set_padbit(ch,p) (ch)->padbit=p +#define rtcp_common_header_set_rc(ch,rc) (ch)->rc=rc +#define rtcp_common_header_set_packet_type(ch,pt) (ch)->packet_type=pt +#define rtcp_common_header_set_length(ch,l) (ch)->length=htons(l) + +#define rtcp_common_header_get_version(ch,v) ((ch)->version) +#define rtcp_common_header_get padbit(ch,p) ((ch)->padbit) +#define rtcp_common_header_get_rc(ch,rc) ((ch)->rc) +#define rtcp_common_header_get_packet_type(ch,pt) ((ch)->packet_type) +#define rtcp_common_header_get_length(ch,l) ntohs((ch)->length) + + +/* SR or RR packets */ + +typedef struct sender_info +{ + guint32 ntp_timestamp_msw; + guint32 ntp_timestamp_lsw; + guint32 rtp_timestamp; + guint32 senders_packet_count; + guint32 senders_octet_count; +} sender_info_t; + +typedef struct report_block +{ + guint32 ssrc; + guint32 fraction_lost:8; + guint32 cum_num_packet_lost:24; /*cumulative number of packet lost*/ + guint32 ext_high_seq_num_rec; /*extended highest sequence number received */ + guint32 interarrival_jitter; + guint32 lsr; /*last SR */ + guint32 delay_snc_last_sr; /*delay since last sr*/ +} report_block_t; + + +/* SDES packets */ + +typedef enum { + RTCP_SDES_END = 0, + RTCP_SDES_CNAME = 1, + RTCP_SDES_NAME = 2, + RTCP_SDES_EMAIL = 3, + RTCP_SDES_PHONE = 4, + RTCP_SDES_LOC = 5, + RTCP_SDES_TOOL = 6, + RTCP_SDES_NOTE = 7, + RTCP_SDES_PRIV = 8, + RTCP_SDES_MAX = 9 +} rtcp_sdes_type_t; + +typedef struct sdes_chunk +{ + guint32 csrc; +} sdes_chunk_t; + +typedef struct sdes_item +{ + guint8 item_type; + guint8 len; + gchar content[1]; +} sdes_item_t; + +#define RTCP_SDES_MAX_STRING_SIZE 255 +#define RTCP_SDES_ITEM_HEADER_SIZE 2 +#define RTCP_SDES_CHUNK_DEFAULT_SIZE 1024 +#define RTCP_SDES_CHUNK_HEADER_SIZE (sizeof(sdes_chunk_t)) + +/* RTCP bye packet */ + +typedef struct rtcp_bye_reason +{ + guint8 len; + gchar content[1]; +} rtcp_bye_reason_t; + +typedef struct rtcp_bye +{ + rtcp_common_header_t ch; + guint32 ssrc[1]; /* the bye may contain several ssrc/csrc */ +} rtcp_bye_t; +#define RTCP_BYE_HEADER_SIZE sizeof(rtcp_bye_t) +#define RTCP_BYE_REASON_MAX_STRING_SIZE 255 + +#define rtcp_bye_set_ssrc(b,pos,ssrc) (b)->ssrc[pos]=htonl(ssrc) +#define rtcp_bye_get_ssrc(b,pos) ntohl((b)->ssrc[pos]) + + +typedef struct rtcp_sr{ + rtcp_common_header_t ch; + guint32 ssrc; + sender_info_t si; + report_block_t rb[1]; +} rtcp_sr_t; + +typedef struct rtcp_rr{ + rtcp_common_header_t ch; + guint32 ssrc; + report_block_t rb[1]; +} rtcp_rr_t; + +struct _RtpSession; +void rtp_session_rtcp_process(struct _RtpSession *s); + +#define RTCP_DEFAULT_REPORT_INTERVAL 5 + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcpparse.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcpparse.c new file mode 100644 index 00000000..77e38245 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcpparse.c @@ -0,0 +1,218 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This source code file was written by Nicola Baldo as an extension of + the oRTP library. Copyright (C) 2005 Nicola Baldo [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <ortp.h> + + + +void report_block_parse(RtpSession *session, report_block_t *rb, struct timeval rcv_time_tv) +{ + rb->ssrc = ntohl(rb->ssrc); + + if ( rb->ssrc != session->send_ssrc ) + + { + ortp_debug("Received rtcp report block related to unknown ssrc (not from us)... discarded"); + return; + } + + else + + { + guint32 rcv_time_msw; + guint32 rcv_time_lsw; + guint32 rcv_time; + double rtt; + + rcv_time_msw = rcv_time_tv.tv_sec; + rcv_time_lsw = (guint32) ((double)rcv_time_tv.tv_usec*(double)(1LL<<32)*1.0e-6); + rcv_time = (rcv_time_msw<<16) | (rcv_time_lsw >> 16); + + rb->cum_num_packet_lost = ntoh24(rb->cum_num_packet_lost); + rb->ext_high_seq_num_rec = ntohl(rb->ext_high_seq_num_rec); + rb->interarrival_jitter = ntohl(rb->interarrival_jitter); + rb->lsr = ntohl(rb->lsr); + rb->delay_snc_last_sr = ntohl(rb->delay_snc_last_sr); + + + /* calculating Round Trip Time*/ + if (rb->lsr != 0) + { + rtt = (double) (rcv_time - rb->delay_snc_last_sr - rb->lsr); + rtt = rtt/65536; + //printf("RTT = %f s\n",rtt); + } + + } + +} + + +void rtcp_parse(RtpSession *session, mblk_t *mp) +{ + rtcp_common_header_t *rtcp; + int msgsize; + int rtcp_pk_size; + RtpStream *rtpstream=&session->rtp; + struct timeval rcv_time_tv; + + + gettimeofday(&rcv_time_tv,NULL); + + g_return_if_fail(mp!=NULL); + + msgsize=mp->b_wptr-mp->b_rptr; + + + + if (msgsize < RTCP_COMMON_HEADER_SIZE) + { + ortp_debug("Receiving too short rtcp packet... discarded"); + return; + } + + rtcp=(rtcp_common_header_t *)mp->b_rptr; + + + /* compound rtcp packet can be composed by more than one rtcp message */ + while (msgsize >= RTCP_COMMON_HEADER_SIZE) + + { + + if (rtcp->version!=2) + { + ortp_debug("Receiving rtcp packet with version number !=2...discarded"); + return; + } + + /* convert header data from network order to host order */ + rtcp->length = ntohs(rtcp->length); + + + switch (rtcp->packet_type) + + { + + case RTCP_SR: + + { + rtcp_sr_t *sr = (rtcp_sr_t *) rtcp; + report_block_t *rb; + int i; + + if ( ntohl(sr->ssrc) != session->recv_ssrc ) + { + ortp_debug("Receiving rtcp sr packet from unknown ssrc.. discarded"); + return; + } + + if (msgsize < RTCP_COMMON_HEADER_SIZE + RTCP_SSRC_FIELD_SIZE + RTCP_SENDER_INFO_SIZE + (RTCP_REPORT_BLOCK_SIZE*sr->ch.rc)) + { + ortp_debug("Receiving too short rtcp sr packet... discarded"); + return; + } + + /* parsing RTCP Sender Info */ + sr->si.ntp_timestamp_msw = ntohl(sr->si.ntp_timestamp_msw); + sr->si.ntp_timestamp_lsw = ntohl(sr->si.ntp_timestamp_lsw); + sr->si.rtp_timestamp = ntohl(sr->si.rtp_timestamp); + sr->si.senders_packet_count = ntohl(sr->si.senders_packet_count); + sr->si.senders_octet_count = ntohl(sr->si.senders_octet_count); + + /* saving data to fill LSR and DLSR field in next RTCP report to be transmitted */ + rtpstream->last_rcv_SR_ts = (sr->si.ntp_timestamp_msw << 16) | (sr->si.ntp_timestamp_lsw >> 16); + rtpstream->last_rcv_SR_time.tv_usec = rcv_time_tv.tv_usec; + rtpstream->last_rcv_SR_time.tv_sec = rcv_time_tv.tv_sec; + + + /* parsing all RTCP report blocks */ + for (i=0; i<sr->ch.rc; i++) + { + rb = &(sr->rb[i]); + report_block_parse(session, rb, rcv_time_tv); + } + + } + break; + + + + case RTCP_RR: + + { + rtcp_rr_t *rr = (rtcp_rr_t *) rtcp; + report_block_t *rb; + int i; + + if ( ntohl(rr->ssrc) != session->recv_ssrc ) + { + ortp_debug("Receiving rtcp rr packet from unknown ssrc.. discarded"); + return; + } + + if (msgsize < RTCP_COMMON_HEADER_SIZE + RTCP_SSRC_FIELD_SIZE + (RTCP_REPORT_BLOCK_SIZE*rr->ch.rc)) + { + ortp_debug("Receiving too short rtcp sr packet... discarded"); + return; + } + + /* parsing all RTCP report blocks */ + for (i=0; i<rr->ch.rc; i++) + { + rb = &(rr->rb[i]); + report_block_parse(session, rb, rcv_time_tv); + } + + } + break; + + + case RTCP_SDES: + /* to be implemented */ + break; + + + case RTCP_BYE: + /* to be implemented */ + break; + + + case RTCP_APP: + /* to be implemented */ + break; + + + default: + + ortp_debug("Receiving unknown rtcp packet type... discarded"); + return; + + } + + + rtcp_pk_size = ((rtcp->length)+1)*4; /* current RTCP packet size, in octets */ + msgsize -= rtcp_pk_size; /* size of unparsed portion of UDP packet, in octets */ + rtcp = (rtcp_common_header_t *) (rtcp_pk_size + (char *) rtcp); /* pointer to next RTCP packet in current UDP packet */ + + } +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtp.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtp.h new file mode 100644 index 00000000..625d2111 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtp.h @@ -0,0 +1,90 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef RTP_H +#define RTP_H + +#include <rtpport.h> + + + + +#define RTP_MAX_RQ_SIZE 100 /* max number of packet allowed to be enqueued */ + +#define IPMAXLEN 20 +#define UDP_MAX_SIZE 65536 +#define RTP_FIXED_HEADER_SIZE 12 +#define RTP_DEFAULT_JITTER_TIME 80 /*miliseconds*/ + + + +typedef struct rtp_header +{ +#ifdef WORDS_BIGENDIAN + guint16 version:2; + guint16 padbit:1; + guint16 extbit:1; + guint16 cc:4; + guint16 markbit:1; + guint16 paytype:7; +#else + guint16 cc:4; + guint16 extbit:1; + guint16 padbit:1; + guint16 version:2; + guint16 paytype:7; + guint16 markbit:1; +#endif + guint16 seq_number; + guint32 timestamp; + guint32 ssrc; + guint32 csrc[16]; +} rtp_header_t; + + + + +typedef struct rtp_stats +{ + guint64 packet_sent; + guint64 sent; /* bytes sent */ + guint64 recv; /* bytes received and delivered in time to the application */ + guint64 hw_recv; /* bytes of udp packets received */ + guint64 packet_recv; /* number of packets received */ + guint64 unavaillable; /* packets not availlable when they were queried */ + guint64 outoftime; /* number of packets that were received too late */ + guint64 skipped; /* number of packets skipped (that the application never queried + or that need to be skipped in order to compensate a clock slide (see adaptive jitter control)) */ + guint64 cum_packet_loss; /* cumulative number of packet lost */ + guint64 bad; /* packets that did not appear to be RTP */ + guint64 discarded; /* incoming packets discarded because the queue exceeds its max size */ +} rtp_stats_t; + +#define RTP_TIMESTAMP_IS_NEWER_THAN(ts1,ts2) \ + ((guint32)((guint32)(ts1) - (guint32)(ts2))< (guint32)(1<<31)) + +#define RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN(ts1,ts2) \ + ( ((guint32)((guint32)(ts1) - (guint32)(ts2))< (guint32)(1<<31)) && (ts1)!=(ts2) ) + +#define TIME_IS_NEWER_THAN(t1,t2) RTP_TIMESTAMP_IS_NEWER_THAN(t1,t2) + +#define TIME_IS_STRICTLY_NEWER_THAN(t1,t2) RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN(t1,t2) + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.c new file mode 100644 index 00000000..50aeef10 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.c @@ -0,0 +1,122 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + + +#include <rtp.h> +#include "rtpmod.h" + +#define RTP_SEQ_IS_GREATER(seq1,seq2)\ + ((guint16)((guint16)(seq1) - (guint16)(seq2))< (guint16)(1<<15)) + +/* put an rtp packet in queue. It is called by rtp_parse()*/ +void rtp_putq(queue_t *q, mblk_t *mp) +{ + mblk_t *tmp; + rtp_header_t *rtp=(rtp_header_t*)mp->b_rptr,*tmprtp; + /* insert message block by increasing time stamp order : the last (at the bottom) + message of the queue is the newest*/ + ortp_debug("rtp_putq(): Enqueuing packet with ts=%i and seq=%i",rtp->timestamp,rtp->seq_number); + + if (qempty(q)) { + putq(q,mp); + return; + } + tmp=qlast(q); + /* we look at the queue from bottom to top, because enqueued packets have a better chance + to be enqueued at the bottom, since there are surely newer */ + while (!qend(q,tmp)) + { + tmprtp=(rtp_header_t*)tmp->b_rptr; + ortp_debug("rtp_putq(): Seeing packet with seq=%i",tmprtp->seq_number); + + if (rtp->seq_number == tmprtp->seq_number) + { + /* this is a duplicated packet. Don't queue it */ + ortp_debug("rtp_putq: duplicated message."); + freemsg(mp); + return; + }else if (RTP_SEQ_IS_GREATER(rtp->seq_number,tmprtp->seq_number)){ + + insq(q,tmp->b_next,mp); + return; + } + tmp=tmp->b_prev; + } + /* this packet is the oldest, it has to be + placed on top of the queue */ + insq(q,qfirst(q),mp); + +} + + + +mblk_t *rtp_getq(queue_t *q,guint32 timestamp, int *rejected) +{ + mblk_t *tmp,*ret=NULL,*old; + rtp_header_t *tmprtp; + guint32 oldest; + guint32 ts_found=0; + + *rejected=0; + ortp_debug("rtp_getq(): Timestamp %i wanted.",timestamp); + + if (qempty(q)) + { + /*ortp_debug("rtp_getq: q is empty.");*/ + return NULL; + } + /* prevent somebody to ask for a timestamp that is older than the oldest of the queue */ + oldest=((rtp_header_t*) qfirst(q)->b_rptr)->timestamp; + if (RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN(oldest,timestamp)) + { + ortp_debug("rtp_getq(): asking for too old packet ! oldest=%i",oldest); + return NULL; + } + ret=NULL; + old=NULL; + /* return the packet with ts just equal or older than the asked timestamp */ + while ((tmp=qfirst(q))!=NULL) + { + tmprtp=(rtp_header_t*)tmp->b_rptr; + ortp_debug("rtp_getq: Seeing packet with ts=%i",tmprtp->timestamp); + if ( RTP_TIMESTAMP_IS_NEWER_THAN(timestamp,tmprtp->timestamp) ) + { + if (ret!=NULL && tmprtp->timestamp==ts_found) { + /* we've found two packets with same timestamp. return the first one */ + break; + } + if (old!=NULL) { + ortp_debug("rtp_getq: discarding too old packet with ts=%i",ts_found); + (*rejected)++; + freemsg(old); + } + ret=getq(q); /* dequeue the packet, since it has an interesting timestamp*/ + ts_found=tmprtp->timestamp; + ortp_debug("rtp_getq: Found packet with ts=%i",tmprtp->timestamp); + old=ret; + } + else + { + break; + } + } + return ret; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.h new file mode 100644 index 00000000..e675394d --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.h @@ -0,0 +1,31 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef RTPMOD_H +#define RTPMOD_H + +#include <rtpport.h> +#include <str_utils.h> +#include <rtp.h> + +void rtp_putq(queue_t *q, mblk_t *mp); +mblk_t *rtp_getq(queue_t *q,guint32 timestamp, int *rejected); + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c new file mode 100644 index 00000000..50ecba97 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c @@ -0,0 +1,159 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <ortp.h> +#include "rtpmod.h" +#include "jitterctl.h" + + +void split_and_queue(queue_t *q, int maxrqsz, mblk_t *mp, rtp_header_t *rtp, int *discarded) +{ + mblk_t *mdata,*tmp; + int header_size; + *discarded=0; + header_size=RTP_FIXED_HEADER_SIZE+ (4*rtp->cc); + if ((mp->b_wptr - mp->b_rptr)==header_size){ + ortp_debug("Rtp packet contains no data."); + (*discarded)++; + freemsg(mp); + return; + } + /* creates a new mblk_t to be linked with the rtp header*/ + mdata=dupb(mp); + + mp->b_wptr=mp->b_rptr+header_size; + mdata->b_rptr+=header_size; + /* link proto with data */ + mp->b_cont=mdata; + /* and then add the packet to the queue */ + + rtp_putq(q,mp); + /* make some checks: q size must not exceed RtpStream::max_rq_size */ + while (q->q_mcount > maxrqsz) + { + /* remove the oldest mblk_t */ + tmp=getq(q); + if (mp!=NULL) + { + ortp_debug("rtp_putq: Queue is full. Discarding message with ts=%i",((rtp_header_t*)mp->b_rptr)->timestamp); + freemsg(tmp); + (*discarded)++; + } + } +} + +void rtp_parse(RtpSession *session, mblk_t *mp, guint32 local_str_ts) +{ + gint i; + rtp_header_t *rtp; + int msgsize; + RtpStream *rtpstream=&session->rtp; + rtp_stats_t *stats=&rtpstream->stats; + + g_return_if_fail(mp!=NULL); + + msgsize=msgdsize(mp); + ortp_global_stats.hw_recv+=msgsize; + stats->hw_recv+=msgsize; + ortp_global_stats.packet_recv++; + stats->packet_recv++; + + session->rtp.hwrcv_since_last_SR++; + + rtp=(rtp_header_t*)mp->b_rptr; + if (rtp->version!=2) + { + ortp_debug("Receiving rtp packet with version number !=2...discarded"); + stats->bad++; + ortp_global_stats.bad++; + freemsg(mp); + return; + } + + /* convert all header data from network order to host order */ + rtp->seq_number=ntohs(rtp->seq_number); + rtp->timestamp=ntohl(rtp->timestamp); + rtp->ssrc=ntohl(rtp->ssrc); + /* convert csrc if necessary */ + if (rtp->cc*sizeof(guint32) > (msgsize-RTP_FIXED_HEADER_SIZE)){ + ortp_debug("Receiving too short rtp packet."); + stats->bad++; + ortp_global_stats.bad++; + freemsg(mp); + return; + } + for (i=0;i<rtp->cc;i++) + rtp->csrc[i]=ntohl(rtp->csrc[i]); + if (session->recv_ssrc!=0) + { + /*the ssrc is set, so we must check it */ + if (session->recv_ssrc!=rtp->ssrc){ + /*ortp_debug("rtp_parse: bad ssrc - %i",rtp->ssrc);*/ + session->recv_ssrc=rtp->ssrc; + rtp_signal_table_emit(&session->on_ssrc_changed); + } + }else session->recv_ssrc=rtp->ssrc; + + /* update some statistics */ + if (rtp->seq_number>rtpstream->hwrcv_extseq.split.lo){ + rtpstream->hwrcv_extseq.split.lo=rtp->seq_number; + }else if (rtp->seq_number<200 && rtpstream->hwrcv_extseq.split.lo>((1<<16) - 200)){ + /* this is a check for sequence number looping */ + rtpstream->hwrcv_extseq.split.lo=rtp->seq_number; + rtpstream->hwrcv_extseq.split.hi++; + } + + + /* check for possible telephone events */ + if (rtp->paytype==session->telephone_events_pt){ + split_and_queue(&session->rtp.tev_rq,session->rtp.max_rq_size,mp,rtp,&i); + stats->discarded+=i; + ortp_global_stats.discarded+=i; + return; + } + + if (!(session->flags & RTP_SESSION_RECV_SYNC)){ + gint32 slide=0; + gint32 safe_delay=0; + jitter_control_new_packet(&session->rtp.jittctl,rtp->timestamp,local_str_ts,&slide,&safe_delay); + + session->rtp.rcv_diff_ts=session->rtp.hwrcv_diff_ts + slide - safe_delay; + ortp_debug(" rcv_diff_ts=%i", session->rtp.rcv_diff_ts); + + /* detect timestamp important jumps in the future, to workaround stupid rtp senders */ + if (RTP_TIMESTAMP_IS_NEWER_THAN(rtp->timestamp,session->rtp.rcv_last_ts+session->rtp.ts_jump)){ + ortp_debug("rtp_parse: timestamp jump ?"); + rtp_signal_table_emit2(&session->on_timestamp_jump,&rtp->timestamp); + } + else if (RTP_TIMESTAMP_IS_NEWER_THAN(session->rtp.rcv_last_ts,rtp->timestamp)){ + /* avoid very old packet to enqueued, because the user is no more supposed to get them */ + ortp_debug("rtp_parse: silently discarding very old packet (ts=%i)",rtp->timestamp); + freemsg(mp); + stats->outoftime++; + ortp_global_stats.outoftime++; + return; + } + + } + + split_and_queue(&session->rtp.rq,session->rtp.max_rq_size,mp,rtp,&i); + stats->discarded+=i; + ortp_global_stats.discarded+=i; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpport.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpport.h new file mode 100644 index 00000000..65e48530 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpport.h @@ -0,0 +1,308 @@ +/* + The oRTP LinPhone RTP library intends to provide basics for a RTP stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +/* this file is responsible of the portability of the stack */ + +#ifndef RTPPORT_H +#define RTPPORT_H + +#ifdef UGLIB_H +#define HAVE_GLIB +#endif + +#ifndef _WIN32 /* do not include ortp-config.h when we are on win32 */ +# ifdef _ORTP_SOURCE +# include <ortp-config.h> +# else +# include <ortp-config.h> +# endif +#else + #include "ortp-config-win32.h" +#endif + +#define INT_TO_POINTER(truc) ((gpointer)(long)(truc)) +#define POINTER_TO_INT(truc) ((int)(long)(truc)) + +/* defines things that should be defined when we have not glib */ +#ifndef HAVE_GLIB + +#include <errno.h> +#include <sys/types.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +/* integer types */ +typedef uint64_t guint64; +typedef uint16_t guint16; +typedef uint32_t guint32; +typedef signed short gint16; +typedef int32_t gint32; +typedef unsigned int guint; +typedef int gint; +typedef char gchar; +typedef unsigned char guchar; +typedef unsigned char guint8; +typedef void* gpointer; +typedef int gboolean; +typedef double gdouble; +typedef float gfloat; + +#define TRUE 1 +#define FALSE 0 + + +/*misc*/ +#define g_return_if_fail(expr) if (!(expr)) {printf("%s:%i- assertion" #expr "failed\n",__FILE__,__LINE__); return;} +#define g_return_val_if_fail(expr,ret) if (!(expr)) {printf("%s:%i- assertion" #expr "failed\n",__FILE__,__LINE__); return (ret);} + +#include <unistd.h> +#include <stdio.h> +#include <stdarg.h> + +typedef enum { + /* GLib log levels */ + G_LOG_LEVEL_ERROR = 1 << 2, /* always fatal */ + G_LOG_LEVEL_CRITICAL = 1 << 3, + G_LOG_LEVEL_WARNING = 1 << 4, + G_LOG_LEVEL_MESSAGE = 1 << 5, + G_LOG_LEVEL_MASK = ~0 + +} GLogLevelFlags; + +#ifndef G_LOG_DOMAIN +#define G_LOG_DOMAIN ((const gchar*)"") +#endif +#ifdef __cplusplus +extern "C" { +#endif + +void g_log(const gchar *log_domain,GLogLevelFlags log_level,const gchar *format,...); +void g_logv(const gchar *log_domain,GLogLevelFlags log_level,const gchar *format,va_list args); +typedef void (*GLogFunc) (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data); +static inline void g_warning(const gchar *fmt,...) +{ + va_list args; + va_start (args, fmt); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, fmt, args); + va_end (args); +} +static inline void g_error(const gchar *fmt,...) +{ + va_list args; + va_start (args, fmt); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, fmt, args); + va_end (args); +} +static inline void g_message(const gchar *fmt,...) +{ + va_list args; + va_start (args, fmt); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, args); + va_end (args); +} +/* in order to simplify, domain is ignored when using the folowing function, ie all logs will go through your handler +whatever the domain is */ +void g_log_set_handler(const gchar *domain, GLogLevelFlags levels, GLogFunc func, gpointer ud); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_GLIB */ + + +#if defined(TIME_WITH_SYS_TIME) +#include <time.h> +#include <sys/time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#endif + + +#ifdef HAVE_GLIB + +#ifndef UGLIB_H +#include <glib.h> +#endif +#include <string.h> + + +#else /* not HAVE_GLIB */ +/* things that in glib, but should only be defined when we are not in the HPUX kernel. */ +#include <stdlib.h> +#include <pthread.h> +#include <sched.h> +#include <string.h> + +#ifdef ENABLE_MEMCHECK +extern gint ortp_allocations; +#endif + +/* memory allocation functions */ +static inline void * g_malloc(int sz) +{ + void *p=malloc(sz); + if (p==NULL) { + printf("g_malloc: Failed to allocate %i bytes: %s.\n",sz,strerror(errno)); + abort(); + } +#ifdef ENABLE_MEMCHECK + ortp_allocations++; +#endif + return p; +} + +static inline void * g_malloc0(int sz) +{ + void *p=malloc(sz); + if (p==NULL) { + printf("g_malloc: Failed to allocate %i bytes: %s.\n",sz,strerror(errno)); + abort(); + } + memset(p,0,sz); +#ifdef ENABLE_MEMCHECK + ortp_allocations++; +#endif + return p; +} + +#define g_new(type,count) (type *)g_malloc(sizeof(type)*(count)) +#define g_new0(type, count) (type *)g_malloc0(sizeof(type)*(count)) +#define g_realloc(p,sz) realloc((p),(sz)) +static inline void g_free(void *p) +{ +#ifdef ENABLE_MEMCHECK + ortp_allocations--; +#endif + free(p); +} + +#define g_strdup(machin) strdup(machin) + +typedef pthread_mutex_t GMutex; +static inline GMutex * g_mutex_new() +{ + pthread_mutex_t *mutex=g_new(pthread_mutex_t,1); + pthread_mutex_init(mutex,NULL); + return mutex; +} +typedef enum +{ + G_THREAD_PRIORITY_LOW, + G_THREAD_PRIORITY_NORMAL, + G_THREAD_PRIORITY_HIGH, + G_THREAD_PRIORITY_URGENT +} GThreadPriority; +typedef pthread_t GThread; +typedef gpointer (*GThreadFunc)(gpointer data); +static inline GThread *g_thread_create(GThreadFunc func, gpointer data, gboolean joinable, void **error){ + GThread *thread=g_new(GThread,1); + pthread_create(thread,NULL,func,data); + return thread; +} + +static inline void g_thread_join(GThread *thread){ + pthread_join(*thread,NULL); + g_free(thread); +} + +static inline void g_thread_set_priority(GThread *thread,GThreadPriority prio){ + if (prio>G_THREAD_PRIORITY_NORMAL){ + /* this is unsupported on HPUX */ + /* + struct sched_param param; + param.sched_priority=1; + sched_setscheduler(*thread,SCHED_RR,¶m); + */ + } +} + +#define g_mutex_lock(mutex) pthread_mutex_lock((mutex)) +#define g_mutex_unlock(mutex) pthread_mutex_unlock((mutex)) +#define g_mutex_free(mutex) pthread_mutex_destroy((mutex));g_free((mutex)) + +typedef pthread_cond_t GCond; +static inline GCond * g_cond_new() +{ + pthread_cond_t *cond=g_new(pthread_cond_t,1); + pthread_cond_init(cond,NULL); + return cond; +} +#define g_cond_wait(cond,mutex) pthread_cond_wait((cond),(mutex)) +#define g_cond_signal(cond) pthread_cond_signal((cond)) +#define g_cond_broadcast(cond) pthread_cond_broadcast((cond)) +#define g_cond_free(cond) pthread_cond_destroy((cond)); g_free((cond)) + +#define g_thread_init(vtable) +#define g_thread_supported() (1) + +#endif /* HAVE_GLIB */ + + +#ifndef RTP_DEBUG +#define ortp_debug(...) +#else +#define ortp_debug g_message +#endif + +#ifdef _WIN32 +extern char *getSocketError(); +#define getSocketErrorCode() WSAGetLastError () +#else +#define getSocketError() strerror(errno) +#define getSocketErrorCode() (errno) +#endif + +#ifdef UGLIB_H +#undef HAVE_GLIB +#endif + +#undef MIN +#define MIN(a,b) (((a)>(b)) ? (b) : (a)) +#undef MAX +#define MAX(a,b) (((a)>(b)) ? (a) : (b)) + +typedef struct _dwsplit_t{ +#ifdef WORDS_BIGENDIAN + guint16 hi; + guint16 lo; +#else + guint16 lo; + guint16 hi; +#endif +} dwsplit_t; + +typedef union{ + dwsplit_t split; + guint32 one; +} poly32_t; + +#ifdef WORDS_BIGENDIAN +#define hton24(x) (x) +#else +#define hton24(x) ((( (x) & 0x00ff0000) >>16) | (( (x) & 0x000000ff) <<16) | ( (x) & 0x0000ff00) ) +#endif +#define ntoh24(x) hton24(x) + +#endif /*RTPPORT_H*/ diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.c new file mode 100644 index 00000000..de6b2e7d --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.c @@ -0,0 +1,1954 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <ortp.h> +#include <telephonyevents.h> +#include "rtpmod.h" +#include "jitterctl.h" +#include "scheduler.h" +#include "port_fct.h" +#include "utils.h" + +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> + +#ifndef _WIN32 +# include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +# ifdef INET6 +# include <netdb.h> +# endif +#else +# include <winsock2.h> +# include "errno-win32.h" +#endif + + +#if defined(HAVE_POLL_H) +#include <poll.h> +#elif defined(HAVE_SYS_POLL_H) +#include <sys/poll.h> +#endif +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#define USE_SENDMSG 1 +#endif + + + +void wait_point_init(WaitPoint *wp){ + wp->lock=g_mutex_new(); + wp->cond=g_cond_new(); + wp->time=0; + wp->wakeup=FALSE; +} +void wait_point_uninit(WaitPoint *wp){ + g_cond_free(wp->cond); + g_mutex_free(wp->lock); +} + +#define wait_point_lock(wp) g_mutex_lock((wp)->lock) +#define wait_point_unlock(wp) g_mutex_unlock((wp)->lock) + +void wait_point_wakeup_at(WaitPoint *wp, guint32 t, gboolean dosleep){ + wp->time=t; + wp->wakeup=TRUE; + if (dosleep) g_cond_wait(wp->cond,wp->lock); +} + + +gboolean wait_point_check(WaitPoint *wp, guint32 t){ + gboolean ok=FALSE; + + if (wp->wakeup){ + if (TIME_IS_NEWER_THAN(t,wp->time)){ + wp->wakeup=FALSE; + ok=TRUE; + + } + } + return ok; +} +#define wait_point_wakeup(wp) g_cond_signal((wp)->cond); + +extern void rtp_parse(RtpSession *session, mblk_t *mp, guint32 local_str_ts); + + +static guint32 guint32_random(){ + return random(); +} + +void +rtp_session_init (RtpSession * session, gint mode) +{ + memset (session, 0, sizeof (RtpSession)); + session->lock = g_mutex_new (); + session->rtp.max_rq_size = RTP_MAX_RQ_SIZE; + session->mode = mode; + if ((mode == RTP_SESSION_RECVONLY) || (mode == RTP_SESSION_SENDRECV)) + { + rtp_session_set_flag (session, RTP_SESSION_RECV_SYNC); + rtp_session_set_flag (session, RTP_SESSION_RECV_NOT_STARTED); + + } + if ((mode == RTP_SESSION_SENDONLY) || (mode == RTP_SESSION_SENDRECV)) + { + rtp_session_set_flag (session, RTP_SESSION_SEND_NOT_STARTED); + rtp_session_set_flag (session, RTP_SESSION_SEND_SYNC); + session->send_ssrc=guint32_random(); + /* set default source description */ + rtp_session_set_source_description(session,"unknown@unknown",NULL,NULL, + NULL,NULL,"oRTP-" ORTP_VERSION,"This is free sofware (LGPL) !"); + } + session->telephone_events_pt=-1; /* not defined a priori */ + rtp_session_set_profile (session, &av_profile); /*the default profile to work with */ + session->payload_type=0;/* default to something */ + qinit(&session->rtp.rq); + qinit(&session->rtp.tev_rq); + qinit(&session->contributing_sources); + /* init signal tables */ + rtp_signal_table_init (&session->on_ssrc_changed, session,"ssrc_changed"); + rtp_signal_table_init (&session->on_payload_type_changed, session,"payload_type_changed"); + rtp_signal_table_init (&session->on_telephone_event, session,"telephone-event"); + rtp_signal_table_init (&session->on_telephone_event_packet, session,"telephone-event_packet"); + rtp_signal_table_init (&session->on_timestamp_jump,session,"timestamp_jump"); + rtp_signal_table_init (&session->on_network_error,session,"network_error"); + wait_point_init(&session->send_wp); + wait_point_init(&session->recv_wp); + rtp_session_set_jitter_compensation(session,RTP_DEFAULT_JITTER_TIME); + rtp_session_enable_adaptive_jitter_compensation(session,FALSE); + rtp_session_set_time_jump_limit(session,5000); + session->max_buf_size = UDP_MAX_SIZE; +} + +/** + *rtp_session_new: + *@mode: One of the #RtpSessionMode flags. + * + * Creates a new rtp session. + * If the session is able to send data (RTP_SESSION_SENDONLY or RTP_SESSION_SENDRECV), then a + * random SSRC number is choosed for the outgoing stream. + * + *Returns: the newly created rtp session. +**/ + +RtpSession * +rtp_session_new (gint mode) +{ + RtpSession *session; + session = g_malloc (sizeof (RtpSession)); + rtp_session_init (session, mode); + return session; +} + +/** + *rtp_session_set_scheduling_mode: + *@session: a rtp session. + *@yesno: a boolean to indicate the scheduling mode. + * + * Sets the scheduling mode of the rtp session. If @yesno is TRUE, the rtp session is in + * the scheduled mode, that means that you can use session_set_select() to block until it's time + * to receive or send on this session according to the timestamp passed to the respective functions. + * You can also use blocking mode (see rtp_session_set_blocking_mode() ), to simply block within + * the receive and send functions. + * If @yesno is FALSE, the ortp scheduler will not manage those sessions, meaning that blocking mode + * and the use of session_set_select() for this session are disabled. + * +**/ + +void +rtp_session_set_scheduling_mode (RtpSession * session, gint yesno) +{ + if (yesno) + { + RtpScheduler *sched; + sched = ortp_get_scheduler (); + if (sched != NULL) + { + rtp_session_set_flag (session, RTP_SESSION_SCHEDULED); + session->sched = sched; + rtp_scheduler_add_session (sched, session); + } + else + g_warning + ("rtp_session_set_scheduling_mode: Cannot use scheduled mode because the " + "scheduler is not started. Use ortp_scheduler_init() before."); + } + else + rtp_session_unset_flag (session, RTP_SESSION_SCHEDULED); +} + + +/** + *rtp_session_set_blocking_mode: + *@session: a rtp session + *@yesno: a boolean + * + * Using this function implies that you previously enabled scheduled mode on the session + * (see rtp_session_set_scheduling_mode() ). + * rtp_session_set_blocking_mode() defines the behaviour of the rtp_session_recv_with_ts() and + * rtp_session_send_with_ts() functions. If @yesno is TRUE, rtp_session_recv_with_ts() + * will block until it is time for the packet to be received, according to the timestamp + * passed to the function. After this time, the function returns. + * For rtp_session_send_with_ts(), it will block until it is time for the packet to be sent. + * If @yesno is FALSE, then the two functions will return immediately. + * +**/ +void +rtp_session_set_blocking_mode (RtpSession * session, gint yesno) +{ + if (yesno) + rtp_session_set_flag (session, RTP_SESSION_BLOCKING_MODE); + else + rtp_session_unset_flag (session, RTP_SESSION_BLOCKING_MODE); +} + +/** + *rtp_session_set_profile: + *@session: a rtp session + *@profile: a rtp profile + * + * Set the RTP profile to be used for the session. By default, all session are created by + * rtp_session_new() are initialized with the AV profile, as defined in RFC 1890. The application + * can set any other profile instead using that function. + * + * +**/ + +void +rtp_session_set_profile (RtpSession * session, RtpProfile * profile) +{ + session->profile = profile; + rtp_session_telephone_events_supported(session); +} + + +/** + *rtp_session_signal_connect: + *@session: a rtp session + *@signal: the name of a signal + *@cb: a #RtpCallback + *@user_data: a pointer to any data to be passed when invoking the callback. + * + * This function provides the way for an application to be informed of various events that + * may occur during a rtp session. @signal is a string identifying the event, and @cb is + * a user supplied function in charge of processing it. The application can register + * several callbacks for the same signal, in the limit of #RTP_CALLBACK_TABLE_MAX_ENTRIES. + * Here are name and meaning of supported signals types: + * + * "ssrc_changed" : the SSRC of the incoming stream has changed. + * + * "payload_type_changed" : the payload type of the incoming stream has changed. + * + * "telephone-event_packet" : a telephone-event rtp packet (RFC2833) is received. + * + * "telephone-event" : a telephone event has occured. This is a high-level shortcut for "telephone-event_packet". + * + * "network_error" : a network error happened on a socket. Arguments of the callback functions are + * a const char * explaining the error, an int errno error code and the user_data as usual. + * + * "timestamp_jump" : we have received a packet with timestamp in far future compared to last timestamp received. + * The farness of far future is set by rtp_sesssion_set_time_jump_limit() + * + * Returns: 0 on success, -EOPNOTSUPP if the signal does not exists, -1 if no more callbacks + * can be assigned to the signal type. +**/ +int +rtp_session_signal_connect (RtpSession * session, const char *signal, + RtpCallback cb, gpointer user_data) +{ + OList *elem; + for (elem=session->signal_tables;elem!=NULL;elem=o_list_next(elem)){ + RtpSignalTable *s=(RtpSignalTable*) elem->data; + if (strcmp(signal,s->signal_name)==0){ + return rtp_signal_table_add(s,cb,user_data); + } + } + g_warning ("rtp_session_signal_connect: inexistant signal %s",signal); + return -1; +} + + +/** + *rtp_session_signal_disconnect_by_callback: + *@session: a rtp session + *@signal: a signal name + *@cb: a callback function. + * + * Removes callback function @cb to the list of callbacks for signal @signal. + * + *Returns: 0 on success, -ENOENT if the callbacks was not found. +**/ + +int +rtp_session_signal_disconnect_by_callback (RtpSession * session, const gchar *signal, + RtpCallback cb) +{ + OList *elem; + for (elem=session->signal_tables;elem!=NULL;elem=o_list_next(elem)){ + RtpSignalTable *s=(RtpSignalTable*) elem->data; + if (strcmp(signal,s->signal_name)==0){ + return rtp_signal_table_remove_by_callback(s,cb); + } + } + g_warning ("rtp_session_signal_connect: inexistant signal %s",signal); + return -1; +} + +/** + *rtp_session_set_local_addr: + *@session: a rtp session freshly created. + *@addr: a local IP address in the xxx.xxx.xxx.xxx form. + *@port: a local port. + * + * Specify the local addr to be use to listen for rtp packets or to send rtp packet from. + * In case where the rtp session is send-only, then it is not required to call this function: + * when calling rtp_session_set_remote_addr(), if no local address has been set, then the + * default INADRR_ANY (0.0.0.0) IP address with a random port will be used. Calling + * rtp_sesession_set_local_addr() is mandatory when the session is recv-only or duplex. + * + * Returns: 0 on success. +**/ + +gint +rtp_session_set_local_addr (RtpSession * session, const gchar * addr, gint port) +{ + gint err; + gint optval = 1; +#ifdef INET6 + char num[8]; + struct addrinfo hints, *res0, *res; +#endif + + if (session->rtp.socket>0) { + /* dont try to rebind, close socket before */ + close_socket(session->rtp.socket); + close_socket(session->rtcp.socket); + session->rtp.socket=0; + session->rtcp.socket=0; + } + +#ifdef INET6 + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + snprintf(num, sizeof(num), "%d",port); + err = getaddrinfo(addr,num, &hints, &res0); + if (err!=0) { + g_warning ("Error: %s", gai_strerror(err)); + return err; + } + + for (res = res0; res; res = res->ai_next) { + session->rtp.socket = socket(res->ai_family, res->ai_socktype, 0); + if (session->rtp.socket < 0) + continue; + + err = setsockopt (session->rtp.socket, SOL_SOCKET, SO_REUSEADDR, + (void*)&optval, sizeof (optval)); + if (err < 0) + { + g_warning ("Fail to set rtp address reusable: %s.", getSocketError()); + } + + session->rtp.socktype=res->ai_family; + memcpy(&session->rtp.loc_addr, res->ai_addr, res->ai_addrlen); + err = bind (session->rtp.socket, res->ai_addr, res->ai_addrlen); + if (err != 0) + { + g_warning ("Fail to bind rtp socket to port %i: %s.", port, getSocketError()); + close_socket (session->rtp.socket); + continue; + } +#ifndef __hpux + switch (res->ai_family) + { + case AF_INET: + if (IN_MULTICAST(ntohl(((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr))) + { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr; + mreq.imr_interface.s_addr = INADDR_ANY; + err = setsockopt(session->rtp.socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (err < 0) + { + g_warning ("Fail to join address group: %s.", getSocketError()); + close_socket (session->rtp.socket); + continue; + } + } + break; + case AF_INET6: + if (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr))) + { + struct ipv6_mreq mreq; + mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; + mreq.ipv6mr_interface = 0; + err = setsockopt(session->rtp.socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + if (err < 0) + { + g_warning ("Fail to join address group: %s.", getSocketError()); + close_socket (session->rtp.socket); + continue; + } + } + break; + } +#endif + break; + } + freeaddrinfo(res0); + if (session->rtp.socket < 0){ + if (session->mode==RTP_SESSION_RECVONLY) g_warning("Could not create rtp socket with address %s: %s",addr,getSocketError()); + return -1; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + snprintf(num, sizeof(num), "%d", (port + 1)); + + err = getaddrinfo(addr, num, &hints, &res0); + if (err!=0) { + g_warning ("Error: %s", gai_strerror(err)); + return err; + } + + for (res = res0; res; res = res->ai_next) { + session->rtcp.socket = socket(res->ai_family, res->ai_socktype, 0); + + if (session->rtcp.socket < 0) + continue; + + err = setsockopt (session->rtcp.socket, SOL_SOCKET, SO_REUSEADDR, + (void*)&optval, sizeof (optval)); + if (err < 0) + { + g_warning ("Fail to set rtcp address reusable: %s.",getSocketError()); + } + session->rtcp.socktype=res->ai_family; + memcpy( &session->rtcp.loc_addr, res->ai_addr, res->ai_addrlen); + err = bind (session->rtcp.socket, res->ai_addr, res->ai_addrlen); + if (err != 0) + { + g_warning ("Fail to bind rtp socket to port %i: %s.", port, getSocketError()); + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + continue; + } +#ifndef __hpux + switch (res->ai_family) + { + case AF_INET: + if (IN_MULTICAST(ntohl(((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr))) + { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr; + mreq.imr_interface.s_addr = INADDR_ANY; + err = setsockopt(session->rtcp.socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (err < 0) + { + g_warning ("Fail to join address group: %s.", getSocketError()); + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + continue; + } + } + break; + case AF_INET6: + if (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr))) + { + struct ipv6_mreq mreq; + mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; + mreq.ipv6mr_interface = 0; + err = setsockopt(session->rtcp.socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + if (err < 0) + { + g_warning ("Fail to join address group: %s.", getSocketError()); + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + continue; + } + } + break; + } +#endif + + break; + } + freeaddrinfo(res0); + if (session->rtp.socket < 0){ + g_warning("Could not create rtcp socket with address %s: %s",addr,getSocketError()); + return -1; + } +#else + session->rtp.loc_addr.sin_family = AF_INET; + + err = inet_aton (addr, &session->rtp.loc_addr.sin_addr); + + if (err < 0) + { + g_warning ("Error in socket address:%s.", getSocketError()); + return err; + } + session->rtp.loc_addr.sin_port = htons (port); + + session->rtp.socket = socket (PF_INET, SOCK_DGRAM, 0); + g_return_val_if_fail (session->rtp.socket > 0, -1); + + err = setsockopt (session->rtp.socket, SOL_SOCKET, SO_REUSEADDR, + (void*)&optval, sizeof (optval)); + if (err < 0) + { + g_warning ("Fail to set rtp address reusable: %s.",getSocketError()); + } + + err = bind (session->rtp.socket, + (struct sockaddr *) &session->rtp.loc_addr, + sizeof (struct sockaddr_in)); + + if (err != 0) + { + g_warning ("Fail to bind rtp socket to port %i: %s.", port, getSocketError()); + close_socket (session->rtp.socket); + return -1; + } + memcpy (&session->rtcp.loc_addr, &session->rtp.loc_addr, + sizeof (struct sockaddr_in)); + session->rtcp.loc_addr.sin_port = htons (port + 1); + session->rtcp.socket = socket (PF_INET, SOCK_DGRAM, 0); + g_return_val_if_fail (session->rtcp.socket > 0, -1); + + err = setsockopt (session->rtcp.socket, SOL_SOCKET, SO_REUSEADDR, + (void*)&optval, sizeof (optval)); + if (err < 0) + { + g_warning ("Fail to set rtcp address reusable: %s.",getSocketError()); + } + + err = bind (session->rtcp.socket, + (struct sockaddr *) &session->rtcp.loc_addr, + sizeof (struct sockaddr_in)); + if (err != 0) + { + g_warning ("Fail to bind rtcp socket to port %i: %s.", port + 1, getSocketError()); + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + return -1; + } +#ifndef __hpux + if (IN_MULTICAST(ntohl(session->rtp.loc_addr.sin_addr.s_addr))) + { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = session->rtp.loc_addr.sin_addr.s_addr; + mreq.imr_interface.s_addr = INADDR_ANY; + err = setsockopt(session->rtp.socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (err == 0) + err = setsockopt(session->rtcp.socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (err < 0) + { + g_warning ("Fail to join address group: %s.", getSocketError()); + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + return -1; + } + } +#endif +#endif + /* set RTP socket options */ + set_non_blocking_socket (session->rtp.socket); + /* set RTCP socket options */ + set_non_blocking_socket (session->rtcp.socket); + return 0; +} + + +/** + *rtp_session_set_remote_addr: + *@session: a rtp session freshly created. + *@addr: a local IP address in the xxx.xxx.xxx.xxx form. + *@port: a local port. + * + * Sets the remote address of the rtp session, ie the destination address where rtp packet + * are sent. If the session is recv-only or duplex, it also sets the origin of incoming RTP + * packets. Rtp packets that don't come from addr:port are discarded. + * + * Returns: 0 on success. +**/ + +gint +rtp_session_set_remote_addr (RtpSession * session, const gchar * addr, gint port) +{ + gint err; +#ifdef INET6 + struct addrinfo hints, *res0, *res; + char num[8]; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + snprintf(num, sizeof(num), "%d", port); + err = getaddrinfo(addr, num, &hints, &res0); + if (err) { + g_warning ("Error in socket address: %s", gai_strerror(err)); + return err; + } +#endif + + if (session->rtp.socket == 0) + { + int retry; + /* the session has not its socket bound, do it */ + g_message ("Setting random local addresses."); + for (retry=0;retry<10;retry++) + { + int localport; + do + { + localport = (rand () + 5000) & 0xfffe; + } + while ((localport < 5000) || (localport > 0xffff)); +#ifdef INET6 + /* bind to an address type that matches the destination address */ + if (res0->ai_addr->sa_family==AF_INET6) + err = rtp_session_set_local_addr (session, "::", localport); + else err=rtp_session_set_local_addr (session, "0.0.0.0", localport); +#else + err = rtp_session_set_local_addr (session, "0.0.0.0", localport); +#endif + + if (err == 0) + break; + } + if (retry == 10){ + g_warning("rtp_session_set_remote_addr: Could not find a random local address for socket !"); + return -1; + } + } + + +#ifdef INET6 + err=1; + for (res = res0; res; res = res->ai_next) { + /* set a destination address that has the same type as the local address */ + if (res->ai_family==session->rtp.socktype ) { + memcpy( &session->rtp.rem_addr, res->ai_addr, res->ai_addrlen); + session->rtp.addrlen=res->ai_addrlen; + err=0; + break; + } + } + freeaddrinfo(res0); + if (err) { + g_warning("Could not set destination for RTP socket to %s:%i.",addr,port); + return -1; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + snprintf(num, sizeof(num), "%d", (port + 1)); + err = getaddrinfo(addr, num, &hints, &res0); + if (err) { + g_warning ("Error: %s", gai_strerror(err)); + return err; + } + err=1; + for (res = res0; res; res = res->ai_next) { + /* set a destination address that has the same type as the local address */ + if (res->ai_family==session->rtp.socktype ) { + err=0; + memcpy( &session->rtcp.rem_addr, res->ai_addr, res->ai_addrlen); + session->rtcp.addrlen=res->ai_addrlen; + break; + } + } + freeaddrinfo(res0); + if (err) { + g_warning("Could not set destination for RCTP socket to %s:%i.",addr,port+1); + return -1; + } +#else + session->rtp.addrlen=sizeof(session->rtp.rem_addr); + session->rtp.rem_addr.sin_family = AF_INET; + + err = inet_aton (addr, &session->rtp.rem_addr.sin_addr); + if (err < 0) + { + g_warning ("Error in socket address:%s.", getSocketError()); + return err; + } + session->rtp.rem_addr.sin_port = htons (port); + + memcpy (&session->rtcp.rem_addr, &session->rtp.rem_addr, + sizeof (struct sockaddr_in)); + session->rtcp.rem_addr.sin_port = htons (port + 1); + session->rtcp.addrlen=sizeof(session->rtp.rem_addr); +#endif +#ifndef NOCONNECT + if (session->mode == RTP_SESSION_SENDONLY) + { + err = connect (session->rtp.socket, + (struct sockaddr *) &session->rtp.rem_addr, +#ifdef INET6 + session->rtp.addrlen); +#else + sizeof (struct sockaddr_in)); +#endif + if (err != 0) + { + g_message ("Can't connect rtp socket: %s.",getSocketError()); + return err; + } + err = connect (session->rtcp.socket, + (struct sockaddr *) &session->rtcp.rem_addr, +#ifdef INET6 + session->rtcp.addrlen); +#else + sizeof (struct sockaddr_in)); +#endif + if (err != 0) + { + g_message ("Can't connect rtp socket: %s.",getSocketError()); + return err; + } + } +#endif + return 0; +} + +void rtp_session_set_sockets(RtpSession *session, gint rtpfd, gint rtcpfd) +{ + if (rtpfd>0) set_non_blocking_socket(rtpfd); + if (rtcpfd>0) set_non_blocking_socket(rtcpfd); + session->rtp.socket=rtpfd; + session->rtcp.socket=rtcpfd; + session->flags|=RTP_SESSION_USING_EXT_SOCKETS; +} + +/** + *rtp_session_flush_sockets: + *@session: a rtp session + * + * Flushes the sockets for all pending incoming packets. + * This can be usefull if you did not listen to the stream for a while + * and wishes to start to receive again. During the time no receive is made + * packets get bufferised into the internal kernel socket structure. + * +**/ +void rtp_session_flush_sockets(RtpSession *session){ + char trash[4096]; +#ifdef INET6 + struct sockaddr_storage from; +#else + struct sockaddr from; +#endif + socklen_t fromlen=sizeof(from); + if (session->rtp.socket>0){ + while (recvfrom(session->rtp.socket,(void*)trash,sizeof(trash),0,(struct sockaddr *)&from,&fromlen)>0){}; + } + if (session->rtcp.socket>0){ + while (recvfrom(session->rtcp.socket,(void*)trash,sizeof(trash),0,(struct sockaddr*)&from,&fromlen)>0){}; + } +} + +/** + *rtp_session_set_seq_number: + *@session: a rtp session freshly created. + *@addr: a 16 bit unsigned number. + * + * sets the initial sequence number of a sending session. + * +**/ +void rtp_session_set_seq_number(RtpSession *session, guint16 seq){ + session->rtp.snd_seq=seq; +} + + +guint16 rtp_session_get_seq_number(RtpSession *session){ + return session->rtp.snd_seq; +} + + +#ifdef USE_SENDMSG +#define MAX_IOV 10 +static gint rtp_sendmsg(int sock,mblk_t *m, struct sockaddr *rem_addr, int addr_len){ + int error; + struct msghdr msg; + struct iovec iov[MAX_IOV]; + int iovlen; + for(iovlen=0; iovlen<MAX_IOV && m!=NULL; m=m->b_cont,iovlen++){ + iov[iovlen].iov_base=m->b_rptr; + iov[iovlen].iov_len=m->b_wptr-m->b_rptr; + } + msg.msg_name=(void*)rem_addr; + msg.msg_namelen=addr_len; + msg.msg_iov=&iov[0]; + msg.msg_iovlen=iovlen; + msg.msg_control=NULL; + msg.msg_controllen=0; + msg.msg_flags=0; + + error=sendmsg(sock,&msg,0); + return error; +} +#endif + +static gint +ortp_rtp_send (RtpSession * session, mblk_t * m) +{ + gint error; + int i; + rtp_header_t *hdr; + + hdr = (rtp_header_t *) m->b_rptr; + /* perform host to network conversions */ + hdr->ssrc = htonl (hdr->ssrc); + hdr->timestamp = htonl (hdr->timestamp); + hdr->seq_number = htons (hdr->seq_number); + for (i = 0; i < hdr->cc; i++) + hdr->csrc[i] = htonl (hdr->csrc[i]); + +#ifdef USE_SENDMSG + if (session->flags & RTP_SESSION_USING_EXT_SOCKETS){ + error=rtp_sendmsg(session->rtp.socket,m,(struct sockaddr *)NULL,0); + }else { + error=rtp_sendmsg(session->rtp.socket,m,(struct sockaddr *) &session->rtp.rem_addr, + session->rtp.addrlen); + } +#else + if (m->b_cont!=NULL){ + mblk_t *newm=msgpullup(m,-1); + freemsg(m); + m=newm; + } + if (session->flags & RTP_SESSION_USING_EXT_SOCKETS){ + error=send(session->rtp.socket, m->b_rptr, (m->b_wptr - m->b_rptr),0); + }else error = sendto (session->rtp.socket, m->b_rptr, + (m->b_wptr - m->b_rptr), 0, + (struct sockaddr *) &session->rtp.rem_addr, + session->rtp.addrlen); +#endif + if (error < 0){ + if (session->on_network_error.count>0){ + rtp_signal_table_emit3(&session->on_network_error,(gpointer)"Error sending RTP packet",INT_TO_POINTER(getSocketErrorCode())); + }else g_warning ("Error sending rtp packet: %s ; socket=%i", getSocketError(), session->rtp.socket); + } + freemsg (m); + return error; +} + +gint +ortp_rtcp_send (RtpSession * session, mblk_t * m) +{ + gint error=0; + gboolean using_ext_socket=(session->flags & RTP_SESSION_USING_EXT_SOCKETS)!=0; + if ( (using_ext_socket && session->rtcp.socket>0 ) || session->rtcp.addrlen>0){ + +#ifndef USE_SENDMSG + if (m->b_cont!=NULL){ + mblk_t *newm=msgpullup(m,-1); + freemsg(m); + m=newm; + } +#endif + if (using_ext_socket && session->rtcp.socket>0 ){ +#ifdef USE_SENDMSG + error=rtp_sendmsg(session->rtcp.socket,m,(struct sockaddr *)NULL,0); +#else + error=send(session->rtcp.socket, m->b_rptr, (m->b_wptr - m->b_rptr),0); +#endif + }else { +#ifdef USE_SENDMSG + error=rtp_sendmsg(session->rtcp.socket,m,(struct sockaddr *) &session->rtcp.rem_addr, + session->rtcp.addrlen); +#else + error = sendto (session->rtcp.socket, m->b_rptr, + (m->b_wptr - m->b_rptr), 0, + (struct sockaddr *) &session->rtcp.rem_addr, + session->rtcp.addrlen); +#endif + } + + if (error < 0){ + if (session->on_network_error.count>0){ + rtp_signal_table_emit3(&session->on_network_error,(gpointer)"Error sending RTCP packet",INT_TO_POINTER(getSocketErrorCode())); + }else g_warning ("Error sending rtcp packet: %s ; socket=%i", getSocketError(), session->rtcp.socket); + } + }else g_warning("Cannot send rtcp report because I don't know the remote address."); + freemsg (m); + return error; +} + + +/** + *rtp_session_set_ssrc: + *@session: a rtp session. + *@ssrc: an unsigned 32bit integer representing the synchronisation source identifier (SSRC). + * + * Sets the SSRC for the outgoing stream. + * If not done, a random ssrc is used. + * +**/ +void +rtp_session_set_ssrc (RtpSession * session, guint32 ssrc) +{ + session->send_ssrc = ssrc; +} + +/* this function initialize all session parameter's that depend on the payload type */ +static void payload_type_changed(RtpSession *session, PayloadType *pt){ + jitter_control_set_payload(&session->rtp.jittctl,pt); + session->rtp.rtcp_report_snt_interval=RTCP_DEFAULT_REPORT_INTERVAL*pt->clock_rate; + rtp_session_set_time_jump_limit(session,session->rtp.time_jump); +} + +/** + *rtp_session_set_payload_type: + *@session: a rtp session + *@paytype: the payload type + * + * Sets the payload type of the rtp session. It decides of the payload types written in the + * of the rtp header for the outgoing stream, if the session is SENDRECV or SENDONLY. + * For the incoming stream, it sets the waited payload type. If that value does not match + * at any time this waited value, then the application can be informed by registering + * for the "payload_type_changed" signal, so that it can make the necessary changes + * on the downstream decoder that deals with the payload of the packets. + * + *Returns: 0 on success, -1 if the payload is not defined. +**/ + +int +rtp_session_set_payload_type (RtpSession * session, int paytype) +{ + PayloadType *pt; + session->payload_type = paytype; + pt=rtp_profile_get_payload(session->profile,paytype); + if (pt!=NULL){ + payload_type_changed(session,pt); + } + return 0; +} + +int rtp_session_get_payload_type(RtpSession *session){ + return session->payload_type; +} + + +/** + *rtp_session_set_payload_type_with_string: + *@session: a rtp session + *@paytype: the payload type + * + * Sets the payload type of the rtp session. It decides of the payload types written in the + * of the rtp header for the outgoing stream, if the session is SENDRECV or SENDONLY. + * Unlike #rtp_session_set_payload_type(), it takes as argument a string referencing the + * payload type (mime type). + * For the incoming stream, it sets the waited payload type. If that value does not match + * at any time this waited value, then the application can be informed by registering + * for the "payload_type_changed" signal, so that it can make the necessary changes + * on the downstream decoder that deals with the payload of the packets. + * + *Returns: 0 on success, -1 if the payload is not defined. +**/ + +int +rtp_session_set_payload_type_with_string (RtpSession * session, const char * mime) +{ + int pt; + pt=rtp_profile_get_payload_number_from_mime(session->profile,mime); + if (pt<0) { + g_warning("%s is not a know mime string within the rtpsession's profile.",mime); + return -1; + } + rtp_session_set_payload_type(session,pt); + return 0; +} + + +/** + *rtp_session_create_packet: + *@session: a rtp session. + *@header_size: the rtp header size. For standart size (without extensions), it is #RTP_FIXED_HEADER_SIZE + *@payload :data to be copied into the rtp packet. + *@payload_size : size of data carried by the rtp packet. + * + * Allocates a new rtp packet. In the header, ssrc and payload_type according to the session's + * context. Timestamp and seq number are not set, there will be set when the packet is going to be + * sent with rtp_session_sendm_with_ts(). + * + *Returns: a rtp packet in a mblk_t (message block) structure. +**/ +mblk_t * rtp_session_create_packet(RtpSession *session,gint header_size, const char *payload, gint payload_size) +{ + mblk_t *mp; + gint msglen=header_size+payload_size; + rtp_header_t *rtp; + + mp=allocb(msglen,BPRI_MED); + rtp=(rtp_header_t*)mp->b_rptr; + rtp->version = 2; + rtp->padbit = 0; + rtp->extbit = 0; + rtp->markbit= 0; + rtp->cc = 0; + rtp->paytype = session->payload_type; + rtp->ssrc = session->send_ssrc; + rtp->timestamp = 0; /* set later, when packet is sended */ + rtp->seq_number = 0; /*set later, when packet is sended */ + /*copy the payload */ + mp->b_wptr+=header_size; + memcpy(mp->b_wptr,payload,payload_size); + mp->b_wptr+=payload_size; + return mp; +} + +/** + *rtp_session_create_packet_with_data: + *@session: a rtp session. + *@payload : the data to be sent with this packet + *@payload_size : size of data + *@freefn : a function that will be called when the payload buffer is no more needed. + * + * Creates a new rtp packet using the given payload buffer (no copy). The header will be allocated separetely. + * In the header, ssrc and payload_type according to the session's + * context. Timestamp and seq number are not set, there will be set when the packet is going to be + * sent with rtp_session_sendm_with_ts(). + * oRTP will send this packet using libc's sendmsg() (if this function is availlable!) so that there will be no + * packet concatenation involving copies to be done in user-space. + * @freefn can be NULL, in that case payload will be kept untouched. + * + *Returns: a rtp packet in a mblk_t (message block) structure. +**/ + +mblk_t * rtp_session_create_packet_with_data(RtpSession *session, char *payload, gint payload_size, void (*freefn)(void*)) +{ + mblk_t *mp,*mpayload; + gint header_size=RTP_FIXED_HEADER_SIZE; /* revisit when support for csrc is done */ + rtp_header_t *rtp; + + mp=allocb(header_size,BPRI_MED); + rtp=(rtp_header_t*)mp->b_rptr; + rtp->version = 2; + rtp->padbit = 0; + rtp->extbit = 0; + rtp->markbit= 0; + rtp->cc = 0; + rtp->paytype = session->payload_type; + rtp->ssrc = session->send_ssrc; + rtp->timestamp = 0; /* set later, when packet is sended */ + rtp->seq_number = 0; /*set later, when packet is sended */ + mp->b_wptr+=header_size; + /* create a mblk_t around the user supplied payload buffer */ + mpayload=allocb_with_buf(payload,payload_size,BPRI_MED,freefn); + mpayload->b_wptr+=payload_size; + /* link it with the header */ + mp->b_cont=mpayload; + return mp; +} + + +/** + *rtp_session_create_packet_in_place: + *@session: a rtp session. + *@buffer: a buffer that contains first just enough place to write a RTP header, then the data to send. + *@size : the size of the buffer + *@freefn : a function that will be called once the buffer is no more needed (the data has been sent). + * + * Creates a new rtp packet using the buffer given in arguments (no copy). + * In the header, ssrc and payload_type according to the session's + * context. Timestamp and seq number are not set, there will be set when the packet is going to be + * sent with rtp_session_sendm_with_ts(). + * @freefn can be NULL, in that case payload will be kept untouched. + * + *Returns: a rtp packet in a mblk_t (message block) structure. +**/ +mblk_t * rtp_session_create_packet_in_place(RtpSession *session,char *buffer, gint size, void (*freefn)(void*) ) +{ + mblk_t *mp; + rtp_header_t *rtp; + + mp=allocb_with_buf(buffer,size,BPRI_MED,freefn); + + rtp=(rtp_header_t*)mp->b_rptr; + rtp->version = 2; + rtp->padbit = 0; + rtp->extbit = 0; + rtp->markbit= 0; + rtp->cc = 0; + rtp->paytype = session->payload_type; + rtp->ssrc = session->send_ssrc; + rtp->timestamp = 0; /* set later, when packet is sended */ + rtp->seq_number = 0; /*set later, when packet is sended */ + return mp; +} + + +/** + *rtp_session_sendm_with_ts: + *@session : a rtp session. + *@mp : a rtp packet presented as a mblk_t. + *@timestamp: the timestamp of the data to be sent. Refer to the rfc to know what it is. + * + * Send the rtp datagram @mp to the destination set by rtp_session_set_remote_addr() + * with timestamp @timestamp. For audio data, the timestamp is the number + * of the first sample resulting of the data transmitted. See rfc1889 for details. + * The packet (@mp) is freed once it is sended. + * + *Returns: the number of bytes sent over the network. +**/ +gint +rtp_session_sendm_with_ts (RtpSession * session, mblk_t *mp, guint32 timestamp) +{ + rtp_header_t *rtp; + guint32 packet_time; + gint error = 0; + gint payloadsize; + RtpScheduler *sched=session->sched; + RtpStream *stream=&session->rtp; + + if (session->flags & RTP_SESSION_SEND_NOT_STARTED) + { + session->rtp.snd_ts_offset = timestamp; + if (session->flags & RTP_SESSION_SCHEDULED) + { + session->rtp.snd_time_offset = sched->time_; + } + rtp_session_unset_flag (session,RTP_SESSION_SEND_NOT_STARTED); + } + /* if we are in blocking mode, then suspend the process until the scheduler it's time to send the + * next packet */ + /* if the timestamp of the packet queued is older than current time, then you we must + * not block */ + if (session->flags & RTP_SESSION_SCHEDULED) + { + packet_time = + rtp_session_ts_to_time (session, + timestamp - + session->rtp.snd_ts_offset) + + session->rtp.snd_time_offset; + /*g_message("rtp_session_send_with_ts: packet_time=%i time=%i",packet_time,sched->time_);*/ + wait_point_lock(&session->send_wp); + if (TIME_IS_STRICTLY_NEWER_THAN (packet_time, sched->time_)) + { + wait_point_wakeup_at(&session->send_wp,packet_time,(session->flags & RTP_SESSION_BLOCKING_MODE)!=0); + session_set_clr(&sched->w_sessions,session); /* the session has written */ + } + else session_set_set(&sched->w_sessions,session); /*to indicate select to return immediately */ + wait_point_unlock(&session->send_wp); + } + + + rtp=(rtp_header_t*)mp->b_rptr; + + payloadsize = msgdsize(mp) - RTP_FIXED_HEADER_SIZE - (rtp->cc*sizeof(guint32)); + rtp_session_lock (session); + + /* set a seq number */ + rtp->seq_number=session->rtp.snd_seq; + rtp->timestamp=timestamp; + session->rtp.snd_seq++; + session->rtp.snd_last_ts = timestamp; + + + ortp_global_stats.sent += payloadsize; + stream->stats.sent += payloadsize; + ortp_global_stats.packet_sent++; + stream->stats.packet_sent++; + + error = ortp_rtp_send (session, mp); + rtp_session_rtcp_process(session); + rtp_session_unlock (session); + + return error; +} + + +/** + *rtp_session_send_with_ts: + *@session: a rtp session. + *@buffer: a buffer containing the data to be sent in a rtp packet. + *@len: the length of the data buffer, in bytes. + *@userts: the timestamp of the data to be sent. Refer to the rfc to know what it is. + * + * Send a rtp datagram to the destination set by rtp_session_set_remote_addr() containing + * the data from @buffer with timestamp @userts. This is a high level function that uses + * rtp_session_create_packet() and rtp_session_sendm_with_ts() to send the data. + * + * + *Returns: the number of bytes sent over the network. +**/ +gint +rtp_session_send_with_ts (RtpSession * session, const gchar * buffer, gint len, + guint32 userts) +{ + mblk_t *m; + int err; +#ifdef USE_SENDMSG + m=rtp_session_create_packet_with_data(session,(gchar*)buffer,len,NULL); +#else + m = rtp_session_create_packet(session,RTP_FIXED_HEADER_SIZE,(gchar*)buffer,len); +#endif + err=rtp_session_sendm_with_ts(session,m,userts); + return err; +} + + +static gint +rtp_recv (RtpSession * session, guint32 user_ts) +{ + gint error; + struct sockaddr remaddr; + socklen_t addrlen = sizeof (remaddr); + char *p; + mblk_t *mp; + RtpStream *stream=&session->rtp; + + if (session->rtp.socket<1) return -1; /*session has no sockets for the moment*/ + + + while (1) + { + if (session->rtp.cached_mp==NULL) + session->rtp.cached_mp = allocb (session->max_buf_size, 0); + mp=session->rtp.cached_mp; + if (session->flags & RTP_SESSION_USING_EXT_SOCKETS){ + error=recv(session->rtp.socket,mp->b_wptr,session->max_buf_size,0); + }else error = recvfrom (session->rtp.socket, mp->b_wptr, + session->max_buf_size, 0, + (struct sockaddr *) &remaddr, + &addrlen); + if (error > 0) + { + if (error<RTP_FIXED_HEADER_SIZE){ + g_warning("Packet too small to be a rtp packet (%i)!",error); + stream->stats.bad++; + ortp_global_stats.bad++; + /* don't free, it will be reused next time */ + }else{ + /* resize the memory allocated to fit the udp message */ + + p = g_realloc (mp->b_wptr, error); + if (p != mp->b_wptr) + ortp_debug("The recv area has moved during reallocation."); + mp->b_datap->db_base = mp->b_rptr = + mp->b_wptr = p; + mp->b_wptr += error; + mp->b_datap->db_lim = mp->b_wptr; + /* then parse the message and put on queue */ + rtp_parse (session, mp, user_ts + session->rtp.hwrcv_diff_ts); + session->rtp.cached_mp=NULL; + } + } + else + { + if (error == 0) + { + g_warning + ("rtp_recv: strange... recv() returned zero."); + } + else if (errno!=EWOULDBLOCK && errno!=EAGAIN) + { + if (session->on_network_error.count>0){ + rtp_signal_table_emit3(&session->on_network_error,(gpointer)"Error receiving RTP packet",INT_TO_POINTER(getSocketErrorCode())); + }else g_warning("Error receiving RTP packet: %s.",getSocketError()); + } + /* don't free the cached_mp, it will be reused next time */ + return -1; /* avoids an infinite loop ! */ + } + } + return error; +} + +extern void rtcp_parse(RtpSession *session, mblk_t *mp); + +static gint +rtcp_recv (RtpSession * session) +{ + gint error; + struct sockaddr remaddr; + socklen_t addrlen=0; + char *p; + mblk_t *mp; + + + if (session->rtcp.socket<1) return -1; /*session has no rtcp sockets for the moment*/ + + + while (1) + { + if (session->rtcp.cached_mp==NULL) + session->rtcp.cached_mp = allocb (RTCP_MAX_RECV_BUFSIZE, 0); + + mp=session->rtcp.cached_mp; + if (session->flags & RTP_SESSION_USING_EXT_SOCKETS){ + error=recv(session->rtcp.socket,mp->b_wptr,RTCP_MAX_RECV_BUFSIZE,0); + }else { + addrlen=sizeof (remaddr); + error=recvfrom (session->rtcp.socket, mp->b_wptr, + RTCP_MAX_RECV_BUFSIZE, 0, + (struct sockaddr *) &remaddr, + &addrlen); + } + if (error > 0) + { + /* resize the memory allocated to fit the udp message */ + + p = g_realloc (mp->b_wptr, error); + if (p != mp->b_wptr) + ortp_debug("The recv area has moved during reallocation."); + mp->b_datap->db_base = mp->b_rptr = + mp->b_wptr = p; + mp->b_wptr += error; + mp->b_datap->db_lim = mp->b_wptr; + /* then parse the message */ + rtcp_parse (session, mp); + freemsg(mp); + session->rtcp.cached_mp=NULL; + if (addrlen>0){ + /* store the sender rtcp address to send him receiver reports */ + memcpy(&session->rtcp.rem_addr,&remaddr,addrlen); + } + } + else + { + if (error == 0) + { + g_warning + ("rtcp_recv: strange... recv() returned zero."); + } + else if (errno!=EWOULDBLOCK && errno!=EAGAIN) + { + if (session->on_network_error.count>0){ + rtp_signal_table_emit3(&session->on_network_error,(gpointer)"Error receiving RTCP packet",INT_TO_POINTER(getSocketErrorCode())); + }else g_warning("Error receiving RTCP packet: %s.",getSocketError()); + } + /* don't free the cached_mp, it will be reused next time */ + return -1; /* avoids an infinite loop ! */ + } + } + return error; +} + + +static void payload_type_changed_incoming(RtpSession *session, int paytype){ + /* check if we support this payload type */ + PayloadType *pt=rtp_profile_get_payload(session->profile,paytype); + if (pt!=0){ + g_message ("rtp_parse: payload type changed to %i(%s) !", + paytype,pt->mime_type); + session->payload_type = paytype; + payload_type_changed(session,pt); + rtp_signal_table_emit (&session->on_payload_type_changed); + }else{ + g_warning("Receiving packet with unknown payload type %i.",paytype); + } +} + + +/** + *rtp_session_recvm_with_ts: + *@session: a rtp session. + *@user_ts: a timestamp. + * + * Try to get a rtp packet presented as a mblk_t structure from the rtp session. + * The @user_ts parameter is relative to the first timestamp of the incoming stream. In other + * words, the application does not have to know the first timestamp of the stream, it can + * simply call for the first time this function with @user_ts=0, and then incrementing it + * as it want. The RtpSession takes care of synchronisation between the stream timestamp + * and the user timestamp given here. + * + *Returns: a rtp packet presented as a mblk_t. +**/ + +mblk_t * +rtp_session_recvm_with_ts (RtpSession * session, guint32 user_ts) +{ + mblk_t *mp = NULL; + rtp_header_t *rtp; + guint32 ts; + guint32 packet_time; + RtpScheduler *sched=session->sched; + RtpStream *stream=&session->rtp; + gint rejected=0; + + /* if we are scheduled, remember the scheduler time at which the application has + * asked for its first timestamp */ + + if (session->flags & RTP_SESSION_RECV_NOT_STARTED) + { + + session->rtp.rcv_query_ts_offset = user_ts; + if (session->flags & RTP_SESSION_SCHEDULED) + { + session->rtp.rcv_time_offset = sched->time_; + //g_message("setting snd_time_offset=%i",session->rtp.snd_time_offset); + } + rtp_session_unset_flag (session,RTP_SESSION_RECV_NOT_STARTED); + } + session->rtp.rcv_last_app_ts = user_ts; + rtp_recv (session, user_ts); + rtcp_recv(session); + /* check for telephone event first */ + /* first lock the session */ + rtp_session_lock (session); + mp=getq(&session->rtp.tev_rq); + if (mp!=NULL){ + rtp_signal_table_emit2(&session->on_telephone_event_packet,(gpointer)mp); + if (session->on_telephone_event.count>0){ + rtp_session_check_telephone_events(session,mp); + } + freemsg(mp); + mp=NULL; + } + + /* then now try to return a media packet, if possible */ + /* first condition: if the session is starting, don't return anything + * until the queue size reaches jitt_comp */ + + if (session->flags & RTP_SESSION_RECV_SYNC) + { + rtp_header_t *oldest, *newest; + queue_t *q = &session->rtp.rq; + if (qempty(q)) + { + ortp_debug ("Queue is empty."); + goto end; + } + oldest = (rtp_header_t *) qfirst(q)->b_rptr; + newest = (rtp_header_t *) qlast(q)->b_rptr; + if ((guint32) (newest->timestamp - oldest->timestamp) < + session->rtp.jittctl.jitt_comp_ts) + { + ortp_debug("Not enough packet bufferised."); + goto end; + } + /* enough packet bufferised */ + mp = getq (&session->rtp.rq); + rtp = (rtp_header_t *) mp->b_rptr; + session->rtp.rcv_ts_offset = rtp->timestamp; + /* remember the timestamp offset between the stream timestamp (random) + * and the user timestamp, that very often starts at zero */ + session->rtp.rcv_diff_ts = rtp->timestamp - user_ts; + /* remember the difference between the last received on the socket timestamp and the user timestamp */ + session->rtp.hwrcv_diff_ts=session->rtp.rcv_diff_ts + session->rtp.jittctl.jitt_comp_ts; + session->rtp.rcv_last_ret_ts = user_ts; /* just to have an init value */ + session->rtp.rcv_last_ts = rtp->timestamp; + session->recv_ssrc = rtp->ssrc; + /* delete the recv synchronisation flag */ + rtp_session_unset_flag (session, RTP_SESSION_RECV_SYNC); + ortp_debug("Returning FIRST packet with ts=%i, hwrcv_diff_ts=%i, rcv_diff_ts=%i", rtp->timestamp, + session->rtp.hwrcv_diff_ts,session->rtp.rcv_diff_ts); + + goto end; + } + /* else this the normal case */ + /*calculate the stream timestamp from the user timestamp */ + ts = user_ts + session->rtp.rcv_diff_ts; + session->rtp.rcv_last_ts = ts; + mp = rtp_getq (&session->rtp.rq, ts,&rejected); + + stream->stats.skipped+=rejected; + ortp_global_stats.skipped+=rejected; + + /* perhaps we can now make some checks to see if a resynchronization is needed */ + /* TODO */ + goto end; + + end: + if (mp != NULL) + { + int msgsize = msgdsize (mp); /* evaluate how much bytes (including header) is received by app */ + guint32 packet_ts; + ortp_global_stats.recv += msgsize; + stream->stats.recv += msgsize; + rtp = (rtp_header_t *) mp->b_rptr; + packet_ts=rtp->timestamp; + ortp_debug("Returning mp with ts=%i", packet_ts); + /* check for payload type changes */ + if (session->payload_type != rtp->paytype) + { + payload_type_changed_incoming(session, rtp->paytype); + } + /* patch the packet so that it has a timestamp compensated by the + adaptive jitter buffer mechanism */ + if (session->rtp.jittctl.adaptive){ + rtp->timestamp-=session->rtp.jittctl.corrective_slide; + /*printf("Returned packet has timestamp %u, with clock slide compensated it is %u\n",packet_ts,rtp->timestamp);*/ + } + } + else + { + ortp_debug ("No mp for timestamp queried"); + stream->stats.unavaillable++; + ortp_global_stats.unavaillable++; + } + rtp_session_rtcp_process(session); + rtp_session_unlock (session); + + if (session->flags & RTP_SESSION_SCHEDULED) + { + /* if we are in blocking mode, then suspend the calling process until timestamp + * wanted expires */ + /* but we must not block the process if the timestamp wanted by the application is older + * than current time */ + packet_time = + rtp_session_ts_to_time (session, + user_ts - + session->rtp.rcv_query_ts_offset) + + session->rtp.rcv_time_offset; + ortp_debug ("rtp_session_recvm_with_ts: packet_time=%i, time=%i",packet_time, sched->time_); + wait_point_lock(&session->recv_wp); + if (TIME_IS_STRICTLY_NEWER_THAN (packet_time, sched->time_)) + { + wait_point_wakeup_at(&session->recv_wp,packet_time, (session->flags & RTP_SESSION_BLOCKING_MODE)!=0); + session_set_clr(&sched->r_sessions,session); + } + else session_set_set(&sched->r_sessions,session); /*to unblock _select() immediately */ + wait_point_unlock(&session->recv_wp); + } + return mp; +} + + +gint msg_to_buf (mblk_t * mp, char *buffer, gint len) +{ + gint rlen = len; + mblk_t *m, *mprev; + gint mlen; + m = mp->b_cont; + mprev = mp; + while (m != NULL) + { + mlen = m->b_wptr - m->b_rptr; + if (mlen <= rlen) + { + mblk_t *consumed = m; + memcpy (buffer, m->b_rptr, mlen); + /* go to next mblk_t */ + mprev->b_cont = m->b_cont; + m = m->b_cont; + consumed->b_cont = NULL; + freeb (consumed); + buffer += mlen; + rlen -= mlen; + } + else + { /*if mlen>rlen */ + memcpy (buffer, m->b_rptr, rlen); + m->b_rptr += rlen; + return len; + } + } + return len - rlen; +} + +/** + *rtp_session_recv_with_ts: + *@session: a rtp session. + *@buffer: a user supplied buffer to write the data. + *@len: the length in bytes of the user supplied buffer. + *@time: the timestamp wanted. + *@have_more: the address of an integer to indicate if more data is availlable for the given timestamp. + * + * Tries to read the bytes of the incoming rtp stream related to timestamp @time. In case + * where the user supplied buffer @buffer is not large enough to get all the data + * related to timestamp @time, then *( @have_more) is set to 1 to indicate that the application + * should recall the function with the same timestamp to get more data. + * + * When the rtp session is scheduled (see rtp_session_set_scheduling_mode() ), and the + * blocking mode is on (see rtp_session_set_blocking_mode() ), then the calling thread + * is suspended until the timestamp given as argument expires, whatever a received packet + * fits the query or not. + * + * Important note: it is clear that the application cannot know the timestamp of the first + * packet of the incoming stream, because it can be random. The @time timestamp given to the + * function is used relatively to first timestamp of the stream. In simple words, 0 is a good + * value to start calling this function. + * + * This function internally calls rtp_session_recvm_with_ts() to get a rtp packet. The content + * of this packet is then copied into the user supplied buffer in an intelligent manner: + * the function takes care of the size of the supplied buffer and the timestamp given in + * argument. Using this function it is possible to read continous audio data (e.g. pcma,pcmu...) + * with for example a standart buffer of size of 160 with timestamp incrementing by 160 while the incoming + * stream has a different packet size. + * + *Returns: if a packet was availlable with the corresponding timestamp supplied in argument + * then the number of bytes written in the user supplied buffer is returned. If no packets + * are availlable, either because the sender has not started to send the stream, or either + * because silence packet are not transmitted, or either because the packet was lost during + * network transport, then the function returns zero. +**/ +gint rtp_session_recv_with_ts (RtpSession * session, gchar * buffer, + gint len, guint32 time, gint * have_more) +{ + mblk_t *mp; + gint rlen = len; + gint wlen, mlen; + guint32 ts_int = 0; /*the length of the data returned in the user supplied buffer, in TIMESTAMP UNIT */ + PayloadType *payload; + RtpStream *stream=&session->rtp; + + *have_more = 0; + + mp = rtp_session_recvm_with_ts (session, time); + payload =rtp_profile_get_payload (session->profile, + session->payload_type); + if (payload==NULL){ + g_warning("rtp_session_recv_with_ts: unable to recv an unsupported payload."); + if (mp!=NULL) freemsg(mp); + return -1; + } + if (!(session->flags & RTP_SESSION_RECV_SYNC)) + { + //ortp_debug("time=%i rcv_last_ret_ts=%i",time,session->rtp.rcv_last_ret_ts); + if (RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN + (time, session->rtp.rcv_last_ret_ts)) + { + /* the user has missed some data previously, so we are going to give him now. */ + /* we must tell him to call the function once again with the same timestamp + * by setting *have_more=1 */ + *have_more = 1; + } + if (payload->type == PAYLOAD_AUDIO_CONTINUOUS) + { + ts_int = (len * payload->bits_per_sample) >> 3; + session->rtp.rcv_last_ret_ts += ts_int; + //ortp_debug("ts_int=%i",ts_int); + } + else + ts_int = 0; + } + else return 0; + + /* try to fill the user buffer */ + while (1) + { + + if (mp != NULL) + { + mlen = msgdsize (mp->b_cont); + wlen = msg_to_buf (mp, buffer, rlen); + buffer += wlen; + rlen -= wlen; + ortp_debug("mlen=%i wlen=%i rlen=%i", mlen, wlen, + rlen); + /* do we fill all the buffer ? */ + if (rlen > 0) + { + /* we did not fill all the buffer */ + freemsg (mp); + /* if we have continuous audio, try to get other packets to fill the buffer, + * ie continue the loop */ + //ortp_debug("User buffer not filled entirely"); + if (ts_int > 0) + { + time = session->rtp.rcv_last_ret_ts; + ortp_debug("Need more: will ask for %i.", + time); + } + else + return len - rlen; + } + else if (mlen > wlen) + { + int unread = + mlen - wlen + (mp->b_wptr - + mp->b_rptr); + /* not enough space in the user supplied buffer */ + /* we re-enqueue the msg with its updated read pointers for next time */ + ortp_debug ("Re-enqueuing packet."); + rtp_session_lock (session); + rtp_putq (&session->rtp.rq, mp); + rtp_session_unlock (session); + /* quite ugly: I change the stats ... */ + ortp_global_stats.recv -= unread; + stream->stats.recv -= unread; + return len; + } + else + { + /* the entire packet was written to the user buffer */ + freemsg (mp); + return len; + } + } + else + { + /* fill with a zero pattern (silence) */ + if (payload->pattern_length != 0) + { + int i = 0, j = 0; + while (i < rlen) + { + buffer[i] = payload->zero_pattern[j]; + i++; + j++; + if (j <= payload->pattern_length) + j = 0; + } + return len; + } + *have_more = 0; + return 0; + } + mp = rtp_session_recvm_with_ts (session, time); + payload = rtp_profile_get_payload (session->profile, + session->payload_type); + if (payload==NULL){ + g_warning("rtp_session_recv_with_ts: unable to recv an unsupported payload."); + if (mp!=NULL) freemsg(mp); + return -1; + } + } + return -1; +} +/** + *rtp_session_get_current_send_ts: + *@session: a rtp session. + * + * When the rtp session is scheduled and has started to send packets, this function + * computes the timestamp that matches to the present time. Using this function can be + * usefull when sending discontinuous streams. Some time can be elapsed between the end + * of a stream burst and the begin of a new stream burst, and the application may be not + * not aware of this elapsed time. In order to get a valid (current) timestamp to pass to + * #rtp_session_send_with_ts() or #rtp_session_sendm_with_ts(), the application may + * use rtp_session_get_current_send_ts(). + * + *Returns: the current send timestamp for the rtp session. +**/ +guint32 rtp_session_get_current_send_ts(RtpSession *session) +{ + guint32 userts; + guint32 session_time; + RtpScheduler *sched=session->sched; + PayloadType *payload; + g_return_val_if_fail (session->payload_type<128, 0); + payload=rtp_profile_get_payload(session->profile,session->payload_type); + g_return_val_if_fail(payload!=NULL, 0); + if ( (session->flags & RTP_SESSION_SCHEDULED)==0 ){ + g_warning("can't guess current timestamp because session is not scheduled."); + return 0; + } + session_time=sched->time_-session->rtp.snd_time_offset; + userts= (guint32)( ( (gdouble)(session_time) * (gdouble) payload->clock_rate )/ 1000.0) + + session->rtp.snd_ts_offset; + return userts; +} + +/** + *rtp_session_get_current_recv_ts: + *@session: a rtp session. + * + * Same thing as rtp_session_get_current_send_ts() except that it's for an incoming stream. + * Works only on scheduled mode. + * + * Returns: the theoritical that would have to be receive now. + * +**/ +guint32 rtp_session_get_current_recv_ts(RtpSession *session){ + guint32 userts; + guint32 session_time; + RtpScheduler *sched=ortp_get_scheduler(); + PayloadType *payload; + g_return_val_if_fail (session->payload_type<128, 0); + payload=rtp_profile_get_payload(session->profile,session->payload_type); + g_return_val_if_fail(payload!=NULL, 0); + if ( (session->flags & RTP_SESSION_SCHEDULED)==0 ){ + g_warning("can't guess current timestamp because session is not scheduled."); + return 0; + } + session_time=sched->time_-session->rtp.rcv_time_offset; + userts= (guint32)( ( (gdouble)(session_time) * (gdouble) payload->clock_rate )/ 1000.0) + + session->rtp.rcv_ts_offset; + return userts; +} + +/** + *rtp_session_set_time_jump_limit: + *@session: the rtp session + *@ts_step: a time interval in miliseconds + * + * oRTP has the possibility to inform the application through a callback registered + * with rtp_session_signal_connect about crazy incoming RTP stream that jumps from + * a timestamp N to N+<some crazy value>. This lets the opportunity for the application + * to reset the session in order to resynchronize, or any other action like stopping the call + * and reporting an error. +**/ +void rtp_session_set_time_jump_limit(RtpSession *session, gint milisecs){ + guint32 ts; + session->rtp.time_jump=milisecs; + ts=rtp_session_time_to_ts(session,milisecs); + if (ts==0) session->rtp.ts_jump=1<<31; /* do not detect ts jump */ + else session->rtp.ts_jump=ts; +} + +void rtp_session_uninit (RtpSession * session) +{ + /* first of all remove the session from the scheduler */ + if (session->flags & RTP_SESSION_SCHEDULED) + { + rtp_scheduler_remove_session (session->sched,session); + } + /*flush all queues */ + flushq (&session->rtp.rq, FLUSHALL); + + /* close sockets */ + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + + wait_point_uninit(&session->send_wp); + wait_point_uninit(&session->recv_wp); + g_mutex_free (session->lock); + session->lock=NULL; + if (session->current_tev!=NULL) freemsg(session->current_tev); + if (session->rtp.cached_mp!=NULL) freemsg(session->rtp.cached_mp); + if (session->rtcp.cached_mp!=NULL) freemsg(session->rtcp.cached_mp); + if (session->sd!=NULL) freemsg(session->sd); +} + +/** + *rtp_session_reset: + *@session: a rtp session. + * + * Reset the session: local and remote addresses are kept unchanged but the internal + * queue for ordering and buffering packets is flushed, the session is ready to be + * re-synchronised to another incoming stream. + * +**/ +void rtp_session_reset (RtpSession * session) +{ + + if (session->flags & RTP_SESSION_SCHEDULED) rtp_session_lock (session); + + flushq (&session->rtp.rq, FLUSHALL); + rtp_session_set_flag (session, RTP_SESSION_RECV_SYNC); + rtp_session_set_flag (session, RTP_SESSION_SEND_SYNC); + rtp_session_set_flag (session, RTP_SESSION_RECV_NOT_STARTED); + rtp_session_set_flag (session, RTP_SESSION_SEND_NOT_STARTED); + //session->ssrc=0; + session->rtp.snd_time_offset = 0; + session->rtp.snd_ts_offset = 0; + session->rtp.snd_rand_offset = 0; + session->rtp.snd_last_ts = 0; + session->rtp.rcv_time_offset = 0; + session->rtp.rcv_ts_offset = 0; + session->rtp.rcv_query_ts_offset = 0; + session->rtp.rcv_diff_ts = 0; + session->rtp.rcv_ts = 0; + session->rtp.rcv_last_ts = 0; + session->rtp.rcv_last_app_ts = 0; + session->rtp.hwrcv_extseq.one = 0; + session->rtp.hwrcv_since_last_SR=0; + session->rtp.snd_seq = 0; + rtp_stats_reset(&session->rtp.stats); + jitter_control_init(&session->rtp.jittctl,-1,NULL); + + if (session->flags & RTP_SESSION_SCHEDULED) rtp_session_unlock (session); + +} + +/** + *rtp_session_destroy: + *@session: a rtp session. + * + * Destroys a rtp session. + * +**/ +void rtp_session_destroy (RtpSession * session) +{ + rtp_session_uninit (session); + g_free (session); +} + +guint32 rtp_session_time_to_ts(RtpSession *session, gint time){ + PayloadType *payload; + g_return_val_if_fail (session->payload_type < 127, 0); + payload = + rtp_profile_get_payload (session->profile, + session->payload_type); + if (payload == NULL) + { + g_warning + ("rtp_session_ts_to_t: use of unsupported payload type."); + return 0; + } + /* the return value is in milisecond */ + return (double)payload->clock_rate*(double)time/1000.0; +} + +/* function used by the scheduler only:*/ +guint32 rtp_session_ts_to_time (RtpSession * session, guint32 timestamp) +{ + PayloadType *payload; + g_return_val_if_fail (session->payload_type < 127, 0); + payload = + rtp_profile_get_payload (session->profile, + session->payload_type); + if (payload == NULL) + { + g_warning + ("rtp_session_ts_to_t: use of unsupported payload type."); + return 0; + } + /* the return value is in milisecond */ + return (guint32) (1000.0 * + ((double) timestamp / + (double) payload->clock_rate)); +} + + +/* time is the number of miliseconds elapsed since the start of the scheduler */ +void rtp_session_process (RtpSession * session, guint32 time, RtpScheduler *sched) +{ + wait_point_lock(&session->send_wp); + if (wait_point_check(&session->send_wp,time)){ + session_set_set(&sched->w_sessions,session); + wait_point_wakeup(&session->send_wp); + } + wait_point_unlock(&session->send_wp); + + wait_point_lock(&session->recv_wp); + if (wait_point_check(&session->recv_wp,time)){ + session_set_set(&sched->r_sessions,session); + wait_point_wakeup(&session->recv_wp); + } + wait_point_unlock(&session->recv_wp); +} + + +void rtp_session_make_time_distorsion(RtpSession *session, gint milisec) +{ + session->rtp.snd_time_offset+=milisec; +} + + +/* packet api */ + +void rtp_add_csrc(mblk_t *mp, guint32 csrc) +{ + rtp_header_t *hdr=(rtp_header_t*)mp->b_rptr; + hdr->csrc[hdr->cc]=csrc; + hdr->cc++; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.h new file mode 100644 index 00000000..e7702000 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.h @@ -0,0 +1,287 @@ + /* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef RTPSESSION_H +#define RTPSESSION_H + + +#include <rtpport.h> +#include <rtp.h> +#include <payloadtype.h> +#include <sessionset.h> +#include <rtcp.h> +#include <str_utils.h> +#include <rtpsignaltable.h> + +#include <stdio.h> + + +#ifndef _WIN32 +# include <sys/types.h> +# include <sys/socket.h> +# include <errno.h> +# include <netinet/in.h> +# ifdef _XOPEN_SOURCE_EXTENDED +# include <arpa/inet.h> +# endif +# include <unistd.h> +# include <sys/time.h> +#else +# include <winsock2.h> +#endif /* _WIN32 */ + + + +typedef enum { + RTP_SESSION_RECVONLY, + RTP_SESSION_SENDONLY, + RTP_SESSION_SENDRECV +} RtpSessionMode; + + + +typedef enum { + RTP_SESSION_RECV_SYNC=1, /* the rtp session is synchronising in the incoming stream */ + RTP_SESSION_SEND_SYNC=1<<1, /* the rtp session is synchronising in the outgoing stream */ + RTP_SESSION_SCHEDULED=1<<2, /* the rtp session has to be scheduled */ + RTP_SESSION_BLOCKING_MODE=1<<3, /* in blocking mode */ + RTP_SESSION_RECV_NOT_STARTED=1<<4, /* the application has not started to try to recv */ + RTP_SESSION_SEND_NOT_STARTED=1<<5, /* the application has not started to send something */ + RTP_SESSION_IN_SCHEDULER=1<<6, /* the rtp session is in the scheduler list */ + RTP_SESSION_USING_EXT_SOCKETS=1<<7 /* the session is using externaly supplied sockets */ +}RtpSessionFlags; + + +typedef struct _JitterControl +{ + gint jitt_comp; /* the user jitt_comp in miliseconds*/ + gint jitt_comp_ts; /* the jitt_comp converted in rtp time (same unit as timestamp) */ + gint adapt_jitt_comp_ts; + float slide; + float jitter; + gint count; + gint olddiff; + float inter_jitter; /* interarrival jitter as defined in the RFC */ + gint corrective_step; + gint corrective_slide; + gboolean adaptive; +} JitterControl; + +typedef struct _WaitPoint +{ + GMutex *lock; + GCond *cond; + guint32 time; + gboolean wakeup; +} WaitPoint; + +typedef struct _RtpStream +{ + gint socket; + gint socktype; + gint max_rq_size; + gint time_jump; + guint32 ts_jump; + queue_t rq; + queue_t tev_rq; + mblk_t *cached_mp; +#ifdef INET6 + struct sockaddr_storage loc_addr; + struct sockaddr_storage rem_addr; +#else + struct sockaddr_in loc_addr; + struct sockaddr_in rem_addr; +#endif + int addrlen; + JitterControl jittctl; + guint32 snd_time_offset;/*the scheduler time when the application send its first timestamp*/ + guint32 snd_ts_offset; /* the first application timestamp sent by the application */ + guint32 snd_rand_offset; /* a random number added to the user offset to make the stream timestamp*/ + guint32 snd_last_ts; /* the last stream timestamp sended */ + guint32 rcv_time_offset; /*the scheduler time when the application ask for its first timestamp*/ + guint32 rcv_ts_offset; /* the first stream timestamp */ + guint32 rcv_query_ts_offset; /* the first user timestamp asked by the application */ + guint32 rcv_diff_ts; /* difference between the first user timestamp and first stream timestamp */ + guint32 hwrcv_diff_ts; + guint32 rcv_ts; /* to be unused */ + guint32 rcv_last_ts; /* the last stream timestamp got by the application */ + guint32 rcv_last_app_ts; /* the last application timestamp asked by the application */ + guint32 rcv_last_ret_ts; /* the timestamp of the last sample returned (only for continuous audio)*/ + poly32_t hwrcv_extseq; /* last received on socket extended sequence number */ + guint32 hwrcv_seq_at_last_SR; + guint hwrcv_since_last_SR; + guint32 last_rcv_SR_ts; /* NTP timestamp (middle 32 bits) of last received SR */ + struct timeval last_rcv_SR_time; /* time at which last SR was received */ + guint16 snd_seq; /* send sequence number */ + guint32 last_rtcp_report_snt_r; /* the time of the last rtcp report sent, in recv timestamp unit */ + guint32 last_rtcp_report_snt_s; /* the time of the last rtcp report sent, in send timestamp unit */ + guint32 rtcp_report_snt_interval; /* the interval in timestamp unit between rtcp report sent */ + rtp_stats_t stats; +}RtpStream; + +typedef struct _RtcpStream +{ + gint socket; + gint socktype; + mblk_t *cached_mp; +#ifdef INET6 + struct sockaddr_storage loc_addr; + struct sockaddr_storage rem_addr; +#else + struct sockaddr_in loc_addr; + struct sockaddr_in rem_addr; +#endif + int addrlen; +} RtcpStream; + +typedef struct _RtpSession RtpSession; + + + +struct _RtpSession +{ + RtpSession *next; /* next RtpSession, when the session are enqueued by the scheduler */ + RtpProfile *profile; + WaitPoint recv_wp; + WaitPoint send_wp; + GMutex *lock; + guint32 send_ssrc; + guint32 recv_ssrc; + gint payload_type; + gint max_buf_size; + RtpSignalTable on_ssrc_changed; + RtpSignalTable on_payload_type_changed; + RtpSignalTable on_telephone_event_packet; + RtpSignalTable on_telephone_event; + RtpSignalTable on_timestamp_jump; + RtpSignalTable on_network_error; + struct _OList *signal_tables; + RtpStream rtp; + RtcpStream rtcp; + RtpSessionMode mode; + struct _RtpScheduler *sched; + guint32 flags; + gint mask_pos; /* the position in the scheduler mask of RtpSession */ + gpointer user_data; + + /* telephony events extension */ + gint telephone_events_pt; /* the payload type used for telephony events */ + mblk_t *current_tev; /* the pending telephony events */ + mblk_t *sd; + queue_t contributing_sources; +}; + + + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*private */ +void rtp_session_init(RtpSession *session, gint mode); +#define rtp_session_lock(session) g_mutex_lock(session->lock) +#define rtp_session_unlock(session) g_mutex_unlock(session->lock) +#define rtp_session_set_flag(session,flag) (session)->flags|=(flag) +#define rtp_session_unset_flag(session,flag) (session)->flags&=~(flag) +void rtp_session_uninit(RtpSession *session); + +/* public API */ +RtpSession *rtp_session_new(gint mode); +void rtp_session_set_scheduling_mode(RtpSession *session, gint yesno); +void rtp_session_set_blocking_mode(RtpSession *session, gint yesno); +void rtp_session_set_profile(RtpSession *session,RtpProfile *profile); +#define rtp_session_get_profile(session) (session)->profile +int rtp_session_signal_connect(RtpSession *session,const gchar *signal, RtpCallback cb, gpointer user_data); +int rtp_session_signal_disconnect_by_callback(RtpSession *session,const gchar *signal, RtpCallback cb); +void rtp_session_set_ssrc(RtpSession *session, guint32 ssrc); +void rtp_session_set_seq_number(RtpSession *session, guint16 seq); +guint16 rtp_session_get_seq_number(RtpSession *session); +void rtp_session_set_jitter_compensation(RtpSession *session, int milisec); +void rtp_session_enable_adaptive_jitter_compensation(RtpSession *session, gboolean val); +gboolean rtp_session_adaptive_jitter_compensation_enabled(RtpSession *session); +void rtp_session_set_time_jump_limit(RtpSession *session, gint miliseconds); +int rtp_session_set_local_addr(RtpSession *session,const gchar *addr, gint port); +gint rtp_session_set_remote_addr(RtpSession *session,const gchar *addr, gint port); +/* alternatively to the set_remote_addr() and set_local_addr(), an application can give +a valid socket (potentially connect()ed )to be used by the RtpSession */ +void rtp_session_set_sockets(RtpSession *session, gint rtpfd, gint rtcpfd); +int rtp_session_set_payload_type(RtpSession *session, int paytype); +int rtp_session_get_payload_type(RtpSession *session); +int rtp_session_set_payload_type_with_string (RtpSession * session, const char * mime); +/*low level recv and send functions */ +mblk_t * rtp_session_recvm_with_ts (RtpSession * session, guint32 user_ts); +mblk_t * rtp_session_create_packet(RtpSession *session,gint header_size, const char *payload, gint payload_size); +mblk_t * rtp_session_create_packet_with_data(RtpSession *session, char *payload, gint payload_size, void (*freefn)(void*)); +mblk_t * rtp_session_create_packet_in_place(RtpSession *session,char *buffer, gint size, void (*freefn)(void*) ); +gint rtp_session_sendm_with_ts (RtpSession * session, mblk_t *mp, guint32 userts); +/* high level recv and send functions */ +gint rtp_session_recv_with_ts(RtpSession *session, gchar *buffer, gint len, guint32 time, gint *have_more); +gint rtp_session_send_with_ts(RtpSession *session, const gchar *buffer, gint len, guint32 userts); + + +guint32 rtp_session_get_current_send_ts(RtpSession *session); +guint32 rtp_session_get_current_recv_ts(RtpSession *session); +void rtp_session_flush_sockets(RtpSession *session); +void rtp_session_reset(RtpSession *session); +void rtp_session_destroy(RtpSession *session); + +#define rtp_session_get_stats(session) (&(session)->stats) +#define rtp_session_reset_stats(session) memset(&(session)->stats,0,sizeof(rtp_stats_t)) +#define rtp_session_set_data(session,data) (session)->user_data=(data) +#define rtp_session_get_data(session,data) ((session)->user_data) + +#define rtp_session_max_buf_size_set(session,bufsize) (session)->max_buf_size=(bufsize) + +/* in use with the scheduler to convert a timestamp in scheduler time unit (ms) */ +guint32 rtp_session_ts_to_time(RtpSession *session,guint32 timestamp); +guint32 rtp_session_time_to_ts(RtpSession *session, gint time); +/* this function aims at simulating senders with "imprecise" clocks, resulting in +rtp packets sent with timestamp uncorrelated with the system clock . +This is only availlable to sessions working with the oRTP scheduler */ +void rtp_session_make_time_distorsion(RtpSession *session, gint milisec); + +/*RTCP functions */ +void rtp_session_set_source_description(RtpSession *session, const gchar *cname, + const gchar *name, const gchar *email, const gchar *phone, + const gchar *loc, const gchar *tool, const gchar *note); +void rtp_session_add_contributing_source(RtpSession *session, guint32 csrc, + const gchar *cname, const gchar *name, const gchar *email, const gchar *phone, + const gchar *loc, const gchar *tool, const gchar *note); +void rtp_session_remove_contributing_sources(RtpSession *session, guint32 csrc); +mblk_t* rtp_session_create_rtcp_sdes_packet(RtpSession *session); + + +/* packet api */ +/* the first argument is a mblk_t. The header is supposed to be not splitted */ +#define rtp_set_markbit(mp,value) ((rtp_header_t*)((mp)->b_rptr))->markbit=(value) +#define rtp_set_seqnumber(mp,seq) ((rtp_header_t*)((mp)->b_rptr))->seq_number=(seq) +#define rtp_set_timestamp(mp,ts) ((rtp_header_t*)((mp)->b_rptr))->timestamp=(ts) +#define rtp_set_ssrc(mp,_ssrc) ((rtp_header_t*)((mp)->b_rptr))->ssrc=(_ssrc) +void rtp_add_csrc(mblk_t *mp,guint32 csrc); +#define rtp_set_payload_type(mp,pt) ((rtp_header_t*)((mp)->b_rptr))->paytype=(pt) + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.c new file mode 100644 index 00000000..35b19ae3 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.c @@ -0,0 +1,98 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#include <rtpsession.h> +#include "utils.h" + + +void rtp_signal_table_init(RtpSignalTable *table,RtpSession *session, char *signal_name) +{ + memset(table,0,sizeof(RtpSignalTable)); + table->session=session; + table->signal_name=signal_name; + session->signal_tables=o_list_append(session->signal_tables,(gpointer)table); +} + +int rtp_signal_table_add(RtpSignalTable *table,RtpCallback cb, gpointer user_data) +{ + gint i; + + for (i=0;i<RTP_CALLBACK_TABLE_MAX_ENTRIES;i++){ + if (table->callback[i]==NULL){ + table->callback[i]=cb; + table->user_data[i]=user_data; + table->count++; + return 0; + } + } + return -1; +} + +void rtp_signal_table_emit(RtpSignalTable *table) +{ + gint i,c; + + for (i=0,c=0;c<table->count;i++){ + if (table->callback[i]!=NULL){ + c++; /*I like it*/ + table->callback[i](table->session,table->user_data[i]); + } + } +} + +void rtp_signal_table_emit2(RtpSignalTable *table, gpointer arg) +{ + gint i,c; + + for (i=0,c=0;c<table->count;i++){ + if (table->callback[i]!=NULL){ + c++; /*I like it*/ + table->callback[i](table->session,arg,table->user_data[i]); + } + } +} + +void rtp_signal_table_emit3(RtpSignalTable *table, gpointer arg1, gpointer arg2) +{ + gint i,c; + + for (i=0,c=0;c<table->count;i++){ + if (table->callback[i]!=NULL){ + c++; /*I like it*/ + table->callback[i](table->session,arg1,arg2,table->user_data[i]); + } + } +} + +int rtp_signal_table_remove_by_callback(RtpSignalTable *table,RtpCallback cb) +{ + gint i; + + for (i=0;i<RTP_CALLBACK_TABLE_MAX_ENTRIES;i++){ + if (table->callback[i]==cb){ + table->callback[i]=NULL; + table->user_data[i]=NULL; + table->count--; + return 0; + } + } + return -1; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.h new file mode 100644 index 00000000..c6cbe960 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.h @@ -0,0 +1,47 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define RTP_CALLBACK_TABLE_MAX_ENTRIES 5 + +typedef void (*RtpCallback)(struct _RtpSession *, ...); + +struct _RtpSignalTable +{ + RtpCallback callback[RTP_CALLBACK_TABLE_MAX_ENTRIES]; + gpointer user_data[RTP_CALLBACK_TABLE_MAX_ENTRIES]; + struct _RtpSession *session; + const char *signal_name; + gint count; +}; + +typedef struct _RtpSignalTable RtpSignalTable; + +void rtp_signal_table_init(RtpSignalTable *table,struct _RtpSession *session, char *signal_name); + +int rtp_signal_table_add(RtpSignalTable *table,RtpCallback cb, gpointer user_data); + +void rtp_signal_table_emit(RtpSignalTable *table); + +/* emit but with a second arg */ +void rtp_signal_table_emit2(RtpSignalTable *table, gpointer arg); + +/* emit but with a third arg */ +void rtp_signal_table_emit3(RtpSignalTable *table, gpointer arg1, gpointer arg2); + +int rtp_signal_table_remove_by_callback(RtpSignalTable *table,RtpCallback cb); diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.c new file mode 100644 index 00000000..6ac57e72 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.c @@ -0,0 +1,32 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "rtptimer.h" + +void rtp_timer_set_interval(RtpTimer *timer, struct timeval *interval) +{ + if (timer->state==RTP_TIMER_RUNNING){ + g_warning("Cannot change timer interval while it is running.\n"); + return; + } + timer->interval.tv_sec=interval->tv_sec; + timer->interval.tv_usec=interval->tv_usec; +} + + diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.h new file mode 100644 index 00000000..081e0892 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.h @@ -0,0 +1,52 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef RTPTIMER_H +#define RTPTIMER_H + +#ifndef _WIN32 +#include <sys/time.h> +#else +#include <time.h> +#include "winsock2.h" +#endif + +#include <rtpport.h> + + +typedef void (*RtpTimerFunc)(void); + +struct _RtpTimer +{ + gint state; +#define RTP_TIMER_RUNNING 1 +#define RTP_TIMER_STOPPED 0 + RtpTimerFunc timer_init; + RtpTimerFunc timer_do; + RtpTimerFunc timer_uninit; + struct timeval interval; +}; + +typedef struct _RtpTimer RtpTimer; + +void rtp_timer_set_interval(RtpTimer *timer, struct timeval *interval); + +extern RtpTimer posix_timer; + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.c new file mode 100644 index 00000000..17ff6748 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.c @@ -0,0 +1,235 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _WIN32 /* do not include ortp-config.h when we are on win32 */ + #include <rtpport.h> + #include <sched.h> + #include <unistd.h> + #include <errno.h> +#else + #include "ortp-config-win32.h" +#endif + + + +#include "scheduler.h" + +// To avoid warning during compile +extern void rtp_session_process (RtpSession * session, guint32 time, RtpScheduler *sched); + + +void rtp_scheduler_init(RtpScheduler *sched) +{ + sched->list=0; + sched->time_=0; + /* default to the posix timer */ + rtp_scheduler_set_timer(sched,&posix_timer); + sched->lock=g_mutex_new(); + //sched->unblock_select_mutex=g_mutex_new(); + sched->unblock_select_cond=g_cond_new(); + sched->max_sessions=sizeof(SessionSet)*8; + session_set_init(&sched->all_sessions); + sched->all_max=0; + session_set_init(&sched->r_sessions); + sched->r_max=0; + session_set_init(&sched->w_sessions); + sched->w_max=0; + session_set_init(&sched->e_sessions); + sched->e_max=0; +} + +RtpScheduler * rtp_scheduler_new() +{ + RtpScheduler *sched=g_malloc(sizeof(RtpScheduler)); + memset(sched,0,sizeof(RtpScheduler)); + rtp_scheduler_init(sched); + return sched; +} + +void rtp_scheduler_set_timer(RtpScheduler *sched,RtpTimer *timer) +{ + if (sched->thread_running){ + g_warning("Cannot change timer while the scheduler is running !!"); + return; + } + sched->timer=timer; + /* report the timer increment */ + sched->timer_inc=(timer->interval.tv_usec/1000) + (timer->interval.tv_sec*1000); +} + +void rtp_scheduler_start(RtpScheduler *sched) +{ + if (sched->thread_running==0){ + sched->thread_running=1; + g_mutex_lock(sched->lock); + sched->thread=g_thread_create((GThreadFunc)rtp_scheduler_schedule,(gpointer)sched,TRUE,NULL); + g_cond_wait(sched->unblock_select_cond,sched->lock); + g_mutex_unlock(sched->lock); + } + else g_warning("Scheduler thread already running."); + +} +void rtp_scheduler_stop(RtpScheduler *sched) +{ + if (sched->thread_running==1) + { + sched->thread_running=0; + g_thread_join(sched->thread); + } + else g_warning("Scheduler thread is not running."); +} + +void rtp_scheduler_destroy(RtpScheduler *sched) +{ + if (sched->thread_running) rtp_scheduler_stop(sched); + g_mutex_free(sched->lock); + //g_mutex_free(sched->unblock_select_mutex); + g_cond_free(sched->unblock_select_cond); + g_free(sched); +} + +gpointer rtp_scheduler_schedule(gpointer psched) +{ + RtpScheduler *sched=(RtpScheduler*) psched; + RtpTimer *timer=sched->timer; + RtpSession *current; + int err; + + /* try to get the real time priority by getting root*/ +#ifndef _WIN32 +#ifdef HAVE_SETEUID + err=seteuid(0); +#else + err=setuid(0); +#endif + if (err<0) g_message("Could not get root euid: %s",strerror(errno)); +#endif + g_message("scheduler: trying to reach real time kernel scheduling..."); + + /* take this lock to prevent the thread to start until g_thread_create() returns + because we need sched->thread to be initialized */ + g_mutex_lock(sched->lock); + g_cond_signal(sched->unblock_select_cond); /* unblock the starting thread */ + g_mutex_unlock(sched->lock); + g_thread_set_priority(sched->thread,G_THREAD_PRIORITY_HIGH); + timer->timer_init(); + while(sched->thread_running) + { + /* do the processing here: */ + + g_mutex_lock(sched->lock); + + current=sched->list; + /* processing all scheduled rtp sessions */ + while (current!=NULL) + { + ortp_debug("scheduler: processing session=%p.\n",current); + rtp_session_process(current,sched->time_,sched); + current=current->next; + } + /* wake up all the threads that are sleeping in _select() */ + g_cond_broadcast(sched->unblock_select_cond); + g_mutex_unlock(sched->lock); + + /* now while the scheduler is going to sleep, the other threads can compute their + result mask and see if they have to leave, or to wait for next tick*/ + //g_message("scheduler: sleeping."); + timer->timer_do(); + sched->time_+=sched->timer_inc; + } + /* when leaving the thread, stop the timer */ + timer->timer_uninit(); + return NULL; +} + +void rtp_scheduler_add_session(RtpScheduler *sched, RtpSession *session) +{ + RtpSession *oldfirst; + int i; + if (session->flags & RTP_SESSION_IN_SCHEDULER){ + /* the rtp session is already scheduled, so return silently */ + return; + } + rtp_scheduler_lock(sched); + /* enqueue the session to the list of scheduled sessions */ + oldfirst=sched->list; + sched->list=session; + session->next=oldfirst; + if (sched->max_sessions==0){ + g_error("rtp_scheduler_add_session: max_session=0 !"); + } + /* find a free pos in the session mask*/ + for (i=0;i<sched->max_sessions;i++){ + if (!ORTP_FD_ISSET(i,&sched->all_sessions.rtpset)){ + session->mask_pos=i; + session_set_set(&sched->all_sessions,session); + /* make a new session scheduled not blockable if it has not started*/ + if (session->flags & RTP_SESSION_RECV_NOT_STARTED) + session_set_set(&sched->r_sessions,session); + if (session->flags & RTP_SESSION_SEND_NOT_STARTED) + session_set_set(&sched->w_sessions,session); + if (i>sched->all_max){ + sched->all_max=i; + } + break; + } + } + + rtp_session_set_flag(session,RTP_SESSION_IN_SCHEDULER); + rtp_scheduler_unlock(sched); +} + +void rtp_scheduler_remove_session(RtpScheduler *sched, RtpSession *session) +{ + RtpSession *tmp; + int cond=1; + g_return_if_fail(session!=NULL); + if (!(session->flags & RTP_SESSION_IN_SCHEDULER)){ + /* the rtp session is not scheduled, so return silently */ + return; + } + + rtp_scheduler_lock(sched); + tmp=sched->list; + if (tmp==session){ + sched->list=tmp->next; + rtp_session_unset_flag(session,RTP_SESSION_IN_SCHEDULER); + session_set_clr(&sched->all_sessions,session); + rtp_scheduler_unlock(sched); + return; + } + /* go the position of session in the list */ + while(cond){ + if (tmp!=NULL){ + if (tmp->next==session){ + tmp->next=tmp->next->next; + cond=0; + } + else tmp=tmp->next; + }else { + /* the session was not found ! */ + g_warning("rtp_scheduler_remove_session: the session was not found in the scheduler list!"); + cond=0; + } + } + rtp_session_unset_flag(session,RTP_SESSION_IN_SCHEDULER); + /* delete the bit in the mask */ + session_set_clr(&sched->all_sessions,session); + rtp_scheduler_unlock(sched); +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.h new file mode 100644 index 00000000..91cde6a9 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.h @@ -0,0 +1,70 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SCHEDULER_H +#define SCHEDULER_H + +#include <rtpsession.h> +#include <sessionset.h> +#include "rtptimer.h" +#include "port_fct.h" + + +struct _RtpScheduler { + + RtpSession *list; /* list of scheduled sessions*/ + SessionSet all_sessions; /* mask of scheduled sessions */ + gint all_max; /* the highest pos in the all mask */ + SessionSet r_sessions; /* mask of sessions that have a recv event */ + gint r_max; + SessionSet w_sessions; /* mask of sessions that have a send event */ + gint w_max; + SessionSet e_sessions; /* mask of session that have error event */ + gint e_max; + gint max_sessions; /* the number of position in the masks */ + /* GMutex *unblock_select_mutex; */ + GCond *unblock_select_cond; + GMutex *lock; + GThread *thread; + gint thread_running; + struct _RtpTimer *timer; + guint32 time_; /*number of miliseconds elapsed since the start of the thread */ + guint32 timer_inc; /* the timer increment in milisec */ +}; + +typedef struct _RtpScheduler RtpScheduler; + +RtpScheduler * rtp_scheduler_new(); +void rtp_scheduler_set_timer(RtpScheduler *sched,RtpTimer *timer); +void rtp_scheduler_start(RtpScheduler *sched); +void rtp_scheduler_stop(RtpScheduler *sched); +void rtp_scheduler_destroy(RtpScheduler *sched); + +void rtp_scheduler_add_session(RtpScheduler *sched, RtpSession *session); +void rtp_scheduler_remove_session(RtpScheduler *sched, RtpSession *session); + +gpointer rtp_scheduler_schedule(gpointer sched); + +#define rtp_scheduler_lock(sched) g_mutex_lock((sched)->lock) +#define rtp_scheduler_unlock(sched) g_mutex_unlock((sched)->lock) + +/* void rtp_scheduler_add_set(RtpScheduler *sched, SessionSet *set); */ + +RtpScheduler * ortp_get_scheduler(); +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.c new file mode 100644 index 00000000..7b5ad921 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.c @@ -0,0 +1,187 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <ortp.h> +#include <sessionset.h> +#include "scheduler.h" + +/** + *session_set_init: + *@ss: a SessionSet statically allocated. + * + * Initializes a session set. It is unusefull to call this function on a session set object + * returned by session_set_new(). + * +**/ + + +/** + *session_set_new: + * + * Allocates and initialize a new empty session set. + * + *Returns: the session set. +**/ +SessionSet * session_set_new() +{ + SessionSet *set=g_malloc(sizeof(SessionSet)); + session_set_init(set); + return set; +} + + +/** + *session_set_destroy: + *@set: a SessionSet + * Destroys a session set. + * +**/ + +void session_set_destroy(SessionSet *set) +{ + g_free(set); +} + +gint session_set_and(SessionSet *sched_set, gint maxs, SessionSet *user_set, SessionSet *result_set) +{ + guint32 *mask1,*mask2,*mask3; + gint i=0; + gint j,ret=0; + mask1=(guint32*)&sched_set->rtpset; + mask2=(guint32*)&user_set->rtpset; + mask3=(guint32*)&result_set->rtpset; + while(i<maxs+1){ + *mask3=(*mask1) & (*mask2); /* computes the AND between the two masks*/ + /* and unset the sessions that have been found from the sched_set */ + *mask1=(*mask1) & (~(*mask3)); + if ((*mask3)!=0){ + for (j=0;j<32;j++){ + if ( ((*mask3)>>j) & 1){ + ret++; + } + } + } + i+=32; + mask1++; + mask2++; + mask3++; + } + //printf("session_set_and: ret=%i\n",ret); + return ret; +} + +/** + *session_set_select: + *@recvs: a set of rtp sessions to be watched for read events + *@sends: a set of rtp sessions to be watched for write events + *@errors: a set of rtp sessions to be watched for errors + * + * This function performs similarly as libc select() function, but performs on #RtpSession + * instead of file descriptors. + * session_set_select() suspends the calling process until some events arrive on one of the + * three sets passed in argument. Two of the sets can be NULL. + * The first set @recvs is interpreted as a set of RtpSession waiting for receive events: + * a new buffer (perhaps empty) is availlable on one or more sessions of the set, or the last + * receive operation with rtp_session_recv_with_ts() would have finished if it were in + * blocking mode. + * The second set is interpreted as a set of RtpSession waiting for send events, i.e. the last + * rtp_session_send_with_ts() call on a session would have finished if it were in blocking mode. + * + * When some events arrived on some of sets, then the function returns and sets are changed + * to indicate the sessions where events happened. + * Sessions can be added to sets using session_set_set(), a session has to be tested to be + * part of a set using session_set_is_set(). + * + *Returns: the number of sessions on which the selected events happened. +**/ +int session_set_select(SessionSet *recvs, SessionSet *sends, SessionSet *errors) +{ + gint ret=0,bits; + SessionSet temp; + RtpScheduler *sched=ortp_get_scheduler(); + + /*lock the scheduler to not read the masks while they are being modified by the scheduler*/ + rtp_scheduler_lock(sched); + + while(1){ + /* computes the SessionSet intersection (in the other words mask intersection) between + the mask given by the user and scheduler masks */ + if (recvs!=NULL){ + bits=session_set_and(&sched->r_sessions,sched->all_max,recvs,&temp); + if (bits>0){ + ret+=bits; + /* copy the result set in the given user set */ + session_set_copy(recvs,&temp); + } + } + if (sends!=NULL){ + bits=session_set_and(&sched->w_sessions,sched->all_max,sends,&temp); + if (bits>0){ + ret+=bits; + /* copy the result set in the given user set */ + session_set_copy(sends,&temp); + } + } + if (errors!=NULL){ + bits=session_set_and(&sched->e_sessions,sched->all_max,errors,&temp); + if (bits>0){ + ret+=bits; + /* copy the result set in the given user set */ + session_set_copy(errors,&temp); + } + } + if (ret>0){ + /* there are set file descriptors, return immediately */ + //printf("There are %i sessions set, returning.\n",ret); + rtp_scheduler_unlock(sched); + return ret; + } + //printf("There are %i sessions set.\n",ret); + /* else we wait until the next loop of the scheduler*/ + g_cond_wait(sched->unblock_select_cond,sched->lock); + } + + return -1; +} + +/** + *session_set_set: + *@ss: a set (#SessionSet object) + *@rtpsession: a rtp session + * + * This macro adds rtp session @_session to set @_set. +**/ + +/** + *session_set_is_set: + *@ss: a set (#SessionSet object) + *@rtpsession: a rtp session + * + * This macro tests if @_session is part of @_set. 1 is returned if true, 0 else. +**/ + +/** + *session_set_clr: + *@ss: a set of sessions. + *@rtpsession: a rtp session. + * + * Removes the @_session from the _set. + * + * +**/ diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.h new file mode 100644 index 00000000..623b9d10 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.h @@ -0,0 +1,102 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SESSIONSET_H +#define SESSIONSET_H + + +#include <rtpsession.h> + + +#ifndef _WIN32 +/* UNIX */ +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + +#define ORTP_FD_SET(d, s) FD_SET(d, s) +#define ORTP_FD_CLR(d, s) FD_CLR(d, s) +#define ORTP_FD_ISSET(d, s) FD_ISSET(d, s) +#define ORTP_FD_ZERO(s) FD_ZERO(s) + +typedef fd_set ortp_fd_set; + + +#else +/* WIN32 */ + +#define ORTP_FD_ZERO(s) \ + do { \ + unsigned int __i; \ + ortp_fd_set *__arr = (s); \ + for (__i = 0; __i < sizeof (ortp_fd_set) / sizeof (ortp__fd_mask); ++__i) \ + ORTP__FDS_BITS (__arr)[__i] = 0; \ + } while (0) +#define ORTP_FD_SET(d, s) (ORTP__FDS_BITS (s)[ORTP__FDELT(d)] |= ORTP__FDMASK(d)) +#define ORTP_FD_CLR(d, s) (ORTP__FDS_BITS (s)[ORTP__FDELT(d)] &= ~ORTP__FDMASK(d)) +#define ORTP_FD_ISSET(d, s) ((ORTP__FDS_BITS (s)[ORTP__FDELT(d)] & ORTP__FDMASK(d)) != 0) + + + +/* The fd_set member is required to be an array of longs. */ +typedef long int ortp__fd_mask; + + +/* Number of bits per word of `fd_set' (some code assumes this is 32). */ +#define ORTP__FD_SETSIZE 1024 + +/* It's easier to assume 8-bit bytes than to get CHAR_BIT. */ +#define ORTP__NFDBITS (8 * sizeof (ortp__fd_mask)) +#define ORTP__FDELT(d) ((d) / ORTP__NFDBITS) +#define ORTP__FDMASK(d) ((ortp__fd_mask) 1 << ((d) % ORTP__NFDBITS)) + + +/* fd_set for select and pselect. */ +typedef struct + { + ortp__fd_mask fds_bits[ORTP__FD_SETSIZE / ORTP__NFDBITS]; +# define ORTP__FDS_BITS(set) ((set)->fds_bits) + } ortp_fd_set; + + +#endif /*end WIN32*/ + +struct _SessionSet +{ + ortp_fd_set rtpset; +}; + + +typedef struct _SessionSet SessionSet; + +SessionSet * session_set_new(); +#define session_set_init(ss) ORTP_FD_ZERO(&(ss)->rtpset) +#define session_set_set(ss,rtpsession) ORTP_FD_SET((rtpsession)->mask_pos,&(ss)->rtpset) +#define session_set_is_set(ss,rtpsession) ORTP_FD_ISSET((rtpsession)->mask_pos,&(ss)->rtpset) +#define session_set_clr(ss,rtpsession) ORTP_FD_CLR((rtpsession)->mask_pos,&(ss)->rtpset) + +#define session_set_copy(dest,src) memcpy(&(dest)->rtpset,&(src)->rtpset,sizeof(ortp_fd_set)) + +void session_set_destroy(SessionSet *set); + + +int session_set_select(SessionSet *recvs, SessionSet *sends, SessionSet *errors); + + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.c new file mode 100644 index 00000000..813ea707 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.c @@ -0,0 +1,297 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <rtpport.h> +#include <rtp.h> +#include <str_utils.h> + +#include <stdio.h> + +void qinit(queue_t *q){ + mblk_init(&q->_q_first); + mblk_init(&q->_q_last); + q->_q_first.b_next=&q->_q_last; + q->_q_last.b_prev=&q->_q_first; + q->q_mcount=0; +} + +void mblk_init(mblk_t *mp) +{ + mp->b_cont=mp->b_prev=mp->b_next=NULL; + mp->b_rptr=mp->b_wptr=NULL; +} + +mblk_t *allocb(int size, int pri) +{ + mblk_t *mp; + dblk_t *datab; + gchar *buf; + + mp=g_malloc(sizeof(mblk_t)); + mblk_init(mp); + datab=g_malloc(sizeof(dblk_t)); + + buf=g_malloc(size); + + datab->db_base=buf; + datab->db_lim=buf+size; + datab->ref_count=1; + datab->db_freefn=g_free; + + mp->b_datap=datab; + mp->b_rptr=mp->b_wptr=buf; + mp->b_next=mp->b_prev=mp->b_cont=NULL; + return mp; +} + +mblk_t *allocb_with_buf(char *buf, int size, int pri, void (*freefn)(void*) ) +{ + mblk_t *mp; + dblk_t *datab; + + mp=g_malloc(sizeof(mblk_t)); + mblk_init(mp); + datab=g_malloc(sizeof(dblk_t)); + + + datab->db_base=buf; + datab->db_lim=buf+size; + datab->ref_count=1; + datab->db_freefn=freefn; + + mp->b_datap=datab; + mp->b_rptr=mp->b_wptr=buf; + mp->b_next=mp->b_prev=mp->b_cont=NULL; + return mp; +} + + +void freeb(mblk_t *mp) +{ + g_return_if_fail(mp->b_datap!=NULL); + g_return_if_fail(mp->b_datap->db_base!=NULL); + + mp->b_datap->ref_count--; + if (mp->b_datap->ref_count==0) + { + if (mp->b_datap->db_freefn!=NULL) + mp->b_datap->db_freefn(mp->b_datap->db_base); + g_free(mp->b_datap); + } + g_free(mp); +} + +void freemsg(mblk_t *mp) +{ + mblk_t *tmp1,*tmp2; + tmp1=mp; + while(tmp1!=NULL) + { + tmp2=tmp1->b_cont; + freeb(tmp1); + tmp1=tmp2; + } +} + +mblk_t *dupb(mblk_t *mp) +{ + mblk_t *newm; + g_return_val_if_fail(mp->b_datap!=NULL,NULL); + g_return_val_if_fail(mp->b_datap->db_base!=NULL,NULL); + + mp->b_datap->ref_count++; + newm=g_malloc(sizeof(mblk_t)); + mblk_init(newm); + newm->b_datap=mp->b_datap; + newm->b_rptr=mp->b_rptr; + newm->b_wptr=mp->b_wptr; + return newm; +} + +/* duplicates a complex mblk_t */ +mblk_t *dupmsg(mblk_t* m) +{ + mblk_t *newm=NULL,*mp,*prev; + prev=newm=dupb(m); + m=m->b_cont; + while (m!=NULL){ + mp=dupb(m); + prev->b_cont=mp; + prev=mp; + m=m->b_cont; + } + return newm; +} + +void putq(queue_t *q,mblk_t *mp) +{ + q->_q_last.b_prev->b_next=mp; + mp->b_prev=q->_q_last.b_prev; + mp->b_next=&q->_q_last; + q->_q_last.b_prev=mp; + q->q_mcount++; +} + +mblk_t *getq(queue_t *q) +{ + mblk_t *tmp; + tmp=q->_q_first.b_next; + if (tmp==&q->_q_last) return NULL; + q->_q_first.b_next=tmp->b_next; + tmp->b_next->b_prev=&q->_q_first; + tmp->b_prev=NULL; + tmp->b_next=NULL; + q->q_mcount--; + return tmp; +} + +/* insert mp in q just before emp */ +void insq(queue_t *q,mblk_t *emp, mblk_t *mp) +{ + if (emp==NULL){ + putq(q,mp); + return; + } + q->q_mcount++; + emp->b_prev->b_next=mp; + mp->b_prev=emp->b_prev; + emp->b_prev=mp; + mp->b_next=emp; +} + +void remq(queue_t *q, mblk_t *mp){ + q->q_mcount--; + mp->b_prev->b_next=mp->b_next; + mp->b_next->b_prev=mp->b_prev; + mp->b_next=NULL; + mp->b_prev=NULL; +} + +/* remove and free all messages in the q */ +void flushq(queue_t *q, int how) +{ + mblk_t *mp; + + while ((mp=getq(q))!=NULL) + { + freemsg(mp); + } +} + +gint msgdsize(mblk_t *mp) +{ + gint msgsize=0; + while(mp!=NULL){ + msgsize+=mp->b_wptr-mp->b_rptr; + mp=mp->b_cont; + } + return msgsize; +} + +mblk_t * msgpullup(mblk_t *mp,int len) +{ + mblk_t *newm; + gint msgsize=msgdsize(mp); + gint rlen; + gint mlen; + + + if ((len==-1) || (len>msgsize)) len=msgsize; + rlen=len; + newm=allocb(len,BPRI_MED); + + while(mp!=NULL){ + mlen=mp->b_wptr-mp->b_rptr; + if (rlen>=mlen) + { + memcpy(newm->b_wptr,mp->b_rptr,mlen); + rlen-=mlen; + newm->b_wptr+=mlen; + } + else /* rlen < mlen */ + { + memcpy(newm->b_wptr,mp->b_rptr,rlen); + newm->b_wptr+=rlen; + + /* put the end of the original message at the end of the new */ + newm->b_cont=dupmsg(mp); + newm->b_cont->b_rptr+=rlen; + return newm; + } + mp=mp->b_cont; + } + return newm; +} + + +mblk_t *copyb(mblk_t *mp) +{ + mblk_t *newm; + gint len=mp->b_wptr-mp->b_rptr; + newm=allocb(len,BPRI_MED); + memcpy(newm->b_wptr,mp->b_rptr,len); + newm->b_wptr+=len; + return newm; +} + +mblk_t *copymsg(mblk_t *mp) +{ + mblk_t *newm=0,*m; + m=newm=copyb(mp); + mp=mp->b_cont; + while(mp!=NULL){ + m->b_cont=copyb(mp); + m=m->b_cont; + mp=mp->b_cont; + } + return newm; +} + +mblk_t * appendb(mblk_t *mp, const char *data, int size, gboolean pad){ + gint padcnt=0; + int i; + if (pad){ + padcnt= (gint)(4L-( (long)(mp->b_wptr+size) % 4L)) % 4L; + } + if ((mp->b_wptr + size +padcnt) > (char*)mp->b_datap->db_lim){ + /* buffer is not large enough: append a new block (with the same size ?)*/ + int plen=(char*)mp->b_datap->db_lim - (char*) mp->b_datap->db_base; + mp->b_cont=allocb(MAX(plen,size),0); + mp=mp->b_cont; + } + if (size) memcpy(mp->b_wptr,data,size); + mp->b_wptr+=size; + for (i=0;i<padcnt;i++){ + mp->b_wptr[0]=0; + mp->b_wptr++; + } + return mp; +} + +void msgappend(mblk_t *mp, const char *data, int size, gboolean pad){ + while(mp->b_cont!=NULL) mp=mp->b_cont; + appendb(mp,data,size,pad); +} + +mblk_t *concatb(mblk_t *mp, mblk_t *newm){ + while (mp->b_cont!=NULL) mp=mp->b_cont; + mp->b_cont=newm; + while(newm->b_cont!=NULL) newm=newm->b_cont; + return newm; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.h new file mode 100644 index 00000000..b605fc2a --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.h @@ -0,0 +1,118 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef STR_UTILS_H +#define STR_UTILS_H + + +#include <rtpport.h> + + +typedef struct msgb +{ + struct msgb *b_prev; + struct msgb *b_next; + struct msgb *b_cont; + struct datab *b_datap; + char *b_rptr; + char *b_wptr; +} mblk_t; + +typedef struct datab +{ + char *db_base; + char *db_lim; + void (*db_freefn)(void*); + guint ref_count; +} dblk_t; + +typedef struct _queue +{ + mblk_t _q_first; + mblk_t _q_last; + gint q_mcount; /*number of packet in the q */ +} queue_t; + +#ifdef __cplusplus +extern "C" { +#endif + +void qinit(queue_t *q); + +void putq(queue_t *q, mblk_t *m); +mblk_t * getq(queue_t *q); + +void insq(queue_t *q,mblk_t *emp, mblk_t *mp); + +void remq(queue_t *q, mblk_t *mp); + +void mblk_init(mblk_t *mp); + +/* allocates a mblk_t, that points to a datab_t, that points to a buffer of size size. */ +mblk_t *allocb(gint size,gint unused); +#define BPRI_MED 0 + +/* allocates a mblk_t, that points to a datab_t, that points to buf; buf will be freed using freefn */ +mblk_t *allocb_with_buf(char *buf, int size, int pri, void (*freefn)(void*) ); + +/* frees a mblk_t, and if the datab ref_count is 0, frees it and the buffer too */ +void freeb(mblk_t *m); + +/* frees recursively (follow b_cont) a mblk_t, and if the datab +ref_count is 0, frees it and the buffer too */ +void freemsg(mblk_t *mp); + +/* duplicates a mblk_t , buffer is not duplicated*/ +mblk_t *dupb(mblk_t *m); + +/* duplicates a complex mblk_t, buffer is not duplicated */ +mblk_t *dupmsg(mblk_t* m); + +/* remove and free all messages in the q */ +#define FLUSHALL 0 +void flushq(queue_t *q, int how); + +/* returns the size of data of a message */ +gint msgdsize(mblk_t *mp); + +/* concatenates all fragment of a complex message ( a new message is returned, old is untouched*/ +mblk_t * msgpullup(mblk_t *mp,int len); + +/* duplicates a single message, but with buffer included */ +mblk_t *copyb(mblk_t *mp); + +/* duplicates a complex message with buffer included */ +mblk_t *copymsg(mblk_t *mp); + +mblk_t * appendb(mblk_t *mp, const char *data, int size, gboolean pad); +void msgappend(mblk_t *mp, const char *data, int size, gboolean pad); + +mblk_t *concatb(mblk_t *mp, mblk_t *newm); + +#define qempty(q) (&(q)->_q_last==(q)->_q_first.b_next) +#define qfirst(q) ((q)->_q_first.b_next!=&(q)->_q_last ? (q)->_q_first.b_next : NULL) +#define qbegin(q) ((q)->_q_first.b_next) +#define qlast(q) ((q)->_q_last.b_prev!=&(q)->_q_first ? (q)->_q_last.b_prev : NULL) +#define qend(q,mp) ((mp)==&(q)->_q_first || ((mp)==&(q)->_q_last)) +#define qnext(q,mp) ((mp)->b_next) +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.c new file mode 100644 index 00000000..884226ea --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.c @@ -0,0 +1,338 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <telephonyevents.h> + + +PayloadType telephone_event={ + PAYLOAD_AUDIO_PACKETIZED, /*type */ + 8000, /*clock rate */ + 0, /* bytes per sample N/A */ + NULL, /* zero pattern N/A*/ + 0, /*pattern_length N/A */ + 0, /* normal_bitrate */ + "telephone-event", + 0 /*flags */ +}; + +/* tell if the session supports telephony events. For this the telephony events payload_type + must be present in the rtp profile used by the session */ +/** + *rtp_session_telephone_events_supported: + *@session : a rtp session + * + * Tells whether telephony events payload type is supported within the context of the rtp + * session. + * + *Returns: the payload type number used for telephony events if found, -1 if not found. +**/ +gint rtp_session_telephone_events_supported(RtpSession *session) +{ + /* search for a telephony event payload in the current profile */ + session->telephone_events_pt=rtp_profile_get_payload_number_from_mime(session->profile,"telephone-event"); + return session->telephone_events_pt; +} + + +/** + *rtp_session_create_telephone_event_packet: + *@session: a rtp session. + *@start: boolean to indicate if the marker bit should be set. + * + * Allocates a new rtp packet to be used to add named telephony events. The application can use + * then rtp_session_add_telephone_event() to add named events to the packet. + * Finally the packet has to be sent with rtp_session_sendm_with_ts(). + * + *Returns: a message block containing the rtp packet if successfull, NULL if the rtp session + *cannot support telephony event (because the rtp profile it is bound to does not include + *a telephony event payload type). +**/ +mblk_t *rtp_session_create_telephone_event_packet(RtpSession *session, int start) +{ + mblk_t *mp; + rtp_header_t *rtp; + + g_return_val_if_fail(session->telephone_events_pt!=-1,NULL); + + mp=allocb(RTP_FIXED_HEADER_SIZE+TELEPHONY_EVENTS_ALLOCATED_SIZE,BPRI_MED); + if (mp==NULL) return NULL; + rtp=(rtp_header_t*)mp->b_rptr; + rtp->version = 2; + rtp->markbit=start; + rtp->padbit = 0; + rtp->extbit = 0; + rtp->cc = 0; + rtp->ssrc = session->send_ssrc; + /* timestamp set later, when packet is sended */ + /*seq number set later, when packet is sended */ + + /*set the payload type */ + rtp->paytype=session->telephone_events_pt; + + /*copy the payload */ + mp->b_wptr+=RTP_FIXED_HEADER_SIZE; + return mp; +} + + +/** + *rtp_session_add_telephone_event: + *@session: a rtp session. + *@packet: a rtp packet as a #mblk_t + *@event: the event type as described in rfc2833, ie one of the TEV_ macros. + *@end: boolean to indicate if the end bit should be set. (end of tone) + *@volume: the volume of the telephony tone, as described in rfc2833 + *@duration:the duration of the telephony tone, in timestamp unit. + * + * Adds a named telephony event to a rtp packet previously allocated using + * rtp_session_create_telephone_event_packet(). + * + *Returns 0 on success. +**/ +gint rtp_session_add_telephone_event(RtpSession *session, + mblk_t *packet, guchar event, gint end, guchar volume, guint16 duration) +{ + mblk_t *mp=packet; + telephone_event_t *event_hdr; + + + /* find the place where to add the new telephony event to the packet */ + while(mp->b_cont!=NULL) mp=mp->b_cont; + /* see if we need to allocate a new mblk_t */ + if ( (long)mp->b_wptr >= (long) mp->b_datap->db_lim){ + mblk_t *newm=allocb(TELEPHONY_EVENTS_ALLOCATED_SIZE,BPRI_MED); + mp->b_cont=newm; + mp=mp->b_cont; + } + if (mp==NULL) return -1; + event_hdr=(telephone_event_t*)mp->b_wptr; + event_hdr->event=event; + event_hdr->R=0; + event_hdr->E=end; + event_hdr->volume=volume; + event_hdr->duration=htons(duration); + mp->b_wptr+=sizeof(telephone_event_t); + return 0; +} +/** + *rtp_session_send_dtmf: + *@session : a rtp session + *@dtmf : a character meaning the dtmf (ex: '1', '#' , '9' ...) + *@userts : the timestamp + * + * This functions creates telephony events packets for @dtmf and sends them. + * It uses rtp_session_create_telephone_event_packet() and + * rtp_session_add_telephone_event() to create them and finally + * rtp_session_sendm_with_ts() to send them. + * + *Returns: 0 if successfull, -1 if the session cannot support telephony events or if the dtmf + * given as argument is not valid. +**/ +gint rtp_session_send_dtmf(RtpSession *session, gchar dtmf, guint32 userts) +{ + mblk_t *m1,*m2,*m3; + int tev_type; + /* create the first telephony event packet */ + switch (dtmf){ + case '1': + tev_type=TEV_DTMF_1; + break; + case '2': + tev_type=TEV_DTMF_2; + break; + case '3': + tev_type=TEV_DTMF_3; + break; + case '4': + tev_type=TEV_DTMF_4; + break; + case '5': + tev_type=TEV_DTMF_5; + break; + case '6': + tev_type=TEV_DTMF_6; + break; + case '7': + tev_type=TEV_DTMF_7; + break; + case '8': + tev_type=TEV_DTMF_8; + break; + case '9': + tev_type=TEV_DTMF_9; + break; + case '*': + tev_type=TEV_DTMF_STAR; + break; + case '0': + tev_type=TEV_DTMF_0; + break; + case '#': + tev_type=TEV_DTMF_POUND; + break; + default: + g_warning("Bad dtmf: %c.",dtmf); + return -1; + } + + m1=rtp_session_create_telephone_event_packet(session,1); + if (m1==NULL) return -1; + rtp_session_add_telephone_event(session,m1,tev_type,0,0,160); + /* create a second packet */ + m2=rtp_session_create_telephone_event_packet(session,0); + if (m2==NULL) return -1; + rtp_session_add_telephone_event(session,m2,tev_type,0,0,320); + + /* create a third and final packet */ + m3=rtp_session_create_telephone_event_packet(session,0); + if (m3==NULL) return -1; + rtp_session_add_telephone_event(session,m3,tev_type,1,0,480); + + /* and now sends them */ + rtp_session_sendm_with_ts(session,m1,userts); + rtp_session_sendm_with_ts(session,m2,userts); + /* the last packet is sent three times in order to improve reliability*/ + m1=copymsg(m3); + m2=copymsg(m3); + /* NOTE: */ + /* we need to copymsg() instead of dupmsg() because the buffers are modified when + the packet is sended because of the host-to-network conversion of timestamp,ssrc, csrc, and + seq number. + It could be avoided by making a copy of the buffer when sending physically the packet, but + it add one more copy for every buffer. + Using iomapped socket, it is possible to avoid the user to kernel copy. + */ + rtp_session_sendm_with_ts(session,m3,userts); + rtp_session_sendm_with_ts(session,m1,userts); + rtp_session_sendm_with_ts(session,m2,userts); + return 0; +} + +/** + *rtp_session_read_telephone_event: + *@session: a rtp session from which telephony events are received. + *@packet: a rtp packet as a mblk_t. + *@tab: the address of a pointer. + * + * Reads telephony events from a rtp packet. *@tab points to the beginning of the event buffer. + * + *Returns: the number of events in the packet if successfull, 0 if the packet did not + * contain telephony events. +**/ +gint rtp_session_read_telephone_event(RtpSession *session, + mblk_t *packet,telephone_event_t **tab) +{ + int datasize; + gint num; + int i; + telephone_event_t *tev; + rtp_header_t *hdr=(rtp_header_t*)packet->b_rptr; + g_return_val_if_fail(packet->b_cont!=NULL,-1); + if (hdr->paytype!=session->telephone_events_pt) return 0; /* this is not tel ev.*/ + datasize=msgdsize(packet); + tev=*tab=(telephone_event_t*)packet->b_cont->b_rptr; + /* convert from network to host order what should be */ + num=datasize/sizeof(telephone_event_t); + for (i=0;i<num;i++) + { + tev[i].duration=ntohs(tev[i].duration); + } + return num; +} + + +static void notify_events_ended(RtpSession *session, telephone_event_t *events, int num){ + int i; + for (i=0;i<num;i++){ + if (events[i].E==1){ + rtp_signal_table_emit2(&session->on_telephone_event,(gpointer)(long)events[i].event); + } + } +} + +/* for high level telephony event callback */ +void rtp_session_check_telephone_events(RtpSession *session, mblk_t *m0) +{ + telephone_event_t *events,*evbuf; + int num; + int i; + mblk_t *mp; + rtp_header_t *hdr; + mblk_t *cur_tev; + + hdr=(rtp_header_t*)m0->b_rptr; + mp=m0->b_cont; + + num=(mp->b_wptr-mp->b_rptr)/sizeof(telephone_event_t); + events=(telephone_event_t*)mp->b_rptr; + + + if (hdr->markbit==1) + { + /* this is a start of new events. Store the event buffer for later use*/ + if (session->current_tev!=NULL) { + freemsg(session->current_tev); + session->current_tev=NULL; + } + session->current_tev=copymsg(m0); + /* handle the case where the events are short enough to end within the packet that has the marker bit*/ + notify_events_ended(session,events,num); + } + /* whatever there is a markbit set or not, we parse the packet and compare it to previously received one */ + cur_tev=session->current_tev; + if (cur_tev!=NULL) + { + /* first compare timestamp, they must be identical */ + if (((rtp_header_t*)cur_tev->b_rptr)->timestamp== + ((rtp_header_t*)m0->b_rptr)->timestamp) + { + evbuf=(telephone_event_t*)cur_tev->b_cont; + for (i=0;i<num;i++) + { + if (events[i].E==1) + { + /* update events that have ended */ + if (evbuf[i].E==0){ + evbuf[i].E=1; + /* this is a end of event, report it */ + rtp_signal_table_emit2(&session->on_telephone_event,(gpointer)(long)events[i].event); + } + } + } + } + else + { + /* timestamp are not identical: this is not the same events*/ + if (session->current_tev!=NULL) { + freemsg(session->current_tev); + session->current_tev=NULL; + } + session->current_tev=dupmsg(m0); + } + } + else + { + /* there is no pending events, but we did not received marked bit packet + either the sending implementation is not compliant, either it has been lost, + we must deal with it anyway.*/ + session->current_tev=copymsg(m0); + /* inform the application if there are tone ends */ + notify_events_ended(session,events,num); + } +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.h new file mode 100644 index 00000000..6f6936d5 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.h @@ -0,0 +1,98 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef TELEPHONYEVENTS_H +#define TELEPHONYEVENTS_H + + +#include <rtpsession.h> + + +struct _telephone_event +{ +#ifdef WORDS_BIGENDIAN + guint32 event:8; + guint32 E:1; + guint32 R:1; + guint32 volume:6; + guint32 duration:16; +#else + guint32 event:8; + guint32 volume:6; + guint32 R:1; + guint32 E:1; + guint32 duration:16; +#endif +}; + +typedef struct _telephone_event telephone_event_t; + +#ifdef __cplusplus +extern "C" { +#endif + +extern PayloadType telephone_event; + +/* tell if the session supports telephony events. For this the telephony events payload_type + must be present in the rtp profile used by the session */ + +/* low level functions */ +gint rtp_session_telephone_events_supported(RtpSession *session); + +mblk_t *rtp_session_create_telephone_event_packet(RtpSession *session, int start); + +gint rtp_session_add_telephone_event(RtpSession *session, + mblk_t *packet, guchar event, gint end, guchar volume, guint16 duration); + +gint rtp_session_read_telephone_event(RtpSession *session, + mblk_t *packet,telephone_event_t **tab); + +/* high level functions*/ +gint rtp_session_send_dtmf(RtpSession *session, gchar dtmf, guint32 userts); +/* for high level telephony event callback */ +void rtp_session_check_telephone_events(RtpSession *session, mblk_t *m0); + +#ifdef __cplusplus +} +#endif + +/* the size allocated for telephony events packets */ +#define TELEPHONY_EVENTS_ALLOCATED_SIZE (4*sizeof(telephone_event_t)) + +/* list of named events */ +#define TEV_DTMF_0 (0) +#define TEV_DTMF_1 (1) +#define TEV_DTMF_2 (2) +#define TEV_DTMF_3 (3) +#define TEV_DTMF_4 (4) +#define TEV_DTMF_5 (5) +#define TEV_DTMF_6 (6) +#define TEV_DTMF_7 (7) +#define TEV_DTMF_8 (8) +#define TEV_DTMF_9 (9) +#define TEV_DTMF_STAR (10) +#define TEV_DTMF_POUND (11) +#define TEV_DTMF_A (12) +#define TEV_DTMF_B (13) +#define TEV_DTMF_C (14) +#define TEV_DTMF_D (15) +#define TEV_FLASH (16) + + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.c new file mode 100644 index 00000000..1ae601f4 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.c @@ -0,0 +1,44 @@ +/*************************************************************************** + * utils.c + * + * Wed Feb 23 14:15:36 2005 + * Copyright 2005 Simon Morlat + * Email [email protected] + ****************************************************************************/ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <rtpport.h> +#include "utils.h" + +OList *o_list_new(void *data){ + OList *new_elem=g_new0(OList,1); + new_elem->data=data; + return new_elem; +} + +OList * o_list_append(OList *elem, void * data){ + OList *new_elem=o_list_new(data); + OList *it=elem; + if (elem==NULL) return new_elem; + while (it->next!=NULL) it=o_list_next(it); + it->next=new_elem; + new_elem->prev=it; + return elem; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.h new file mode 100644 index 00000000..7b71daf8 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * utils.h + * + * Wed Feb 23 14:15:36 2005 + * Copyright 2005 Simon Morlat + * Email [email protected] + ****************************************************************************/ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT [email protected] + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef UTILS_H +#define UTILS_H + +struct _OList { + struct _OList *next; + struct _OList *prev; + void *data; +}; + +typedef struct _OList OList; + + +#define o_list_next(elem) ((elem)->next) + +OList * o_list_append(OList *elem, void * data); + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/xmllite/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/xmllite/CMakeLists.txt new file mode 100644 index 00000000..8b2e72d4 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/xmllite/CMakeLists.txt @@ -0,0 +1,28 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DPOSIX +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${TQT_INCLUDE_DIRS} +) + + +##### cricketxmllite (static) ################### + +tde_add_library( cricketxmllite STATIC_PIC + SOURCES + qname.cc xmlbuilder.cc xmlconstants.cc xmlelement.cc xmlnsstack.cc + xmlparser.cc xmlprinter.cc +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/CMakeLists.txt new file mode 100644 index 00000000..c68cc840 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/CMakeLists.txt @@ -0,0 +1,29 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DPOSIX +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${CMAKE_BINARY_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### cricketxmpp (static) ###################### + +tde_add_library( cricketxmpp STATIC_PIC + SOURCES + constants.cc jid.cc saslmechanism.cc xmppclient.cc xmppengineimpl.cc + xmppengineimpl_iq.cc xmpplogintask.cc xmppstanzaparser.cc xmpptask.cc +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/xmpppassword.h b/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/xmpppassword.h index f431b4e5..7a58cd6c 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/xmpppassword.h +++ b/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/xmpppassword.h @@ -31,6 +31,8 @@ #include "talk/base/linked_ptr.h" #include "talk/base/scoped_ptr.h" +#include <cstring> + namespace buzz { class XmppPasswordImpl { |