Add Samples subdirectory, with a very basic sample program

This commit is contained in:
Axel Isouard 2016-09-25 19:24:44 +02:00
parent d2b245e7a2
commit 6a6f80d5e9
20 changed files with 940 additions and 1 deletions

View file

@ -67,3 +67,7 @@ set(LIBWEBRTC_BUILD_ROOT ${CMAKE_SOURCE_DIR}/src/out/Default)
set(WEBRTC_CHROMIUM_DEPS git@github.com:aisouard/libwebrtc-chromium-deps.git) set(WEBRTC_CHROMIUM_DEPS git@github.com:aisouard/libwebrtc-chromium-deps.git)
add_subdirectory(Targets) add_subdirectory(Targets)
if(BUILD_SAMPLES)
add_subdirectory(Samples)
endif(BUILD_SAMPLES)

1
Samples/CMakeLists.txt Normal file
View file

@ -0,0 +1 @@
add_subdirectory(PeerConnection)

View file

@ -0,0 +1,35 @@
project(PeerConnection)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(X11 REQUIRED)
set(PEERCONNECTION_SOURCE_FILES
main.cpp
Core.cpp
CreateSessionObserver.cpp
DataChannelObserver.cpp
Peer.cpp
PeerConnectionObserver.cpp
SetLocalSessionDescriptionObserver.cpp
SetRemoteSessionDescriptionObserver.cpp
)
include_directories(${CMAKE_SOURCE_DIR}/out/src)
if(WIN)
add_definitions(-DWEBRTC_WIN)
else(WIN)
add_definitions(-DWEBRTC_POSIX -std=c++11 -fno-rtti -D_GLIBCXX_USE_CXX11_ABI=0)
set(PEERCONNECTION_SOURCE_FILES ${PEERCONNECTION_SOURCE_FILES} UnixConsole.cpp)
endif(WIN)
add_executable(PeerConnection ${PEERCONNECTION_SOURCE_FILES})
set(PEERCONNECTION_LIBRARIES ${CMAKE_BINARY_DIR}/${LIBWEBRTC_LIBRARY} Threads::Threads)
if(UNIX AND NOT APPLE)
set(PEERCONNECTION_LIBRARIES ${PEERCONNECTION_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS})
endif(UNIX AND NOT APPLE)
target_link_libraries(PeerConnection ${PEERCONNECTION_LIBRARIES})

View file

@ -0,0 +1,76 @@
//
// Created by ax on 24/09/16.
//
#include "webrtc/base/ssladapter.h"
#include "Core.h"
rtc::Thread *Core::_signalingThread = NULL;
rtc::Thread *Core::_workerThread = NULL;
webrtc::PeerConnectionFactoryInterface *Core::_peerConnectionFactory = NULL;
bool Core::Init() {
rtc::InitializeSSL();
rtc::InitRandom(rtc::Time());
rtc::ThreadManager::Instance()->WrapCurrentThread();
_signalingThread = new rtc::Thread();
_workerThread = new rtc::Thread();
_signalingThread->SetName("signaling_thread", NULL);
_workerThread->SetName("worker_thread", NULL);
if (!_signalingThread->Start() || !_workerThread->Start()) {
return false;
}
_peerConnectionFactory =
webrtc::CreatePeerConnectionFactory(_signalingThread,
_workerThread,
NULL, NULL, NULL).release();
return true;
}
bool Core::Update() {
return rtc::Thread::Current()->ProcessMessages(0);
}
bool Core::Cleanup() {
_peerConnectionFactory->Release();
_peerConnectionFactory = NULL;
_signalingThread->Stop();
_workerThread->Stop();
delete _signalingThread;
delete _workerThread;
_signalingThread = NULL;
_workerThread = NULL;
return rtc::CleanupSSL();
}
rtc::Thread *Core::GetSignalingThread() {
return _signalingThread;
}
rtc::Thread *Core::GetWorkerThread() {
return _workerThread;
}
webrtc::PeerConnectionFactoryInterface *Core::GetPeerConnectionFactory() {
return _peerConnectionFactory;
}

View file

@ -0,0 +1,28 @@
//
// Created by ax on 24/09/16.
//
#ifndef LIBWEBRTC_CORE_H
#define LIBWEBRTC_CORE_H
#include "webrtc/api/peerconnectioninterface.h"
#include "webrtc/base/thread.h"
class Core {
public:
static bool Init();
static bool Update();
static bool Cleanup();
static rtc::Thread *GetSignalingThread();
static rtc::Thread *GetWorkerThread();
static webrtc::PeerConnectionFactoryInterface *GetPeerConnectionFactory();
private:
static rtc::Thread *_signalingThread;
static rtc::Thread *_workerThread;
static webrtc::PeerConnectionFactoryInterface *_peerConnectionFactory;
};
#endif //LIBWEBRTC_CORE_H

View file

@ -0,0 +1,24 @@
//
// Created by ax on 25/09/16.
//
#include "CreateSessionObserver.h"
#include "UnixConsole.h"
#include "Peer.h"
#include "SetLocalSessionDescriptionObserver.h"
using namespace webrtc;
CreateSessionObserver::CreateSessionObserver(Peer *peer): _peer(peer) {
}
void CreateSessionObserver::OnSuccess(SessionDescriptionInterface* desc) {
rtc::scoped_refptr<SetLocalSessionDescriptionObserver> observer =
new rtc::RefCountedObject<SetLocalSessionDescriptionObserver>(desc);
_peer->SetLocalSessionDescription(desc, observer);
}
void CreateSessionObserver::OnFailure(const std::string& error) {
Console::Print("[CreateSessionObserver::OnFailure] %s", error.c_str());
}

View file

@ -0,0 +1,26 @@
//
// Created by ax on 25/09/16.
//
#ifndef LIBWEBRTC_CREATEOFFEROBSERVER_H
#define LIBWEBRTC_CREATEOFFEROBSERVER_H
#include <webrtc/api/jsep.h>
#include "Peer.h"
class CreateSessionObserver: public webrtc::CreateSessionDescriptionObserver {
public:
CreateSessionObserver(Peer *peer);
void OnSuccess(webrtc::SessionDescriptionInterface* desc);
void OnFailure(const std::string& error);
private:
Peer *_peer;
protected:
~CreateSessionObserver() {}
};
#endif //LIBWEBRTC_CREATEOFFEROBSERVER_H

View file

@ -0,0 +1,31 @@
//
// Created by ax on 25/09/16.
//
#include "DataChannelObserver.h"
#include "UnixConsole.h"
DataChannelObserver::DataChannelObserver(
webrtc::DataChannelInterface *dataChannel): _dataChannel(dataChannel) {
}
void DataChannelObserver::OnStateChange() {
Console::Print("[DataChannelObserver::OnStateChange] %s",
webrtc::DataChannelInterface::DataStateString(_dataChannel->state()));
}
void DataChannelObserver::OnMessage(const webrtc::DataBuffer& buffer) {
size_t len = buffer.size();
const unsigned char *data = buffer.data.cdata();
char *message = new char[len + 1];
memcpy(message, data, len);
message[len] = '\0';
Console::Print("<Remote> %s", message);
delete[] message;
}
void DataChannelObserver::OnBufferedAmountChange(uint64_t previous_amount) {
}

View file

@ -0,0 +1,22 @@
//
// Created by ax on 25/09/16.
//
#ifndef LIBWEBRTC_DATACHANNELOBSERVER_H
#define LIBWEBRTC_DATACHANNELOBSERVER_H
#include <webrtc/api/datachannelinterface.h>
class DataChannelObserver: public webrtc::DataChannelObserver {
public:
DataChannelObserver(webrtc::DataChannelInterface *dataChannel);
void OnStateChange();
void OnMessage(const webrtc::DataBuffer& buffer);
void OnBufferedAmountChange(uint64_t previous_amount);
private:
webrtc::DataChannelInterface *_dataChannel;
};
#endif //LIBWEBRTC_DATACHANNELOBSERVER_H

View file

@ -0,0 +1,186 @@
//
// Created by ax on 24/09/16.
//
#include <iostream>
#include <third_party/jsoncpp/source/include/json/writer.h>
#include "Peer.h"
#include "Core.h"
#include "UnixConsole.h"
#include "DataChannelObserver.h"
using webrtc::PeerConnectionInterface;
using webrtc::MediaConstraintsInterface;
using webrtc::DataChannelInit;
using webrtc::MediaStreamInterface;
using webrtc::DataChannelInterface;
using webrtc::IceCandidateInterface;
using webrtc::SessionDescriptionInterface;
Peer::Peer() {
PeerConnectionInterface::RTCConfiguration config;
PeerConnectionInterface::IceServer googleIceServer;
googleIceServer.uri = "stun:stun.l.google.com:19302";
googleIceServer.urls.push_back("stun:stun.l.google.com:19302");
googleIceServer.urls.push_back("stun:stun1.l.google.com:19302");
googleIceServer.urls.push_back("stun:stun2.l.google.com:19302");
googleIceServer.urls.push_back("stun:stun3.l.google.com:19302");
googleIceServer.urls.push_back("stun:stun4.l.google.com:19302");
config.servers.push_back(googleIceServer);
_dataChannel = NULL;
_dataChannelObserver = NULL;
_peerConnection = Core::GetPeerConnectionFactory()->
CreatePeerConnection(config, &_mediaConstraints,
NULL, NULL, this);
_mediaConstraints.AddOptional(
MediaConstraintsInterface::kEnableDtlsSrtp,
MediaConstraintsInterface::kValueTrue);
_mediaConstraints.AddMandatory(
MediaConstraintsInterface::kOfferToReceiveAudio,
MediaConstraintsInterface::kValueFalse);
_mediaConstraints.AddMandatory(
MediaConstraintsInterface::kOfferToReceiveVideo,
MediaConstraintsInterface::kValueFalse);
}
Peer::~Peer() {
if (_dataChannel) {
_dataChannel->Close();
_dataChannel = NULL;
}
_peerConnection->Close();
_peerConnection = NULL;
if (_dataChannelObserver) {
_dataChannelObserver = NULL;
}
}
void Peer::CreateOffer(webrtc::CreateSessionDescriptionObserver *createSDPObserver) {
DataChannelInit init;
init.reliable = true;
_dataChannel = _peerConnection->CreateDataChannel("MyDataChannel", &init);
_dataChannelObserver = new DataChannelObserver(_dataChannel);
_dataChannel->RegisterObserver(_dataChannelObserver);
_peerConnection->CreateOffer(createSDPObserver, &_mediaConstraints);
}
void Peer::CreateAnswer(webrtc::CreateSessionDescriptionObserver *createSDPObserver) {
_peerConnection->CreateAnswer(createSDPObserver, &_mediaConstraints);
}
bool Peer::AddIceCandidate(webrtc::IceCandidateInterface *candidate) {
return _peerConnection->AddIceCandidate(candidate);
}
void Peer::SetLocalSessionDescription(SessionDescriptionInterface* desc,
webrtc::SetSessionDescriptionObserver *obs) {
_peerConnection->SetLocalDescription(obs, desc);
}
void Peer::SetRemoteSessionDescription(SessionDescriptionInterface* desc,
webrtc::SetSessionDescriptionObserver *obs) {
_peerConnection->SetRemoteDescription(obs, desc);
}
bool Peer::IsConnected() {
if (!_dataChannel) {
return false;
}
return _dataChannel->state() == webrtc::DataChannelInterface::kOpen;
}
void Peer::SendMessage(const std::string& message) {
webrtc::DataBuffer buffer(message);
_dataChannel->Send(buffer);
}
/*
* webrtc::PeerConnectionObserver methods
*/
void Peer::OnSignalingChange(
PeerConnectionInterface::SignalingState new_state) {
Console::Print("[Peer::OnSignalingChange] new signaling state: %d",
new_state);
}
void Peer::OnAddStream(rtc::scoped_refptr<MediaStreamInterface> stream) {
Console::Print("[Peer::OnAddStream]");
}
void Peer::OnRemoveStream(rtc::scoped_refptr<MediaStreamInterface> stream) {
Console::Print("[Peer::OnRemoveStream]");
}
void Peer::OnDataChannel(
rtc::scoped_refptr<DataChannelInterface> data_channel) {
Console::Print("[Peer::OnDataChannel] %s", data_channel->label().c_str());
_dataChannel = data_channel;
_dataChannelObserver = new DataChannelObserver(_dataChannel);
_dataChannel->RegisterObserver(_dataChannelObserver);
}
void Peer::OnRenegotiationNeeded() {
}
void Peer::OnIceConnectionChange(
PeerConnectionInterface::IceConnectionState new_state) {
if (new_state == PeerConnectionInterface::kIceConnectionCompleted) {
Console::Print("Connected!");
} else if (new_state > PeerConnectionInterface::kIceConnectionCompleted) {
Console::Print("Disconnected.");
}
}
void Peer::OnIceGatheringChange(
PeerConnectionInterface::IceGatheringState new_state) {
if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
Console::Print("Gathering ICE candidates, please wait.");
return;
}
if (new_state != PeerConnectionInterface::kIceGatheringComplete) {
return;
}
Json::FastWriter writer;
writer.write(_iceCandidates);
Console::Print("Done, paste this array of ICE candidates once requested." \
"\n\n%s", writer.write(_iceCandidates).c_str());
}
void Peer::OnIceCandidate(const IceCandidateInterface* candidate) {
Json::Value jmessage;
jmessage["sdpMid"] = candidate->sdp_mid();
jmessage["sdpMLineIndex"] = candidate->sdp_mline_index();
std::string sdp;
if (!candidate->ToString(&sdp)) {
Console::Print("[Peer::OnIceCandidate] Failed to serialize candidate");
return;
}
jmessage["candidate"] = sdp;
_iceCandidates.append(jmessage);
}
void Peer::OnIceCandidatesRemoved(
const std::vector<cricket::Candidate>& candidates) {
Console::Print("[Peer::OnIceCandidatesRemoved]");
}
void Peer::OnIceConnectionReceivingChange(bool receiving) {
}

View file

@ -0,0 +1,62 @@
//
// Created by ax on 24/09/16.
//
#ifndef LIBWEBRTC_PEER_H
#define LIBWEBRTC_PEER_H
#include <third_party/jsoncpp/source/include/json/value.h>
#include "webrtc/api/test/fakeconstraints.h"
#include "webrtc/api/peerconnectioninterface.h"
class Peer : public webrtc::PeerConnectionObserver {
public:
Peer();
~Peer();
void CreateOffer(webrtc::CreateSessionDescriptionObserver *createSDPObserver);
void CreateAnswer(webrtc::CreateSessionDescriptionObserver *createSDPObserver);
bool AddIceCandidate(webrtc::IceCandidateInterface *candidate);
void SetLocalSessionDescription(webrtc::SessionDescriptionInterface* desc,
webrtc::SetSessionDescriptionObserver *setSDPObserver);
void SetRemoteSessionDescription(webrtc::SessionDescriptionInterface* desc,
webrtc::SetSessionDescriptionObserver *setSDPObserver);
bool IsConnected();
void SendMessage(const std::string& message);
/*
* webrtc::PeerConnectionObserver methods
*/
void OnSignalingChange(
webrtc::PeerConnectionInterface::SignalingState new_state);
void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream);
void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream);
void OnDataChannel(
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel);
void OnRenegotiationNeeded();
void OnIceConnectionChange(
webrtc::PeerConnectionInterface::IceConnectionState new_state);
void OnIceGatheringChange(
webrtc::PeerConnectionInterface::IceGatheringState new_state);
void OnIceCandidate(const webrtc::IceCandidateInterface* candidate);
void OnIceCandidatesRemoved(
const std::vector<cricket::Candidate>& candidates);
void OnIceConnectionReceivingChange(bool receiving);
private:
rtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
webrtc::FakeConstraints _mediaConstraints;
rtc::scoped_refptr<webrtc::DataChannelInterface> _dataChannel;
webrtc::DataChannelObserver *_dataChannelObserver;
Json::Value _iceCandidates;
};
#endif //LIBWEBRTC_PEER_H

View file

@ -0,0 +1,5 @@
//
// Created by ax on 25/09/16.
//
#include "PeerConnectionObserver.h"

View file

@ -0,0 +1,14 @@
//
// Created by ax on 25/09/16.
//
#ifndef LIBWEBRTC_PEERCONNECTIONOBSERVER_H
#define LIBWEBRTC_PEERCONNECTIONOBSERVER_H
class PeerConnectionObserver {
};
#endif //LIBWEBRTC_PEERCONNECTIONOBSERVER_H

View file

@ -0,0 +1,30 @@
//
// Created by ax on 25/09/16.
//
#include <third_party/jsoncpp/source/include/json/writer.h>
#include "SetLocalSessionDescriptionObserver.h"
#include "UnixConsole.h"
SetLocalSessionDescriptionObserver::SetLocalSessionDescriptionObserver(
webrtc::SessionDescriptionInterface* desc): _desc(desc) {
}
void SetLocalSessionDescriptionObserver::OnSuccess() {
std::string sdp;
_desc->ToString(&sdp);
Json::FastWriter writer;
Json::Value jmessage;
jmessage["type"] = _desc->type();
jmessage["sdp"] = sdp;
Console::Print("Here is the SDP, paste it to the remote client and paste " \
"their answer here.\n\n%s", writer.write(jmessage).c_str());
}
void SetLocalSessionDescriptionObserver::OnFailure(const std::string& error) {
Console::Print("[SetLocalSessionDescriptionObserver::OnFailure] %s",
error.c_str());
}

View file

@ -0,0 +1,27 @@
//
// Created by ax on 25/09/16.
//
#ifndef LIBWEBRTC_SETLOCALSESSIONDESCRIPTIONOBSERVER_H
#define LIBWEBRTC_SETLOCALSESSIONDESCRIPTIONOBSERVER_H
#include <webrtc/api/jsep.h>
class SetLocalSessionDescriptionObserver:
public webrtc::SetSessionDescriptionObserver {
public:
SetLocalSessionDescriptionObserver(webrtc::SessionDescriptionInterface* desc);
void OnSuccess();
void OnFailure(const std::string& error);
private:
webrtc::SessionDescriptionInterface* _desc;
protected:
~SetLocalSessionDescriptionObserver() {}
};
#endif //LIBWEBRTC_SETLOCALSESSIONDESCRIPTIONOBSERVER_H

View file

@ -0,0 +1,27 @@
//
// Created by ax on 25/09/16.
//
#include "SetRemoteSessionDescriptionObserver.h"
#include "CreateSessionObserver.h"
#include "UnixConsole.h"
SetRemoteSessionDescriptionObserver::SetRemoteSessionDescriptionObserver(
Peer *peer, webrtc::SessionDescriptionInterface* desc):
_peer(peer), _desc(desc) {
}
void SetRemoteSessionDescriptionObserver::OnSuccess() {
if (_desc->type() == webrtc::SessionDescriptionInterface::kOffer) {
rtc::scoped_refptr<CreateSessionObserver> createAnswerObserver =
new rtc::RefCountedObject<CreateSessionObserver>(_peer);
_peer->CreateAnswer(createAnswerObserver);
}
}
void SetRemoteSessionDescriptionObserver::OnFailure(const std::string& error) {
Console::Print("[SetRemoteSessionDescriptionObserver::OnFailure] %s",
error.c_str());
}

View file

@ -0,0 +1,28 @@
//
// Created by ax on 25/09/16.
//
#ifndef LIBWEBRTC_SETREMOTESESSIONDESCRIPTIONOBSERVER_H
#define LIBWEBRTC_SETREMOTESESSIONDESCRIPTIONOBSERVER_H
#include <webrtc/api/jsep.h>
#include "Peer.h"
class SetRemoteSessionDescriptionObserver:
public webrtc::SetSessionDescriptionObserver {
public:
SetRemoteSessionDescriptionObserver(Peer *peer, webrtc::SessionDescriptionInterface* desc);
void OnSuccess();
void OnFailure(const std::string& error);
private:
Peer *_peer;
webrtc::SessionDescriptionInterface* _desc;
protected:
~SetRemoteSessionDescriptionObserver() {}
};
#endif //LIBWEBRTC_SETREMOTESESSIONDESCRIPTIONOBSERVER_H

View file

@ -0,0 +1,153 @@
//
// Created by ax on 25/09/16.
//
#include <csignal>
#include <cstdarg>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include "UnixConsole.h"
static int ttyErase;
static int ttyEof;
static struct termios ttyTc;
static size_t cursor;
static std::string buffer;
bool Console::Init() {
struct termios tc;
const char* term = getenv("TERM");
signal(SIGTTIN, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGCONT, Console::Reset);
fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK );
if (!(isatty(STDIN_FILENO) &&
!(term && (!strcmp(term, "raw") || !strcmp(term, "dumb"))))) {
std::cerr << "Input is not a tty." << std::endl;
return false;
}
tcgetattr (STDIN_FILENO, &ttyTc);
ttyErase = ttyTc.c_cc[VERASE];
ttyEof = ttyTc.c_cc[VEOF];
tc = ttyTc;
tc.c_lflag &= ~(ECHO | ICANON);
tc.c_iflag &= ~(ISTRIP | INPCK);
tc.c_cc[VMIN] = 1;
tc.c_cc[VTIME] = 0;
tcsetattr (STDIN_FILENO, TCSADRAIN, &tc);
cursor = 0;
buffer.clear();
return true;
}
bool Console::Update(std::string &input) {
char key;
ssize_t avail = read(STDIN_FILENO, &key, 1);
input.clear();
if (avail == -1) {
return true;
}
if (key == ttyEof) {
return false;
}
if (((key == ttyErase) || (key == 127) || (key == 8)) && cursor > 0)
{
buffer.erase(--cursor, 1);
Console::Back();
return true;
}
if (key == '\n') {
input = buffer;
cursor = 0;
buffer.clear();
write(STDOUT_FILENO, &key, 1);
key = '>';
write(STDOUT_FILENO, &key, 1);
key = ' ';
write(STDOUT_FILENO, &key, 1);
return true;
}
if (key < ' ') {
return true;
}
cursor++;
buffer.append(1, key);
write(STDOUT_FILENO, &key, 1);
return true;
}
void Console::Cleanup() {
tcsetattr (STDIN_FILENO, TCSADRAIN, &ttyTc);
fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) & ~O_NONBLOCK);
}
void Console::Reset(int num) {
Console::Init();
}
void Console::Show() {
char key;
key = '>';
write(STDOUT_FILENO, &key, 1);
key = ' ';
write(STDOUT_FILENO, &key, 1);
for (size_t i = 0; i < cursor; i++) {
key = buffer.at(i);
write(STDOUT_FILENO, &key, 1);
}
}
void Console::Hide() {
for (int i = 0; i < cursor + 2; i++) {
Console::Back();
}
}
void Console::Print(const std::string &fmt, ...) {
va_list argptr;
char string[1024];
if (!fmt.length()) {
return;
}
va_start(argptr, fmt);
vsnprintf(string, sizeof(string), fmt.c_str(), argptr);
va_end(argptr);
Console::Hide();
std::cout << string << std::endl;
Console::Show();
}
void Console::Back()
{
char key;
key = '\b';
write(STDOUT_FILENO, &key, 1);
key = ' ';
write(STDOUT_FILENO, &key, 1);
key = '\b';
write(STDOUT_FILENO, &key, 1);
}

View file

@ -0,0 +1,20 @@
//
// Created by ax on 25/09/16.
//
#ifndef LIBWEBRTC_UNIXCONSOLE_H
#define LIBWEBRTC_UNIXCONSOLE_H
class Console {
public:
static bool Init();
static bool Update(std::string &input);
static void Cleanup();
static void Reset(int num);
static void Print(const std::string &line, ...);
static void Show();
static void Hide();
static void Back();
};
#endif //LIBWEBRTC_UNIXCONSOLE_H

View file

@ -0,0 +1,140 @@
#include <iostream>
#include <third_party/jsoncpp/source/include/json/reader.h>
#include "Core.h"
#include "CreateSessionObserver.h"
#include "DataChannelObserver.h"
#include "Peer.h"
#include "SetRemoteSessionDescriptionObserver.h"
#include "UnixConsole.h"
enum {
STATE_EXCHANGE = 0,
STATE_CHAT
};
static Peer *peer = NULL;
static int state = STATE_EXCHANGE;
void HandleSDP(Json::Value object) {
std::string type = object["type"].asString();
std::string sdp = object["sdp"].asString();
webrtc::SdpParseError error;
webrtc::SessionDescriptionInterface* desc(
webrtc::CreateSessionDescription(type, sdp, &error));
if (!desc) {
Console::Print("Can't parse the SDP: %s", error.description);
return;
}
rtc::scoped_refptr<SetRemoteSessionDescriptionObserver> observer =
new rtc::RefCountedObject<SetRemoteSessionDescriptionObserver>(peer, desc);
peer->SetRemoteSessionDescription(desc, observer);
}
void HandleICECandidate(Json::Value object) {
std::string sdp_mid = object["sdpMid"].asString();
int sdp_mlineindex = object["sdpMLineIndex"].asInt();
std::string sdp = object["candidate"].asString();
webrtc::SdpParseError error;
std::unique_ptr<webrtc::IceCandidateInterface> candidate(
webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp, &error));
if (!candidate.get()) {
Console::Print("Can't parse the ICE candidate: %s", error.description);
return;
}
if (!peer->AddIceCandidate(candidate.get())) {
Console::Print("Failed to add the ICE candidate.");
return;
}
}
void HandleObject(Json::Value object) {
if (object.isMember("type") && object["type"].isString() &&
object.isMember("sdp") && object["sdp"].isString()) {
HandleSDP(object);
return;
}
if (object.isMember("candidate") && object["candidate"].isString() &&
object.isMember("sdpMLineIndex") && object["sdpMLineIndex"].isNumeric() &&
object.isMember("sdpMid") && object["sdpMid"].isString()) {
HandleICECandidate(object);
return;
}
Console::Print("Unknown object.");
}
void HandleCommand(const std::string& input) {
Json::Reader reader;
Json::Value jmessage;
if (peer->IsConnected()) {
peer->SendMessage(input);
return;
}
if (!reader.parse(input, jmessage)) {
Console::Print("Invalid JSON string.");
return;
}
if (jmessage.isArray()) {
for (Json::ValueIterator it = jmessage.begin();
it != jmessage.end(); it++) {
if (!(*it).isObject()) {
continue;
}
HandleObject(*it);
}
return;
}
if (jmessage.isObject()) {
HandleObject(jmessage);
return;
}
Console::Print("Must be an array or object.");
}
int main(int argc, char **argv) {
std::string input;
if (!Console::Init()) {
return EXIT_FAILURE;
}
Core::Init();
peer = new Peer();
if (argc == 1) {
rtc::scoped_refptr<CreateSessionObserver> createOfferObserver =
new rtc::RefCountedObject<CreateSessionObserver>(peer);
peer->CreateOffer(createOfferObserver);
} else {
Console::Print("Recipient mode. Paste the offer made by the emitter.\n");
}
while (Console::Update(input)) {
if (input.length()) {
HandleCommand(input);
}
Core::Update();
}
delete peer;
Core::Cleanup();
Console::Cleanup();
return EXIT_SUCCESS;
}