summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/jabber/jingle
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/protocols/jabber/jingle')
-rw-r--r--kopete/protocols/jabber/jingle/CMakeLists.txt38
-rw-r--r--kopete/protocols/jabber/jingle/jinglevoicecaller.cpp2
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/CMakeLists.txt12
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/CMakeLists.txt19
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/ConfigureChecks.cmake48
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/base/CMakeLists.txt32
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/base/asynctcpsocket.cc1
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/base/bytebuffer.cc1
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/base/host.cc2
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/base/messagequeue.h1
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/base/physicalsocketserver.cc5
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/base/socketadapters.cc1
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/p2p/CMakeLists.txt13
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/CMakeLists.txt52
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/relayserver_main.cc1
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stun.cc1
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver.cc1
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver_main.cc1
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/p2p/client/CMakeLists.txt30
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/session/CMakeLists.txt12
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/session/phone/CMakeLists.txt34
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/session/phone/linphonemediaengine.cc2
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/session/phone/phonesessionclient.cc2
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/CMakeLists.txt13
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/CMakeLists.txt36
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtprecv.h2
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.c2
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.h2
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/CMakeLists.txt32
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/avprofile.c281
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.c25
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.h38
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.c141
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.h38
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp-config.h9
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.c258
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.h54
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.c268
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.h136
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.c183
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.h48
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/posixtimer.c167
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.c294
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.h167
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcpparse.c218
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtp.h90
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.c122
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.h31
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c159
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpport.h308
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.c1954
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.h287
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.c98
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.h47
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.c32
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.h52
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.c235
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.h70
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.c187
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.h102
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.c297
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.h118
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.c338
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.h98
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.c44
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.h43
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/xmllite/CMakeLists.txt28
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/xmpp/CMakeLists.txt29
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/xmpp/xmpppassword.h2
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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+ ****************************************************************************/
+
+#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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+ ****************************************************************************/
+
+#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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ This source code file was written by Nicola Baldo as an extension of
+ the oRTP library. Copyright (C) 2005 Nicola Baldo nicola@baldo.biz
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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,&param);
+ */
+ }
+}
+
+#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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+ ****************************************************************************/
+/*
+ The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack.
+ Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
+
+ 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 simon.morlat@linphone.org
+ ****************************************************************************/
+/*
+ The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack.
+ Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
+
+ 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 {