mirror of
https://github.com/UltraCoderRU/libwebrtc.git
synced 2026-01-28 03:15:11 +00:00
Add Samples subdirectory, with a very basic sample program
This commit is contained in:
parent
d2b245e7a2
commit
6a6f80d5e9
20 changed files with 940 additions and 1 deletions
|
|
@ -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)
|
||||
|
||||
add_subdirectory(Targets)
|
||||
|
||||
if(BUILD_SAMPLES)
|
||||
add_subdirectory(Samples)
|
||||
endif(BUILD_SAMPLES)
|
||||
1
Samples/CMakeLists.txt
Normal file
1
Samples/CMakeLists.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
add_subdirectory(PeerConnection)
|
||||
35
Samples/PeerConnection/CMakeLists.txt
Normal file
35
Samples/PeerConnection/CMakeLists.txt
Normal 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})
|
||||
76
Samples/PeerConnection/Core.cpp
Normal file
76
Samples/PeerConnection/Core.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
28
Samples/PeerConnection/Core.h
Normal file
28
Samples/PeerConnection/Core.h
Normal 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
|
||||
24
Samples/PeerConnection/CreateSessionObserver.cpp
Normal file
24
Samples/PeerConnection/CreateSessionObserver.cpp
Normal 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());
|
||||
}
|
||||
26
Samples/PeerConnection/CreateSessionObserver.h
Normal file
26
Samples/PeerConnection/CreateSessionObserver.h
Normal 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
|
||||
31
Samples/PeerConnection/DataChannelObserver.cpp
Normal file
31
Samples/PeerConnection/DataChannelObserver.cpp
Normal 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) {
|
||||
}
|
||||
22
Samples/PeerConnection/DataChannelObserver.h
Normal file
22
Samples/PeerConnection/DataChannelObserver.h
Normal 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
|
||||
186
Samples/PeerConnection/Peer.cpp
Normal file
186
Samples/PeerConnection/Peer.cpp
Normal 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) {
|
||||
}
|
||||
62
Samples/PeerConnection/Peer.h
Normal file
62
Samples/PeerConnection/Peer.h
Normal 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
|
||||
5
Samples/PeerConnection/PeerConnectionObserver.cpp
Normal file
5
Samples/PeerConnection/PeerConnectionObserver.cpp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
//
|
||||
// Created by ax on 25/09/16.
|
||||
//
|
||||
|
||||
#include "PeerConnectionObserver.h"
|
||||
14
Samples/PeerConnection/PeerConnectionObserver.h
Normal file
14
Samples/PeerConnection/PeerConnectionObserver.h
Normal 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
|
||||
|
|
@ -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());
|
||||
}
|
||||
27
Samples/PeerConnection/SetLocalSessionDescriptionObserver.h
Normal file
27
Samples/PeerConnection/SetLocalSessionDescriptionObserver.h
Normal 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
|
||||
|
|
@ -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());
|
||||
}
|
||||
28
Samples/PeerConnection/SetRemoteSessionDescriptionObserver.h
Normal file
28
Samples/PeerConnection/SetRemoteSessionDescriptionObserver.h
Normal 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
|
||||
153
Samples/PeerConnection/UnixConsole.cpp
Normal file
153
Samples/PeerConnection/UnixConsole.cpp
Normal 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);
|
||||
}
|
||||
20
Samples/PeerConnection/UnixConsole.h
Normal file
20
Samples/PeerConnection/UnixConsole.h
Normal 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
|
||||
140
Samples/PeerConnection/main.cpp
Normal file
140
Samples/PeerConnection/main.cpp
Normal 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;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue