summaryrefslogtreecommitdiffstats
path: root/third_party
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-11-25 19:40:10 +0000
committerBen Murdoch <benm@google.com>2010-12-03 13:52:53 +0000
commit4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7 (patch)
tree938665d93a11fe7a6d0124e3c1e020d1f9d3f947 /third_party
parent7c627d87728a355737862918d144f98f69406954 (diff)
downloadexternal_chromium-4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7.zip
external_chromium-4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7.tar.gz
external_chromium-4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7.tar.bz2
Merge Chromium at r66597: Initial merge by git.
Change-Id: I9639f8a997f90ec219573aa22a49f5dbde78cc7b
Diffstat (limited to 'third_party')
-rw-r--r--third_party/libjingle/source/CHANGELOG12
-rw-r--r--third_party/libjingle/source/talk/base/fileutils.h4
-rw-r--r--third_party/libjingle/source/talk/base/helpers.cc26
-rw-r--r--third_party/libjingle/source/talk/base/helpers.h6
-rw-r--r--third_party/libjingle/source/talk/base/linux.cc15
-rw-r--r--third_party/libjingle/source/talk/base/linux.h5
-rw-r--r--third_party/libjingle/source/talk/base/macutils.cc66
-rw-r--r--third_party/libjingle/source/talk/base/macutils.h4
-rw-r--r--third_party/libjingle/source/talk/examples/call/call_main.cc27
-rw-r--r--third_party/libjingle/source/talk/examples/call/call_main.cc~348
-rw-r--r--third_party/libjingle/source/talk/examples/call/callclient.cc153
-rw-r--r--third_party/libjingle/source/talk/examples/call/callclient.h22
-rw-r--r--third_party/libjingle/source/talk/main.scons86
-rw-r--r--third_party/libjingle/source/talk/p2p/base/constants.cc24
-rw-r--r--third_party/libjingle/source/talk/p2p/base/constants.h23
-rw-r--r--third_party/libjingle/source/talk/p2p/base/parsing.cc20
-rw-r--r--third_party/libjingle/source/talk/p2p/base/parsing.h6
-rw-r--r--third_party/libjingle/source/talk/p2p/base/session.cc142
-rw-r--r--third_party/libjingle/source/talk/p2p/base/session.h12
-rw-r--r--third_party/libjingle/source/talk/p2p/base/sessionmessages.cc34
-rw-r--r--third_party/libjingle/source/talk/p2p/base/sessionmessages.h7
-rw-r--r--third_party/libjingle/source/talk/p2p/base/transport.cc11
-rw-r--r--third_party/libjingle/source/talk/session/phone/call.cc31
-rw-r--r--third_party/libjingle/source/talk/session/phone/call.h20
-rw-r--r--third_party/libjingle/source/talk/session/phone/channel.cc75
-rw-r--r--third_party/libjingle/source/talk/session/phone/channel.h45
-rw-r--r--third_party/libjingle/source/talk/session/phone/filemediaengine.h8
-rw-r--r--third_party/libjingle/source/talk/session/phone/mediachannel.h32
-rw-r--r--third_party/libjingle/source/talk/session/phone/mediasessionclient.cc379
-rw-r--r--third_party/libjingle/source/talk/session/phone/mediasessionclient.h72
-rw-r--r--third_party/libjingle/source/talk/session/phone/mediasink.h49
-rw-r--r--third_party/libjingle/source/talk/session/phone/rtpdump.cc45
-rw-r--r--third_party/libjingle/source/talk/session/phone/rtpdump.h23
-rw-r--r--third_party/libjingle/source/talk/session/phone/srtpfilter.cc1
-rw-r--r--third_party/libjingle/source/talk/session/phone/srtpfilter.h2
-rw-r--r--third_party/libjingle/source/talk/session/phone/videocommon.h31
-rw-r--r--third_party/libjingle/source/talk/site_scons/site_tools/talk_noops.pycbin975 -> 0 bytes
-rw-r--r--third_party/libjingle/source/talk/site_scons/talk.py98
-rw-r--r--third_party/libjingle/source/talk/site_scons/talk.pycbin15030 -> 0 bytes
39 files changed, 1347 insertions, 617 deletions
diff --git a/third_party/libjingle/source/CHANGELOG b/third_party/libjingle/source/CHANGELOG
index 3dee65e..d1574d8 100644
--- a/third_party/libjingle/source/CHANGELOG
+++ b/third_party/libjingle/source/CHANGELOG
@@ -1,5 +1,17 @@
Libjingle
+0.5.1 - Nov 2, 2010
+ - Added support for call encryption.
+ - Added addtional XEP-166 and XEP-167 features:
+ - Call redirection
+ - Candidates in session-accept or session-initiate
+ - Added support for bandwidth control.
+ - Added features in examples/call:
+ - bandwidth control on initiate or accept
+ - turn on/off SSL
+ - control signaling protocol
+ - send chat message
+
0.5.0 - Sep 16, 2010
- Implemented Jingle protocols XEP-166 and XEP-167.
- Backward compatible with Google Talk Call Signaling protocol implemented
diff --git a/third_party/libjingle/source/talk/base/fileutils.h b/third_party/libjingle/source/talk/base/fileutils.h
index 8ad631f..217cd83 100644
--- a/third_party/libjingle/source/talk/base/fileutils.h
+++ b/third_party/libjingle/source/talk/base/fileutils.h
@@ -339,6 +339,10 @@ class Filesystem {
return EnsureDefaultFilesystem()->MoveFile(old_path, new_path);
}
+ static bool CopyFolder(const Pathname &old_path, const Pathname &new_path) {
+ return EnsureDefaultFilesystem()->CopyFolder(old_path, new_path);
+ }
+
static bool CopyFile(const Pathname &old_path, const Pathname &new_path) {
return EnsureDefaultFilesystem()->CopyFile(old_path, new_path);
}
diff --git a/third_party/libjingle/source/talk/base/helpers.cc b/third_party/libjingle/source/talk/base/helpers.cc
index 94ca57e..f8d8a9f 100644
--- a/third_party/libjingle/source/talk/base/helpers.cc
+++ b/third_party/libjingle/source/talk/base/helpers.cc
@@ -32,7 +32,7 @@
#include <windows.h>
#include <ntsecapi.h>
#else
-#ifdef USE_OPENSSL
+#ifdef SSL_USE_OPENSSL
#include <openssl/rand.h>
#endif
#endif
@@ -98,7 +98,7 @@ class SecureRandomGenerator : public RandomGenerator {
RtlGenRandomProc rtl_gen_random_;
};
#else
-#ifndef USE_OPENSSL
+#ifndef SSL_USE_OPENSSL
// The old RNG.
class SecureRandomGenerator : public RandomGenerator {
public:
@@ -139,14 +139,14 @@ class SecureRandomGenerator : public RandomGenerator {
virtual bool Init(const void* seed, size_t len) {
// By default, seed from the system state.
if (!inited_) {
- if (RAND_poll() != 0) {
+ if (RAND_poll() <= 0) {
return false;
}
inited_ = true;
}
// Allow app data to be mixed in, if provided.
if (seed) {
- RAND_add(seed, len);
+ RAND_seed(seed, len);
}
return true;
}
@@ -154,13 +154,13 @@ class SecureRandomGenerator : public RandomGenerator {
if (!inited_ && !Init(NULL, 0)) {
return false;
}
- return (RAND_bytes(buf, len) == 0);
+ return (RAND_bytes(reinterpret_cast<unsigned char*>(buf), len) > 0);
}
private:
bool inited_;
};
-#endif // USE_OPENSSL
+#endif // SSL_USE_OPENSSL
#endif // WIN32
// A test random generator, for predictable output.
@@ -220,14 +220,22 @@ bool InitRandom(const char* seed, size_t len) {
std::string CreateRandomString(size_t len) {
std::string str;
+ CreateRandomString(len, &str);
+ return str;
+}
+
+bool CreateRandomString(size_t len, std::string* str) {
+ str->clear();
scoped_array<uint8> bytes(new uint8[len]);
if (!g_rng->Generate(bytes.get(), len)) {
LOG(LS_ERROR) << "Failed to generate random string!";
+ return false;
}
- for (size_t i = 0; i < len; i++) {
- str.push_back(BASE64[bytes[i] & 63]);
+ str->reserve(len);
+ for (size_t i = 0; i < len; ++i) {
+ str->push_back(BASE64[bytes[i] & 63]);
}
- return str;
+ return true;
}
uint32 CreateRandomId() {
diff --git a/third_party/libjingle/source/talk/base/helpers.h b/third_party/libjingle/source/talk/base/helpers.h
index 878efc1..83a3c7f 100644
--- a/third_party/libjingle/source/talk/base/helpers.h
+++ b/third_party/libjingle/source/talk/base/helpers.h
@@ -42,8 +42,14 @@ bool InitRandom(const char* seed, size_t len);
// Generates a (cryptographically) random string of the given length.
// We generate base64 values so that they will be printable.
+// WARNING: could silently fail. Use the version below instead.
std::string CreateRandomString(size_t length);
+// Generates a (cryptographically) random string of the given length.
+// We generate base64 values so that they will be printable.
+// Return false if the random number generator failed.
+bool CreateRandomString(size_t length, std::string* str);
+
// Generates a random id.
uint32 CreateRandomId();
diff --git a/third_party/libjingle/source/talk/base/linux.cc b/third_party/libjingle/source/talk/base/linux.cc
index 2061d73..03d486b 100644
--- a/third_party/libjingle/source/talk/base/linux.cc
+++ b/third_party/libjingle/source/talk/base/linux.cc
@@ -14,6 +14,10 @@
namespace talk_base {
+static const char kCpuInfoFile[] = "/proc/cpuinfo";
+static const char kCpuMaxFreqFile[] =
+ "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
+
ProcCpuInfo::ProcCpuInfo() {
}
@@ -22,7 +26,7 @@ ProcCpuInfo::~ProcCpuInfo() {
bool ProcCpuInfo::LoadFromSystem() {
ConfigParser procfs;
- if (!procfs.Open("/proc/cpuinfo"))
+ if (!procfs.Open(kCpuInfoFile))
return false;
return procfs.Parse(&cpu_info_);
};
@@ -214,6 +218,15 @@ std::string ReadLinuxUname() {
return sstr.str();
}
+int ReadCpuMaxFreq() {
+ FileStream fs;
+ std::string str;
+ if (!fs.Open(kCpuMaxFreqFile, "r") || SR_SUCCESS != fs.ReadLine(&str)) {
+ return -1;
+ }
+ return atoi(str.c_str());
+}
+
} // namespace talk_base
#endif // LINUX
diff --git a/third_party/libjingle/source/talk/base/linux.h b/third_party/libjingle/source/talk/base/linux.h
index 808dc0e..37b845b 100644
--- a/third_party/libjingle/source/talk/base/linux.h
+++ b/third_party/libjingle/source/talk/base/linux.h
@@ -91,6 +91,11 @@ std::string ReadLinuxLsbRelease();
// Returns the output of "uname".
std::string ReadLinuxUname();
+// Returns the content (int) of
+// /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
+// Returns -1 on error.
+int ReadCpuMaxFreq();
+
} // namespace talk_base
#endif // LINUX
diff --git a/third_party/libjingle/source/talk/base/macutils.cc b/third_party/libjingle/source/talk/base/macutils.cc
index 69a2f5d..fefe2b9 100644
--- a/third_party/libjingle/source/talk/base/macutils.cc
+++ b/third_party/libjingle/source/talk/base/macutils.cc
@@ -144,13 +144,77 @@ bool GetQuickTimeVersion(std::string* out) {
int ver;
if (!GetGestalt(gestaltQuickTimeVersion, &ver))
return false;
-
+
std::stringstream ss;
ss << std::hex << ver;
*out = ss.str();
return true;
}
+bool RunAppleScript(const std::string& script) {
+ ComponentInstance component = NULL;
+ AEDesc script_desc;
+ AEDesc result_data;
+ OSStatus err;
+ OSAID script_id, result_id;
+
+ AECreateDesc(typeNull, NULL, 0, &script_desc);
+ AECreateDesc(typeNull, NULL, 0, &result_data);
+ script_id = kOSANullScript;
+ result_id = kOSANullScript;
+
+ component = OpenDefaultComponent(kOSAComponentType, typeAppleScript);
+ if (component == NULL) {
+ LOG(LS_ERROR) << "Failed opening Apple Script component";
+ return false;
+ }
+ err = AECreateDesc(typeUTF8Text, script.data(), script.size(), &script_desc);
+ if (err != noErr) {
+ CloseComponent(component);
+ LOG(LS_ERROR) << "Failed creating Apple Script description";
+ return false;
+ }
+
+ err = OSACompile(component, &script_desc, kOSAModeCanInteract, &script_id);
+ if (err != noErr) {
+ AEDisposeDesc(&script_desc);
+ if (script_id != kOSANullScript) {
+ OSADispose(component, script_id);
+ }
+ CloseComponent(component);
+ LOG(LS_ERROR) << "Error compiling Apple Script";
+ return false;
+ }
+
+ err = OSAExecute(component, script_id, kOSANullScript, kOSAModeCanInteract,
+ &result_id);
+
+ if (err == errOSAScriptError) {
+ LOG(LS_ERROR) << "Error when executing Apple Script: " << script;
+ AECreateDesc(typeNull, NULL, 0, &result_data);
+ OSAScriptError(component, kOSAErrorMessage, typeChar, &result_data);
+ int len = AEGetDescDataSize(&result_data);
+ char* data = (char*) malloc(len);
+ if (data != NULL) {
+ err = AEGetDescData(&result_data, data, len);
+ LOG(LS_ERROR) << "Script error: " << data;
+ }
+ AEDisposeDesc(&script_desc);
+ AEDisposeDesc(&result_data);
+ return false;
+ }
+ AEDisposeDesc(&script_desc);
+ if (script_id != kOSANullScript) {
+ OSADispose(component, script_id);
+ }
+ if (result_id != kOSANullScript) {
+ OSADispose(component, result_id);
+ }
+ CloseComponent(component);
+ return true;
+}
+
+
///////////////////////////////////////////////////////////////////////////////
} // namespace talk_base
diff --git a/third_party/libjingle/source/talk/base/macutils.h b/third_party/libjingle/source/talk/base/macutils.h
index 1cd64ab..30bb300 100644
--- a/third_party/libjingle/source/talk/base/macutils.h
+++ b/third_party/libjingle/source/talk/base/macutils.h
@@ -55,6 +55,10 @@ bool GetOSVersion(int* major, int* minor, int* bugfix);
MacOSVersionName GetOSVersionName();
bool GetQuickTimeVersion(std::string* version);
+// Runs the given apple script. Only supports scripts that does not
+// require user interaction.
+bool RunAppleScript(const std::string& script);
+
///////////////////////////////////////////////////////////////////////////////
} // namespace talk_base
diff --git a/third_party/libjingle/source/talk/examples/call/call_main.cc b/third_party/libjingle/source/talk/examples/call/call_main.cc
index dde0784..541aca8 100644
--- a/third_party/libjingle/source/talk/examples/call/call_main.cc
+++ b/third_party/libjingle/source/talk/examples/call/call_main.cc
@@ -36,6 +36,7 @@
#include "talk/base/stream.h"
#include "talk/base/ssladapter.h"
#include "talk/base/win32socketserver.h"
+#include "talk/p2p/base/constants.h"
#include "talk/xmpp/xmppclientsettings.h"
#include "talk/examples/login/xmppthread.h"
#include "talk/examples/login/xmppauth.h"
@@ -194,7 +195,7 @@ cricket::MediaEngine* CreateFileMediaEngine(const char* voice_in,
// the the input voice and video streams.
std::vector<cricket::AudioCodec> voice_codecs;
voice_codecs.push_back(
- cricket::AudioCodec(9, "G722", 16000, 64000, 1, 0));
+ cricket::AudioCodec(9, "G722", 16000, 0, 1, 0));
file_media_engine->set_voice_codecs(voice_codecs);
std::vector<cricket::VideoCodec> video_codecs;
video_codecs.push_back(
@@ -214,7 +215,11 @@ int main(int argc, char **argv) {
// define options
DEFINE_bool(a, false, "Turn on auto accept.");
DEFINE_bool(d, false, "Turn on debugging.");
+ DEFINE_string(
+ protocol, "hybrid",
+ "Initial signaling protocol to use: jingle, gingle, or hybrid.");
DEFINE_bool(testserver, false, "Use test server");
+ DEFINE_bool(plainserver, false, "Turn off tls and allow plain password.");
DEFINE_int(portallocator, 0, "Filter out unwanted connection types.");
DEFINE_string(filterhost, NULL, "Filter out the host from all candidates.");
DEFINE_string(pmuc, "groupchat.google.com", "The persistant muc domain.");
@@ -234,11 +239,25 @@ int main(int argc, char **argv) {
bool auto_accept = FLAG_a;
bool debug = FLAG_d;
+ std::string protocol = FLAG_protocol;
bool test_server = FLAG_testserver;
+ bool plain_server = FLAG_plainserver;
int32 portallocator_flags = FLAG_portallocator;
std::string pmuc_domain = FLAG_pmuc;
std::string server = FLAG_s;
+ cricket::SignalingProtocol initial_protocol = cricket::PROTOCOL_HYBRID;
+ if (protocol == "jingle") {
+ initial_protocol = cricket::PROTOCOL_JINGLE;
+ } else if (protocol == "gingle") {
+ initial_protocol = cricket::PROTOCOL_GINGLE;
+ } else if (protocol == "hybrid") {
+ initial_protocol = cricket::PROTOCOL_HYBRID;
+ } else {
+ printf("Invalid protocol. Must be jingle, gingle, or hybrid.");
+ return 1;
+ }
+
// parse username and password, if present
buzz::Jid jid;
std::string username;
@@ -279,6 +298,10 @@ int main(int argc, char **argv) {
xcs.set_host(jid.domain());
xcs.set_use_tls(!test_server);
+ if (plain_server) {
+ xcs.set_use_tls(false);
+ xcs.set_allow_plain(true);
+ }
if (test_server) {
pass.password() = jid.node();
xcs.set_allow_plain(true);
@@ -329,6 +352,8 @@ int main(int argc, char **argv) {
client->SetAutoAccept(auto_accept);
client->SetPmucDomain(pmuc_domain);
client->SetPortAllocatorFlags(portallocator_flags);
+ client->SetAllowLocalIps(true);
+ client->SetInitialProtocol(initial_protocol);
console->Start();
if (debug) {
diff --git a/third_party/libjingle/source/talk/examples/call/call_main.cc~ b/third_party/libjingle/source/talk/examples/call/call_main.cc~
deleted file mode 100644
index fd7aafd..0000000
--- a/third_party/libjingle/source/talk/examples/call/call_main.cc~
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <time.h>
-#include <iomanip>
-#include <cstdio>
-#include <cstring>
-#include <vector>
-#include "talk/base/logging.h"
-#include "talk/base/flags.h"
-#include "talk/base/pathutils.h"
-#include "talk/base/stream.h"
-#include "talk/base/ssladapter.h"
-#include "talk/base/win32socketserver.h"
-#include "talk/xmpp/xmppclientsettings.h"
-#include "talk/examples/login/xmppthread.h"
-#include "talk/examples/login/xmppauth.h"
-#include "talk/examples/login/xmpppump.h"
-#include "talk/examples/call/callclient.h"
-#include "talk/examples/call/console.h"
-#include "talk/session/phone/filemediaengine.h"
-
-class DebugLog : public sigslot::has_slots<> {
- public:
- DebugLog() :
- debug_input_buf_(NULL), debug_input_len_(0), debug_input_alloc_(0),
- debug_output_buf_(NULL), debug_output_len_(0), debug_output_alloc_(0),
- censor_password_(false)
- {}
- char * debug_input_buf_;
- int debug_input_len_;
- int debug_input_alloc_;
- char * debug_output_buf_;
- int debug_output_len_;
- int debug_output_alloc_;
- bool censor_password_;
-
- void Input(const char * data, int len) {
- if (debug_input_len_ + len > debug_input_alloc_) {
- char * old_buf = debug_input_buf_;
- debug_input_alloc_ = 4096;
- while (debug_input_alloc_ < debug_input_len_ + len) {
- debug_input_alloc_ *= 2;
- }
- debug_input_buf_ = new char[debug_input_alloc_];
- memcpy(debug_input_buf_, old_buf, debug_input_len_);
- delete[] old_buf;
- }
- memcpy(debug_input_buf_ + debug_input_len_, data, len);
- debug_input_len_ += len;
- DebugPrint(debug_input_buf_, &debug_input_len_, false);
- }
-
- void Output(const char * data, int len) {
- if (debug_output_len_ + len > debug_output_alloc_) {
- char * old_buf = debug_output_buf_;
- debug_output_alloc_ = 4096;
- while (debug_output_alloc_ < debug_output_len_ + len) {
- debug_output_alloc_ *= 2;
- }
- debug_output_buf_ = new char[debug_output_alloc_];
- memcpy(debug_output_buf_, old_buf, debug_output_len_);
- delete[] old_buf;
- }
- memcpy(debug_output_buf_ + debug_output_len_, data, len);
- debug_output_len_ += len;
- DebugPrint(debug_output_buf_, &debug_output_len_, true);
- }
-
- static bool IsAuthTag(const char * str, size_t len) {
- if (str[0] == '<' && str[1] == 'a' &&
- str[2] == 'u' &&
- str[3] == 't' &&
- str[4] == 'h' &&
- str[5] <= ' ') {
- std::string tag(str, len);
-
- if (tag.find("mechanism") != std::string::npos)
- return true;
- }
- return false;
- }
-
- void DebugPrint(char * buf, int * plen, bool output) {
- int len = *plen;
- if (len > 0) {
- time_t tim = time(NULL);
- struct tm * now = localtime(&tim);
- char *time_string = asctime(now);
- if (time_string) {
- size_t time_len = strlen(time_string);
- if (time_len > 0) {
- time_string[time_len-1] = 0; // trim off terminating \n
- }
- }
- LOG(INFO) << (output ? "SEND >>>>>>>>>>>>>>>>" : "RECV <<<<<<<<<<<<<<<<")
- << " : " << time_string;
-
- bool indent;
- int start = 0, nest = 3;
- for (int i = 0; i < len; i += 1) {
- if (buf[i] == '>') {
- if ((i > 0) && (buf[i-1] == '/')) {
- indent = false;
- } else if ((start + 1 < len) && (buf[start + 1] == '/')) {
- indent = false;
- nest -= 2;
- } else {
- indent = true;
- }
-
- // Output a tag
- LOG(INFO) << std::setw(nest) << " "
- << std::string(buf + start, i + 1 - start);
-
- if (indent)
- nest += 2;
-
- // Note if it's a PLAIN auth tag
- if (IsAuthTag(buf + start, i + 1 - start)) {
- censor_password_ = true;
- }
-
- // incr
- start = i + 1;
- }
-
- if (buf[i] == '<' && start < i) {
- if (censor_password_) {
- LOG(INFO) << std::setw(nest) << " " << "## TEXT REMOVED ##";
- censor_password_ = false;
- } else {
- LOG(INFO) << std::setw(nest) << " "
- << std::string(buf + start, i - start);
- }
- start = i;
- }
- }
- len = len - start;
- memcpy(buf, buf + start, len);
- *plen = len;
- }
- }
-};
-
-static DebugLog debug_log_;
-static const int DEFAULT_PORT = 5222;
-
-
-cricket::MediaEngine* CreateFileMediaEngine(const char* voice_in,
- const char* voice_out,
- const char* video_in,
- const char* video_out) {
- cricket::FileMediaEngine* file_media_engine = new cricket::FileMediaEngine;
- // Set the RTP dump file names.
- if (voice_in) {
- file_media_engine->set_voice_input_filename(voice_in);
- }
- if (voice_out) {
- file_media_engine->set_voice_output_filename(voice_out);
- }
- if (video_in) {
- file_media_engine->set_video_input_filename(video_in);
- }
- if (video_out) {
- file_media_engine->set_video_output_filename(video_out);
- }
-
- // Set voice and video codecs. TODO: The codecs actually depend on
- // the the input voice and video streams.
- std::vector<cricket::AudioCodec> voice_codecs;
- voice_codecs.push_back(
- cricket::AudioCodec(9, "G722", 16000, 0, 1, 0));
- file_media_engine->set_voice_codecs(voice_codecs);
- std::vector<cricket::VideoCodec> video_codecs;
- video_codecs.push_back(
- cricket::VideoCodec(97, "H264", 320, 240, 30, 0));
- file_media_engine->set_video_codecs(video_codecs);
-
- return file_media_engine;
-}
-
-int main(int argc, char **argv) {
- // This app has three threads. The main thread will run the XMPP client,
- // which will print to the screen in its own thread. A second thread
- // will get input from the console, parse it, and pass the appropriate
- // message back to the XMPP client's thread. A third thread is used
- // by MediaSessionClient as its worker thread.
-
- // define options
- DEFINE_bool(a, false, "Turn on auto accept.");
- DEFINE_bool(d, false, "Turn on debugging.");
- DEFINE_bool(testserver, false, "Use test server");
- DEFINE_int(portallocator, 0, "Filter out unwanted connection types.");
- DEFINE_string(filterhost, NULL, "Filter out the host from all candidates.");
- DEFINE_string(pmuc, "groupchat.google.com", "The persistant muc domain.");
- DEFINE_string(s, "talk.google.com", "The connection server to use.");
- DEFINE_string(voiceinput, NULL, "RTP dump file for voice input.");
- DEFINE_string(voiceoutput, NULL, "RTP dump file for voice output.");
- DEFINE_string(videoinput, NULL, "RTP dump file for video input.");
- DEFINE_string(videooutput, NULL, "RTP dump file for video output.");
- DEFINE_bool(help, false, "Prints this message");
-
- // parse options
- FlagList::SetFlagsFromCommandLine(&argc, argv, true);
- if (FLAG_help) {
- FlagList::Print(NULL, false);
- return 0;
- }
-
- bool auto_accept = FLAG_a;
- bool debug = FLAG_d;
- bool test_server = FLAG_testserver;
- int32 portallocator_flags = FLAG_portallocator;
- std::string pmuc_domain = FLAG_pmuc;
- std::string server = FLAG_s;
-
- // parse username and password, if present
- buzz::Jid jid;
- std::string username;
- talk_base::InsecureCryptStringImpl pass;
- if (argc > 1) {
- username = argv[1];
- if (argc > 2) {
- pass.password() = argv[2];
- }
- }
-
- if (debug)
- talk_base::LogMessage::LogToDebug(talk_base::LS_VERBOSE);
-
- if (username.empty()) {
- std::cout << "JID: ";
- std::cin >> username;
- }
- if (username.find('@') == std::string::npos) {
- username.append("@localhost");
- }
- jid = buzz::Jid(username);
- if (!jid.IsValid() || jid.node() == "") {
- printf("Invalid JID. JIDs should be in the form user@domain\n");
- return 1;
- }
- if (pass.password().empty() && !test_server) {
- Console::SetEcho(false);
- std::cout << "Password: ";
- std::cin >> pass.password();
- Console::SetEcho(true);
- std::cout << std::endl;
- }
-
- buzz::XmppClientSettings xcs;
- xcs.set_user(jid.node());
- xcs.set_resource("call");
- xcs.set_host(jid.domain());
- xcs.set_use_tls(!test_server);
-
- if (test_server) {
- pass.password() = jid.node();
- xcs.set_allow_plain(true);
- }
- xcs.set_pass(talk_base::CryptString(pass));
-
- std::string host;
- int port;
-
- int colon = server.find(':');
- if (colon == -1) {
- host = server;
- port = DEFAULT_PORT;
- } else {
- host = server.substr(0, colon);
- port = atoi(server.substr(colon + 1).c_str());
- }
-
- xcs.set_server(talk_base::SocketAddress(host, port));
- printf("Logging in to %s as %s\n", server.c_str(), jid.Str().c_str());
-
- talk_base::InitializeSSL();
-
-
-#if WIN32
- // Need to pump messages on our main thread on Windows.
- talk_base::Win32Thread w32_thread;
- talk_base::ThreadManager::SetCurrent(&w32_thread);
-#endif
- talk_base::Thread* main_thread = talk_base::Thread::Current();
-
- XmppPump pump;
- CallClient *client = new CallClient(pump.client());
-
- if (FLAG_voiceinput || FLAG_voiceoutput ||
- FLAG_videoinput || FLAG_videooutput) {
- // If any dump file is specified, we use FileMediaEngine.
- cricket::MediaEngine* engine = CreateFileMediaEngine(FLAG_voiceinput,
- FLAG_voiceoutput,
- FLAG_videoinput,
- FLAG_videooutput);
- // The engine will be released by the client later.
- client->SetMediaEngine(engine);
- }
-
- Console *console = new Console(main_thread, client);
- client->SetConsole(console);
- client->SetAutoAccept(auto_accept);
- client->SetPmucDomain(pmuc_domain);
- client->SetPortAllocatorFlags(portallocator_flags);
- console->Start();
-
- if (debug) {
- pump.client()->SignalLogInput.connect(&debug_log_, &DebugLog::Input);
- pump.client()->SignalLogOutput.connect(&debug_log_, &DebugLog::Output);
- }
-
- pump.DoLogin(xcs, new XmppSocket(true), NULL);
- main_thread->Run();
- pump.DoDisconnect();
-
- console->Stop();
- delete console;
- delete client;
-
- return 0;
-}
diff --git a/third_party/libjingle/source/talk/examples/call/callclient.cc b/third_party/libjingle/source/talk/examples/call/callclient.cc
index 03edf95..eb761d1 100644
--- a/third_party/libjingle/source/talk/examples/call/callclient.cc
+++ b/third_party/libjingle/source/talk/examples/call/callclient.cc
@@ -35,6 +35,7 @@
#include "talk/base/network.h"
#include "talk/base/socketaddress.h"
#include "talk/base/stringutils.h"
+#include "talk/base/stringencode.h"
#include "talk/p2p/base/sessionmanager.h"
#include "talk/p2p/client/basicportallocator.h"
#include "talk/p2p/client/sessionmanagertask.h"
@@ -82,6 +83,25 @@ const char* DescribeStatus(buzz::Status::Show show, const std::string& desc) {
}
}
+std::string GetWord(const std::vector<std::string>& words,
+ size_t index, const std::string& def) {
+ if (words.size() > index) {
+ return words[index];
+ } else {
+ return def;
+ }
+}
+
+int GetInt(const std::vector<std::string>& words, size_t index, int def) {
+ int val;
+ if (words.size() > index && talk_base::FromString(words[index], &val)) {
+ return val;
+ } else {
+ return def;
+ }
+}
+
+
} // namespace
const char* CALL_COMMANDS =
@@ -97,7 +117,7 @@ const char* CALL_COMMANDS =
const char* RECEIVE_COMMANDS =
"Available commands:\n"
"\n"
-" accept Accepts the incoming call and switches to it.\n"
+" accept [bw] Accepts the incoming call and switches to it.\n"
" reject Rejects the incoming call and stays with the current call.\n"
" quit Quits the application.\n"
"";
@@ -107,10 +127,10 @@ const char* CONSOLE_COMMANDS =
"\n"
" roster Prints the online friends from your roster.\n"
" friend user Request to add a user to your roster.\n"
-" call [jid] Initiates a call to the user[/room] with the\n"
-" given JID.\n"
-" vcall [jid] Initiates a video call to the user[/room] with\n"
-" the given JID.\n"
+" call [jid] [bw] Initiates a call to the user[/room] with the\n"
+" given JID and with optional bandwidth.\n"
+" vcall [jid] [bw] Initiates a video call to the user[/room] with\n"
+" the given JID and with optional bandwidth.\n"
" voicemail [jid] Leave a voicemail for the user with the given JID.\n"
" join [room] Joins a multi-user-chat.\n"
" invite user [room] Invites a friend to a multi-user-chat.\n"
@@ -142,53 +162,73 @@ void CallClient::ParseLine(const std::string& line) {
}
// Global commands
- if ((words.size() == 1) && (words[0] == "quit")) {
+ const std::string& command = GetWord(words, 0, "");
+ if (command == "quit") {
Quit();
} else if (call_ && incoming_call_) {
- if ((words.size() == 1) && (words[0] == "accept")) {
- Accept();
- } else if ((words.size() == 1) && (words[0] == "reject")) {
+ if (command == "accept") {
+ cricket::CallOptions options;
+ options.video_bandwidth = GetInt(words, 1, cricket::kAutoBandwidth);
+ Accept(options);
+ } else if (command == "reject") {
Reject();
} else {
console_->Print(RECEIVE_COMMANDS);
}
} else if (call_) {
- if ((words.size() == 1) && (words[0] == "hangup")) {
+ if (command == "hangup") {
// TODO: do more shutdown here, move to Terminate()
call_->Terminate();
call_ = NULL;
session_ = NULL;
console_->SetPrompt(NULL);
- } else if ((words.size() == 1) && (words[0] == "mute")) {
+ } else if (command == "mute") {
call_->Mute(true);
- } else if ((words.size() == 1) && (words[0] == "unmute")) {
+ } else if (command == "unmute") {
call_->Mute(false);
- } else if ((words.size() == 2) && (words[0] == "dtmf")) {
+ } else if ((command == "dtmf") && (words.size() == 2)) {
int ev = std::string("0123456789*#").find(words[1][0]);
call_->PressDTMF(ev);
} else {
console_->Print(CALL_COMMANDS);
}
} else {
- if ((words.size() == 1) && (words[0] == "roster")) {
+ if (command == "roster") {
PrintRoster();
- } else if ((words.size() == 2) && (words[0] == "friend")) {
+ } else if (command == "send") {
+ buzz::Jid jid(words[1]);
+ if (jid.IsValid()) {
+ last_sent_to_ = words[1];
+ SendChat(words[1], words[2]);
+ } else if (!last_sent_to_.empty()) {
+ SendChat(last_sent_to_, words[1]);
+ } else {
+ console_->Printf(
+ "Invalid JID. JIDs should be in the form user@domain\n");
+ }
+ } else if ((words.size() == 2) && (command == "friend")) {
InviteFriend(words[1]);
- } else if ((words.size() >= 1) && (words[0] == "call")) {
- MakeCallTo((words.size() >= 2) ? words[1] : "", false);
- } else if ((words.size() >= 1) && (words[0] == "vcall")) {
- MakeCallTo((words.size() >= 2) ? words[1] : "", true);
- } else if ((words.size() >= 1) && (words[0] == "join")) {
- JoinMuc((words.size() >= 2) ? words[1] : "");
- } else if ((words.size() >= 2) && (words[0] == "invite")) {
- InviteToMuc(words[1], (words.size() >= 3) ? words[2] : "");
- } else if ((words.size() >= 1) && (words[0] == "leave")) {
- LeaveMuc((words.size() >= 2) ? words[1] : "");
- } else if ((words.size() == 1) && (words[0] == "getdevs")) {
+ } else if (command == "call") {
+ std::string to = GetWord(words, 1, "");
+ MakeCallTo(to, cricket::CallOptions());
+ } else if (command == "vcall") {
+ std::string to = GetWord(words, 1, "");
+ int bandwidth = GetInt(words, 2, cricket::kAutoBandwidth);
+ cricket::CallOptions options;
+ options.is_video = true;
+ options.video_bandwidth = bandwidth;
+ MakeCallTo(to, options);
+ } else if (command == "join") {
+ JoinMuc(GetWord(words, 1, ""));
+ } else if ((words.size() >= 2) && (command == "invite")) {
+ InviteToMuc(words[1], GetWord(words, 2, ""));
+ } else if (command == "leave") {
+ LeaveMuc(GetWord(words, 1, ""));
+ } else if (command == "getdevs") {
GetDevices();
- } else if ((words.size() == 2) && (words[0] == "setvol")) {
+ } else if ((words.size() == 2) && (command == "setvol")) {
SetVolume(words[1]);
- } else if ((words.size() >= 1) && (words[0] == "voicemail")) {
+ } else if (command == "voicemail") {
CallVoicemail((words.size() >= 2) ? words[1] : "");
} else {
console_->Print(CONSOLE_COMMANDS);
@@ -201,7 +241,8 @@ CallClient::CallClient(buzz::XmppClient* xmpp_client)
call_(NULL), incoming_call_(false),
auto_accept_(false), pmuc_domain_("groupchat.google.com"),
local_renderer_(NULL), remote_renderer_(NULL),
- roster_(new RosterMap), portallocator_flags_(0)
+ roster_(new RosterMap), portallocator_flags_(0),
+ allow_local_ips_(false), initial_protocol_(cricket::PROTOCOL_HYBRID)
#ifdef USE_TALK_SOUND
, sound_system_factory_(NULL)
#endif
@@ -309,6 +350,8 @@ void CallClient::InitPhone() {
port_allocator_, worker_thread_);
session_manager_->SignalRequestSignaling.connect(
this, &CallClient::OnRequestSignaling);
+ session_manager_->SignalSessionCreate.connect(
+ this, &CallClient::OnSessionCreate);
session_manager_->OnSignalingReady();
session_manager_task_ =
@@ -348,6 +391,11 @@ void CallClient::OnRequestSignaling() {
session_manager_->OnSignalingReady();
}
+void CallClient::OnSessionCreate(cricket::Session* session, bool initiate) {
+ session->set_allow_local_ips(allow_local_ips_);
+ session->set_current_protocol(initial_protocol_);
+}
+
void CallClient::OnCallCreate(cricket::Call* call) {
call->SignalSessionState.connect(this, &CallClient::OnSessionState);
if (call->video()) {
@@ -365,8 +413,9 @@ void CallClient::OnSessionState(cricket::Call* call,
call_ = call;
session_ = session;
incoming_call_ = true;
+ cricket::CallOptions options;
if (auto_accept_) {
- Accept();
+ Accept(options);
}
} else if (state == cricket::Session::STATE_SENTINITIATE) {
console_->Print("calling...");
@@ -458,6 +507,19 @@ void CallClient::PrintRoster() {
console_->SetPrompting(true);
}
+void CallClient::SendChat(const std::string& to, const std::string msg) {
+ buzz::XmlElement* stanza = new buzz::XmlElement(buzz::QN_MESSAGE);
+ stanza->AddAttr(buzz::QN_TO, to);
+ stanza->AddAttr(buzz::QN_ID, talk_base::CreateRandomString(16));
+ stanza->AddAttr(buzz::QN_TYPE, "chat");
+ buzz::XmlElement* body = new buzz::XmlElement(buzz::QN_BODY);
+ body->SetBodyText(msg);
+ stanza->AddElement(body);
+
+ xmpp_client_->SendStanza(stanza);
+ delete stanza;
+}
+
void CallClient::InviteFriend(const std::string& name) {
buzz::Jid jid(name);
if (!jid.IsValid() || jid.node() == "") {
@@ -473,16 +535,20 @@ void CallClient::InviteFriend(const std::string& name) {
console_->Printf("Requesting to befriend %s.\n", name.c_str());
}
-void CallClient::MakeCallTo(const std::string& name, bool video) {
+void CallClient::MakeCallTo(const std::string& name,
+ const cricket::CallOptions& given_options) {
+ // Copy so we can change .is_muc.
+ cricket::CallOptions options = given_options;
+
bool found = false;
- bool is_muc = false;
+ options.is_muc = false;
buzz::Jid callto_jid(name);
buzz::Jid found_jid;
if (name.length() == 0 && mucs_.size() > 0) {
// if no name, and in a MUC, establish audio with the MUC
found_jid = mucs_.begin()->first;
found = true;
- is_muc = true;
+ options.is_muc = true;
} else if (name[0] == '+') {
// if the first character is a +, assume it's a phone number
found_jid = callto_jid;
@@ -507,28 +573,29 @@ void CallClient::MakeCallTo(const std::string& name, bool video) {
mucs_[callto_jid]->state() == buzz::Muc::MUC_JOINED) {
found = true;
found_jid = callto_jid;
- is_muc = true;
+ options.is_muc = true;
}
}
}
if (found) {
- console_->Printf("Found %s '%s'", is_muc ? "room" : "online friend",
+ console_->Printf("Found %s '%s'", options.is_muc ? "room" : "online friend",
found_jid.Str().c_str());
- PlaceCall(found_jid, is_muc, video);
+ PlaceCall(found_jid, options);
} else {
console_->Printf("Could not find online friend '%s'", name.c_str());
}
}
-void CallClient::PlaceCall(const buzz::Jid& jid, bool is_muc, bool video) {
+void CallClient::PlaceCall(const buzz::Jid& jid,
+ const cricket::CallOptions& options) {
media_client_->SignalCallDestroy.connect(
this, &CallClient::OnCallDestroy);
if (!call_) {
- call_ = media_client_->CreateCall(video, is_muc);
+ call_ = media_client_->CreateCall();
console_->SetPrompt(jid.Str().c_str());
- session_ = call_->InitiateSession(jid);
- if (is_muc) {
+ session_ = call_->InitiateSession(jid, options);
+ if (options.is_muc) {
// If people in this room are already in a call, must add all their
// streams.
buzz::Muc::MemberMap& members = mucs_[jid]->members();
@@ -566,7 +633,7 @@ void CallClient::CallVoicemail(const std::string& name) {
void CallClient::OnFoundVoicemailJid(const buzz::Jid& to,
const buzz::Jid& voicemail) {
console_->Printf("Calling %s's voicemail.\n", to.Str().c_str());
- PlaceCall(voicemail, false, false);
+ PlaceCall(voicemail, cricket::CallOptions());
}
void CallClient::OnVoicemailJidError(const buzz::Jid& to) {
@@ -587,10 +654,10 @@ void CallClient::RemoveStream(uint32 audio_src_id, uint32 video_src_id) {
}
}
-void CallClient::Accept() {
+void CallClient::Accept(const cricket::CallOptions& options) {
ASSERT(call_ && incoming_call_);
ASSERT(call_->sessions().size() == 1);
- call_->AcceptSession(call_->sessions()[0]);
+ call_->AcceptSession(call_->sessions()[0], options);
media_client_->SetFocus(call_);
if (call_->video()) {
call_->SetLocalRenderer(local_renderer_);
diff --git a/third_party/libjingle/source/talk/examples/call/callclient.h b/third_party/libjingle/source/talk/examples/call/callclient.h
index af27f34..a5686b4 100644
--- a/third_party/libjingle/source/talk/examples/call/callclient.h
+++ b/third_party/libjingle/source/talk/examples/call/callclient.h
@@ -66,7 +66,9 @@ class MediaEngine;
class MediaSessionClient;
class Receiver;
class Call;
+struct CallOptions;
class SessionManagerTask;
+enum SignalingProtocol;
}
struct RosterItem {
@@ -98,11 +100,20 @@ class CallClient: public sigslot::has_slots<> {
void ParseLine(const std::string &str);
+ void SendChat(const std::string& to, const std::string msg);
void InviteFriend(const std::string& user);
void JoinMuc(const std::string& room);
void InviteToMuc(const std::string& user, const std::string& room);
void LeaveMuc(const std::string& room);
void SetPortAllocatorFlags(uint32 flags) { portallocator_flags_ = flags; }
+ void SetAllowLocalIps(bool allow_local_ips) {
+ allow_local_ips_ = allow_local_ips;
+ }
+
+ void SetInitialProtocol(cricket::SignalingProtocol initial_protocol) {
+ initial_protocol_ = initial_protocol;
+ }
+
typedef std::map<buzz::Jid, buzz::Muc*> MucMap;
@@ -119,6 +130,7 @@ class CallClient: public sigslot::has_slots<> {
void InitPresence();
void RefreshStatus();
void OnRequestSignaling();
+ void OnSessionCreate(cricket::Session* session, bool initiate);
void OnCallCreate(cricket::Call* call);
void OnCallDestroy(cricket::Call* call);
void OnSessionState(cricket::Call* call,
@@ -137,10 +149,10 @@ class CallClient: public sigslot::has_slots<> {
static const std::string strerror(buzz::XmppEngine::Error err);
void PrintRoster();
- void MakeCallTo(const std::string& name, bool video);
- void PlaceCall(const buzz::Jid& jid, bool is_muc, bool video);
+ void MakeCallTo(const std::string& name, const cricket::CallOptions& options);
+ void PlaceCall(const buzz::Jid& jid, const cricket::CallOptions& options);
void CallVoicemail(const std::string& name);
- void Accept();
+ void Accept(const cricket::CallOptions& options);
void Reject();
void Quit();
@@ -178,6 +190,10 @@ class CallClient: public sigslot::has_slots<> {
buzz::FriendInviteSendTask* friend_invite_send_;
RosterMap* roster_;
uint32 portallocator_flags_;
+
+ bool allow_local_ips_;
+ cricket::SignalingProtocol initial_protocol_;
+ std::string last_sent_to_;
#ifdef USE_TALK_SOUND
cricket::SoundSystemFactory* sound_system_factory_;
#endif
diff --git a/third_party/libjingle/source/talk/main.scons b/third_party/libjingle/source/talk/main.scons
index d4163df..a1348ff 100644
--- a/third_party/libjingle/source/talk/main.scons
+++ b/third_party/libjingle/source/talk/main.scons
@@ -17,6 +17,7 @@
#
import talk
import os
+import platform
#-------------------------------------------------------------------------------
# The build files/directories to 'build'.
@@ -40,6 +41,7 @@ root_env = Environment(
'component_setup',
'replace_strings',
'talk_noops',
+ #'talk_linux',
],
BUILD_SCONSCRIPTS = components,
DESTINATION_ROOT = '$MAIN_DIR/build',
@@ -60,6 +62,16 @@ root_env = Environment(
]
)
+# This is where we set common environments
+#
+# Detect if running on 64 bit or 32 bit host.
+DeclareBit('platform_arch_64bit', 'Host Platform is 64 Bit')
+if platform.architecture()[0] == "64bit":
+ root_env.SetBits('platform_arch_64bit')
+
+DeclareBit('use_static_openssl', 'Build OpenSSL as a static library')
+
+
#-------------------------------------------------------------------------------
# W I N D O W S
#
@@ -130,6 +142,9 @@ win_env.Append(
# this NTDDI version or else the headers
# that LMI includes from it won't compile.
'NTDDI_VERSION=NTDDI_WINXP',
+
+ # npapi.h requires the following:
+ '_WINDOWS',
],
CPPPATH = [
'$THIRD_PARTY/wtl_71/include',
@@ -211,6 +226,8 @@ posix_env.Append(
'POSIX',
'DISABLE_DYNAMIC_CAST',
'HAVE_OPENSSL_SSL_H=1',
+ # The POSIX standard says we have to define this.
+ '_REENTRANT',
],
CCFLAGS = [
'-m32',
@@ -271,13 +288,9 @@ mac_dbg_env = mac_env.Clone(
BUILD_TYPE = 'dbg',
BUILD_TYPE_DESCRIPTION = 'Mac debug build',
BUILD_GROUPS = ['default', 'all'],
- tools = ['target_debug']
+ tools = ['target_debug'],
)
mac_dbg_env.Append(
- CPPDEFINES = [
- 'FLAVOR_DBG',
- 'ENABLE_DEBUG',
- ],
CCFLAGS = [
'-O0',
]
@@ -288,7 +301,7 @@ mac_opt_env = mac_env.Clone(
BUILD_TYPE = 'opt',
BUILD_TYPE_DESCRIPTION = 'Mac opt build',
BUILD_GROUPS = ['all'],
- tools = ['target_optimized']
+ tools = ['target_optimized'],
)
mac_opt_env.Append(
CCFLAGS = [
@@ -303,45 +316,92 @@ envs.append(mac_opt_env)
#-------------------------------------------------------------------------------
# L I N U X
#
-linux_env = posix_env.Clone(
- tools = ['target_platform_linux'],
+linux_common_env = posix_env.Clone(
+ tools = [
+ 'target_platform_linux',
+ #'talk_linux',
+ ],
)
-linux_env.Append(
+linux_common_env.Append(
CPPDEFINES = [
'LINUX',
'HAVE_GLIB',
# TODO() Enable once we figure out multiple defines with gips lib
# Also consider other linux flags: 64bit, no-strict-aliasing, wrap, etc
+ #'USE_TALK_SOUND',
+ ],
+ CCFLAGS = [
+ # TODO: Some or all of this may be desirable for Mac too.
+ # Needed for link-time dead-code removal to work properly.
+ '-ffunction-sections',
+ '-fdata-sections',
+ # Needed for a clean ABI and for link-time dead-code removal to work
+ # properly.
+ '-fvisibility=hidden',
+ # Generate debugging info in the DWARF2 format.
+ '-gdwarf-2',
+ # Generate maximal debugging information. (It is stripped from what we ship
+ # to users, so we want it for both dbg and opt.)
+ '-g3',
],
LINKFLAGS = [
- # TODO consider enabling gc-sections. Perhaps only in opt.
- #'-Wl,--gc-sections',
+ # Enable dead-code removal.
+ '-Wl,--gc-sections',
'-Wl,--start-group',
],
_LIBFLAGS = ['-Wl,--end-group'],
)
+# Remove default rpath set by Hammer. Hammer sets it to LIB_DIR, which is wrong.
+# The rpath is the _run-time_ library search path for the resulting binary, i.e.
+# the one used by ld.so at load time. Setting it equal to the path to build
+# output on the build machine is nonsense.
+linux_common_env.Replace(
+ RPATH = [],
+)
+
+#-------------------------------------------------------------------------------
+# L I N U X -- T R A D I T I O N A L
+#
+# Settings that are specific to our desktop Linux targets.
+linux_env = linux_common_env.Clone()
+# OpenSSL has infamously poor ABI stability, so that building against one
+# version and running against a different one often will not work. Since our
+# non-ChromeOS Linux builds are used on many different distros and distro
+# versions, this means we can't safely dynamically link to OpenSSL because the
+# product would end up being broken on any computer with a different version
+# installed. So instead we build it ourself and statically link to it.
+linux_env.SetBits('use_static_openssl')
+
linux_dbg_env = linux_env.Clone(
BUILD_TYPE = 'dbg',
BUILD_TYPE_DESCRIPTION = 'Linux debug build',
BUILD_GROUPS = ['default', 'all'],
- tools = ['target_debug']
+ tools = ['target_debug'],
)
+# Remove -g set by hammer, which is not what we want (we have set -g3 above).
+linux_dbg_env.FilterOut(CCFLAGS = ['-g'])
envs.append(linux_dbg_env)
linux_opt_env = linux_env.Clone(
BUILD_TYPE = 'opt',
BUILD_TYPE_DESCRIPTION = 'Linux optimized build',
BUILD_GROUPS = ['all'],
- tools = ['target_optimized']
+ tools = ['target_optimized'],
)
+# Remove -O2 set by hammer, which is not what we want.
+linux_opt_env.FilterOut(CCFLAGS = ['-O2'])
+linux_opt_env.Append(CCFLAGS = ['-Os'])
envs.append(linux_opt_env)
# TODO(): Clone linux envs for 64bit. See 'variant' documentation.
+# Create a group for installers
+AddTargetGroup('all_installers', 'installers that can be built')
+
# Parse child .scons files
BuildEnvironments(envs)
diff --git a/third_party/libjingle/source/talk/p2p/base/constants.cc b/third_party/libjingle/source/talk/p2p/base/constants.cc
index 9e45457..1becb39 100644
--- a/third_party/libjingle/source/talk/p2p/base/constants.cc
+++ b/third_party/libjingle/source/talk/p2p/base/constants.cc
@@ -25,7 +25,10 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <string>
+
#include "talk/p2p/base/constants.h"
+#include "talk/xmllite/qname.h"
namespace cricket {
@@ -61,6 +64,10 @@ const std::string GINGLE_ACTION_REJECT("reject");
const std::string GINGLE_ACTION_TERMINATE("terminate");
const std::string GINGLE_ACTION_CANDIDATES("candidates");
+const std::string LN_ERROR("error");
+const buzz::QName QN_GINGLE_REDIRECT(true, NS_GINGLE, "redirect");
+const std::string STR_REDIRECT_PREFIX("xmpp:");
+
// Session Contents (aka Gingle <session><description>
// or Jingle <content><description>)
const std::string LN_DESCRIPTION("description");
@@ -81,6 +88,7 @@ const std::string PAYLOADTYPE_PARAMETER_BITRATE("bitrate");
const std::string PAYLOADTYPE_PARAMETER_HEIGHT("height");
const std::string PAYLOADTYPE_PARAMETER_WIDTH("width");
const std::string PAYLOADTYPE_PARAMETER_FRAMERATE("framerate");
+const std::string LN_BANDWIDTH("bandwidth");
const std::string CN_AUDIO("audio");
const std::string CN_VIDEO("video");
@@ -91,6 +99,8 @@ const buzz::QName QN_JINGLE_RTP_CONTENT(
true, NS_JINGLE_RTP, LN_DESCRIPTION);
const buzz::QName QN_JINGLE_RTP_PAYLOADTYPE(
true, NS_JINGLE_RTP, LN_PAYLOADTYPE);
+const buzz::QName QN_JINGLE_RTP_BANDWIDTH(
+ true, NS_JINGLE_RTP, LN_BANDWIDTH);
const buzz::QName QN_PARAMETER(true, NS_JINGLE_RTP, "parameter");
const std::string NS_GINGLE_AUDIO("http://www.google.com/session/phone");
@@ -105,7 +115,19 @@ const buzz::QName QN_GINGLE_VIDEO_CONTENT(
const buzz::QName QN_GINGLE_VIDEO_PAYLOADTYPE(
true, NS_GINGLE_VIDEO, LN_PAYLOADTYPE);
const buzz::QName QN_GINGLE_VIDEO_SRCID(true, NS_GINGLE_VIDEO, "src-id");
-const buzz::QName QN_GINGLE_VIDEO_BANDWIDTH(true, NS_GINGLE_VIDEO, "bandwidth");
+const buzz::QName QN_GINGLE_VIDEO_BANDWIDTH(
+ true, NS_GINGLE_VIDEO, LN_BANDWIDTH);
+
+// Crypto support.
+const buzz::QName QN_ENCRYPTION(true, NS_JINGLE_RTP, "encryption");
+const buzz::QName QN_ENCRYPTION_REQUIRED(true, NS_EMPTY, "required");
+const buzz::QName QN_CRYPTO(true, NS_JINGLE_RTP, "crypto");
+const buzz::QName QN_GINGLE_AUDIO_CRYPTO_USAGE(true, NS_GINGLE_AUDIO, "usage");
+const buzz::QName QN_GINGLE_VIDEO_CRYPTO_USAGE(true, NS_GINGLE_VIDEO, "usage");
+const buzz::QName QN_CRYPTO_SUITE(true, NS_EMPTY, "crypto-suite");
+const buzz::QName QN_CRYPTO_KEY_PARAMS(true, NS_EMPTY, "key-params");
+const buzz::QName QN_CRYPTO_TAG(true, NS_EMPTY, "tag");
+const buzz::QName QN_CRYPTO_SESSION_PARAMS(true, NS_EMPTY, "session-params");
// transports and candidates
const std::string LN_TRANSPORT("transport");
diff --git a/third_party/libjingle/source/talk/p2p/base/constants.h b/third_party/libjingle/source/talk/p2p/base/constants.h
index 7e33c5b..9f93cbc 100644
--- a/third_party/libjingle/source/talk/p2p/base/constants.h
+++ b/third_party/libjingle/source/talk/p2p/base/constants.h
@@ -36,13 +36,6 @@
namespace cricket {
-// There are 3 different types of Jingle messages or protocols: Jingle
-// (the spec in XEP-166, etc), Gingle (the legacy protocol) and hybrid
-// (both at the same time). Gingle2 is a temporary protocol that we
-// are only keeping around right now during this refactoring phase.
-// Once we finish refactoring and start implementing Jingle, we will
-// remove Gingle2.
-
// NS_ == namespace
// QN_ == buzz::QName (namespace + name)
// LN_ == "local name" == QName::LocalPart()
@@ -87,6 +80,9 @@ extern const std::string GINGLE_ACTION_REJECT;
extern const std::string GINGLE_ACTION_TERMINATE;
extern const std::string GINGLE_ACTION_CANDIDATES;
+extern const std::string LN_ERROR;
+extern const buzz::QName QN_GINGLE_REDIRECT;
+extern const std::string STR_REDIRECT_PREFIX;
// Session Contents (aka Gingle <session><description>
// or Jingle <content><description>)
@@ -109,6 +105,7 @@ extern const std::string PAYLOADTYPE_PARAMETER_BITRATE;
extern const std::string PAYLOADTYPE_PARAMETER_HEIGHT;
extern const std::string PAYLOADTYPE_PARAMETER_WIDTH;
extern const std::string PAYLOADTYPE_PARAMETER_FRAMERATE;
+extern const std::string LN_BANDWIDTH;
// CN_ == "content name". When we initiate a session, we choose the
// name, and when we receive a Gingle session, we provide default
@@ -122,6 +119,7 @@ extern const std::string CN_OTHER;
extern const std::string NS_JINGLE_RTP;
extern const buzz::QName QN_JINGLE_RTP_CONTENT;
extern const buzz::QName QN_JINGLE_RTP_PAYLOADTYPE;
+extern const buzz::QName QN_JINGLE_RTP_BANDWIDTH;
extern const std::string NS_GINGLE_AUDIO;
extern const buzz::QName QN_GINGLE_AUDIO_CONTENT;
@@ -133,6 +131,17 @@ extern const buzz::QName QN_GINGLE_VIDEO_PAYLOADTYPE;
extern const buzz::QName QN_GINGLE_VIDEO_SRCID;
extern const buzz::QName QN_GINGLE_VIDEO_BANDWIDTH;
+// Crypto support.
+extern const buzz::QName QN_ENCRYPTION;
+extern const buzz::QName QN_ENCRYPTION_REQUIRED;
+extern const buzz::QName QN_CRYPTO;
+extern const buzz::QName QN_GINGLE_AUDIO_CRYPTO_USAGE;
+extern const buzz::QName QN_GINGLE_VIDEO_CRYPTO_USAGE;
+extern const buzz::QName QN_CRYPTO_SUITE;
+extern const buzz::QName QN_CRYPTO_KEY_PARAMS;
+extern const buzz::QName QN_CRYPTO_TAG;
+extern const buzz::QName QN_CRYPTO_SESSION_PARAMS;
+
// transports and candidates
extern const std::string LN_TRANSPORT;
extern const std::string LN_CANDIDATE;
diff --git a/third_party/libjingle/source/talk/p2p/base/parsing.cc b/third_party/libjingle/source/talk/p2p/base/parsing.cc
index 1ece5d0..da4c31b 100644
--- a/third_party/libjingle/source/talk/p2p/base/parsing.cc
+++ b/third_party/libjingle/source/talk/p2p/base/parsing.cc
@@ -27,9 +27,15 @@
#include "talk/p2p/base/parsing.h"
+#include <algorithm>
#include <stdlib.h>
#include "talk/base/stringutils.h"
+namespace {
+std::string kTrue = "true";
+std::string kOne = "1";
+}
+
namespace cricket {
bool BadParse(const std::string& text, ParseError* err) {
@@ -53,6 +59,20 @@ std::string GetXmlAttr(const buzz::XmlElement* elem,
return val.empty() ? def : val;
}
+std::string GetXmlAttr(const buzz::XmlElement* elem,
+ const buzz::QName& name,
+ const char* def) {
+ return GetXmlAttr(elem, name, std::string(def));
+}
+
+bool GetXmlAttr(const buzz::XmlElement* elem,
+ const buzz::QName& name, bool def) {
+ std::string val = elem->Attr(name);
+ std::transform(val.begin(), val.end(), val.begin(), tolower);
+
+ return val.empty() ? def : (val == kTrue || val == kOne);
+}
+
int GetXmlAttr(const buzz::XmlElement* elem,
const buzz::QName& name, int def) {
std::string val = elem->Attr(name);
diff --git a/third_party/libjingle/source/talk/p2p/base/parsing.h b/third_party/libjingle/source/talk/p2p/base/parsing.h
index 0ae7403..805372b 100644
--- a/third_party/libjingle/source/talk/p2p/base/parsing.h
+++ b/third_party/libjingle/source/talk/p2p/base/parsing.h
@@ -77,6 +77,12 @@ bool BadWrite(const std::string& text, WriteError* error);
std::string GetXmlAttr(const buzz::XmlElement* elem,
const buzz::QName& name,
const std::string& def);
+std::string GetXmlAttr(const buzz::XmlElement* elem,
+ const buzz::QName& name,
+ const char* def);
+// Return true if the value is "true" or "1".
+bool GetXmlAttr(const buzz::XmlElement* elem,
+ const buzz::QName& name, bool def);
int GetXmlAttr(const buzz::XmlElement* elem,
const buzz::QName& name, int def);
void AddXmlAttr(buzz::XmlElement* elem,
diff --git a/third_party/libjingle/source/talk/p2p/base/session.cc b/third_party/libjingle/source/talk/p2p/base/session.cc
index 806c025..38b91ff 100644
--- a/third_party/libjingle/source/talk/p2p/base/session.cc
+++ b/third_party/libjingle/source/talk/p2p/base/session.cc
@@ -416,6 +416,42 @@ TransportInfos Session::GetEmptyTransportInfos(
return tinfos;
}
+
+bool Session::OnRemoteCandidates(
+ const TransportInfos& tinfos, ParseError* error) {
+ for (TransportInfos::const_iterator tinfo = tinfos.begin();
+ tinfo != tinfos.end(); ++tinfo) {
+ TransportProxy* transproxy = GetTransportProxy(tinfo->content_name);
+ if (transproxy == NULL) {
+ return BadParse("Unknown content name: " + tinfo->content_name, error);
+ }
+
+ // Must complete negotiation before sending remote candidates, or
+ // there won't be any channel impls.
+ transproxy->CompleteNegotiation();
+ for (Candidates::const_iterator cand = tinfo->candidates.begin();
+ cand != tinfo->candidates.end(); ++cand) {
+ if (!transproxy->impl()->VerifyCandidate(*cand, error))
+ return false;
+
+ if (!transproxy->impl()->HasChannel(cand->name())) {
+ buzz::XmlElement* extra_info =
+ new buzz::XmlElement(QN_GINGLE_P2P_UNKNOWN_CHANNEL_NAME);
+ extra_info->AddAttr(buzz::QN_NAME, cand->name());
+ error->extra = extra_info;
+
+ return BadParse("channel named in candidate does not exist: " +
+ cand->name() + " for content: "+ tinfo->content_name,
+ error);
+ }
+ }
+ transproxy->impl()->OnRemoteCandidates(tinfo->candidates);
+ }
+
+ return true;
+}
+
+
TransportProxy* Session::GetOrCreateTransportProxy(
const std::string& content_name) {
TransportProxy* transproxy = GetTransportProxy(content_name);
@@ -467,16 +503,6 @@ void Session::SpeculativelyConnectAllTransportChannels() {
}
}
-void Session::CompleteTransportNegotiations(const TransportInfos& transports) {
- for (TransportInfos::const_iterator transport = transports.begin();
- transport != transports.end(); ++transport) {
- TransportProxy* transproxy = GetTransportProxy(transport->content_name);
- if (transproxy) {
- transproxy->CompleteNegotiation();
- }
- }
-}
-
TransportParserMap Session::GetTransportParsers() {
TransportParserMap parsers;
parsers[transport_type_] = transport_parser_;
@@ -646,6 +672,20 @@ void Session::OnFailedSend(const buzz::XmlElement* orig_stanza,
return;
}
+ // If the error is a session redirect, call OnRedirectError, which will
+ // continue the session with a new remote JID.
+ SessionRedirect redirect;
+ if (FindSessionRedirect(error_stanza, &redirect)) {
+ SessionError error;
+ if (!OnRedirectError(redirect, &error)) {
+ // TODO: Should we send a message back? The standard
+ // says nothing about it.
+ LOG(LS_ERROR) << "Failed to redirect: " << error.text;
+ SetError(ERROR_RESPONSE);
+ }
+ return;
+ }
+
std::string error_type = "cancel";
const buzz::XmlElement* error = error_stanza->FirstNamed(buzz::QN_ERROR);
@@ -706,9 +746,8 @@ bool Session::OnInitiateMessage(const SessionMessage& msg,
// Users of Session may listen to state change and call Reject().
if (state_ != STATE_SENTREJECT) {
- // TODO: Jingle spec allows candidates to be in the
- // initiate. We should support receiving them.
- CompleteTransportNegotiations(init.transports);
+ if (!OnRemoteCandidates(init.transports, error))
+ return false;
}
return true;
}
@@ -728,9 +767,8 @@ bool Session::OnAcceptMessage(const SessionMessage& msg, MessageError* error) {
// Users of Session may listen to state change and call Reject().
if (state_ != STATE_SENTREJECT) {
- // TODO: Jingle spec allows candidates to be in the
- // accept. We should support receiving them.
- CompleteTransportNegotiations(accept.transports);
+ if (!OnRemoteCandidates(accept.transports, error))
+ return false;
}
return true;
@@ -773,31 +811,8 @@ bool Session::OnTransportInfoMessage(const SessionMessage& msg,
GetTransportParsers(), &tinfos, error))
return false;
- for (TransportInfos::iterator tinfo = tinfos.begin();
- tinfo != tinfos.end(); ++tinfo) {
- TransportProxy* transproxy = GetTransportProxy(tinfo->content_name);
- if (transproxy == NULL)
- return BadParse("Unknown content name: " + tinfo->content_name, error);
-
- for (Candidates::const_iterator cand = tinfo->candidates.begin();
- cand != tinfo->candidates.end(); ++cand) {
- if (!transproxy->impl()->VerifyCandidate(*cand, error))
- return false;
-
- if (!transproxy->impl()->HasChannel(cand->name())) {
- buzz::XmlElement* extra_info =
- new buzz::XmlElement(QN_GINGLE_P2P_UNKNOWN_CHANNEL_NAME);
- extra_info->AddAttr(buzz::QN_NAME, cand->name());
- error->extra = extra_info;
- return BadParse("channel named in candidate does not exist: " +
- cand->name() + " for content: "+ tinfo->content_name,
- error);
- }
- }
-
- transproxy->impl()->OnRemoteCandidates(tinfo->candidates);
- transproxy->CompleteNegotiation();
- }
+ if (!OnRemoteCandidates(tinfos, error))
+ return false;
return true;
}
@@ -809,6 +824,32 @@ bool Session::OnTransportAcceptMessage(const SessionMessage& msg,
return true;
}
+bool BareJidsEqual(const std::string& name1,
+ const std::string& name2) {
+ buzz::Jid jid1(name1);
+ buzz::Jid jid2(name2);
+
+ return jid1.IsValid() && jid2.IsValid() && jid1.BareEquals(jid2);
+}
+
+bool Session::OnRedirectError(const SessionRedirect& redirect,
+ SessionError* error) {
+ MessageError message_error;
+ if (!CheckState(STATE_SENTINITIATE, &message_error)) {
+ return BadWrite(message_error.text, error);
+ }
+
+ if (!BareJidsEqual(remote_name_, redirect.target))
+ return BadWrite("Redirection not allowed: must be the same bare jid.",
+ error);
+
+ // When we receive a redirect, we point the session at the new JID
+ // and resend the candidates.
+ remote_name_ = redirect.target;
+ return (SendInitiateMessage(local_description(), error) &&
+ ResendAllTransportInfoMessages(error));
+}
+
bool Session::CheckState(State state, MessageError* error) {
ASSERT(state_ == state);
if (state_ != state) {
@@ -909,6 +950,25 @@ bool Session::WriteSessionAction(SignalingProtocol protocol,
elems, error);
}
+bool Session::ResendAllTransportInfoMessages(SessionError* error) {
+ for (TransportMap::iterator iter = transports_.begin();
+ iter != transports_.end(); ++iter) {
+ TransportProxy* transproxy = iter->second;
+ if (transproxy->sent_candidates().size() > 0) {
+ if (!SendTransportInfoMessage(
+ TransportInfo(
+ transproxy->content_name(),
+ transproxy->type(),
+ transproxy->sent_candidates()),
+ error)) {
+ return false;
+ }
+ transproxy->ClearSentCandidates();
+ }
+ }
+ return true;
+}
+
bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
SessionError* error) {
talk_base::scoped_ptr<buzz::XmlElement> stanza(
diff --git a/third_party/libjingle/source/talk/p2p/base/session.h b/third_party/libjingle/source/talk/p2p/base/session.h
index 64bb83a..ddbc663 100644
--- a/third_party/libjingle/source/talk/p2p/base/session.h
+++ b/third_party/libjingle/source/talk/p2p/base/session.h
@@ -251,6 +251,10 @@ class BaseSession : public sigslot::has_slots<>,
// The worker thread used by the session manager
virtual talk_base::Thread *worker_thread() = 0;
+ talk_base::Thread *signaling_thread() {
+ return signaling_thread_;
+ }
+
// Returns the JID of this client.
const std::string& local_name() const { return local_name_; }
@@ -382,14 +386,12 @@ class Session : public BaseSession {
bool CreateTransportProxies(const TransportInfos& tinfos,
SessionError* error);
void SpeculativelyConnectAllTransportChannels();
- // For each transport proxy with a matching content name, complete
- // the transport negotiation.
- void CompleteTransportNegotiations(const TransportInfos& tinfos);
+ bool OnRemoteCandidates(const TransportInfos& tinfos,
+ ParseError* error);
// Returns a TransportInfo without candidates for each content name.
// Uses the transport_type_ of the session.
TransportInfos GetEmptyTransportInfos(const ContentInfos& contents) const;
-
// Called when the first channel of a transport begins connecting. We use
// this to start a timer, to make sure that the connection completes in a
// reasonable amount of time.
@@ -437,6 +439,7 @@ class Session : public BaseSession {
bool SendTerminateMessage(const std::string& reason, SessionError* error);
bool SendTransportInfoMessage(const TransportInfo& tinfo,
SessionError* error);
+ bool ResendAllTransportInfoMessages(SessionError* error);
// Both versions of SendMessage send a message of the given type to
// the other client. Can pass either a set of elements or an
@@ -507,6 +510,7 @@ class Session : public BaseSession {
bool OnTerminateMessage(const SessionMessage& msg, MessageError* error);
bool OnTransportInfoMessage(const SessionMessage& msg, MessageError* error);
bool OnTransportAcceptMessage(const SessionMessage& msg, MessageError* error);
+ bool OnRedirectError(const SessionRedirect& redirect, SessionError* error);
// Verifies that we are in the appropriate state to receive this message.
bool CheckState(State state, MessageError* error);
diff --git a/third_party/libjingle/source/talk/p2p/base/sessionmessages.cc b/third_party/libjingle/source/talk/p2p/base/sessionmessages.cc
index f7c424e..cfd035d 100644
--- a/third_party/libjingle/source/talk/p2p/base/sessionmessages.cc
+++ b/third_party/libjingle/source/talk/p2p/base/sessionmessages.cc
@@ -25,10 +25,12 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <string>
#include "talk/p2p/base/sessionmessages.h"
#include "talk/base/logging.h"
#include "talk/base/scoped_ptr.h"
+#include "talk/xmllite/xmlconstants.h"
#include "talk/xmpp/constants.h"
#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/p2ptransport.h"
@@ -163,7 +165,7 @@ bool ParseJingleSessionMessage(const buzz::XmlElement* jingle,
std::string type_string = jingle->Attr(buzz::QN_ACTION);
msg->type = ToActionType(type_string);
msg->sid = jingle->Attr(buzz::QN_ID);
- msg->initiator = GetXmlAttr(jingle, QN_INITIATOR, "");
+ msg->initiator = GetXmlAttr(jingle, QN_INITIATOR, buzz::STR_EMPTY);
msg->action_elem = jingle;
if (msg->type == ACTION_UNKNOWN)
@@ -818,4 +820,34 @@ bool WriteTransportInfos(SignalingProtocol protocol,
}
}
+bool GetUriTarget(const std::string& prefix, const std::string& str,
+ std::string* after) {
+ size_t pos = str.find(prefix);
+ if (pos == std::string::npos)
+ return false;
+
+ *after = str.substr(pos + prefix.size(), std::string::npos);
+ return true;
+}
+
+bool FindSessionRedirect(const buzz::XmlElement* stanza,
+ SessionRedirect* redirect) {
+ const buzz::XmlElement* error_elem = GetXmlChild(stanza, LN_ERROR);
+ if (error_elem == NULL)
+ return false;
+
+ const buzz::XmlElement* redirect_elem =
+ error_elem->FirstNamed(QN_GINGLE_REDIRECT);
+ if (redirect_elem == NULL)
+ redirect_elem = error_elem->FirstNamed(buzz::QN_STANZA_REDIRECT);
+ if (redirect_elem == NULL)
+ return false;
+
+ if (!GetUriTarget(STR_REDIRECT_PREFIX, redirect_elem->BodyText(),
+ &redirect->target))
+ return false;
+
+ return true;
+}
+
} // namespace cricket
diff --git a/third_party/libjingle/source/talk/p2p/base/sessionmessages.h b/third_party/libjingle/source/talk/p2p/base/sessionmessages.h
index ff8641c..eee8452 100644
--- a/third_party/libjingle/source/talk/p2p/base/sessionmessages.h
+++ b/third_party/libjingle/source/talk/p2p/base/sessionmessages.h
@@ -149,6 +149,10 @@ struct SessionTerminate {
std::string debug_reason;
};
+struct SessionRedirect {
+ std::string target;
+};
+
bool IsSessionMessage(const buzz::XmlElement* stanza);
bool ParseSessionMessage(const buzz::XmlElement* stanza,
SessionMessage* msg,
@@ -208,6 +212,9 @@ bool WriteTransportInfos(SignalingProtocol protocol,
const TransportParserMap& trans_parsers,
XmlElements* elems,
WriteError* error);
+// Handles both Gingle and Jingle syntax.
+bool FindSessionRedirect(const buzz::XmlElement* stanza,
+ SessionRedirect* redirect);
} // namespace cricket
#endif // TALK_P2P_BASE_SESSIONMESSAGES_H_
diff --git a/third_party/libjingle/source/talk/p2p/base/transport.cc b/third_party/libjingle/source/talk/p2p/base/transport.cc
index 663a608..9d8fc32 100644
--- a/third_party/libjingle/source/talk/p2p/base/transport.cc
+++ b/third_party/libjingle/source/talk/p2p/base/transport.cc
@@ -155,17 +155,20 @@ void Transport::DestroyChannel_w(const std::string& name) {
}
if (connect_requested_ && channels_.empty()) {
- // We're not longer attempting to connect.
+ // We're no longer attempting to connect.
signaling_thread()->Post(this, MSG_CONNECTING, NULL);
}
- if (impl)
+ if (impl) {
+ // Check in case the deleted channel was the only non-writable channel.
+ OnChannelWritableState(impl);
DestroyTransportChannel(impl);
+ }
}
void Transport::ConnectChannels() {
ASSERT(signaling_thread()->IsCurrent());
- worker_thread()->Post(this, MSG_CONNECTCHANNELS, NULL);
+ worker_thread()->Send(this, MSG_CONNECTCHANNELS, NULL);
}
void Transport::ConnectChannels_w() {
@@ -211,7 +214,7 @@ void Transport::DestroyAllChannels_w() {
void Transport::ResetChannels() {
ASSERT(signaling_thread()->IsCurrent());
- worker_thread()->Post(this, MSG_RESETCHANNELS, NULL);
+ worker_thread()->Send(this, MSG_RESETCHANNELS, NULL);
}
void Transport::ResetChannels_w() {
diff --git a/third_party/libjingle/source/talk/session/phone/call.cc b/third_party/libjingle/source/talk/session/phone/call.cc
index c85be6a..fa4d33d 100644
--- a/third_party/libjingle/source/talk/session/phone/call.cc
+++ b/third_party/libjingle/source/talk/session/phone/call.cc
@@ -30,6 +30,7 @@
#include "talk/base/logging.h"
#include "talk/base/thread.h"
#include "talk/session/phone/call.h"
+#include "talk/session/phone/mediasessionclient.h"
namespace cricket {
@@ -45,10 +46,13 @@ const int kNoVoicemailTimeout = 1000*180;
const int kMediaMonitorInterval = 1000*15;
}
-Call::Call(MediaSessionClient *session_client, bool video, bool mux)
- : id_(talk_base::CreateRandomId()), session_client_(session_client),
- local_renderer_(NULL), video_(video), mux_(mux),
- muted_(false), send_to_voicemail_(true), playing_dtmf_(false) {
+Call::Call(MediaSessionClient* session_client)
+ : id_(talk_base::CreateRandomId()),
+ session_client_(session_client),
+ local_renderer_(NULL),
+ muted_(false),
+ send_to_voicemail_(true),
+ playing_dtmf_(false) {
}
Call::~Call() {
@@ -60,8 +64,9 @@ Call::~Call() {
talk_base::Thread::Current()->Clear(this);
}
-Session *Call::InitiateSession(const buzz::Jid &jid) {
- const SessionDescription* offer = session_client_->CreateOffer(video_, mux_);
+Session *Call::InitiateSession(const buzz::Jid &jid,
+ const CallOptions& options) {
+ const SessionDescription* offer = session_client_->CreateOffer(options);
Session *session = session_client_->CreateSession(this);
AddSession(session, offer);
@@ -86,13 +91,14 @@ void Call::IncomingSession(
SignalSessionState(this, session, Session::STATE_RECEIVEDINITIATE);
}
-void Call::AcceptSession(BaseSession *session) {
+void Call::AcceptSession(BaseSession* session,
+ const cricket::CallOptions& options) {
std::vector<Session *>::iterator it;
it = std::find(sessions_.begin(), sessions_.end(), session);
ASSERT(it != sessions_.end());
if (it != sessions_.end()) {
session->Accept(
- session_client_->CreateAnswer(session->remote_description()));
+ session_client_->CreateAnswer(session->remote_description(), options));
}
}
@@ -196,6 +202,9 @@ bool Call::AddSession(Session *session, const SessionDescription* offer) {
VideoChannel *video_channel = NULL;
const ContentInfo* audio_offer = GetFirstAudioContent(offer);
+ const ContentInfo* video_offer = GetFirstVideoContent(offer);
+ video_ = (video_offer != NULL);
+
ASSERT(audio_offer != NULL);
// Create voice channel and start a media monitor
voice_channel = session_client_->channel_manager()->CreateVoiceChannel(
@@ -212,8 +221,6 @@ bool Call::AddSession(Session *session, const SessionDescription* offer) {
// If desired, create video channel and start a media monitor
if (video_ && succeeded) {
- const ContentInfo* video_offer = GetFirstVideoContent(offer);
- ASSERT(video_offer != NULL);
video_channel = session_client_->channel_manager()->CreateVideoChannel(
session, video_offer->name, true, voice_channel);
// video_channel can be NULL in case of NullVideoEngine.
@@ -441,7 +448,7 @@ void Call::OnConnectionMonitor(VoiceChannel *channel,
SignalConnectionMonitor(this, infos);
}
-void Call::OnMediaMonitor(VoiceChannel *channel, const MediaInfo& info) {
+void Call::OnMediaMonitor(VoiceChannel *channel, const VoiceMediaInfo& info) {
SignalMediaMonitor(this, info);
}
@@ -454,7 +461,7 @@ void Call::OnConnectionMonitor(VideoChannel *channel,
SignalVideoConnectionMonitor(this, infos);
}
-void Call::OnMediaMonitor(VideoChannel *channel, const MediaInfo& info) {
+void Call::OnMediaMonitor(VideoChannel *channel, const VideoMediaInfo& info) {
SignalVideoMediaMonitor(this, info);
}
diff --git a/third_party/libjingle/source/talk/session/phone/call.h b/third_party/libjingle/source/talk/session/phone/call.h
index de92086..8e9bcdc 100644
--- a/third_party/libjingle/source/talk/session/phone/call.h
+++ b/third_party/libjingle/source/talk/session/phone/call.h
@@ -36,22 +36,21 @@
#include "talk/p2p/base/session.h"
#include "talk/p2p/client/socketmonitor.h"
#include "talk/xmpp/jid.h"
-#include "talk/session/phone/mediasessionclient.h"
-#include "talk/session/phone/voicechannel.h"
#include "talk/session/phone/audiomonitor.h"
+#include "talk/session/phone/voicechannel.h"
namespace cricket {
class MediaSessionClient;
+struct CallOptions;
class Call : public talk_base::MessageHandler, public sigslot::has_slots<> {
public:
- Call(MediaSessionClient *session_client,
- bool video = false, bool mux = false);
+ Call(MediaSessionClient* session_client);
~Call();
- Session *InitiateSession(const buzz::Jid &jid);
- void AcceptSession(BaseSession *session);
+ Session *InitiateSession(const buzz::Jid &jid, const CallOptions& options);
+ void AcceptSession(BaseSession *session, const CallOptions& options);
void RejectSession(BaseSession *session);
void TerminateSession(BaseSession *session);
void Terminate();
@@ -92,11 +91,11 @@ class Call : public talk_base::MessageHandler, public sigslot::has_slots<> {
SignalReceivedTerminateReason;
sigslot::signal2<Call *, const std::vector<ConnectionInfo> &>
SignalConnectionMonitor;
- sigslot::signal2<Call *, const MediaInfo&> SignalMediaMonitor;
+ sigslot::signal2<Call *, const VoiceMediaInfo&> SignalMediaMonitor;
sigslot::signal2<Call *, const AudioInfo&> SignalAudioMonitor;
sigslot::signal2<Call *, const std::vector<ConnectionInfo> &>
SignalVideoConnectionMonitor;
- sigslot::signal2<Call *, const MediaInfo&> SignalVideoMediaMonitor;
+ sigslot::signal2<Call *, const VideoMediaInfo&> SignalVideoMediaMonitor;
private:
void OnMessage(talk_base::Message *message);
@@ -111,11 +110,11 @@ class Call : public talk_base::MessageHandler, public sigslot::has_slots<> {
void Join(Call *call, bool enable);
void OnConnectionMonitor(VoiceChannel *channel,
const std::vector<ConnectionInfo> &infos);
- void OnMediaMonitor(VoiceChannel *channel, const MediaInfo& info);
+ void OnMediaMonitor(VoiceChannel *channel, const VoiceMediaInfo& info);
void OnAudioMonitor(VoiceChannel *channel, const AudioInfo& info);
void OnConnectionMonitor(VideoChannel *channel,
const std::vector<ConnectionInfo> &infos);
- void OnMediaMonitor(VideoChannel *channel, const MediaInfo& info);
+ void OnMediaMonitor(VideoChannel *channel, const VideoMediaInfo& info);
VoiceChannel* GetVoiceChannel(BaseSession* session);
VideoChannel* GetVideoChannel(BaseSession* session);
void ContinuePlayDTMF();
@@ -127,7 +126,6 @@ class Call : public talk_base::MessageHandler, public sigslot::has_slots<> {
std::map<std::string, VideoChannel *> video_channel_map_;
VideoRenderer* local_renderer_;
bool video_;
- bool mux_;
bool muted_;
bool send_to_voicemail_;
diff --git a/third_party/libjingle/source/talk/session/phone/channel.cc b/third_party/libjingle/source/talk/session/phone/channel.cc
index 5fb1dab..76c1cb4 100644
--- a/third_party/libjingle/source/talk/session/phone/channel.cc
+++ b/third_party/libjingle/source/talk/session/phone/channel.cc
@@ -32,6 +32,7 @@
#include "talk/p2p/base/transportchannel.h"
#include "talk/session/phone/channelmanager.h"
#include "talk/session/phone/mediasessionclient.h"
+#include "talk/session/phone/mediasink.h"
namespace cricket {
@@ -45,11 +46,19 @@ BaseChannel::BaseChannel(talk_base::Thread* thread, MediaEngine* media_engine,
MediaChannel* media_channel, BaseSession* session,
const std::string& content_name,
TransportChannel* transport_channel)
- : worker_thread_(thread), media_engine_(media_engine),
- session_(session), media_channel_(media_channel),
+ : worker_thread_(thread),
+ media_engine_(media_engine),
+ session_(session),
+ media_channel_(media_channel),
+ received_media_sink_(NULL),
+ sent_media_sink_(NULL),
content_name_(content_name),
- transport_channel_(transport_channel), rtcp_transport_channel_(NULL),
- enabled_(false), writable_(false), has_codec_(false), muted_(false) {
+ transport_channel_(transport_channel),
+ rtcp_transport_channel_(NULL),
+ enabled_(false),
+ writable_(false),
+ has_codec_(false),
+ muted_(false) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
media_channel_->SetInterface(this);
transport_channel_->SignalWritableState.connect(
@@ -233,6 +242,18 @@ int BaseChannel::SendPacket(bool rtcp, const void* data, size_t len) {
real_data = reinterpret_cast<const char*>(work);
}
+ {
+ talk_base::CritScope cs(&sink_critical_section_);
+ if (sent_media_sink_) {
+ // Put the sent RTP or RTCP packet to the sink.
+ if (!rtcp) {
+ sent_media_sink_->OnRtpPacket(real_data, real_len);
+ } else {
+ sent_media_sink_->OnRtcpPacket(real_data, real_len);
+ }
+ }
+ }
+
// Bon voyage. Return a number that the caller can understand.
return (channel->SendPacket(real_data, real_len) == real_len) ? len : -1;
}
@@ -271,6 +292,18 @@ void BaseChannel::HandlePacket(bool rtcp, const char* data, size_t len) {
} else {
media_channel_->OnRtcpReceived(real_data, real_len);
}
+
+ {
+ talk_base::CritScope cs(&sink_critical_section_);
+ if (received_media_sink_) {
+ // Put the received RTP or RTCP packet to the sink.
+ if (!rtcp) {
+ received_media_sink_->OnRtpPacket(real_data, real_len);
+ } else {
+ received_media_sink_->OnRtcpPacket(real_data, real_len);
+ }
+ }
+ }
}
void BaseChannel::OnSessionState(BaseSession* session,
@@ -371,8 +404,9 @@ void BaseChannel::ChannelNotWritable_w() {
ChangeState();
}
+// Sets the maximum video bandwidth for automatic bandwidth adjustment.
bool BaseChannel::SetMaxSendBandwidth_w(int max_bandwidth) {
- return media_channel()->SetMaxSendBandwidth(max_bandwidth);
+ return media_channel()->SetSendBandwidth(true, max_bandwidth);
}
bool BaseChannel::SetRtcpCName_w(const std::string& cname) {
@@ -670,6 +704,11 @@ bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
ret = media_channel()->SetSendCodecs(audio->codecs());
}
+ int audio_options = audio->conference_mode() ? OPT_CONFERENCE : 0;
+ if (!media_channel()->SetOptions(audio_options)) {
+ // Log an error on failure, but don't abort the call.
+ LOG(LS_ERROR) << "Failed to set voice channel options";
+ }
// update state
if (ret) {
@@ -786,6 +825,7 @@ VideoChannel::VideoChannel(talk_base::Thread* thread,
// Can't go in BaseChannel because certain session states will
// trigger pure virtual functions, such as GetFirstContent()
OnSessionState(session, session->state());
+
}
VideoChannel::~VideoChannel() {
@@ -807,6 +847,16 @@ bool VideoChannel::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
}
+
+bool VideoChannel::SendIntraFrame() {
+ Send(MSG_SENDINTRAFRAME);
+ return true;
+}
+bool VideoChannel::RequestIntraFrame() {
+ Send(MSG_REQUESTINTRAFRAME);
+ return true;
+}
+
void VideoChannel::ChangeState() {
// render incoming data if we are the active call
// we receive data on the default channel and multiplexed streams
@@ -890,7 +940,12 @@ bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
if (ret) {
ret = SetRtcpMux_w(video->rtcp_mux(), action, CS_REMOTE);
}
- // TODO: Set bandwidth appropriately here.
+ // Set video bandwidth parameters.
+ if (ret) {
+ int bandwidth_bps = video->bandwidth();
+ bool auto_bandwidth = (bandwidth_bps == kAutoBandwidth);
+ ret = media_channel()->SetSendBandwidth(auto_bandwidth, bandwidth_bps);
+ }
if (ret) {
ret = media_channel()->SetSendCodecs(video->codecs());
}
@@ -927,6 +982,13 @@ void VideoChannel::OnMessage(talk_base::Message *pmsg) {
SetRenderer_w(data->ssrc, data->renderer);
break;
}
+ case MSG_SENDINTRAFRAME:
+ SendIntraFrame_w();
+ break;
+ case MSG_REQUESTINTRAFRAME:
+ RequestIntraFrame_w();
+ break;
+
default:
BaseChannel::OnMessage(pmsg);
break;
@@ -944,6 +1006,7 @@ void VideoChannel::OnMediaMonitorUpdate(
SignalMediaMonitor(this, info);
}
+
// TODO: Move to own file in a future CL.
// Leaving here for now to avoid having to mess with the Mac build.
RtcpMuxFilter::RtcpMuxFilter() : state_(ST_INIT), offer_enable_(false) {
diff --git a/third_party/libjingle/source/talk/session/phone/channel.h b/third_party/libjingle/source/talk/session/phone/channel.h
index b7981d9..b82a4bf 100644
--- a/third_party/libjingle/source/talk/session/phone/channel.h
+++ b/third_party/libjingle/source/talk/session/phone/channel.h
@@ -32,6 +32,7 @@
#include <vector>
#include "talk/base/asyncudpsocket.h"
+#include "talk/base/criticalsection.h"
#include "talk/base/network.h"
#include "talk/base/sigslot.h"
#include "talk/p2p/client/socketmonitor.h"
@@ -45,6 +46,7 @@
namespace cricket {
class MediaContentDescription;
+class MediaSinkInterface;
struct CryptoParams;
enum {
@@ -62,9 +64,9 @@ enum {
MSG_SETRINGBACKTONE = 13,
MSG_PLAYRINGBACKTONE = 14,
MSG_SETMAXSENDBANDWIDTH = 15,
- MSG_ADDSCREENCAST = 16,
- MSG_REMOVESCREENCAST = 17,
- MSG_SETRTCPCNAME = 18
+ MSG_SETRTCPCNAME = 18,
+ MSG_SENDINTRAFRAME = 19,
+ MSG_REQUESTINTRAFRAME = 20,
};
// TODO: Move to own file.
@@ -108,6 +110,7 @@ class BaseChannel
talk_base::Thread* worker_thread() const { return worker_thread_; }
BaseSession* session() const { return session_; }
+ const std::string& content_name() { return content_name_; }
TransportChannel* transport_channel() const {
return transport_channel_;
}
@@ -134,6 +137,24 @@ class BaseChannel
void StartConnectionMonitor(int cms);
void StopConnectionMonitor();
+ // Set and get media sinks for recording media.
+ void set_received_media_sink(MediaSinkInterface* sink) {
+ talk_base::CritScope cs(&sink_critical_section_);
+ received_media_sink_ = sink;
+ }
+ const MediaSinkInterface* received_media_sink() {
+ talk_base::CritScope cs(&sink_critical_section_);
+ return received_media_sink_;
+ }
+ void set_sent_media_sink(MediaSinkInterface* sink) {
+ talk_base::CritScope cs(&sink_critical_section_);
+ sent_media_sink_ = sink;
+ }
+ const MediaSinkInterface* sent_media_sink() {
+ talk_base::CritScope cs(&sink_critical_section_);
+ return sent_media_sink_;
+ }
+
protected:
MediaEngine* media_engine() const { return media_engine_; }
virtual MediaChannel* media_channel() const { return media_channel_; }
@@ -143,6 +164,7 @@ class BaseChannel
bool has_codec() const { return has_codec_; }
void set_has_codec(bool has_codec) { has_codec_ = has_codec; }
bool muted() const { return muted_; }
+ talk_base::Thread* signaling_thread() { return session_->signaling_thread(); }
void Send(uint32 id, talk_base::MessageData *pdata = NULL);
void Post(uint32 id, talk_base::MessageData *pdata = NULL);
@@ -230,6 +252,12 @@ class BaseChannel
MediaEngine *media_engine_;
BaseSession *session_;
MediaChannel *media_channel_;
+ // Media sinks to handle the received or sent RTP/RTCP packets. These are
+ // reference to the objects owned by the media recorder.
+ MediaSinkInterface* received_media_sink_;
+ MediaSinkInterface* sent_media_sink_;
+ talk_base::CriticalSection sink_critical_section_;
+
std::string content_name_;
TransportChannel *transport_channel_;
TransportChannel *rtcp_transport_channel_;
@@ -374,6 +402,9 @@ class VideoChannel : public BaseChannel {
void StopMediaMonitor();
sigslot::signal2<VideoChannel*, const VideoMediaInfo&> SignalMediaMonitor;
+ bool SendIntraFrame();
+ bool RequestIntraFrame();
+
private:
// overrides from BaseChannel
virtual void ChangeState();
@@ -387,6 +418,13 @@ class VideoChannel : public BaseChannel {
void AddStream_w(uint32 ssrc, uint32 voice_ssrc);
void RemoveStream_w(uint32 ssrc);
+ void SendIntraFrame_w() {
+ media_channel()->SendIntraFrame();
+ }
+ void RequestIntraFrame_w() {
+ media_channel()->RequestIntraFrame();
+ }
+
struct RenderMessageData : public talk_base::MessageData {
RenderMessageData(uint32 s, VideoRenderer* r) : ssrc(s), renderer(r) {}
uint32 ssrc;
@@ -402,7 +440,6 @@ class VideoChannel : public BaseChannel {
SocketMonitor *monitor, const std::vector<ConnectionInfo> &infos);
virtual void OnMediaMonitorUpdate(
VideoMediaChannel *media_channel, const VideoMediaInfo& info);
-
VoiceChannel *voice_channel_;
VideoRenderer *renderer_;
talk_base::scoped_ptr<VideoMediaMonitor> media_monitor_;
diff --git a/third_party/libjingle/source/talk/session/phone/filemediaengine.h b/third_party/libjingle/source/talk/session/phone/filemediaengine.h
index 272449a..cc6788c 100644
--- a/third_party/libjingle/source/talk/session/phone/filemediaengine.h
+++ b/third_party/libjingle/source/talk/session/phone/filemediaengine.h
@@ -149,7 +149,7 @@ class FileVoiceChannel : public VoiceMediaChannel {
virtual void SetSendSsrc(uint32 id) {} // TODO: change RTP packet?
virtual bool SetRtcpCName(const std::string& cname) { return true; }
virtual bool Mute(bool on) { return false; }
- virtual bool SetMaxSendBandwidth(int max_bandwidth) { return true; }
+ virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
virtual bool SetOptions(int options) { return true; }
private:
@@ -174,7 +174,9 @@ class FileVideoChannel : public VideoMediaChannel {
virtual bool SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
return true;
}
- virtual bool GetStats(VoiceMediaInfo* info) { return true; }
+ virtual bool GetStats(VideoMediaInfo* info) { return true; }
+ virtual bool SendIntraFrame() { return false; }
+ virtual bool RequestIntraFrame() { return false; }
// Implement pure virtual methods of MediaChannel.
virtual void OnPacketReceived(const void* data, int len);
@@ -182,7 +184,7 @@ class FileVideoChannel : public VideoMediaChannel {
virtual void SetSendSsrc(uint32 id) {} // TODO: change RTP packet?
virtual bool SetRtcpCName(const std::string& cname) { return true; }
virtual bool Mute(bool on) { return false; }
- virtual bool SetMaxSendBandwidth(int max_bandwidth) { return true; }
+ virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
virtual bool SetOptions(int options) { return true; }
private:
diff --git a/third_party/libjingle/source/talk/session/phone/mediachannel.h b/third_party/libjingle/source/talk/session/phone/mediachannel.h
index ee9d3c7..01bd8b5 100644
--- a/third_party/libjingle/source/talk/session/phone/mediachannel.h
+++ b/third_party/libjingle/source/talk/session/phone/mediachannel.h
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2007, Google Inc.
+ * Copyright 2004--2010, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -88,7 +88,7 @@ class MediaChannel : public sigslot::has_slots<> {
virtual bool Mute(bool on) = 0;
virtual bool SetRtpExtensionHeaders(bool enable_all) { return true; }
- virtual bool SetMaxSendBandwidth(int max_bandwidth) = 0;
+ virtual bool SetSendBandwidth(bool autobw, int bps) = 0;
virtual bool SetOptions(int options) = 0;
protected:
@@ -101,7 +101,6 @@ enum SendFlags {
SEND_MICROPHONE
};
-// TODO: separate into VoiceMediaInfo and VideoMediaInfo
struct MediaInfo {
int fraction_lost;
int cum_lost;
@@ -114,8 +113,13 @@ struct MediaInfo {
int packetsReceived;
};
-typedef MediaInfo VoiceMediaInfo;
-typedef MediaInfo VideoMediaInfo;
+struct VoiceMediaInfo : MediaInfo {
+};
+
+struct VideoMediaInfo : MediaInfo {
+ int receive_framerate;
+ int send_framerate;
+};
class VoiceMediaChannel : public MediaChannel {
public:
@@ -180,6 +184,11 @@ class VideoFrame {
virtual void SetElapsedTime(int64 elapsed_time) = 0;
virtual void SetTimeStamp(int64 time_stamp) = 0;
+ // Make a copy of the frame. The frame buffer itself may not be copied,
+ // in which case both the current and new VideoFrame will share a single
+ // reference-counted frame buffer.
+ virtual VideoFrame *Copy() const = 0;
+
// Writes the frame into the given frame buffer, provided that it is of
// sufficient size. Returns the frame's actual size, regardless of whether
// it was written or not (like snprintf). If there is insufficient space,
@@ -228,7 +237,7 @@ class VideoFrame {
// Size of an I420 image of given dimensions when stored as a frame buffer.
static size_t SizeOf(size_t w, size_t h) {
- return w * h * 3 / 2;
+ return w * h + ((w + 1) / 2) * ((h + 1) / 2) * 2;
}
protected:
@@ -260,6 +269,10 @@ class NullVideoFrame : public VideoFrame {
virtual void SetElapsedTime(int64 elapsed_time) {}
virtual void SetTimeStamp(int64 time_stamp) {}
+ virtual VideoFrame *Copy() const {
+ return NULL;
+ }
+
virtual size_t CopyToBuffer(uint8 *buffer, size_t size) const {
return 0;
}
@@ -332,6 +345,13 @@ class VideoMediaChannel : public MediaChannel {
virtual bool SetRenderer(uint32 ssrc, VideoRenderer* renderer) = 0;
// Gets quality stats for the channel.
virtual bool GetStats(VideoMediaInfo* info) = 0;
+
+ // Send an intra frame to the receivers.
+ virtual bool SendIntraFrame() = 0;
+ // Reuqest each of the remote senders to send an intra frame.
+ virtual bool RequestIntraFrame() = 0;
+
+
protected:
VideoRenderer *renderer_;
};
diff --git a/third_party/libjingle/source/talk/session/phone/mediasessionclient.cc b/third_party/libjingle/source/talk/session/phone/mediasessionclient.cc
index 001cf73..f16b531 100644
--- a/third_party/libjingle/source/talk/session/phone/mediasessionclient.cc
+++ b/third_party/libjingle/source/talk/session/phone/mediasessionclient.cc
@@ -25,23 +25,37 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <string>
+
#include "talk/session/phone/mediasessionclient.h"
+#include "talk/base/helpers.h"
#include "talk/base/logging.h"
#include "talk/base/stringutils.h"
+#include "talk/base/stringencode.h"
#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/parsing.h"
+#include "talk/session/phone/cryptoparams.h"
+#include "talk/session/phone/srtpfilter.h"
#include "talk/xmpp/constants.h"
#include "talk/xmllite/qname.h"
+#include "talk/xmllite/xmlconstants.h"
using namespace talk_base;
+namespace {
+const std::string kInline = "inline:";
+}
+
namespace cricket {
+typedef std::vector<CryptoParams> CryptoParamsVec;
+
MediaSessionClient::MediaSessionClient(
const buzz::Jid& jid, SessionManager *manager)
: jid_(jid), session_manager_(manager), focus_call_(NULL),
- channel_manager_(new ChannelManager(session_manager_->worker_thread())) {
+ channel_manager_(new ChannelManager(session_manager_->worker_thread())),
+ secure_(SEC_DISABLED) {
Construct();
}
@@ -50,7 +64,8 @@ MediaSessionClient::MediaSessionClient(
MediaEngine* media_engine, DeviceManager* device_manager)
: jid_(jid), session_manager_(manager), focus_call_(NULL),
channel_manager_(new ChannelManager(
- media_engine, device_manager, session_manager_->worker_thread())) {
+ media_engine, device_manager, session_manager_->worker_thread())),
+ secure_(SEC_DISABLED) {
Construct();
}
@@ -81,7 +96,46 @@ MediaSessionClient::~MediaSessionClient() {
session_manager_->RemoveClient(NS_JINGLE_RTP);
}
-SessionDescription* MediaSessionClient::CreateOffer(bool video, bool set_ssrc) {
+bool CreateCryptoParams(int tag, const std::string& cipher, CryptoParams *out) {
+ std::string key;
+ key.reserve(SRTP_MASTER_KEY_BASE64_LEN);
+
+ if (!CreateRandomString(SRTP_MASTER_KEY_BASE64_LEN, &key)) {
+ return false;
+ }
+ out->tag = tag;
+ out->cipher_suite = cipher;
+ out->key_params = kInline + key;
+ return true;
+}
+
+bool AddCryptoParams(const std::string& cipher_suite, CryptoParamsVec *out) {
+ int size = out->size();
+
+ out->resize(size + 1);
+ return CreateCryptoParams(size, cipher_suite, &out->at(size));
+}
+
+// For audio, HMAC 32 is prefered because of the low overhead.
+bool GetSupportedAudioCryptos(CryptoParamsVec* cryptos) {
+#ifdef HAVE_SRTP
+ return AddCryptoParams(CS_AES_CM_128_HMAC_SHA1_32, cryptos) &&
+ AddCryptoParams(CS_AES_CM_128_HMAC_SHA1_80, cryptos);
+#else
+ return false;
+#endif
+}
+
+bool GetSupportedVideoCryptos(CryptoParamsVec* cryptos) {
+#ifdef HAVE_SRTP
+ return AddCryptoParams(CS_AES_CM_128_HMAC_SHA1_80, cryptos);
+#else
+ return false;
+#endif
+}
+
+SessionDescription* MediaSessionClient::CreateOffer(
+ const CallOptions& options) {
SessionDescription* offer = new SessionDescription();
AudioContentDescription* audio = new AudioContentDescription();
@@ -92,14 +146,31 @@ SessionDescription* MediaSessionClient::CreateOffer(bool video, bool set_ssrc) {
codec != audio_codecs.end(); ++codec) {
audio->AddCodec(*codec);
}
- if (set_ssrc) {
+ if (options.is_muc) {
audio->set_ssrc(0);
}
audio->SortCodecs();
+
+ if (secure() != SEC_DISABLED) {
+ CryptoParamsVec audio_cryptos;
+ if (GetSupportedAudioCryptos(&audio_cryptos)) {
+ for (CryptoParamsVec::const_iterator crypto = audio_cryptos.begin();
+ crypto != audio_cryptos.end(); ++crypto) {
+ audio->AddCrypto(*crypto);
+ }
+ }
+ if (secure() == SEC_REQUIRED) {
+ if (audio->cryptos().empty()) {
+ return NULL; // Abort, crypto required but none found.
+ }
+ audio->set_crypto_required(true);
+ }
+ }
+
offer->AddContent(CN_AUDIO, NS_JINGLE_RTP, audio);
// add video codecs, if this is a video call
- if (video) {
+ if (options.is_video) {
VideoContentDescription* video = new VideoContentDescription();
VideoCodecs video_codecs;
channel_manager_->GetSupportedVideoCodecs(&video_codecs);
@@ -107,10 +178,28 @@ SessionDescription* MediaSessionClient::CreateOffer(bool video, bool set_ssrc) {
codec != video_codecs.end(); ++codec) {
video->AddCodec(*codec);
}
- if (set_ssrc) {
+ if (options.is_muc) {
video->set_ssrc(0);
}
+ video->set_bandwidth(options.video_bandwidth);
video->SortCodecs();
+
+ if (secure() != SEC_DISABLED) {
+ CryptoParamsVec video_cryptos;
+ if (GetSupportedVideoCryptos(&video_cryptos)) {
+ for (CryptoParamsVec::const_iterator crypto = video_cryptos.begin();
+ crypto != video_cryptos.end(); ++crypto) {
+ video->AddCrypto(*crypto);
+ }
+ }
+ if (secure() == SEC_REQUIRED) {
+ if (video->cryptos().empty()) {
+ return NULL; // Abort, crypto required but none found.
+ }
+ video->set_crypto_required(true);
+ }
+ }
+
offer->AddContent(CN_VIDEO, NS_JINGLE_RTP, video);
}
@@ -144,8 +233,25 @@ const ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc) {
return GetFirstMediaContent(sdesc, MEDIA_TYPE_VIDEO);
}
+// For video support only 80-bit SHA1 HMAC. For audio 32-bit HMAC is
+// tolerated because it is low overhead. Pick the crypto in the list
+// that is supported.
+bool SelectCrypto(const MediaContentDescription* offer, CryptoParams *crypto) {
+ bool audio = offer->type() == MEDIA_TYPE_AUDIO;
+ const CryptoParamsVec& cryptos = offer->cryptos();
+
+ for (CryptoParamsVec::const_iterator i = cryptos.begin();
+ i != cryptos.end(); ++i) {
+ if (CS_AES_CM_128_HMAC_SHA1_80 == i->cipher_suite ||
+ (CS_AES_CM_128_HMAC_SHA1_32 == i->cipher_suite && audio)) {
+ return CreateCryptoParams(i->tag, i->cipher_suite, crypto);
+ }
+ }
+ return false;
+}
+
SessionDescription* MediaSessionClient::CreateAnswer(
- const SessionDescription* offer) {
+ const SessionDescription* offer, const CallOptions& options) {
// The answer contains the intersection of the codecs in the offer with the
// codecs we support, ordered by our local preference. As indicated by
// XEP-0167, we retain the same payload ids from the offer in the answer.
@@ -171,6 +277,19 @@ SessionDescription* MediaSessionClient::CreateAnswer(
}
audio_accept->SortCodecs();
+
+ if (secure() != SEC_DISABLED) {
+ CryptoParams crypto;
+
+ if (SelectCrypto(audio_offer, &crypto)) {
+ audio_accept->AddCrypto(crypto);
+ }
+ }
+
+ if (audio_accept->cryptos().empty() &&
+ (audio_offer->crypto_required() || secure() == SEC_REQUIRED)) {
+ return NULL; // Fails the session setup.
+ }
accept->AddContent(audio_content->name, audio_content->type, audio_accept);
}
@@ -193,15 +312,29 @@ SessionDescription* MediaSessionClient::CreateAnswer(
}
}
+ video_accept->set_bandwidth(options.video_bandwidth);
video_accept->SortCodecs();
+
+ if (secure() != SEC_DISABLED) {
+ CryptoParams crypto;
+
+ if (SelectCrypto(video_offer, &crypto)) {
+ video_accept->AddCrypto(crypto);
+ }
+ }
+
+ if (video_accept->cryptos().empty() &&
+ (video_offer->crypto_required() || secure() == SEC_REQUIRED)) {
+ return NULL; // Fails the session setup.
+ }
accept->AddContent(video_content->name, video_content->type, video_accept);
}
return accept;
}
-Call *MediaSessionClient::CreateCall(bool video, bool mux) {
- Call *call = new Call(this, video, mux);
+Call *MediaSessionClient::CreateCall() {
+ Call *call = new Call(this);
calls_[call->id()] = call;
SignalCallCreate(call);
return call;
@@ -228,15 +361,14 @@ void MediaSessionClient::OnSessionState(BaseSession* base_session,
// If our accept would have no codecs, then we must reject this call.
const SessionDescription* offer = session->remote_description();
- const SessionDescription* accept = CreateAnswer(offer);
+ const SessionDescription* accept = CreateAnswer(offer, CallOptions());
const ContentInfo* audio_content = GetFirstAudioContent(accept);
- const ContentInfo* video_content = GetFirstVideoContent(accept);
const AudioContentDescription* audio_accept = (!audio_content) ? NULL :
static_cast<const AudioContentDescription*>(audio_content->description);
// For some reason, we need to create the call even when we
// reject.
- Call *call = CreateCall(video_content != NULL);
+ Call *call = CreateCall();
session_map_[session->id()] = call;
call->IncomingSession(session, offer);
@@ -344,6 +476,70 @@ void ParseGingleSsrc(const buzz::XmlElement* parent_elem,
}
}
+bool ParseCryptoParams(const buzz::XmlElement* element,
+ CryptoParams* out,
+ ParseError* error) {
+ if (!element->HasAttr(QN_CRYPTO_SUITE)) {
+ return BadParse("crypto: crypto-suite attribute missing ", error);
+ } else if (!element->HasAttr(QN_CRYPTO_KEY_PARAMS)) {
+ return BadParse("crypto: key-params attribute missing ", error);
+ } else if (!element->HasAttr(QN_CRYPTO_TAG)) {
+ return BadParse("crypto: tag attribute missing ", error);
+ }
+
+ const std::string& crypto_suite = element->Attr(QN_CRYPTO_SUITE);
+ const std::string& key_params = element->Attr(QN_CRYPTO_KEY_PARAMS);
+ const int tag = GetXmlAttr(element, QN_CRYPTO_TAG, 0);
+ const std::string& session_params =
+ element->Attr(QN_CRYPTO_SESSION_PARAMS); // Optional.
+
+ *out = CryptoParams(tag, crypto_suite, key_params, session_params);
+ return true;
+}
+
+
+// Parse the first encryption element found with a matching 'usage'
+// element.
+// <usage/> is specific to Gingle. In Jingle, <crypto/> is already
+// scoped to a content.
+// Return false if there was an encryption element and it could not be
+// parsed.
+bool ParseGingleEncryption(const buzz::XmlElement* desc,
+ const buzz::QName& usage,
+ MediaContentDescription* media,
+ ParseError* error) {
+ for (const buzz::XmlElement* encryption = desc->FirstNamed(QN_ENCRYPTION);
+ encryption != NULL;
+ encryption = encryption->NextNamed(QN_ENCRYPTION)) {
+ if (encryption->FirstNamed(usage) != NULL) {
+ media->set_crypto_required(
+ GetXmlAttr(encryption, QN_ENCRYPTION_REQUIRED, false));
+ for (const buzz::XmlElement* crypto = encryption->FirstNamed(QN_CRYPTO);
+ crypto != NULL;
+ crypto = crypto->NextNamed(QN_CRYPTO)) {
+ CryptoParams params;
+ if (!ParseCryptoParams(crypto, &params, error)) {
+ return false;
+ }
+ media->AddCrypto(params);
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+void ParseBandwidth(const buzz::XmlElement* parent_elem,
+ MediaContentDescription* media) {
+ const buzz::XmlElement* bw_elem = GetXmlChild(parent_elem, LN_BANDWIDTH);
+ int bandwidth_kbps;
+ if (bw_elem && FromString(bw_elem->BodyText(), &bandwidth_kbps)) {
+ if (bandwidth_kbps >= 0) {
+ media->set_bandwidth(bandwidth_kbps * 1000);
+ }
+ }
+}
+
bool ParseGingleAudioContent(const buzz::XmlElement* content_elem,
const ContentDescription** content,
ParseError* error) {
@@ -368,11 +564,15 @@ bool ParseGingleAudioContent(const buzz::XmlElement* content_elem,
ParseGingleSsrc(content_elem, QN_GINGLE_VIDEO_SRCID, audio);
+ if (!ParseGingleEncryption(content_elem, QN_GINGLE_AUDIO_CRYPTO_USAGE,
+ audio, error)) {
+ return false;
+ }
+
*content = audio;
return true;
}
-
bool ParseGingleVideoContent(const buzz::XmlElement* content_elem,
const ContentDescription** content,
ParseError* error) {
@@ -389,6 +589,12 @@ bool ParseGingleVideoContent(const buzz::XmlElement* content_elem,
}
ParseGingleSsrc(content_elem, QN_GINGLE_VIDEO_SRCID, video);
+ ParseBandwidth(content_elem, video);
+
+ if (!ParseGingleEncryption(content_elem, QN_GINGLE_VIDEO_CRYPTO_USAGE,
+ video, error)) {
+ return false;
+ }
*content = video;
return true;
@@ -398,8 +604,10 @@ void ParsePayloadTypeParameters(const buzz::XmlElement* element,
std::map<std::string, std::string>* paramap) {
for (const buzz::XmlElement* param = element->FirstNamed(QN_PARAMETER);
param != NULL; param = param->NextNamed(QN_PARAMETER)) {
- std::string name = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_NAME, "");
- std::string value = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_VALUE, "");
+ std::string name = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_NAME,
+ buzz::STR_EMPTY);
+ std::string value = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_VALUE,
+ buzz::STR_EMPTY);
if (!name.empty() && !value.empty()) {
paramap->insert(make_pair(name, value));
}
@@ -412,12 +620,40 @@ int FindWithDefault(const std::map<std::string, std::string>& map,
return (iter == map.end()) ? def : atoi(iter->second.c_str());
}
+
+// Parse the first encryption element found.
+// Return false if there was an encryption element and it could not be
+// parsed.
+bool ParseJingleEncryption(const buzz::XmlElement* content_elem,
+ MediaContentDescription* media,
+ ParseError* error) {
+ const buzz::XmlElement* encryption =
+ content_elem->FirstNamed(QN_ENCRYPTION);
+ if (encryption == NULL) {
+ return true;
+ }
+
+ media->set_crypto_required(
+ GetXmlAttr(encryption, QN_ENCRYPTION_REQUIRED, false));
+
+ for (const buzz::XmlElement* crypto = encryption->FirstNamed(QN_CRYPTO);
+ crypto != NULL;
+ crypto = crypto->NextNamed(QN_CRYPTO)) {
+ CryptoParams params;
+ if (!ParseCryptoParams(crypto, &params, error)) {
+ return false;
+ }
+ media->AddCrypto(params);
+ }
+ return true;
+}
+
bool ParseJingleAudioCodec(const buzz::XmlElement* elem, AudioCodec* codec) {
int id = GetXmlAttr(elem, QN_ID, -1);
if (id < 0)
return false;
- std::string name = GetXmlAttr(elem, QN_NAME, "");
+ std::string name = GetXmlAttr(elem, QN_NAME, buzz::STR_EMPTY);
int clockrate = GetXmlAttr(elem, QN_CLOCKRATE, 0);
int channels = GetXmlAttr(elem, QN_CHANNELS, 1);
@@ -434,7 +670,7 @@ bool ParseJingleVideoCodec(const buzz::XmlElement* elem, VideoCodec* codec) {
if (id < 0)
return false;
- std::string name = GetXmlAttr(elem, QN_NAME, "");
+ std::string name = GetXmlAttr(elem, QN_NAME, buzz::STR_EMPTY);
std::map<std::string, std::string> paramap;
ParsePayloadTypeParameters(elem, &paramap);
@@ -461,6 +697,9 @@ bool ParseJingleAudioContent(const buzz::XmlElement* content_elem,
}
}
+ if (!ParseJingleEncryption(content_elem, audio, error)) {
+ return false;
+ }
// TODO: Figure out how to integrate SSRC into Jingle.
*content = audio;
return true;
@@ -481,6 +720,11 @@ bool ParseJingleVideoContent(const buzz::XmlElement* content_elem,
}
}
+ ParseBandwidth(content_elem, video);
+
+ if (!ParseJingleEncryption(content_elem, video, error)) {
+ return false;
+ }
// TODO: Figure out how to integrate SSRC into Jingle.
*content = video;
return true;
@@ -547,8 +791,58 @@ buzz::XmlElement* CreateGingleSsrcElem(const buzz::QName& name, uint32 ssrc) {
return elem;
}
+buzz::XmlElement* CreateBandwidthElem(const buzz::QName& name, int bps) {
+ int kbps = bps / 1000;
+ buzz::XmlElement* elem = new buzz::XmlElement(name);
+ elem->AddAttr(buzz::QN_TYPE, "AS");
+ SetXmlBody(elem, kbps);
+ return elem;
+}
+
+// For Jingle, usage_qname is empty.
+buzz::XmlElement* CreateJingleEncryptionElem(const CryptoParamsVec& cryptos,
+ bool required) {
+ buzz::XmlElement* encryption_elem = new buzz::XmlElement(QN_ENCRYPTION);
+
+ if (required) {
+ encryption_elem->SetAttr(QN_ENCRYPTION_REQUIRED, "true");
+ }
+
+ for (CryptoParamsVec::const_iterator i = cryptos.begin();
+ i != cryptos.end();
+ ++i) {
+ buzz::XmlElement* crypto_elem = new buzz::XmlElement(QN_CRYPTO);
+
+ AddXmlAttr(crypto_elem, QN_CRYPTO_TAG, i->tag);
+ crypto_elem->AddAttr(QN_CRYPTO_SUITE, i->cipher_suite);
+ crypto_elem->AddAttr(QN_CRYPTO_KEY_PARAMS, i->key_params);
+ if (!i->session_params.empty()) {
+ crypto_elem->AddAttr(QN_CRYPTO_SESSION_PARAMS, i->session_params);
+ }
+ encryption_elem->AddElement(crypto_elem);
+ }
+ return encryption_elem;
+}
+
+buzz::XmlElement* CreateGingleEncryptionElem(const CryptoParamsVec& cryptos,
+ const buzz::QName& usage_qname,
+ bool required) {
+ buzz::XmlElement* encryption_elem =
+ CreateJingleEncryptionElem(cryptos, required);
+
+ if (required) {
+ encryption_elem->SetAttr(QN_ENCRYPTION_REQUIRED, "true");
+ }
+
+ buzz::XmlElement* usage_elem = new buzz::XmlElement(usage_qname);
+ encryption_elem->AddElement(usage_elem);
+
+ return encryption_elem;
+}
+
buzz::XmlElement* CreateGingleAudioContentElem(
- const AudioContentDescription* audio) {
+ const AudioContentDescription* audio,
+ bool crypto_required) {
buzz::XmlElement* elem =
new buzz::XmlElement(QN_GINGLE_AUDIO_CONTENT, true);
@@ -561,12 +855,20 @@ buzz::XmlElement* CreateGingleAudioContentElem(
QN_GINGLE_AUDIO_SRCID, audio->ssrc()));
}
+ const CryptoParamsVec& cryptos = audio->cryptos();
+ if (!cryptos.empty()) {
+ elem->AddElement(CreateGingleEncryptionElem(cryptos,
+ QN_GINGLE_AUDIO_CRYPTO_USAGE,
+ crypto_required));
+ }
+
return elem;
}
buzz::XmlElement* CreateGingleVideoContentElem(
- const VideoContentDescription* video) {
+ const VideoContentDescription* video,
+ bool crypto_required) {
buzz::XmlElement* elem =
new buzz::XmlElement(QN_GINGLE_VIDEO_CONTENT, true);
@@ -578,6 +880,17 @@ buzz::XmlElement* CreateGingleVideoContentElem(
elem->AddElement(CreateGingleSsrcElem(
QN_GINGLE_VIDEO_SRCID, video->ssrc()));
}
+ if (video->bandwidth() != kAutoBandwidth) {
+ elem->AddElement(CreateBandwidthElem(QN_GINGLE_VIDEO_BANDWIDTH,
+ video->bandwidth()));
+ }
+
+ const CryptoParamsVec& cryptos = video->cryptos();
+ if (!cryptos.empty()) {
+ elem->AddElement(CreateGingleEncryptionElem(cryptos,
+ QN_GINGLE_VIDEO_CRYPTO_USAGE,
+ crypto_required));
+ }
return elem;
}
@@ -627,7 +940,7 @@ buzz::XmlElement* CreateJingleVideoCodecElem(const VideoCodec& codec) {
}
buzz::XmlElement* CreateJingleAudioContentElem(
- const AudioContentDescription* audio) {
+ const AudioContentDescription* audio, bool crypto_required) {
buzz::XmlElement* elem =
new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true);
@@ -638,12 +951,17 @@ buzz::XmlElement* CreateJingleAudioContentElem(
elem->AddElement(CreateJingleAudioCodecElem(*codec));
}
+ const CryptoParamsVec& cryptos = audio->cryptos();
+ if (!cryptos.empty()) {
+ elem->AddElement(CreateJingleEncryptionElem(cryptos, crypto_required));
+ }
+
// TODO: Figure out how to integrate SSRC into Jingle.
return elem;
}
buzz::XmlElement* CreateJingleVideoContentElem(
- const VideoContentDescription* video) {
+ const VideoContentDescription* video, bool crypto_required) {
buzz::XmlElement* elem =
new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true);
@@ -654,6 +972,16 @@ buzz::XmlElement* CreateJingleVideoContentElem(
elem->AddElement(CreateJingleVideoCodecElem(*codec));
}
+ const CryptoParamsVec& cryptos = video->cryptos();
+ if (!cryptos.empty()) {
+ elem->AddElement(CreateJingleEncryptionElem(cryptos, crypto_required));
+ }
+
+ if (video->bandwidth() != kAutoBandwidth) {
+ elem->AddElement(CreateBandwidthElem(QN_JINGLE_RTP_BANDWIDTH,
+ video->bandwidth()));
+ }
+
// TODO: Figure out how to integrate SSRC into Jingle.
return elem;
}
@@ -664,22 +992,23 @@ bool MediaSessionClient::WriteContent(SignalingProtocol protocol,
WriteError* error) {
const MediaContentDescription* media =
static_cast<const MediaContentDescription*>(content);
+ bool crypto_required = secure() == SEC_REQUIRED;
if (media->type() == MEDIA_TYPE_AUDIO) {
const AudioContentDescription* audio =
static_cast<const AudioContentDescription*>(media);
if (protocol == PROTOCOL_GINGLE) {
- *elem = CreateGingleAudioContentElem(audio);
+ *elem = CreateGingleAudioContentElem(audio, crypto_required);
} else {
- *elem = CreateJingleAudioContentElem(audio);
+ *elem = CreateJingleAudioContentElem(audio, crypto_required);
}
} else if (media->type() == MEDIA_TYPE_VIDEO) {
const VideoContentDescription* video =
static_cast<const VideoContentDescription*>(media);
if (protocol == PROTOCOL_GINGLE) {
- *elem = CreateGingleVideoContentElem(video);
+ *elem = CreateGingleVideoContentElem(video, crypto_required);
} else {
- *elem = CreateJingleVideoContentElem(video);
+ *elem = CreateJingleVideoContentElem(video, crypto_required);
}
} else {
return BadWrite("Unknown content type: " + media->type(), error);
diff --git a/third_party/libjingle/source/talk/session/phone/mediasessionclient.h b/third_party/libjingle/source/talk/session/phone/mediasessionclient.h
index 533341b..a74fe3e 100644
--- a/third_party/libjingle/source/talk/session/phone/mediasessionclient.h
+++ b/third_party/libjingle/source/talk/session/phone/mediasessionclient.h
@@ -51,8 +51,38 @@ class SessionDescription;
typedef std::vector<AudioCodec> AudioCodecs;
typedef std::vector<VideoCodec> VideoCodecs;
+// SEC_ENABLED and SEC_REQUIRED should only be used if the session
+// was negotiated over TLS, to protect the inline crypto material
+// exchange.
+// SEC_DISABLED: No crypto in outgoing offer and answer. Fail any
+// offer with crypto required.
+// SEC_ENABLED: Crypto in outgoing offer and answer. Fail any offer
+// with unsupported required crypto. Crypto set but not
+// required in outgoing offer.
+// SEC_REQUIRED: Crypto in outgoing offer and answer with
+// required='true'. Fail any offer with no or
+// unsupported crypto (implicit crypto required='true'
+// in the offer.)
+enum SecureMediaPolicy {SEC_DISABLED, SEC_ENABLED, SEC_REQUIRED};
+
+const int kAutoBandwidth = -1;
+
+struct CallOptions {
+ CallOptions() :
+ is_video(false),
+ is_muc(false),
+ video_bandwidth(kAutoBandwidth) {
+ }
+
+ bool is_video;
+ bool is_muc;
+ // bps. -1 == auto.
+ int video_bandwidth;
+};
+
class MediaSessionClient: public SessionClient, public sigslot::has_slots<> {
public:
+
MediaSessionClient(const buzz::Jid& jid, SessionManager *manager);
// Alternative constructor, allowing injection of media_engine
// and device_manager.
@@ -66,7 +96,7 @@ class MediaSessionClient: public SessionClient, public sigslot::has_slots<> {
int GetCapabilities() { return channel_manager_->GetCapabilities(); }
- Call *CreateCall(bool video = false, bool mux = false);
+ Call *CreateCall();
void DestroyCall(Call *call);
Call *GetFocus();
@@ -100,8 +130,12 @@ class MediaSessionClient: public SessionClient, public sigslot::has_slots<> {
sigslot::signal1<Call *> SignalCallDestroy;
sigslot::repeater0<> SignalDevicesChange;
- SessionDescription* CreateOffer(bool video = false, bool set_ssrc = false);
- SessionDescription* CreateAnswer(const SessionDescription* offer);
+ SessionDescription* CreateOffer(const CallOptions& options);
+ SessionDescription* CreateAnswer(const SessionDescription* offer,
+ const CallOptions& options);
+
+ SecureMediaPolicy secure() const { return secure_; }
+ void set_secure(SecureMediaPolicy s) { secure_ = s; }
private:
void Construct();
@@ -124,7 +158,7 @@ class MediaSessionClient: public SessionClient, public sigslot::has_slots<> {
ChannelManager *channel_manager_;
std::map<uint32, Call *> calls_;
std::map<std::string, Call *> session_map_;
-
+ SecureMediaPolicy secure_;
friend class Call;
};
@@ -135,8 +169,14 @@ enum MediaType {
class MediaContentDescription : public ContentDescription {
public:
- MediaContentDescription() : ssrc_(0), ssrc_set_(false), rtcp_mux_(false),
- rtp_headers_disabled_(false) {}
+ MediaContentDescription()
+ : ssrc_(0),
+ ssrc_set_(false),
+ rtcp_mux_(false),
+ rtp_headers_disabled_(false),
+ crypto_required_(false),
+ bandwidth_(kAutoBandwidth) {
+ }
virtual MediaType type() const = 0;
@@ -161,12 +201,22 @@ class MediaContentDescription : public ContentDescription {
void AddCrypto(const CryptoParams& params) {
cryptos_.push_back(params);
}
+ bool crypto_required() const { return crypto_required_; }
+ void set_crypto_required(bool crypto) {
+ crypto_required_ = crypto;
+ }
+ int bandwidth() const { return bandwidth_; }
+ void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; }
+
+ protected:
uint32 ssrc_;
bool ssrc_set_;
bool rtcp_mux_;
bool rtp_headers_disabled_;
std::vector<CryptoParams> cryptos_;
+ bool crypto_required_;
+ int bandwidth_;
};
template <class C>
@@ -190,16 +240,22 @@ class MediaContentDescriptionImpl : public MediaContentDescription {
class AudioContentDescription : public MediaContentDescriptionImpl<AudioCodec> {
public:
- AudioContentDescription()
- {}
+ AudioContentDescription() :
+ conference_mode_(false) {}
virtual MediaType type() const { return MEDIA_TYPE_AUDIO; }
+ bool conference_mode() const { return conference_mode_; }
+ void set_conference_mode(bool enable) {
+ conference_mode_ = enable;
+ }
+
const std::string &lang() const { return lang_; }
void set_lang(const std::string &lang) { lang_ = lang; }
private:
+ bool conference_mode_;
std::string lang_;
};
diff --git a/third_party/libjingle/source/talk/session/phone/mediasink.h b/third_party/libjingle/source/talk/session/phone/mediasink.h
new file mode 100644
index 0000000..078b534
--- /dev/null
+++ b/third_party/libjingle/source/talk/session/phone/mediasink.h
@@ -0,0 +1,49 @@
+/*
+ * libjingle
+ * Copyright 2004--2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_SESSION_PHONE_MEDIASINK_H_
+#define TALK_SESSION_PHONE_MEDIASINK_H_
+
+namespace cricket {
+
+// MediaSinkInterface is a sink to handle RTP and RTCP packets that are sent or
+// received by a channel. Each channel needs two MediaSinkInterface, one for
+// the sent packets and the other for the received packets.
+class MediaSinkInterface {
+ public:
+ virtual ~MediaSinkInterface() {}
+
+ virtual void SetMaxSize(size_t size) = 0;
+ virtual bool Enable(bool enable) = 0;
+ virtual bool IsEnabled() const = 0;
+ virtual void OnRtpPacket(const void* data, size_t size) = 0;
+ virtual void OnRtcpPacket(const void* data, size_t size) = 0;
+};
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_MEDIASINK_H_
diff --git a/third_party/libjingle/source/talk/session/phone/rtpdump.cc b/third_party/libjingle/source/talk/session/phone/rtpdump.cc
index 1006015..bd67cad 100644
--- a/third_party/libjingle/source/talk/session/phone/rtpdump.cc
+++ b/third_party/libjingle/source/talk/session/phone/rtpdump.cc
@@ -35,32 +35,24 @@
namespace cricket {
-static const char kRtpDumpFileFirstLine[] = "#!rtpplay1.0 0.0.0.0/0\n";
-
-struct RtpDumpFileHeader {
- RtpDumpFileHeader(uint32 start_ms, uint32 s, uint16 p)
- : start_sec(start_ms / 1000),
- start_usec(start_ms % 1000 * 1000),
- source(s),
- port(p),
- padding(0) {
- }
-
- void WriteToByteBuffer(talk_base::ByteBuffer* buf) {
- buf->WriteUInt32(start_sec);
- buf->WriteUInt32(start_usec);
- buf->WriteUInt32(source);
- buf->WriteUInt16(port);
- buf->WriteUInt16(padding);
- }
+const std::string RtpDumpFileHeader::kFirstLine =
+ "#!rtpplay1.0 0.0.0.0/0\n";
+
+RtpDumpFileHeader::RtpDumpFileHeader(uint32 start_ms, uint32 s, uint16 p)
+ : start_sec(start_ms / 1000),
+ start_usec(start_ms % 1000 * 1000),
+ source(s),
+ port(p),
+ padding(0) {
+}
- static const size_t kHeaderLength = 16;
- uint32 start_sec; // start of recording, the seconds part.
- uint32 start_usec; // start of recording, the microseconds part.
- uint32 source; // network source (multicast address).
- uint16 port; // UDP port.
- uint16 padding; // 2 bytes padding.
-};
+void RtpDumpFileHeader::WriteToByteBuffer(talk_base::ByteBuffer* buf) {
+ buf->WriteUInt32(start_sec);
+ buf->WriteUInt32(start_usec);
+ buf->WriteUInt32(source);
+ buf->WriteUInt16(port);
+ buf->WriteUInt16(padding);
+}
// RTP packet format (http://www.networksorcery.com/enp/protocol/rtp.htm).
static const int kRtpSeqNumOffset = 2;
@@ -308,7 +300,8 @@ talk_base::StreamResult RtpDumpWriter::WritePacket(
talk_base::StreamResult RtpDumpWriter::WriteFileHeader() {
talk_base::StreamResult res = stream_->WriteAll(
- kRtpDumpFileFirstLine, strlen(kRtpDumpFileFirstLine), NULL, NULL);
+ RtpDumpFileHeader::kFirstLine.c_str(),
+ RtpDumpFileHeader::kFirstLine.size(), NULL, NULL);
if (res != talk_base::SR_SUCCESS) {
return res;
}
diff --git a/third_party/libjingle/source/talk/session/phone/rtpdump.h b/third_party/libjingle/source/talk/session/phone/rtpdump.h
index 40c4e03..66275e6 100644
--- a/third_party/libjingle/source/talk/session/phone/rtpdump.h
+++ b/third_party/libjingle/source/talk/session/phone/rtpdump.h
@@ -35,6 +35,10 @@
#include "talk/base/basictypes.h"
#include "talk/base/stream.h"
+namespace talk_base {
+class ByteBuffer;
+}
+
namespace cricket {
// We use the RTP dump file format compatible to the format used by rtptools
@@ -44,6 +48,19 @@ namespace cricket {
// For each packet, the file contains a 8 byte dump packet header, followed by
// the actual RTP or RTCP packet.
+struct RtpDumpFileHeader {
+ RtpDumpFileHeader(uint32 start_ms, uint32 s, uint16 p);
+ void WriteToByteBuffer(talk_base::ByteBuffer* buf);
+
+ static const std::string kFirstLine;
+ static const size_t kHeaderLength = 16;
+ uint32 start_sec; // start of recording, the seconds part.
+ uint32 start_usec; // start of recording, the microseconds part.
+ uint32 source; // network source (multicast address).
+ uint16 port; // UDP port.
+ uint16 padding; // 2 bytes padding.
+};
+
struct RtpDumpPacket {
RtpDumpPacket() {}
@@ -166,6 +183,12 @@ class RtpDumpWriter {
}
uint32 GetElapsedTime() const;
+ bool GetDumpSize(size_t* size) {
+ // Note that we use GetPosition(), rather than GetSize(), to avoid flush the
+ // stream per write.
+ return stream_ && size && stream_->GetPosition(size);
+ }
+
protected:
talk_base::StreamResult WriteFileHeader();
diff --git a/third_party/libjingle/source/talk/session/phone/srtpfilter.cc b/third_party/libjingle/source/talk/session/phone/srtpfilter.cc
index 63daed6..f8d2dd4 100644
--- a/third_party/libjingle/source/talk/session/phone/srtpfilter.cc
+++ b/third_party/libjingle/source/talk/session/phone/srtpfilter.cc
@@ -62,6 +62,7 @@ namespace cricket {
const std::string& CS_DEFAULT = CS_AES_CM_128_HMAC_SHA1_80;
const std::string CS_AES_CM_128_HMAC_SHA1_80 = "AES_CM_128_HMAC_SHA1_80";
const std::string CS_AES_CM_128_HMAC_SHA1_32 = "AES_CM_128_HMAC_SHA1_32";
+const int SRTP_MASTER_KEY_BASE64_LEN = SRTP_MASTER_KEY_LEN * 4 / 3;
SrtpFilter::SrtpFilter() : state_(ST_INIT) {
}
diff --git a/third_party/libjingle/source/talk/session/phone/srtpfilter.h b/third_party/libjingle/source/talk/session/phone/srtpfilter.h
index 71b74e0..3401004 100644
--- a/third_party/libjingle/source/talk/session/phone/srtpfilter.h
+++ b/third_party/libjingle/source/talk/session/phone/srtpfilter.h
@@ -51,6 +51,8 @@ extern const std::string& CS_DEFAULT;
extern const std::string CS_AES_CM_128_HMAC_SHA1_80;
// 128-bit AES with 32-bit SHA-1 HMAC.
extern const std::string CS_AES_CM_128_HMAC_SHA1_32;
+// Key is 128 bits and salt is 112 bits == 30 bytes. B64 bloat => 40 bytes.
+extern const int SRTP_MASTER_KEY_BASE64_LEN;
// Class that wraps a libSRTP session. Used internally by SrtpFilter, below.
class SrtpSession {
diff --git a/third_party/libjingle/source/talk/session/phone/videocommon.h b/third_party/libjingle/source/talk/session/phone/videocommon.h
index 1092b5c..230b1ff 100644
--- a/third_party/libjingle/source/talk/session/phone/videocommon.h
+++ b/third_party/libjingle/source/talk/session/phone/videocommon.h
@@ -58,24 +58,17 @@ inline std::string GetFourccName(uint32 fourcc) {
// Some good pages discussing FourCC codes:
// http://developer.apple.com/quicktime/icefloe/dispatch020.html
// http://www.fourcc.org/yuv.php
-enum {
+enum FourCC {
+ // Canonical fourccs used in our code.
FOURCC_I420 = FOURCC('I', '4', '2', '0'),
- FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420
- FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Alias for I420
FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'),
FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'),
- FOURCC_HDYC = FOURCC('H', 'D', 'Y', 'C'),
FOURCC_24BG = FOURCC('2', '4', 'B', 'G'),
- FOURCC_RGB1 = FOURCC('R', 'G', 'B', '1'),
FOURCC_RGBA = FOURCC('R', 'G', 'B', 'A'),
- FOURCC_RGB2 = FOURCC('R', 'G', 'B', '2'),
- FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'),
FOURCC_BGRA = FOURCC('B', 'G', 'R', 'A'),
+ FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'),
FOURCC_MJPG = FOURCC('M', 'J', 'P', 'G'),
FOURCC_JPEG = FOURCC('J', 'P', 'E', 'G'),
- FOURCC_2VUY = FOURCC('2', 'v', 'u', 'y'), // Alias for UYVY
- FOURCC_YUVS = FOURCC('y', 'u', 'v', 's'), // Alias for YUY2
- FOURCC_YUYV = FOURCC('Y', 'U', 'Y', 'V'), // Alias for YUY2
FOURCC_RAW = FOURCC('r', 'a', 'w', ' '),
// Next five are Bayer RGB formats. The four characters define the order of
// the colours in each 2x2 pixel grid, going left-to-right and top-to-bottom.
@@ -83,10 +76,26 @@ enum {
FOURCC_BGGR = FOURCC('B', 'G', 'G', 'R'),
FOURCC_GRBG = FOURCC('G', 'R', 'B', 'G'),
FOURCC_GBRG = FOURCC('G', 'B', 'R', 'G'),
+
+ // Aliases for canonical fourccs, replaced with their canonical equivalents by
+ // CanonicalFourCC().
+ FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420
+ FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Alias for I420
+ FOURCC_YUYV = FOURCC('Y', 'U', 'Y', 'V'), // Alias for YUY2
+ FOURCC_YUVS = FOURCC('y', 'u', 'v', 's'), // Alias for YUY2
+ FOURCC_HDYC = FOURCC('H', 'D', 'Y', 'C'), // Alias for UYVY
+ FOURCC_2VUY = FOURCC('2', 'v', 'u', 'y'), // Alias for UYVY
+ FOURCC_RGB1 = FOURCC('R', 'G', 'B', '1'), // Alias for RGBA
+ FOURCC_RGB2 = FOURCC('R', 'G', 'B', '2'), // Alias for BGRA
FOURCC_BA81 = FOURCC('B', 'A', '8', '1'), // Alias for BGGR
- FOURCC_ANY = 0xFFFFFFFF, // Match any fourcc.
+
+ // Match any fourcc.
+ FOURCC_ANY = 0xFFFFFFFF,
};
+// Converts fourcc aliases into canonical ones.
+uint32 CanonicalFourCC(uint32 fourcc);
+
//////////////////////////////////////////////////////////////////////////////
// Definition of VideoFormat.
//////////////////////////////////////////////////////////////////////////////
diff --git a/third_party/libjingle/source/talk/site_scons/site_tools/talk_noops.pyc b/third_party/libjingle/source/talk/site_scons/site_tools/talk_noops.pyc
deleted file mode 100644
index d25fa59..0000000
--- a/third_party/libjingle/source/talk/site_scons/site_tools/talk_noops.pyc
+++ /dev/null
Binary files differ
diff --git a/third_party/libjingle/source/talk/site_scons/talk.py b/third_party/libjingle/source/talk/site_scons/talk.py
index e5ede4f..b9e93ef 100644
--- a/third_party/libjingle/source/talk/site_scons/talk.py
+++ b/third_party/libjingle/source/talk/site_scons/talk.py
@@ -6,27 +6,42 @@
#
import os
-# Keep a global list of what libraries have a 64 bit version. We use it for
-# replacements when linking a 64 bit dylib or executable.
-libs64 = []
+# Keep a global dictionary of library target params for lookups in
+# ExtendComponent().
+_all_lib_targets = {}
+
+def _GenericLibrary(env, static, **kwargs):
+ """Extends ComponentLibrary to support multiplatform builds
+ of dynamic or static libraries.
+
+ Args:
+ env: The environment object.
+ kwargs: The keyword arguments.
+
+ Returns:
+ See swtoolkit ComponentLibrary
+ """
+ params = CombineDicts(kwargs, {'COMPONENT_STATIC': static})
+ return ExtendComponent(env, 'ComponentLibrary', **params)
+
def Library(env, **kwargs):
- """Extends ComponentLibrary to support multiplatform builds.
+ """Extends ComponentLibrary to support multiplatform builds of static
+ libraries.
Args:
env: The current environment.
kwargs: The keyword arguments.
- """
- params = CombineDicts(kwargs, {'COMPONENT_STATIC': True})
- if params.has_key('also64bit'):
- libs64.append(params['name'])
- return ExtendComponent(env, 'ComponentLibrary', **params)
+ Returns:
+ See swtoolkit ComponentLibrary
+ """
+ return _GenericLibrary(env, True, **kwargs)
def DynamicLibrary(env, **kwargs):
"""Extends ComponentLibrary to support multiplatform builds
- of dynmic libraries. This use COMPONENT_STATIC = false.
+ of dynmic libraries.
Args:
env: The environment object.
@@ -35,8 +50,7 @@ def DynamicLibrary(env, **kwargs):
Returns:
See swtoolkit ComponentLibrary
"""
- params = CombineDicts(kwargs, {'COMPONENT_STATIC': False})
- return ExtendComponent(env, 'ComponentLibrary', **params)
+ return _GenericLibrary(env, False, **kwargs)
def Object(env, **kwargs):
@@ -73,9 +87,9 @@ def Unittest(env, **kwargs):
'ws2_32'
]
common_test_params['lin_libs'] = [
+ 'crypto',
'pthread',
- ':libssl.so.0.9.8',
- ':libcrypto.so.0.9.8',
+ 'ssl',
]
params = CombineDicts(kwargs, common_test_params)
@@ -190,6 +204,7 @@ def AddMediaLibs(env, **kwargs):
elif env.Bit('linux'):
ipp_libdir %= 'v_5_2_linux'
+
AddToDict(kwargs, 'libdirs', [
'$MAIN_DIR/third_party/gips/Libraries/',
ipp_libdir,
@@ -207,6 +222,7 @@ def AddMediaLibs(env, **kwargs):
elif env.Bit('linux'):
gips_lib = 'VoiceEngine_Linux_external_gcc'
+
AddToDict(kwargs, 'libs', [
gips_lib,
'LmiAudioCommon',
@@ -367,6 +383,26 @@ def MergeAndFilterByPlatform(env, params):
return merged
+# Linux can build both 32 and 64 bit on 64 bit host, but 32 bit host can
+# only build 32 bit. For 32 bit debian installer a 32 bit host is required.
+# ChromeOS (linux) ebuild don't support 64 bit and requires 32 bit build only
+# for now.
+# TODO: Detect ChromeOS chroot board for ChromeOS x64 build.
+def Allow64BitCompile(env):
+ return (env.Bit('linux') and env.Bit('platform_arch_64bit') and
+ not env.Bit('linux_chromeos'))
+
+def MergeSettingsFromLibraryDependencies(env, params):
+ if params.has_key('libs'):
+ for lib in params['libs']:
+ if (_all_lib_targets.has_key(lib) and
+ _all_lib_targets[lib].has_key('dependent_target_settings')):
+ params = CombineDicts(
+ params,
+ MergeAndFilterByPlatform(
+ env,
+ _all_lib_targets[lib]['dependent_target_settings']))
+ return params
def ExtendComponent(env, component, **kwargs):
"""A wrapper around a scons builder function that preprocesses and post-
@@ -388,22 +424,27 @@ def ExtendComponent(env, component, **kwargs):
"""
env = env.Clone()
+ # prune parameters intended for other platforms, then merge
+ params = MergeAndFilterByPlatform(env, kwargs)
+
# get the 'target' field
- name = GetEntry(kwargs, 'name')
+ name = GetEntry(params, 'name')
+
+ # save pristine params of lib targets for future reference
+ if 'ComponentLibrary' == component:
+ _all_lib_targets[name] = dict(params)
+
+ # add any dependent target settings from library dependencies
+ params = MergeSettingsFromLibraryDependencies(env, params)
# if this is a signed binary we need to make an unsigned version first
- signed = env.Bit('windows') and GetEntry(kwargs, 'signed')
+ signed = env.Bit('windows') and GetEntry(params, 'signed')
if signed:
name = 'unsigned_' + name
- also64bit = env.Bit('linux') and GetEntry(kwargs, 'also64bit')
-
# add default values
- if GetEntry(kwargs, 'include_talk_media_libs'):
- kwargs = AddMediaLibs(env, **kwargs)
-
- # prune parameters intended for other platforms, then merge
- params = MergeAndFilterByPlatform(env, kwargs)
+ if GetEntry(params, 'include_talk_media_libs'):
+ params = AddMediaLibs(env, **params)
# potentially exit now
srcs = GetEntry(params, 'srcs')
@@ -411,7 +452,7 @@ def ExtendComponent(env, component, **kwargs):
return None
# apply any explicit dependencies
- dependencies = GetEntry(kwargs, 'depends')
+ dependencies = GetEntry(params, 'depends')
if dependencies is not None:
env.Depends(name, dependencies)
@@ -442,7 +483,7 @@ def ExtendComponent(env, component, **kwargs):
env.Prepend(**{var : values})
# workaround for pulse stripping link flag for unknown reason
- if env.Bit('linux'):
+ if Allow64BitCompile(env):
env['SHLINKCOM'] = ('$SHLINK -o $TARGET -m32 $SHLINKFLAGS $SOURCES '
'$_LIBDIRFLAGS $_LIBFLAGS')
env['LINKCOM'] = ('$LINK -o $TARGET -m32 $LINKFLAGS $SOURCES '
@@ -458,7 +499,7 @@ def ExtendComponent(env, component, **kwargs):
node = builder(name, srcs)
# make a parallel 64bit version if requested
- if also64bit:
+ if Allow64BitCompile(env) and GetEntry(params, 'also64bit'):
env_64bit = env.Clone()
env_64bit.FilterOut(CCFLAGS = ['-m32'], LINKFLAGS = ['-m32'])
env_64bit.Prepend(CCFLAGS = ['-m64', '-fPIC'], LINKFLAGS = ['-m64'])
@@ -471,7 +512,8 @@ def ExtendComponent(env, component, **kwargs):
# link 64 bit versions of libraries
libs = []
for lib in env_64bit['LIBS']:
- if lib in set(libs64):
+ if (_all_lib_targets.has_key(lib) and
+ _all_lib_targets[lib].has_key('also64bit')):
libs.append(lib + '64')
else:
libs.append(lib)
@@ -495,7 +537,7 @@ def ExtendComponent(env, component, **kwargs):
target = '$STAGING_DIR/' + target,
)
env.Alias('signed_binaries', signed_node)
- return signed
+ return signed_node
return node
diff --git a/third_party/libjingle/source/talk/site_scons/talk.pyc b/third_party/libjingle/source/talk/site_scons/talk.pyc
deleted file mode 100644
index 308d2e8..0000000
--- a/third_party/libjingle/source/talk/site_scons/talk.pyc
+++ /dev/null
Binary files differ