Skip to content

Instantly share code, notes, and snippets.

@MatrixMuto
Last active June 12, 2017 23:28
Show Gist options
  • Save MatrixMuto/e37f50567e4b9b982dd8673a1e49dcbe to your computer and use it in GitHub Desktop.
Save MatrixMuto/e37f50567e4b9b982dd8673a1e49dcbe to your computer and use it in GitHub Desktop.
webrtc local peer connection example
rtc_executable("mytest") {
testonly = true
sources = [
"mytest/mytest.cc",
]
deps = [
"../base:rtc_base",
"//webrtc/base:rtc_base_approved",
"//webrtc/p2p:rtc_p2p",
"//webrtc/pc:rtc_pc",
"//webrtc/base:rtc_json",
"//webrtc/system_wrappers:field_trial_default",
"//webrtc/system_wrappers:metrics_default",
"//webrtc/pc:libjingle_peerconnection",
]
if (!build_with_chromium && is_clang) {
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
}
}
#include <stdio.h>
#include <iostream>
#include <thread>
#include <fstream>
#include "webrtc/base/sigslot.h"
#include "webrtc/base/json.h"
#include "webrtc/base/physicalsocketserver.h"
#include <webrtc/base/ssladapter.h>
#include "webrtc/api/peerconnectioninterface.h"
using webrtc::PeerConnectionFactoryInterface;
using webrtc::MediaStreamInterface;
using webrtc::DataChannelInterface;
using webrtc::PeerConnectionInterface;
using webrtc::IceCandidateInterface;
using webrtc::CreateSessionDescriptionObserver;
using webrtc::SessionDescriptionInterface;
using webrtc::DataBuffer;
class test : public sigslot::has_slots<> {
};
class MyObserver :
public webrtc::PeerConnectionObserver,
public CreateSessionDescriptionObserver {
public:
virtual ~MyObserver() {}
virtual void OnSignalingChange(
PeerConnectionInterface::SignalingState new_state) override;
// Triggered when media is received on a new stream from remote peer.
virtual void OnAddStream(rtc::scoped_refptr<MediaStreamInterface> stream) override;
// Triggered when a remote peer close a stream.
virtual void OnRemoveStream(
rtc::scoped_refptr<MediaStreamInterface> stream) override;
// Triggered when a remote peer opens a data channel.
virtual void OnDataChannel(
rtc::scoped_refptr<DataChannelInterface> data_channel) override;
// Triggered when renegotiation is needed. For example, an ICE restart
// has begun.
virtual void OnRenegotiationNeeded() override;
// Called any time the IceConnectionState changes.
//
// Note that our ICE states lag behind the standard slightly. The most
// notable differences include the fact that "failed" occurs after 15
// seconds, not 30, and this actually represents a combination ICE + DTLS
// state, so it may be "failed" if DTLS fails while ICE succeeds.
virtual void OnIceConnectionChange(
PeerConnectionInterface::IceConnectionState new_state) override;
// Called any time the IceGatheringState changes.
virtual void OnIceGatheringChange(
PeerConnectionInterface::IceGatheringState new_state) override;
// A new ICE candidate has been gathered.
virtual void OnIceCandidate(const IceCandidateInterface *candidate) override;
// CreateSessionDescriptionObserver
virtual void OnSuccess(SessionDescriptionInterface *desc) override;
virtual void OnFailure(const std::string &error) override;
};
class MySetObserver : public webrtc::SetSessionDescriptionObserver {
public:
virtual void OnSuccess() {
LOG(INFO) << __FUNCTION__ << "";
}
virtual void OnFailure(const std::string &error) {
LOG(INFO) << __FUNCTION__ << "";
}
};
rtc::scoped_refptr<MyObserver> observer = new rtc::RefCountedObject<MyObserver>();
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory;
rtc::scoped_refptr<PeerConnectionInterface> peer_conn;
rtc::scoped_refptr<MySetObserver> mySetObserver;
rtc::scoped_refptr<DataChannelInterface> data_channel;
std::string label = "1234";
std::string sdp_in;
std::string sdp_out;
std::string ice_in;
std::string ice_out;
void MyObserver::OnSignalingChange(PeerConnectionInterface::SignalingState new_state) {
LOG(INFO) << __FUNCTION__ << "";
}
void MyObserver::OnAddStream(rtc::scoped_refptr<MediaStreamInterface> stream) {
LOG(INFO) << __FUNCTION__ << "";
}
void MyObserver::OnRemoveStream(rtc::scoped_refptr<MediaStreamInterface> stream) {
LOG(INFO) << __FUNCTION__ << "";
}
void MyObserver::OnDataChannel(rtc::scoped_refptr<DataChannelInterface> data_channel2) {
data_channel = data_channel2;
LOG(INFO) << __FUNCTION__ << "";
LOG(INFO) << __FUNCTION__ << "";
LOG(INFO) << __FUNCTION__ << "";
LOG(INFO) << __FUNCTION__ << "";
LOG(INFO) << __FUNCTION__ << "";
LOG(INFO) << __FUNCTION__ << "";
LOG(INFO) << __FUNCTION__ << "";
}
void MyObserver::OnRenegotiationNeeded() {
LOG(INFO) << __FUNCTION__ << "";
}
void MyObserver::OnIceConnectionChange(PeerConnectionInterface::IceConnectionState new_state) {
LOG(INFO) << __FUNCTION__ << " new state:" << new_state;
}
void MyObserver::OnIceGatheringChange(PeerConnectionInterface::IceGatheringState new_state) {
LOG(INFO) << __FUNCTION__ << " new state:" << new_state;
}
std::vector<Json::Value> ices;
const char kCandidateSdpMidName[] = "sdpMid";
const char kCandidateSdpMlineIndexName[] = "sdpMLineIndex";
const char kCandidateSdpName[] = "candidate";
Json::Value root;
void MyObserver::OnIceCandidate(const IceCandidateInterface *candidate) {
std::string sdp;
Json::StyledWriter writer;
Json::Value jmessage;
jmessage[kCandidateSdpMidName] = candidate->sdp_mid();
jmessage[kCandidateSdpMlineIndexName] = candidate->sdp_mline_index();
if (!candidate->ToString(&sdp)) {
LOG(LS_ERROR) << "Failed to serialize candidate";
return;
}
jmessage[kCandidateSdpName] = sdp;
ices.push_back(jmessage);
;
root.append(jmessage);
LOG(INFO) << __FUNCTION__ << writer.write(root);
LOG(INFO) << sdp;
}
void MyObserver::OnSuccess(SessionDescriptionInterface *desc) {
LOG(INFO) << __FUNCTION__ << " ";
std::string sdp;
desc->ToString(&sdp);
std::ofstream out(sdp_out);
out.write(sdp.c_str(), sdp.length());
out.close();
LOG(INFO) << sdp;
mySetObserver = new rtc::RefCountedObject<MySetObserver>();
peer_conn->SetLocalDescription(mySetObserver, desc);
}
void MyObserver::OnFailure(const std::string &error) {
LOG(INFO) << __FUNCTION__ << "";
}
class MyDataChannelObserver : public webrtc::DataChannelObserver {
public:
// The data channel state have changed.
virtual void OnStateChange() {
LOG(INFO) << __FUNCTION__ << "";
}
// A data buffer was successfully received.
virtual void OnMessage(const DataBuffer &buffer) {
LOG(INFO) << __FUNCTION__ << "";
}
};
MyDataChannelObserver data_chn_observer;
void peer_one() {
LOG(INFO) << "CreateDataChannel";
webrtc::DataChannelInit init;
data_channel = peer_conn->CreateDataChannel(label, &init);
data_channel->RegisterObserver(&data_chn_observer);
LOG(INFO) << "CreateOffer";
PeerConnectionInterface::RTCOfferAnswerOptions options;
peer_conn->CreateOffer(observer, nullptr);
LOG(INFO) << "Waiting Peer SDP:";
char a;
std::cin >> a;
std::string sdp;
std::string line;
std::ifstream file(sdp_in);
while (std::getline(file, line)) {
sdp += line;
sdp += "\n";
}
file.close();
LOG(INFO) << "sdp:" << std::endl << sdp;
LOG(INFO) << "SetRemoteDesc";
webrtc::SdpParseError error;
SessionDescriptionInterface *session_desc;
session_desc = webrtc::CreateSessionDescription(
SessionDescriptionInterface::kAnswer, sdp, &error);
rtc::scoped_refptr<MySetObserver> set_observer = new rtc::RefCountedObject<MySetObserver>();
peer_conn->SetRemoteDescription(set_observer, session_desc);
#if 0
webrtc::SdpParseError error;
LOG(INFO) << "next SetRemoteDecc, wati confirm:";
std::cin >> a;
LOG(INFO) << "SetRemoteDesc";
SessionDescriptionInterface *session_desc;
session_desc = webrtc::CreateSessionDescription(
SessionDescriptionInterface::kOffer, , &error);
rtc::scoped_refptr<MySetObserver> set_observer = new rtc::RefCountedObject<MySetObserver>();
peer_conn->SetRemoteDescription(set_observer, session_desc);
#endif
}
void peer_two() {
LOG(INFO) << "Wait Input:";
char a;
std::cin >> a;
LOG(INFO) << "CreateDataChannel";
webrtc::DataChannelInit init;
data_channel = peer_conn->CreateDataChannel(label, &init);
data_channel->RegisterObserver(&data_chn_observer);
std::string sdp;
std::string line;
std::ifstream file(sdp_in);
while (std::getline(file, line)) {
sdp += line;
sdp += "\n";
}
file.close();
LOG(INFO) << "sdp:" << std::endl << sdp;
LOG(INFO) << "SetRemoteDesc";
webrtc::SdpParseError error;
SessionDescriptionInterface *session_desc;
session_desc = webrtc::CreateSessionDescription(
SessionDescriptionInterface::kOffer, sdp, &error);
rtc::scoped_refptr<MySetObserver> set_observer = new rtc::RefCountedObject<MySetObserver>();
peer_conn->SetRemoteDescription(set_observer, session_desc);
peer_conn->CreateAnswer(observer, nullptr);
}
void create_factory_then_run() {
LOG(INFO) << "CreatePeerConnectionFactory";
factory = webrtc::CreatePeerConnectionFactory();
PeerConnectionInterface::RTCConfiguration config;
PeerConnectionInterface::IceServer server;
server.uri = "stun:stun.l.google.com:19302";
config.servers.push_back(server);
// config.enable_dtls_srtp = rtc::Optional<bool>(false);
LOG(INFO) << "CreatePeerConnection";
peer_conn = factory->CreatePeerConnection(config, NULL, NULL, observer);
rtc::Thread *thread = rtc::Thread::Current();
rtc::PhysicalSocketServer socketServer;
thread->Run();
}
int main(int argc, char *argv[]) {
rtc::InitializeSSL();
std::thread th(create_factory_then_run);
std::string cmd;
while (std::cin >> cmd) {
if (cmd == "offer") {
sdp_out = "sdp_offer";
sdp_in = "sdp_answer";
ice_out = "ice_offer";
ice_in = "ice_answer";
peer_one();
} else if (cmd == "answer") {
sdp_out = "sdp_answer";
sdp_in = "sdp_offer";
ice_out = "ice_answer";
ice_in = "ice_offer";
peer_two();
} else if (cmd == "getice") {
Json::FastWriter writer;
std::string json_string = writer.write(root);
std::ofstream out(ice_out);
out.write(json_string.c_str(), json_string.length());
out.close();
#if 0
for (auto iter : ices) {
Json::Value v = iter;
std::string mid;
rtc::GetStringFromJsonObject(v, kCandidateSdpMidName, &mid);
int mid_index;
rtc::GetIntFromJsonObject(v, kCandidateSdpMlineIndexName, &mid_index);
std::string sdp;
rtc::GetStringFromJsonObject(v, kCandidateSdpName, &sdp);
webrtc::SdpParseError error;
webrtc::IceCandidateInterface *ice = webrtc::CreateIceCandidate(
mid, mid_index, sdp,&error);
peer_conn->AddIceCandidate(ice);
}
#endif
} else if (cmd == "addice") {
std::string json_string;
std::ifstream in(ice_in);
std::getline(in, json_string);
in.close();
LOG(INFO) << json_string;
Json::Reader reader;
Json::Value root;
reader.parse(json_string, root);
for (auto it=root.begin(); it != root.end(); ++it) {
Json::Value v = *it;
std::string mid;
rtc::GetStringFromJsonObject(v, kCandidateSdpMidName, &mid);
int mid_index;
rtc::GetIntFromJsonObject(v, kCandidateSdpMlineIndexName, &mid_index);
std::string sdp;
rtc::GetStringFromJsonObject(v, kCandidateSdpName, &sdp);
webrtc::SdpParseError error;
webrtc::IceCandidateInterface *ice = webrtc::CreateIceCandidate(
mid, mid_index, sdp,&error);
peer_conn->AddIceCandidate(ice);
}
} else if (cmd == "send") {
LOG(INFO) << "Ready to Send Data?";
std::string message;
std::cin >> message;
DataBuffer buffer(message);
data_channel->Send(buffer);
} else if (cmd == "label") {
std::cin >> label;
std::cout << label;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment