Revert r7886:7887.
Broke build steps in other code that uses securetunnelsessionclient.cc and others. TBR=tommi@webrtc.org,pthatcher@webrtc.org BUG= Review URL: https://webrtc-codereview.appspot.com/36439004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7890 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
11
talk/examples/call/Info.plist
Normal file
11
talk/examples/call/Info.plist
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.google.call</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>call</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
497
talk/examples/call/call_main.cc
Normal file
497
talk/examples/call/call_main.cc
Normal file
@@ -0,0 +1,497 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/flags.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#ifdef OSX
|
||||
#include "webrtc/base/maccocoasocketserver.h"
|
||||
#endif
|
||||
#include "talk/examples/call/callclient.h"
|
||||
#include "talk/examples/call/console.h"
|
||||
#include "talk/examples/call/mediaenginefactory.h"
|
||||
#include "webrtc/p2p/base/constants.h"
|
||||
#include "talk/session/media/mediasessionclient.h"
|
||||
#include "talk/session/media/srtpfilter.h"
|
||||
#include "webrtc/libjingle/xmpp/xmppauth.h"
|
||||
#include "webrtc/libjingle/xmpp/xmppclientsettings.h"
|
||||
#include "webrtc/libjingle/xmpp/xmpppump.h"
|
||||
#include "webrtc/libjingle/xmpp/xmppsocket.h"
|
||||
#include "webrtc/base/pathutils.h"
|
||||
#include "webrtc/base/ssladapter.h"
|
||||
#include "webrtc/base/stream.h"
|
||||
#include "webrtc/base/win32socketserver.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;
|
||||
|
||||
#ifdef ANDROID
|
||||
static std::vector<cricket::AudioCodec> codecs;
|
||||
static const cricket::AudioCodec ISAC(103, "ISAC", 40000, 16000, 1, 0);
|
||||
|
||||
cricket::MediaEngineInterface *CreateAndroidMediaEngine() {
|
||||
cricket::FakeMediaEngine *engine = new cricket::FakeMediaEngine();
|
||||
|
||||
codecs.push_back(ISAC);
|
||||
engine->SetAudioCodecs(codecs);
|
||||
return engine;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: Move this into Console.
|
||||
void Print(const char* chars) {
|
||||
printf("%s", chars);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
bool GetSecurePolicy(const std::string& in, cricket::SecurePolicy* out) {
|
||||
if (in == "disable") {
|
||||
*out = cricket::SEC_DISABLED;
|
||||
} else if (in == "enable") {
|
||||
*out = cricket::SEC_ENABLED;
|
||||
} else if (in == "require") {
|
||||
*out = cricket::SEC_REQUIRED;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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_string(s, "talk.google.com", "The connection server to use.");
|
||||
DEFINE_string(tls, "require",
|
||||
"Select connection encryption: disable, enable, require.");
|
||||
DEFINE_bool(allowplain, false, "Allow plain authentication.");
|
||||
DEFINE_bool(testserver, false, "Use test server.");
|
||||
DEFINE_string(oauth, "", "OAuth2 access token.");
|
||||
DEFINE_bool(a, false, "Turn on auto accept for incoming calls.");
|
||||
DEFINE_string(signaling, "hybrid",
|
||||
"Initial signaling protocol to use: jingle, gingle, or hybrid.");
|
||||
DEFINE_string(transport, "hybrid",
|
||||
"Initial transport protocol to use: ice, gice, or hybrid.");
|
||||
DEFINE_string(sdes, "enable",
|
||||
"Select SDES media encryption: disable, enable, require.");
|
||||
DEFINE_string(dtls, "disable",
|
||||
"Select DTLS transport encryption: disable, enable, require.");
|
||||
DEFINE_int(portallocator, 0, "Filter out unwanted connection types.");
|
||||
DEFINE_string(pmuc, "groupchat.google.com", "The persistant muc domain.");
|
||||
DEFINE_string(capsnode, "http://code.google.com/p/libjingle/call",
|
||||
"Caps node: A URI identifying the app.");
|
||||
DEFINE_string(capsver, "0.6",
|
||||
"Caps ver: A string identifying the version of the app.");
|
||||
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(render, true, "Renders the video.");
|
||||
DEFINE_string(datachannel, "",
|
||||
"Enable a data channel, and choose the type: rtp or sctp.");
|
||||
DEFINE_bool(d, false, "Turn on debugging.");
|
||||
DEFINE_string(log, "", "Turn on debugging to a file.");
|
||||
DEFINE_bool(debugsrtp, false, "Enable debugging for srtp.");
|
||||
DEFINE_bool(help, false, "Prints this message");
|
||||
DEFINE_bool(multisession, false,
|
||||
"Enable support for multiple sessions in calls.");
|
||||
DEFINE_bool(roster, false,
|
||||
"Enable roster messages printed in console.");
|
||||
|
||||
// parse options
|
||||
rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
|
||||
if (FLAG_help) {
|
||||
rtc::FlagList::Print(NULL, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool auto_accept = FLAG_a;
|
||||
bool debug = FLAG_d;
|
||||
std::string log = FLAG_log;
|
||||
std::string signaling = FLAG_signaling;
|
||||
std::string transport = FLAG_transport;
|
||||
bool test_server = FLAG_testserver;
|
||||
bool allow_plain = FLAG_allowplain;
|
||||
std::string tls = FLAG_tls;
|
||||
std::string oauth_token = FLAG_oauth;
|
||||
int32 portallocator_flags = FLAG_portallocator;
|
||||
std::string pmuc_domain = FLAG_pmuc;
|
||||
std::string server = FLAG_s;
|
||||
std::string sdes = FLAG_sdes;
|
||||
std::string dtls = FLAG_dtls;
|
||||
std::string caps_node = FLAG_capsnode;
|
||||
std::string caps_ver = FLAG_capsver;
|
||||
bool debugsrtp = FLAG_debugsrtp;
|
||||
bool render = FLAG_render;
|
||||
std::string data_channel = FLAG_datachannel;
|
||||
bool multisession_enabled = FLAG_multisession;
|
||||
rtc::SSLIdentity* ssl_identity = NULL;
|
||||
bool show_roster_messages = FLAG_roster;
|
||||
|
||||
// Set up debugging.
|
||||
if (debug) {
|
||||
rtc::LogMessage::LogToDebug(rtc::LS_VERBOSE);
|
||||
}
|
||||
|
||||
if (!log.empty()) {
|
||||
rtc::StreamInterface* stream =
|
||||
rtc::Filesystem::OpenFile(log, "a");
|
||||
if (stream) {
|
||||
rtc::LogMessage::LogToStream(stream, rtc::LS_VERBOSE);
|
||||
} else {
|
||||
Print(("Cannot open debug log " + log + "\n").c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (debugsrtp) {
|
||||
cricket::EnableSrtpDebugging();
|
||||
}
|
||||
|
||||
// Set up the crypto subsystem.
|
||||
rtc::InitializeSSL();
|
||||
|
||||
// Parse username and password, if present.
|
||||
buzz::Jid jid;
|
||||
std::string username;
|
||||
rtc::InsecureCryptStringImpl pass;
|
||||
if (argc > 1) {
|
||||
username = argv[1];
|
||||
if (argc > 2) {
|
||||
pass.password() = argv[2];
|
||||
}
|
||||
}
|
||||
|
||||
if (username.empty()) {
|
||||
Print("JID: ");
|
||||
std::cin >> username;
|
||||
}
|
||||
if (username.find('@') == std::string::npos) {
|
||||
username.append("@localhost");
|
||||
}
|
||||
jid = buzz::Jid(username);
|
||||
if (!jid.IsValid() || jid.node() == "") {
|
||||
Print("Invalid JID. JIDs should be in the form user@domain\n");
|
||||
return 1;
|
||||
}
|
||||
if (pass.password().empty() && !test_server && oauth_token.empty()) {
|
||||
Console::SetEcho(false);
|
||||
Print("Password: ");
|
||||
std::cin >> pass.password();
|
||||
Console::SetEcho(true);
|
||||
Print("\n");
|
||||
}
|
||||
|
||||
// Decide on the connection settings.
|
||||
buzz::XmppClientSettings xcs;
|
||||
xcs.set_user(jid.node());
|
||||
xcs.set_resource("call");
|
||||
xcs.set_host(jid.domain());
|
||||
xcs.set_allow_plain(allow_plain);
|
||||
|
||||
if (tls == "disable") {
|
||||
xcs.set_use_tls(buzz::TLS_DISABLED);
|
||||
} else if (tls == "enable") {
|
||||
xcs.set_use_tls(buzz::TLS_ENABLED);
|
||||
} else if (tls == "require") {
|
||||
xcs.set_use_tls(buzz::TLS_REQUIRED);
|
||||
} else {
|
||||
Print("Invalid TLS option, must be enable, disable, or require.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (test_server) {
|
||||
pass.password() = jid.node();
|
||||
xcs.set_allow_plain(true);
|
||||
xcs.set_use_tls(buzz::TLS_DISABLED);
|
||||
xcs.set_test_server_domain("google.com");
|
||||
}
|
||||
xcs.set_pass(rtc::CryptString(pass));
|
||||
if (!oauth_token.empty()) {
|
||||
xcs.set_auth_token(buzz::AUTH_MECHANISM_OAUTH2, oauth_token);
|
||||
}
|
||||
|
||||
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(rtc::SocketAddress(host, port));
|
||||
|
||||
// Decide on the signaling and crypto settings.
|
||||
cricket::SignalingProtocol signaling_protocol = cricket::PROTOCOL_HYBRID;
|
||||
if (signaling == "jingle") {
|
||||
signaling_protocol = cricket::PROTOCOL_JINGLE;
|
||||
} else if (signaling == "gingle") {
|
||||
signaling_protocol = cricket::PROTOCOL_GINGLE;
|
||||
} else if (signaling == "hybrid") {
|
||||
signaling_protocol = cricket::PROTOCOL_HYBRID;
|
||||
} else {
|
||||
Print("Invalid signaling protocol. Must be jingle, gingle, or hybrid.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cricket::TransportProtocol transport_protocol = cricket::ICEPROTO_HYBRID;
|
||||
if (transport == "ice") {
|
||||
transport_protocol = cricket::ICEPROTO_RFC5245;
|
||||
} else if (transport == "gice") {
|
||||
transport_protocol = cricket::ICEPROTO_GOOGLE;
|
||||
} else if (transport == "hybrid") {
|
||||
transport_protocol = cricket::ICEPROTO_HYBRID;
|
||||
} else {
|
||||
Print("Invalid transport protocol. Must be ice, gice, or hybrid.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cricket::DataChannelType data_channel_type = cricket::DCT_NONE;
|
||||
if (data_channel == "rtp") {
|
||||
data_channel_type = cricket::DCT_RTP;
|
||||
} else if (data_channel == "sctp") {
|
||||
data_channel_type = cricket::DCT_SCTP;
|
||||
} else if (!data_channel.empty()) {
|
||||
Print("Invalid data channel type. Must be rtp or sctp.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cricket::SecurePolicy sdes_policy, dtls_policy;
|
||||
if (!GetSecurePolicy(sdes, &sdes_policy)) {
|
||||
Print("Invalid SDES policy. Must be enable, disable, or require.\n");
|
||||
return 1;
|
||||
}
|
||||
if (!GetSecurePolicy(dtls, &dtls_policy)) {
|
||||
Print("Invalid DTLS policy. Must be enable, disable, or require.\n");
|
||||
return 1;
|
||||
}
|
||||
if (dtls_policy != cricket::SEC_DISABLED) {
|
||||
ssl_identity = rtc::SSLIdentity::Generate(jid.Str());
|
||||
if (!ssl_identity) {
|
||||
Print("Failed to generate identity for DTLS.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
MediaEngineFactory::SetCreateFunction(&CreateAndroidMediaEngine);
|
||||
#endif
|
||||
|
||||
#if WIN32
|
||||
// Need to pump messages on our main thread on Windows.
|
||||
rtc::Win32Thread w32_thread;
|
||||
rtc::ThreadManager::Instance()->SetCurrentThread(&w32_thread);
|
||||
#endif
|
||||
rtc::Thread* main_thread = rtc::Thread::Current();
|
||||
#ifdef OSX
|
||||
rtc::MacCocoaSocketServer ss;
|
||||
rtc::SocketServerScope ss_scope(&ss);
|
||||
#endif
|
||||
|
||||
buzz::XmppPump pump;
|
||||
CallClient *client = new CallClient(pump.client(), caps_node, caps_ver);
|
||||
|
||||
if (FLAG_voiceinput || FLAG_voiceoutput ||
|
||||
FLAG_videoinput || FLAG_videooutput) {
|
||||
// If any dump file is specified, we use a FileMediaEngine.
|
||||
cricket::MediaEngineInterface* engine =
|
||||
MediaEngineFactory::CreateFileMediaEngine(
|
||||
FLAG_voiceinput, FLAG_voiceoutput,
|
||||
FLAG_videoinput, FLAG_videooutput);
|
||||
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);
|
||||
client->SetAllowLocalIps(true);
|
||||
client->SetSignalingProtocol(signaling_protocol);
|
||||
client->SetTransportProtocol(transport_protocol);
|
||||
client->SetSecurePolicy(sdes_policy, dtls_policy);
|
||||
client->SetSslIdentity(ssl_identity);
|
||||
client->SetRender(render);
|
||||
client->SetDataChannelType(data_channel_type);
|
||||
client->SetMultiSessionEnabled(multisession_enabled);
|
||||
client->SetShowRosterMessages(show_roster_messages);
|
||||
console->Start();
|
||||
|
||||
if (debug) {
|
||||
pump.client()->SignalLogInput.connect(&debug_log_, &DebugLog::Input);
|
||||
pump.client()->SignalLogOutput.connect(&debug_log_, &DebugLog::Output);
|
||||
}
|
||||
|
||||
Print(("Logging in to " + server + " as " + jid.Str() + "\n").c_str());
|
||||
pump.DoLogin(xcs, new buzz::XmppSocket(buzz::TLS_REQUIRED), new XmppAuth());
|
||||
main_thread->Run();
|
||||
pump.DoDisconnect();
|
||||
|
||||
console->Stop();
|
||||
delete console;
|
||||
delete client;
|
||||
|
||||
return 0;
|
||||
}
|
37
talk/examples/call/call_unittest.cc
Normal file
37
talk/examples/call/call_unittest.cc
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2008, 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.
|
||||
*/
|
||||
|
||||
// Main function for all unit tests in talk/examples/call
|
||||
|
||||
#include "testing/base/public/gunit.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
rtc::LogMessage::LogToDebug(rtc::LogMessage::NO_LOGGING);
|
||||
testing::ParseGUnitFlags(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
1616
talk/examples/call/callclient.cc
Normal file
1616
talk/examples/call/callclient.cc
Normal file
File diff suppressed because it is too large
Load Diff
352
talk/examples/call/callclient.h
Normal file
352
talk/examples/call/callclient.h
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TALK_EXAMPLES_CALL_CALLCLIENT_H_
|
||||
#define TALK_EXAMPLES_CALL_CALLCLIENT_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "talk/examples/call/console.h"
|
||||
#include "talk/media/base/mediachannel.h"
|
||||
#include "webrtc/p2p/base/session.h"
|
||||
#include "talk/session/media/mediamessages.h"
|
||||
#include "talk/session/media/mediasessionclient.h"
|
||||
#include "webrtc/libjingle/xmpp/hangoutpubsubclient.h"
|
||||
#include "webrtc/libjingle/xmpp/presencestatus.h"
|
||||
#include "webrtc/libjingle/xmpp/xmppclient.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/base/sslidentity.h"
|
||||
|
||||
namespace buzz {
|
||||
class PresencePushTask;
|
||||
class PresenceOutTask;
|
||||
class MucInviteRecvTask;
|
||||
class MucInviteSendTask;
|
||||
class FriendInviteSendTask;
|
||||
class DiscoInfoQueryTask;
|
||||
class Muc;
|
||||
class PresenceStatus;
|
||||
class IqTask;
|
||||
class MucRoomConfigTask;
|
||||
class MucRoomLookupTask;
|
||||
class MucPresenceStatus;
|
||||
class XmlElement;
|
||||
class HangoutPubSubClient;
|
||||
struct AvailableMediaEntry;
|
||||
struct MucRoomInfo;
|
||||
} // namespace buzz
|
||||
|
||||
namespace rtc {
|
||||
class Thread;
|
||||
class NetworkManager;
|
||||
} // namespace rtc
|
||||
|
||||
namespace cricket {
|
||||
class PortAllocator;
|
||||
class MediaEngineInterface;
|
||||
class MediaSessionClient;
|
||||
class Call;
|
||||
class SessionManagerTask;
|
||||
struct CallOptions;
|
||||
struct MediaStreams;
|
||||
struct StreamParams;
|
||||
} // namespace cricket
|
||||
|
||||
struct RosterItem {
|
||||
buzz::Jid jid;
|
||||
buzz::PresenceStatus::Show show;
|
||||
std::string status;
|
||||
};
|
||||
|
||||
struct StaticRenderedView {
|
||||
StaticRenderedView(const cricket::StaticVideoView& view,
|
||||
cricket::VideoRenderer* renderer) :
|
||||
view(view),
|
||||
renderer(renderer) {
|
||||
}
|
||||
|
||||
cricket::StaticVideoView view;
|
||||
cricket::VideoRenderer* renderer;
|
||||
};
|
||||
|
||||
// Maintain a mapping of (session, ssrc) to rendered view.
|
||||
typedef std::map<std::pair<cricket::Session*, uint32>,
|
||||
StaticRenderedView> StaticRenderedViews;
|
||||
|
||||
class CallClient: public sigslot::has_slots<> {
|
||||
public:
|
||||
CallClient(buzz::XmppClient* xmpp_client,
|
||||
const std::string& caps_node,
|
||||
const std::string& version);
|
||||
~CallClient();
|
||||
|
||||
cricket::MediaSessionClient* media_client() const { return media_client_; }
|
||||
void SetMediaEngine(cricket::MediaEngineInterface* media_engine) {
|
||||
media_engine_ = media_engine;
|
||||
}
|
||||
void SetAutoAccept(bool auto_accept) {
|
||||
auto_accept_ = auto_accept;
|
||||
}
|
||||
void SetPmucDomain(const std::string &pmuc_domain) {
|
||||
pmuc_domain_ = pmuc_domain;
|
||||
}
|
||||
void SetRender(bool render) {
|
||||
render_ = render;
|
||||
}
|
||||
void SetDataChannelType(cricket::DataChannelType data_channel_type) {
|
||||
data_channel_type_ = data_channel_type;
|
||||
}
|
||||
void SetMultiSessionEnabled(bool multisession_enabled) {
|
||||
multisession_enabled_ = multisession_enabled;
|
||||
}
|
||||
void SetConsole(Console *console) {
|
||||
console_ = console;
|
||||
}
|
||||
void SetPriority(int priority) {
|
||||
my_status_.set_priority(priority);
|
||||
}
|
||||
void SendStatus() {
|
||||
SendStatus(my_status_);
|
||||
}
|
||||
void SendStatus(const buzz::PresenceStatus& status);
|
||||
|
||||
void ParseLine(const std::string &str);
|
||||
|
||||
void SendChat(const std::string& to, const std::string msg);
|
||||
void SendData(const std::string& stream_name,
|
||||
const std::string& text);
|
||||
void InviteFriend(const std::string& user);
|
||||
void JoinMuc(const buzz::Jid& room_jid);
|
||||
void JoinMuc(const std::string& room_jid_str);
|
||||
void LookupAndJoinMuc(const std::string& room_name);
|
||||
void InviteToMuc(const std::string& user, const std::string& room);
|
||||
bool InMuc();
|
||||
const buzz::Jid* FirstMucJid();
|
||||
void LeaveMuc(const std::string& room);
|
||||
void SetNick(const std::string& muc_nick);
|
||||
void SetPortAllocatorFlags(uint32 flags) { portallocator_flags_ = flags; }
|
||||
void SetAllowLocalIps(bool allow_local_ips) {
|
||||
allow_local_ips_ = allow_local_ips;
|
||||
}
|
||||
|
||||
void SetSignalingProtocol(cricket::SignalingProtocol protocol) {
|
||||
signaling_protocol_ = protocol;
|
||||
}
|
||||
void SetTransportProtocol(cricket::TransportProtocol protocol) {
|
||||
transport_protocol_ = protocol;
|
||||
}
|
||||
void SetSecurePolicy(cricket::SecurePolicy sdes_policy,
|
||||
cricket::SecurePolicy dtls_policy) {
|
||||
sdes_policy_ = sdes_policy;
|
||||
dtls_policy_ = dtls_policy;
|
||||
}
|
||||
void SetSslIdentity(rtc::SSLIdentity* identity) {
|
||||
ssl_identity_.reset(identity);
|
||||
}
|
||||
|
||||
typedef std::map<buzz::Jid, buzz::Muc*> MucMap;
|
||||
|
||||
const MucMap& mucs() const {
|
||||
return mucs_;
|
||||
}
|
||||
|
||||
void SetShowRosterMessages(bool show_roster_messages) {
|
||||
show_roster_messages_ = show_roster_messages;
|
||||
}
|
||||
|
||||
private:
|
||||
void AddStream(uint32 audio_src_id, uint32 video_src_id);
|
||||
void RemoveStream(uint32 audio_src_id, uint32 video_src_id);
|
||||
void OnStateChange(buzz::XmppEngine::State state);
|
||||
|
||||
void InitMedia();
|
||||
void InitPresence();
|
||||
void StartXmppPing();
|
||||
void OnPingTimeout();
|
||||
void OnRequestSignaling();
|
||||
void OnSessionCreate(cricket::Session* session, bool initiate);
|
||||
void OnCallCreate(cricket::Call* call);
|
||||
void OnCallDestroy(cricket::Call* call);
|
||||
void OnSessionState(cricket::Call* call,
|
||||
cricket::Session* session,
|
||||
cricket::Session::State state);
|
||||
void OnStatusUpdate(const buzz::PresenceStatus& status);
|
||||
void OnMucInviteReceived(const buzz::Jid& inviter, const buzz::Jid& room,
|
||||
const std::vector<buzz::AvailableMediaEntry>& avail);
|
||||
void OnMucJoined(const buzz::Jid& endpoint);
|
||||
void OnMucStatusUpdate(const buzz::Jid& jid,
|
||||
const buzz::MucPresenceStatus& status);
|
||||
void OnMucLeft(const buzz::Jid& endpoint, int error);
|
||||
void OnPresenterStateChange(const std::string& nick,
|
||||
bool was_presenting, bool is_presenting);
|
||||
void OnAudioMuteStateChange(const std::string& nick,
|
||||
bool was_muted, bool is_muted);
|
||||
void OnRecordingStateChange(const std::string& nick,
|
||||
bool was_recording, bool is_recording);
|
||||
void OnRemoteMuted(const std::string& mutee_nick,
|
||||
const std::string& muter_nick,
|
||||
bool should_mute_locally);
|
||||
void OnMediaBlocked(const std::string& blockee_nick,
|
||||
const std::string& blocker_nick);
|
||||
void OnHangoutRequestError(const std::string& node,
|
||||
const buzz::XmlElement* stanza);
|
||||
void OnHangoutPublishAudioMuteError(const std::string& task_id,
|
||||
const buzz::XmlElement* stanza);
|
||||
void OnHangoutPublishPresenterError(const std::string& task_id,
|
||||
const buzz::XmlElement* stanza);
|
||||
void OnHangoutPublishRecordingError(const std::string& task_id,
|
||||
const buzz::XmlElement* stanza);
|
||||
void OnHangoutRemoteMuteError(const std::string& task_id,
|
||||
const std::string& mutee_nick,
|
||||
const buzz::XmlElement* stanza);
|
||||
void OnDevicesChange();
|
||||
void OnMediaStreamsUpdate(cricket::Call* call,
|
||||
cricket::Session* session,
|
||||
const cricket::MediaStreams& added,
|
||||
const cricket::MediaStreams& removed);
|
||||
void OnSpeakerChanged(cricket::Call* call,
|
||||
cricket::Session* session,
|
||||
const cricket::StreamParams& speaker_stream);
|
||||
void OnRoomLookupResponse(buzz::MucRoomLookupTask* task,
|
||||
const buzz::MucRoomInfo& room_info);
|
||||
void OnRoomLookupError(buzz::IqTask* task,
|
||||
const buzz::XmlElement* stanza);
|
||||
void OnRoomConfigResult(buzz::MucRoomConfigTask* task);
|
||||
void OnRoomConfigError(buzz::IqTask* task,
|
||||
const buzz::XmlElement* stanza);
|
||||
void OnDataReceived(cricket::Call*,
|
||||
const cricket::ReceiveDataParams& params,
|
||||
const rtc::Buffer& payload);
|
||||
buzz::Jid GenerateRandomMucJid();
|
||||
|
||||
// Depending on |enable|, render (or don't) all the streams in |session|.
|
||||
void RenderAllStreams(cricket::Call* call,
|
||||
cricket::Session* session,
|
||||
bool enable);
|
||||
|
||||
// Depending on |enable|, render (or don't) the streams in |video_streams|.
|
||||
void RenderStreams(cricket::Call* call,
|
||||
cricket::Session* session,
|
||||
const std::vector<cricket::StreamParams>& video_streams,
|
||||
bool enable);
|
||||
|
||||
// Depending on |enable|, render (or don't) the supplied |stream|.
|
||||
void RenderStream(cricket::Call* call,
|
||||
cricket::Session* session,
|
||||
const cricket::StreamParams& stream,
|
||||
bool enable);
|
||||
void AddStaticRenderedView(
|
||||
cricket::Session* session,
|
||||
uint32 ssrc, int width, int height, int framerate,
|
||||
int x_offset, int y_offset);
|
||||
bool RemoveStaticRenderedView(uint32 ssrc);
|
||||
void RemoveCallsStaticRenderedViews(cricket::Call* call);
|
||||
void SendViewRequest(cricket::Call* call, cricket::Session* session);
|
||||
bool SelectFirstDesktopScreencastId(cricket::ScreencastId* screencastid);
|
||||
|
||||
static const std::string strerror(buzz::XmppEngine::Error err);
|
||||
|
||||
void PrintRoster();
|
||||
bool FindJid(const std::string& name,
|
||||
buzz::Jid* found_jid,
|
||||
cricket::CallOptions* options);
|
||||
bool PlaceCall(const std::string& name, cricket::CallOptions options);
|
||||
bool InitiateAdditionalSession(const std::string& name,
|
||||
cricket::CallOptions options);
|
||||
void TerminateAndRemoveSession(cricket::Call* call, const std::string& id);
|
||||
void PrintCalls();
|
||||
void SwitchToCall(uint32 call_id);
|
||||
void Accept(const cricket::CallOptions& options);
|
||||
void Reject();
|
||||
void Quit();
|
||||
|
||||
void GetDevices();
|
||||
void PrintDevices(const std::vector<std::string>& names);
|
||||
|
||||
void SetVolume(const std::string& level);
|
||||
|
||||
cricket::Session* GetFirstSession() { return sessions_[call_->id()][0]; }
|
||||
void AddSession(cricket::Session* session) {
|
||||
sessions_[call_->id()].push_back(session);
|
||||
}
|
||||
|
||||
void PrintStats() const;
|
||||
void SetupAcceptedCall();
|
||||
|
||||
typedef std::map<std::string, RosterItem> RosterMap;
|
||||
|
||||
Console *console_;
|
||||
buzz::XmppClient* xmpp_client_;
|
||||
rtc::Thread* worker_thread_;
|
||||
rtc::NetworkManager* network_manager_;
|
||||
cricket::PortAllocator* port_allocator_;
|
||||
cricket::SessionManager* session_manager_;
|
||||
cricket::SessionManagerTask* session_manager_task_;
|
||||
cricket::MediaEngineInterface* media_engine_;
|
||||
cricket::DataEngineInterface* data_engine_;
|
||||
cricket::MediaSessionClient* media_client_;
|
||||
MucMap mucs_;
|
||||
|
||||
cricket::Call* call_;
|
||||
typedef std::map<uint32, std::vector<cricket::Session *> > SessionMap;
|
||||
SessionMap sessions_;
|
||||
|
||||
buzz::HangoutPubSubClient* hangout_pubsub_client_;
|
||||
bool incoming_call_;
|
||||
bool auto_accept_;
|
||||
std::string pmuc_domain_;
|
||||
bool render_;
|
||||
cricket::DataChannelType data_channel_type_;
|
||||
bool multisession_enabled_;
|
||||
cricket::VideoRenderer* local_renderer_;
|
||||
StaticRenderedViews static_rendered_views_;
|
||||
uint32 static_views_accumulated_count_;
|
||||
uint32 screencast_ssrc_;
|
||||
|
||||
buzz::PresenceStatus my_status_;
|
||||
buzz::PresencePushTask* presence_push_;
|
||||
buzz::PresenceOutTask* presence_out_;
|
||||
buzz::MucInviteRecvTask* muc_invite_recv_;
|
||||
buzz::MucInviteSendTask* muc_invite_send_;
|
||||
buzz::FriendInviteSendTask* friend_invite_send_;
|
||||
RosterMap* roster_;
|
||||
uint32 portallocator_flags_;
|
||||
|
||||
bool allow_local_ips_;
|
||||
cricket::SignalingProtocol signaling_protocol_;
|
||||
cricket::TransportProtocol transport_protocol_;
|
||||
cricket::SecurePolicy sdes_policy_;
|
||||
cricket::SecurePolicy dtls_policy_;
|
||||
rtc::scoped_ptr<rtc::SSLIdentity> ssl_identity_;
|
||||
std::string last_sent_to_;
|
||||
|
||||
bool show_roster_messages_;
|
||||
};
|
||||
|
||||
#endif // TALK_EXAMPLES_CALL_CALLCLIENT_H_
|
47
talk/examples/call/callclient_unittest.cc
Normal file
47
talk/examples/call/callclient_unittest.cc
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2008, 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.
|
||||
*/
|
||||
|
||||
// Unit tests for CallClient
|
||||
|
||||
#include "talk/examples/call/callclient.h"
|
||||
#include "talk/media/base/filemediaengine.h"
|
||||
#include "talk/media/base/mediaengine.h"
|
||||
#include "webrtc/libjingle/xmpp/xmppthread.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
|
||||
TEST(CallClientTest, CreateCallClientWithDefaultMediaEngine) {
|
||||
buzz::XmppPump pump;
|
||||
CallClient *client = new CallClient(pump.client(), "app", "version");
|
||||
delete client;
|
||||
}
|
||||
|
||||
TEST(CallClientTest, CreateCallClientWithFileMediaEngine) {
|
||||
buzz::XmppPump pump;
|
||||
CallClient *client = new CallClient(pump.client(), "app", "version");
|
||||
client->SetMediaEngine(new cricket::FileMediaEngine);
|
||||
delete client;
|
||||
}
|
169
talk/examples/call/console.cc
Normal file
169
talk/examples/call/console.cc
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef POSIX
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#endif // POSIX
|
||||
|
||||
#include "talk/examples/call/callclient.h"
|
||||
#include "talk/examples/call/console.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/messagequeue.h"
|
||||
#include "webrtc/base/stringutils.h"
|
||||
|
||||
#ifdef POSIX
|
||||
static void DoNothing(int unused) {}
|
||||
#endif
|
||||
|
||||
Console::Console(rtc::Thread *thread, CallClient *client) :
|
||||
client_(client),
|
||||
client_thread_(thread),
|
||||
stopped_(false) {}
|
||||
|
||||
Console::~Console() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
void Console::Start() {
|
||||
if (stopped_) {
|
||||
// stdin was closed in Stop(), so we can't restart.
|
||||
LOG(LS_ERROR) << "Cannot re-start";
|
||||
return;
|
||||
}
|
||||
if (console_thread_) {
|
||||
LOG(LS_WARNING) << "Already started";
|
||||
return;
|
||||
}
|
||||
console_thread_.reset(new rtc::Thread());
|
||||
console_thread_->Start();
|
||||
console_thread_->Post(this, MSG_START);
|
||||
}
|
||||
|
||||
void Console::Stop() {
|
||||
if (console_thread_) {
|
||||
#ifdef WIN32
|
||||
CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
|
||||
#else
|
||||
close(fileno(stdin));
|
||||
// This forces the read() in fgets() to return with errno = EINTR. fgets()
|
||||
// will retry the read() and fail, thus returning.
|
||||
pthread_kill(console_thread_->GetPThread(), SIGUSR1);
|
||||
#endif
|
||||
console_thread_->Stop();
|
||||
console_thread_.reset();
|
||||
stopped_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Console::SetEcho(bool on) {
|
||||
#ifdef WIN32
|
||||
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
if ((hIn == INVALID_HANDLE_VALUE) || (hIn == NULL))
|
||||
return;
|
||||
|
||||
DWORD mode;
|
||||
if (!GetConsoleMode(hIn, &mode))
|
||||
return;
|
||||
|
||||
if (on) {
|
||||
mode = mode | ENABLE_ECHO_INPUT;
|
||||
} else {
|
||||
mode = mode & ~ENABLE_ECHO_INPUT;
|
||||
}
|
||||
|
||||
SetConsoleMode(hIn, mode);
|
||||
#else
|
||||
const int fd = fileno(stdin);
|
||||
if (fd == -1)
|
||||
return;
|
||||
|
||||
struct termios tcflags;
|
||||
if (tcgetattr(fd, &tcflags) == -1)
|
||||
return;
|
||||
|
||||
if (on) {
|
||||
tcflags.c_lflag |= ECHO;
|
||||
} else {
|
||||
tcflags.c_lflag &= ~ECHO;
|
||||
}
|
||||
|
||||
tcsetattr(fd, TCSANOW, &tcflags);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Console::PrintLine(const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
|
||||
char buf[4096];
|
||||
int size = vsnprintf(buf, sizeof(buf), format, ap);
|
||||
assert(size >= 0);
|
||||
assert(size < static_cast<int>(sizeof(buf)));
|
||||
buf[size] = '\0';
|
||||
printf("%s\n", buf);
|
||||
fflush(stdout);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Console::RunConsole() {
|
||||
char input_buffer[128];
|
||||
while (fgets(input_buffer, sizeof(input_buffer), stdin) != NULL) {
|
||||
client_thread_->Post(this, MSG_INPUT,
|
||||
new rtc::TypedMessageData<std::string>(input_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
void Console::OnMessage(rtc::Message *msg) {
|
||||
switch (msg->message_id) {
|
||||
case MSG_START:
|
||||
#ifdef POSIX
|
||||
// Install a no-op signal so that we can abort RunConsole() by raising
|
||||
// SIGUSR1.
|
||||
struct sigaction act;
|
||||
act.sa_handler = &DoNothing;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
if (sigaction(SIGUSR1, &act, NULL) < 0) {
|
||||
LOG(LS_WARNING) << "Can't install signal";
|
||||
}
|
||||
#endif
|
||||
RunConsole();
|
||||
break;
|
||||
case MSG_INPUT:
|
||||
rtc::TypedMessageData<std::string> *data =
|
||||
static_cast<rtc::TypedMessageData<std::string>*>(msg->pdata);
|
||||
client_->ParseLine(data->data());
|
||||
break;
|
||||
}
|
||||
}
|
70
talk/examples/call/console.h
Normal file
70
talk/examples/call/console.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TALK_EXAMPLES_CALL_CONSOLE_H_
|
||||
#define TALK_EXAMPLES_CALL_CONSOLE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "webrtc/base/messagequeue.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/base/thread.h"
|
||||
|
||||
class CallClient;
|
||||
|
||||
class Console : public rtc::MessageHandler {
|
||||
public:
|
||||
Console(rtc::Thread *thread, CallClient *client);
|
||||
~Console();
|
||||
|
||||
// Starts reading lines from the console and giving them to the CallClient.
|
||||
void Start();
|
||||
// Stops reading lines. Cannot be restarted.
|
||||
void Stop();
|
||||
|
||||
virtual void OnMessage(rtc::Message *msg);
|
||||
|
||||
void PrintLine(const char* format, ...);
|
||||
|
||||
static void SetEcho(bool on);
|
||||
|
||||
private:
|
||||
enum {
|
||||
MSG_START,
|
||||
MSG_INPUT,
|
||||
};
|
||||
|
||||
void RunConsole();
|
||||
void ParseLine(std::string &str);
|
||||
|
||||
CallClient *client_;
|
||||
rtc::Thread *client_thread_;
|
||||
rtc::scoped_ptr<rtc::Thread> console_thread_;
|
||||
bool stopped_;
|
||||
};
|
||||
|
||||
#endif // TALK_EXAMPLES_CALL_CONSOLE_H_
|
76
talk/examples/call/friendinvitesendtask.cc
Normal file
76
talk/examples/call/friendinvitesendtask.cc
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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 "talk/examples/call/friendinvitesendtask.h"
|
||||
#include "webrtc/libjingle/xmpp/constants.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
XmppReturnStatus
|
||||
FriendInviteSendTask::Send(const Jid& user) {
|
||||
if (GetState() != STATE_INIT && GetState() != STATE_START)
|
||||
return XMPP_RETURN_BADSTATE;
|
||||
|
||||
// Need to first add to roster, then subscribe to presence.
|
||||
XmlElement* iq = new XmlElement(QN_IQ);
|
||||
iq->AddAttr(QN_TYPE, STR_SET);
|
||||
XmlElement* query = new XmlElement(QN_ROSTER_QUERY);
|
||||
XmlElement* item = new XmlElement(QN_ROSTER_ITEM);
|
||||
item->AddAttr(QN_JID, user.Str());
|
||||
item->AddAttr(QN_NAME, user.node());
|
||||
query->AddElement(item);
|
||||
iq->AddElement(query);
|
||||
QueueStanza(iq);
|
||||
|
||||
// Subscribe to presence
|
||||
XmlElement* presence = new XmlElement(QN_PRESENCE);
|
||||
presence->AddAttr(QN_TO, user.Str());
|
||||
presence->AddAttr(QN_TYPE, STR_SUBSCRIBE);
|
||||
XmlElement* invitation = new XmlElement(QN_INVITATION);
|
||||
invitation->AddAttr(QN_INVITE_MESSAGE,
|
||||
"I've been using Google Talk and thought you might like to try it out. "
|
||||
"We can use it to call each other for free over the internet. Here's an "
|
||||
"invitation to download Google Talk. Give it a try!");
|
||||
presence->AddElement(invitation);
|
||||
QueueStanza(presence);
|
||||
|
||||
return XMPP_RETURN_OK;
|
||||
}
|
||||
|
||||
int
|
||||
FriendInviteSendTask::ProcessStart() {
|
||||
const XmlElement* stanza = NextStanza();
|
||||
if (stanza == NULL)
|
||||
return STATE_BLOCKED;
|
||||
|
||||
if (SendStanza(stanza) != XMPP_RETURN_OK)
|
||||
return STATE_ERROR;
|
||||
|
||||
return STATE_START;
|
||||
}
|
||||
|
||||
}
|
49
talk/examples/call/friendinvitesendtask.h
Normal file
49
talk/examples/call/friendinvitesendtask.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FRIENDINVITESENDTASK_H_
|
||||
#define _FRIENDINVITESENDTASK_H_
|
||||
|
||||
#include "webrtc/libjingle/xmpp/xmppengine.h"
|
||||
#include "webrtc/libjingle/xmpp/xmpptask.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class FriendInviteSendTask : public XmppTask {
|
||||
public:
|
||||
explicit FriendInviteSendTask(XmppTaskParentInterface* parent)
|
||||
: XmppTask(parent) {}
|
||||
virtual ~FriendInviteSendTask() {}
|
||||
|
||||
XmppReturnStatus Send(const Jid& user);
|
||||
|
||||
virtual int ProcessStart();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
81
talk/examples/call/mediaenginefactory.cc
Normal file
81
talk/examples/call/mediaenginefactory.cc
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// libjingle
|
||||
// Copyright 2004--2007, 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 "talk/examples/call/mediaenginefactory.h"
|
||||
|
||||
#include "talk/media/base/fakemediaengine.h"
|
||||
#include "talk/media/base/filemediaengine.h"
|
||||
#include "talk/media/base/mediaengine.h"
|
||||
#include "webrtc/base/stringutils.h"
|
||||
|
||||
std::vector<cricket::AudioCodec> RequiredAudioCodecs() {
|
||||
std::vector<cricket::AudioCodec> audio_codecs;
|
||||
audio_codecs.push_back(
|
||||
cricket::AudioCodec(9, "G722", 16000, 0, 1, 0));
|
||||
audio_codecs.push_back(
|
||||
cricket::AudioCodec(0, "PCMU", 8000, 0, 1, 0));
|
||||
audio_codecs.push_back(
|
||||
cricket::AudioCodec(13, "CN", 8000, 0, 1, 0));
|
||||
audio_codecs.push_back(
|
||||
cricket::AudioCodec(105, "CN", 16000, 0, 1, 0));
|
||||
return audio_codecs;
|
||||
}
|
||||
|
||||
std::vector<cricket::VideoCodec> RequiredVideoCodecs() {
|
||||
std::vector<cricket::VideoCodec> video_codecs;
|
||||
video_codecs.push_back(
|
||||
cricket::VideoCodec(97, "H264", 320, 240, 30, 0));
|
||||
video_codecs.push_back(
|
||||
cricket::VideoCodec(99, "H264-SVC", 640, 360, 30, 0));
|
||||
return video_codecs;
|
||||
}
|
||||
|
||||
cricket::MediaEngineInterface* MediaEngineFactory::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.
|
||||
file_media_engine->set_voice_codecs(RequiredAudioCodecs());
|
||||
file_media_engine->set_video_codecs(RequiredVideoCodecs());
|
||||
|
||||
return file_media_engine;
|
||||
}
|
40
talk/examples/call/mediaenginefactory.h
Normal file
40
talk/examples/call/mediaenginefactory.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2011, 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_EXAMPLES_CALL_MEDIAENGINEFACTORY_H_
|
||||
#define TALK_EXAMPLES_CALL_MEDIAENGINEFACTORY_H_
|
||||
|
||||
#include "talk/media/base/mediaengine.h"
|
||||
|
||||
class MediaEngineFactory {
|
||||
public:
|
||||
static cricket::MediaEngineInterface* CreateFileMediaEngine(
|
||||
const char* voice_in, const char* voice_out,
|
||||
const char* video_in, const char* video_out);
|
||||
};
|
||||
|
||||
#endif // TALK_EXAMPLES_CALL_MEDIAENGINEFACTORY_H_
|
66
talk/examples/call/muc.h
Normal file
66
talk/examples/call/muc.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _MUC_H_
|
||||
#define _MUC_H_
|
||||
|
||||
#include <map>
|
||||
#include "webrtc/libjingle/xmpp/jid.h"
|
||||
#include "webrtc/libjingle/xmpp/presencestatus.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class Muc {
|
||||
public:
|
||||
Muc(const Jid& jid, const std::string& nick) : state_(MUC_JOINING),
|
||||
jid_(jid), local_jid_(Jid(jid.Str() + "/" + nick)) {}
|
||||
~Muc() {};
|
||||
|
||||
enum State { MUC_JOINING, MUC_JOINED, MUC_LEAVING };
|
||||
State state() const { return state_; }
|
||||
void set_state(State state) { state_ = state; }
|
||||
const Jid & jid() const { return jid_; }
|
||||
const Jid & local_jid() const { return local_jid_; }
|
||||
|
||||
typedef std::map<std::string, MucPresenceStatus> MemberMap;
|
||||
|
||||
// All the intelligence about how to manage the members is in
|
||||
// CallClient, so we completely expose the map.
|
||||
MemberMap& members() {
|
||||
return members_;
|
||||
}
|
||||
|
||||
private:
|
||||
State state_;
|
||||
Jid jid_;
|
||||
Jid local_jid_;
|
||||
MemberMap members_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
124
talk/examples/call/mucinviterecvtask.cc
Normal file
124
talk/examples/call/mucinviterecvtask.cc
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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 "talk/examples/call/mucinviterecvtask.h"
|
||||
#include "webrtc/libjingle/xmpp/constants.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
const char* types[] = {
|
||||
"unknown",
|
||||
"audio",
|
||||
"video",
|
||||
};
|
||||
|
||||
const char* statuses[] = {
|
||||
"unknown",
|
||||
"sendrecv",
|
||||
"sendonly",
|
||||
"recvonly",
|
||||
"inactive",
|
||||
};
|
||||
|
||||
const char*
|
||||
AvailableMediaEntry::TypeAsString(type_t type) {
|
||||
// The values of the constants have been chosen such that this is correct.
|
||||
return types[type];
|
||||
}
|
||||
|
||||
const char*
|
||||
AvailableMediaEntry::StatusAsString(status_t status) {
|
||||
// The values of the constants have been chosen such that this is correct.
|
||||
return statuses[status];
|
||||
}
|
||||
|
||||
int bodytext_to_array_pos(const XmlElement* elem, const char* array[],
|
||||
int len, int defval = -1) {
|
||||
if (elem) {
|
||||
const std::string& body(elem->BodyText());
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (body == array[i]) {
|
||||
// Found it.
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we get here, it's not any value in the array.
|
||||
return defval;
|
||||
}
|
||||
|
||||
bool
|
||||
MucInviteRecvTask::HandleStanza(const XmlElement* stanza) {
|
||||
// Figuring out that we want to handle this is a lot of the work of
|
||||
// actually handling it, so we handle it right here instead of queueing it.
|
||||
const XmlElement* xstanza;
|
||||
const XmlElement* invite;
|
||||
if (stanza->Name() != QN_MESSAGE) return false;
|
||||
xstanza = stanza->FirstNamed(QN_MUC_USER_X);
|
||||
if (!xstanza) return false;
|
||||
invite = xstanza->FirstNamed(QN_MUC_USER_INVITE);
|
||||
if (!invite) return false;
|
||||
// Else it's an invite and we definitely want to handle it. Parse the
|
||||
// available-media, if any.
|
||||
std::vector<AvailableMediaEntry> v;
|
||||
const XmlElement* avail =
|
||||
invite->FirstNamed(QN_GOOGLE_MUC_USER_AVAILABLE_MEDIA);
|
||||
if (avail) {
|
||||
for (const XmlElement* entry = avail->FirstNamed(QN_GOOGLE_MUC_USER_ENTRY);
|
||||
entry;
|
||||
entry = entry->NextNamed(QN_GOOGLE_MUC_USER_ENTRY)) {
|
||||
AvailableMediaEntry tmp;
|
||||
// In the interest of debugging, we accept as much valid-looking data
|
||||
// as we can.
|
||||
tmp.label = atoi(entry->Attr(QN_LABEL).c_str());
|
||||
tmp.type = static_cast<AvailableMediaEntry::type_t>(
|
||||
bodytext_to_array_pos(
|
||||
entry->FirstNamed(QN_GOOGLE_MUC_USER_TYPE),
|
||||
types,
|
||||
sizeof(types)/sizeof(const char*),
|
||||
AvailableMediaEntry::TYPE_UNKNOWN));
|
||||
tmp.status = static_cast<AvailableMediaEntry::status_t>(
|
||||
bodytext_to_array_pos(
|
||||
entry->FirstNamed(QN_GOOGLE_MUC_USER_STATUS),
|
||||
statuses,
|
||||
sizeof(statuses)/sizeof(const char*),
|
||||
AvailableMediaEntry::STATUS_UNKNOWN));
|
||||
v.push_back(tmp);
|
||||
}
|
||||
}
|
||||
SignalInviteReceived(Jid(invite->Attr(QN_FROM)), Jid(stanza->Attr(QN_FROM)),
|
||||
v);
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
MucInviteRecvTask::ProcessStart() {
|
||||
// We never queue anything so we are always blocked.
|
||||
return STATE_BLOCKED;
|
||||
}
|
||||
|
||||
}
|
82
talk/examples/call/mucinviterecvtask.h
Normal file
82
talk/examples/call/mucinviterecvtask.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _MUCINVITERECVTASK_H_
|
||||
#define _MUCINVITERECVTASK_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/libjingle/xmpp/xmppengine.h"
|
||||
#include "webrtc/libjingle/xmpp/xmpptask.h"
|
||||
#include "webrtc/base/sigslot.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
struct AvailableMediaEntry {
|
||||
enum type_t {
|
||||
// SIP defines other media types, but these are the only ones we use in
|
||||
// multiway jingle.
|
||||
// These numbers are important; see .cc file
|
||||
TYPE_UNKNOWN = 0, // indicates invalid string
|
||||
TYPE_AUDIO = 1,
|
||||
TYPE_VIDEO = 2,
|
||||
};
|
||||
|
||||
enum status_t {
|
||||
// These numbers are important; see .cc file
|
||||
STATUS_UNKNOWN = 0, // indicates invalid string
|
||||
STATUS_SENDRECV = 1,
|
||||
STATUS_SENDONLY = 2,
|
||||
STATUS_RECVONLY = 3,
|
||||
STATUS_INACTIVE = 4,
|
||||
};
|
||||
|
||||
uint32 label;
|
||||
type_t type;
|
||||
status_t status;
|
||||
|
||||
static const char* TypeAsString(type_t type);
|
||||
static const char* StatusAsString(status_t status);
|
||||
};
|
||||
|
||||
class MucInviteRecvTask : public XmppTask {
|
||||
public:
|
||||
explicit MucInviteRecvTask(XmppTaskParentInterface* parent)
|
||||
: XmppTask(parent, XmppEngine::HL_TYPE) {}
|
||||
virtual int ProcessStart();
|
||||
|
||||
// First arg is inviter's JID; second is MUC's JID.
|
||||
sigslot::signal3<const Jid&, const Jid&, const std::vector<AvailableMediaEntry>& > SignalInviteReceived;
|
||||
|
||||
protected:
|
||||
virtual bool HandleStanza(const XmlElement* stanza);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
63
talk/examples/call/mucinvitesendtask.cc
Normal file
63
talk/examples/call/mucinvitesendtask.cc
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 "talk/examples/call/mucinvitesendtask.h"
|
||||
#include "webrtc/libjingle/xmpp/constants.h"
|
||||
#include "webrtc/libjingle/xmpp/xmppclient.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
XmppReturnStatus
|
||||
MucInviteSendTask::Send(const Jid& to, const Jid& invitee) {
|
||||
if (GetState() != STATE_INIT && GetState() != STATE_START)
|
||||
return XMPP_RETURN_BADSTATE;
|
||||
|
||||
XmlElement* message = new XmlElement(QN_MESSAGE);
|
||||
message->AddAttr(QN_TO, to.Str());
|
||||
XmlElement* xstanza = new XmlElement(QN_MUC_USER_X);
|
||||
XmlElement* invite = new XmlElement(QN_MUC_USER_INVITE);
|
||||
invite->AddAttr(QN_TO, invitee.Str());
|
||||
xstanza->AddElement(invite);
|
||||
message->AddElement(xstanza);
|
||||
|
||||
QueueStanza(message);
|
||||
return XMPP_RETURN_OK;
|
||||
}
|
||||
|
||||
int
|
||||
MucInviteSendTask::ProcessStart() {
|
||||
const XmlElement* stanza = NextStanza();
|
||||
if (stanza == NULL)
|
||||
return STATE_BLOCKED;
|
||||
|
||||
if (SendStanza(stanza) != XMPP_RETURN_OK)
|
||||
return STATE_ERROR;
|
||||
|
||||
return STATE_START;
|
||||
}
|
||||
|
||||
}
|
50
talk/examples/call/mucinvitesendtask.h
Normal file
50
talk/examples/call/mucinvitesendtask.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _MUCINVITESENDTASK_H_
|
||||
#define _MUCINVITESENDTASK_H_
|
||||
|
||||
#include "talk/examples/call/muc.h"
|
||||
#include "webrtc/libjingle/xmpp/xmppengine.h"
|
||||
#include "webrtc/libjingle/xmpp/xmpptask.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class MucInviteSendTask : public XmppTask {
|
||||
public:
|
||||
explicit MucInviteSendTask(XmppTaskParentInterface* parent)
|
||||
: XmppTask(parent) {}
|
||||
virtual ~MucInviteSendTask() {}
|
||||
|
||||
XmppReturnStatus Send(const Jid& to, const Jid& invitee);
|
||||
|
||||
virtual int ProcessStart();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
222
talk/examples/call/presencepushtask.cc
Normal file
222
talk/examples/call/presencepushtask.cc
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* 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 "talk/examples/call/presencepushtask.h"
|
||||
|
||||
#include "talk/examples/call/muc.h"
|
||||
#include "webrtc/libjingle/xmpp/constants.h"
|
||||
#include "webrtc/base/stringencode.h"
|
||||
|
||||
|
||||
|
||||
namespace buzz {
|
||||
|
||||
// string helper functions -----------------------------------------------------
|
||||
|
||||
static bool
|
||||
IsXmlSpace(int ch) {
|
||||
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
|
||||
}
|
||||
|
||||
static bool ListContainsToken(const std::string & list,
|
||||
const std::string & token) {
|
||||
size_t i = list.find(token);
|
||||
if (i == std::string::npos || token.empty())
|
||||
return false;
|
||||
bool boundary_before = (i == 0 || IsXmlSpace(list[i - 1]));
|
||||
bool boundary_after = (i == list.length() - token.length() ||
|
||||
IsXmlSpace(list[i + token.length()]));
|
||||
return boundary_before && boundary_after;
|
||||
}
|
||||
|
||||
|
||||
bool PresencePushTask::HandleStanza(const XmlElement * stanza) {
|
||||
if (stanza->Name() != QN_PRESENCE)
|
||||
return false;
|
||||
QueueStanza(stanza);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsUtf8FirstByte(int c) {
|
||||
return (((c)&0x80)==0) || // is single byte
|
||||
((unsigned char)((c)-0xc0)<0x3e); // or is lead byte
|
||||
}
|
||||
|
||||
int PresencePushTask::ProcessStart() {
|
||||
const XmlElement * stanza = NextStanza();
|
||||
if (stanza == NULL)
|
||||
return STATE_BLOCKED;
|
||||
|
||||
Jid from(stanza->Attr(QN_FROM));
|
||||
std::map<Jid, buzz::Muc*>::const_iterator elem =
|
||||
client_->mucs().find(from.BareJid());
|
||||
if (elem == client_->mucs().end()) {
|
||||
HandlePresence(from, stanza);
|
||||
} else {
|
||||
HandleMucPresence(elem->second, from, stanza);
|
||||
}
|
||||
|
||||
return STATE_START;
|
||||
}
|
||||
|
||||
void PresencePushTask::HandlePresence(const Jid& from,
|
||||
const XmlElement* stanza) {
|
||||
if (stanza->Attr(QN_TYPE) == STR_ERROR)
|
||||
return;
|
||||
|
||||
PresenceStatus s;
|
||||
FillStatus(from, stanza, &s);
|
||||
SignalStatusUpdate(s);
|
||||
}
|
||||
|
||||
void PresencePushTask::HandleMucPresence(buzz::Muc* muc,
|
||||
const Jid& from,
|
||||
const XmlElement* stanza) {
|
||||
if (from == muc->local_jid()) {
|
||||
if (!stanza->HasAttr(QN_TYPE)) {
|
||||
// We joined the MUC.
|
||||
const XmlElement* elem = stanza->FirstNamed(QN_MUC_USER_X);
|
||||
// Status code=110 or 100 is not guaranteed to be present, so we
|
||||
// only check the item element and Muc join status.
|
||||
if (elem) {
|
||||
if (elem->FirstNamed(QN_MUC_USER_ITEM) &&
|
||||
muc->state() == buzz::Muc::MUC_JOINING) {
|
||||
SignalMucJoined(muc->jid());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We've been kicked. Bye.
|
||||
int error = 0;
|
||||
if (stanza->Attr(QN_TYPE) == STR_ERROR) {
|
||||
const XmlElement* elem = stanza->FirstNamed(QN_ERROR);
|
||||
if (elem && elem->HasAttr(QN_CODE)) {
|
||||
error = atoi(elem->Attr(QN_CODE).c_str());
|
||||
}
|
||||
}
|
||||
SignalMucLeft(muc->jid(), error);
|
||||
}
|
||||
} else {
|
||||
MucPresenceStatus s;
|
||||
FillMucStatus(from, stanza, &s);
|
||||
SignalMucStatusUpdate(muc->jid(), s);
|
||||
}
|
||||
}
|
||||
|
||||
void PresencePushTask::FillStatus(const Jid& from, const XmlElement* stanza,
|
||||
PresenceStatus* s) {
|
||||
s->set_jid(from);
|
||||
if (stanza->Attr(QN_TYPE) == STR_UNAVAILABLE) {
|
||||
s->set_available(false);
|
||||
} else {
|
||||
s->set_available(true);
|
||||
const XmlElement * status = stanza->FirstNamed(QN_STATUS);
|
||||
if (status != NULL) {
|
||||
s->set_status(status->BodyText());
|
||||
|
||||
// Truncate status messages longer than 300 bytes
|
||||
if (s->status().length() > 300) {
|
||||
size_t len = 300;
|
||||
|
||||
// Be careful not to split legal utf-8 chars in half
|
||||
while (!IsUtf8FirstByte(s->status()[len]) && len > 0) {
|
||||
len -= 1;
|
||||
}
|
||||
std::string truncated(s->status(), 0, len);
|
||||
s->set_status(truncated);
|
||||
}
|
||||
}
|
||||
|
||||
const XmlElement * priority = stanza->FirstNamed(QN_PRIORITY);
|
||||
if (priority != NULL) {
|
||||
int pri;
|
||||
if (rtc::FromString(priority->BodyText(), &pri)) {
|
||||
s->set_priority(pri);
|
||||
}
|
||||
}
|
||||
|
||||
const XmlElement * show = stanza->FirstNamed(QN_SHOW);
|
||||
if (show == NULL || show->FirstChild() == NULL) {
|
||||
s->set_show(PresenceStatus::SHOW_ONLINE);
|
||||
}
|
||||
else {
|
||||
if (show->BodyText() == "away") {
|
||||
s->set_show(PresenceStatus::SHOW_AWAY);
|
||||
}
|
||||
else if (show->BodyText() == "xa") {
|
||||
s->set_show(PresenceStatus::SHOW_XA);
|
||||
}
|
||||
else if (show->BodyText() == "dnd") {
|
||||
s->set_show(PresenceStatus::SHOW_DND);
|
||||
}
|
||||
else if (show->BodyText() == "chat") {
|
||||
s->set_show(PresenceStatus::SHOW_CHAT);
|
||||
}
|
||||
else {
|
||||
s->set_show(PresenceStatus::SHOW_ONLINE);
|
||||
}
|
||||
}
|
||||
|
||||
const XmlElement * caps = stanza->FirstNamed(QN_CAPS_C);
|
||||
if (caps != NULL) {
|
||||
std::string node = caps->Attr(QN_NODE);
|
||||
std::string ver = caps->Attr(QN_VER);
|
||||
std::string exts = caps->Attr(QN_EXT);
|
||||
|
||||
s->set_know_capabilities(true);
|
||||
s->set_caps_node(node);
|
||||
s->set_version(ver);
|
||||
|
||||
if (ListContainsToken(exts, "voice-v1")) {
|
||||
s->set_voice_capability(true);
|
||||
}
|
||||
if (ListContainsToken(exts, "video-v1")) {
|
||||
s->set_video_capability(true);
|
||||
}
|
||||
}
|
||||
|
||||
const XmlElement* delay = stanza->FirstNamed(kQnDelayX);
|
||||
if (delay != NULL) {
|
||||
// Ideally we would parse this according to the Psuedo ISO-8601 rules
|
||||
// that are laid out in JEP-0082:
|
||||
// http://www.jabber.org/jeps/jep-0082.html
|
||||
std::string stamp = delay->Attr(kQnStamp);
|
||||
s->set_sent_time(stamp);
|
||||
}
|
||||
|
||||
const XmlElement* nick = stanza->FirstNamed(QN_NICKNAME);
|
||||
if (nick) {
|
||||
s->set_nick(nick->BodyText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PresencePushTask::FillMucStatus(const Jid& from, const XmlElement* stanza,
|
||||
MucPresenceStatus* s) {
|
||||
FillStatus(from, stanza, s);
|
||||
}
|
||||
|
||||
}
|
70
talk/examples/call/presencepushtask.h
Normal file
70
talk/examples/call/presencepushtask.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PRESENCEPUSHTASK_H_
|
||||
#define _PRESENCEPUSHTASK_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "talk/examples/call/callclient.h"
|
||||
#include "webrtc/libjingle/xmpp/presencestatus.h"
|
||||
#include "webrtc/libjingle/xmpp/xmppengine.h"
|
||||
#include "webrtc/libjingle/xmpp/xmpptask.h"
|
||||
#include "webrtc/base/sigslot.h"
|
||||
|
||||
namespace buzz {
|
||||
|
||||
class PresencePushTask : public XmppTask {
|
||||
public:
|
||||
PresencePushTask(XmppTaskParentInterface* parent, CallClient* client)
|
||||
: XmppTask(parent, XmppEngine::HL_TYPE),
|
||||
client_(client) {}
|
||||
virtual int ProcessStart();
|
||||
|
||||
sigslot::signal1<const PresenceStatus&> SignalStatusUpdate;
|
||||
sigslot::signal1<const Jid&> SignalMucJoined;
|
||||
sigslot::signal2<const Jid&, int> SignalMucLeft;
|
||||
sigslot::signal2<const Jid&, const MucPresenceStatus&> SignalMucStatusUpdate;
|
||||
|
||||
protected:
|
||||
virtual bool HandleStanza(const XmlElement * stanza);
|
||||
void HandlePresence(const Jid& from, const XmlElement * stanza);
|
||||
void HandleMucPresence(buzz::Muc* muc,
|
||||
const Jid& from, const XmlElement * stanza);
|
||||
static void FillStatus(const Jid& from, const XmlElement * stanza,
|
||||
PresenceStatus* status);
|
||||
static void FillMucStatus(const Jid& from, const XmlElement * stanza,
|
||||
MucPresenceStatus* status);
|
||||
|
||||
private:
|
||||
CallClient* client_;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user