Last active
June 12, 2017 23:28
-
-
Save MatrixMuto/e37f50567e4b9b982dd8673a1e49dcbe to your computer and use it in GitHub Desktop.
webrtc local peer connection example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" ] | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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