mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Temp
This commit is contained in:
parent
f5d2d075e2
commit
a9a992b434
@ -29,7 +29,7 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
|||||||
init(theme: PresentationTheme, strings: PresentationStrings, presentController: @escaping (ViewController) -> Void) {
|
init(theme: PresentationTheme, strings: PresentationStrings, presentController: @escaping (ViewController) -> Void) {
|
||||||
self.strings = strings
|
self.strings = strings
|
||||||
|
|
||||||
self.micButton = ChatTextInputMediaRecordingButton(theme: theme, presentController: presentController)
|
self.micButton = ChatTextInputMediaRecordingButton(theme: theme, strings: strings, presentController: presentController)
|
||||||
self.sendButton = HighlightTrackingButtonNode(pointerStyle: .lift)
|
self.sendButton = HighlightTrackingButtonNode(pointerStyle: .lift)
|
||||||
//self.sendButton.adjustsImageWhenHighlighted = false
|
//self.sendButton.adjustsImageWhenHighlighted = false
|
||||||
//self.sendButton.adjustsImageWhenDisabled = false
|
//self.sendButton.adjustsImageWhenDisabled = false
|
||||||
|
@ -155,6 +155,7 @@ private final class ChatTextInputMediaRecordingButtonPresenter : NSObject, TGMod
|
|||||||
|
|
||||||
final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButton, TGModernConversationInputMicButtonDelegate {
|
final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButton, TGModernConversationInputMicButtonDelegate {
|
||||||
private var theme: PresentationTheme
|
private var theme: PresentationTheme
|
||||||
|
private let strings: PresentationStrings
|
||||||
|
|
||||||
var mode: ChatTextInputMediaRecordingButtonMode = .audio
|
var mode: ChatTextInputMediaRecordingButtonMode = .audio
|
||||||
var account: Account?
|
var account: Account?
|
||||||
@ -236,8 +237,9 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(theme: PresentationTheme, presentController: @escaping (ViewController) -> Void) {
|
init(theme: PresentationTheme, strings: PresentationStrings, presentController: @escaping (ViewController) -> Void) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
self.strings = strings
|
||||||
self.innerIconView = UIImageView()
|
self.innerIconView = UIImageView()
|
||||||
self.presentController = presentController
|
self.presentController = presentController
|
||||||
|
|
||||||
@ -399,7 +401,7 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto
|
|||||||
}
|
}
|
||||||
|
|
||||||
func micButtonLock() -> (UIView & TGModernConversationInputMicButtonLock)! {
|
func micButtonLock() -> (UIView & TGModernConversationInputMicButtonLock)! {
|
||||||
let lockView = LockView(frame: CGRect(origin: CGPoint(), size: CGSize(width: 40.0, height: 60.0)), theme: self.theme)
|
let lockView = LockView(frame: CGRect(origin: CGPoint(), size: CGSize(width: 40.0, height: 60.0)), theme: self.theme, strings: self.strings)
|
||||||
lockView.addTarget(self, action: #selector(handleStopTap), for: .touchUpInside)
|
lockView.addTarget(self, action: #selector(handleStopTap), for: .touchUpInside)
|
||||||
return lockView
|
return lockView
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,11 @@ final class LockView: UIButton, TGModernConversationInputMicButtonLock {
|
|||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
init(frame: CGRect, theme: PresentationTheme) {
|
init(frame: CGRect, theme: PresentationTheme, strings: PresentationStrings) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
accessibilityLabel = strings.VoiceOver_Recording_StopAndPreview
|
||||||
|
|
||||||
addSubview(idleView)
|
addSubview(idleView)
|
||||||
idleView.frame = bounds
|
idleView.frame = bounds
|
||||||
|
|
||||||
|
@ -464,7 +464,9 @@ public final class OngoingCallContext {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let context = OngoingCallThreadLocalContextWebrtc(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescriptionWebrtc(connections.primary), alternativeConnections: connections.alternatives.map(callConnectionDescriptionWebrtc), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath)
|
let context = OngoingCallThreadLocalContextWebrtc(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescriptionWebrtc(connections.primary), alternativeConnections: connections.alternatives.map(callConnectionDescriptionWebrtc), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath, sendSignalingData: { [weak callSessionManager] data in
|
||||||
|
callSessionManager?.sendSignalingData(internalId: internalId, data: data)
|
||||||
|
})
|
||||||
|
|
||||||
strongSelf.contextRef = Unmanaged.passRetained(OngoingCallThreadLocalContextHolder(context))
|
strongSelf.contextRef = Unmanaged.passRetained(OngoingCallThreadLocalContextHolder(context))
|
||||||
context.stateChanged = { state in
|
context.stateChanged = { state in
|
||||||
@ -513,9 +515,9 @@ public final class OngoingCallContext {
|
|||||||
self.signalingDataDisposable = (callSessionManager.callSignalingData(internalId: internalId)
|
self.signalingDataDisposable = (callSessionManager.callSignalingData(internalId: internalId)
|
||||||
|> deliverOn(self.queue)).start(next: { [weak self] data in
|
|> deliverOn(self.queue)).start(next: { [weak self] data in
|
||||||
self?.withContext { context in
|
self?.withContext { context in
|
||||||
/*if let context = context as? OngoingCallThreadLocalContextWebrtcCustom {
|
if let context = context as? OngoingCallThreadLocalContextWebrtc {
|
||||||
context.receiveSignaling(data)
|
context.addSignaling(data)
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,79 +1,50 @@
|
|||||||
#ifndef DEMO_CONNECTOR_H
|
#ifndef DEMO_CONNECTOR_H
|
||||||
#define DEMO_CONNECTOR_H
|
#define DEMO_CONNECTOR_H
|
||||||
|
|
||||||
|
|
||||||
#include "Endpoint.h"
|
|
||||||
#include "LayerBase.h"
|
|
||||||
#include "Message.h"
|
|
||||||
|
|
||||||
#include "p2p/base/basic_packet_socket_factory.h"
|
#include "p2p/base/basic_packet_socket_factory.h"
|
||||||
#include "rtc_base/proxy_info.h"
|
#include "rtc_base/proxy_info.h"
|
||||||
#include "rtc_base/task_utils/repeating_task.h"
|
#include "rtc_base/task_utils/repeating_task.h"
|
||||||
#include "rtc_base/third_party/sigslot/sigslot.h"
|
#include "rtc_base/third_party/sigslot/sigslot.h"
|
||||||
#include "rtc_base/thread.h"
|
#include "rtc_base/thread.h"
|
||||||
|
|
||||||
|
#include "p2p/base/p2p_transport_channel.h"
|
||||||
|
#include "p2p/client/basic_port_allocator.h"
|
||||||
|
#include "p2p/base/basic_async_resolver_factory.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
class Connector : public sigslot::has_slots<> {
|
class Connector : public sigslot::has_slots<> {
|
||||||
public:
|
public:
|
||||||
explicit Connector(std::unique_ptr<LayerBase> layer);
|
explicit Connector(bool isOutgoing);
|
||||||
~Connector() override;
|
~Connector() override;
|
||||||
void Start();
|
void Start();
|
||||||
void AddEndpointRelayTcpObfuscated(const rtc::SocketAddress& addr, const Relay::PeerTag& peer_tag);
|
|
||||||
void AddEndpointRelayUdp(const rtc::SocketAddress& addr, const Relay::PeerTag& peer_tag);
|
sigslot::signal1<const std::vector<std::string>&> SignalCandidatesGathered;
|
||||||
void SetEndpointP2p(const rtc::SocketAddress& addr);
|
sigslot::signal1<bool> SignalReadyToSendStateChanged;
|
||||||
sigslot::signal1<const message::Base&> SignalMessage;
|
sigslot::signal1<const rtc::CopyOnWriteBuffer&> SignalPacketReceived;
|
||||||
void SendMessage(const message::Base&);
|
|
||||||
void ResetActiveEndpoint();
|
void AddRemoteCandidates(const std::vector<std::string> &candidates);
|
||||||
void SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username,
|
void SendPacket(const rtc::CopyOnWriteBuffer& data);
|
||||||
const std::string& password);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class PingHistory {
|
void CandidateGathered(cricket::IceTransportInternal *transport, const cricket::Candidate &candidate);
|
||||||
public:
|
void CandidateGatheringState(cricket::IceTransportInternal *transport);
|
||||||
PingHistory();
|
void TransportStateChanged(cricket::IceTransportInternal *transport);
|
||||||
void Ping(uint32_t id);
|
void TransportRoleConflict(cricket::IceTransportInternal *transport);
|
||||||
void Pong(uint32_t id);
|
void TransportReadyToSend(cricket::IceTransportInternal *transport);
|
||||||
double Average();
|
void TransportPacketReceived(rtc::PacketTransportInternal *transport, const char *bytes, size_t size, const int64_t ×tamp, int unused);
|
||||||
|
|
||||||
private:
|
std::unique_ptr<rtc::Thread> networkThread;
|
||||||
void AppendPing(int64_t ms);
|
|
||||||
void UpdatePing(int64_t ms);
|
|
||||||
|
|
||||||
static const size_t history_length;
|
bool isOutgoing;
|
||||||
static const int64_t unavailable_ms;
|
std::unique_ptr<rtc::BasicPacketSocketFactory> socketFactory;
|
||||||
|
std::unique_ptr<rtc::BasicNetworkManager> networkManager;
|
||||||
|
std::unique_ptr<cricket::BasicPortAllocator> portAllocator;
|
||||||
|
std::unique_ptr<webrtc::BasicAsyncResolverFactory> asyncResolverFactory;
|
||||||
|
std::unique_ptr<cricket::P2PTransportChannel> transportChannel;
|
||||||
|
|
||||||
std::queue<int64_t > history;
|
std::vector<std::string> collectedLocalCandidates;
|
||||||
int64_t ping_sum;
|
|
||||||
uint32_t sent_id;
|
|
||||||
int64_t sent_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int64_t tcp_reconnect_delay;
|
|
||||||
static const int64_t ping_interval_ms;
|
|
||||||
static const int64_t endpoint_ping_diff_ms;
|
|
||||||
static const std::set<message::Type> multicast_types;
|
|
||||||
|
|
||||||
EndpointP2p *GetP2pEndpoint() const;
|
|
||||||
void AddEndpoint(std::unique_ptr<EndpointBase>);
|
|
||||||
void DeleteEndpoint(EndpointBase *ep);
|
|
||||||
void RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t len,
|
|
||||||
const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us);
|
|
||||||
void Ready(rtc::AsyncPacketSocket *);
|
|
||||||
void RecvMessage(const message::Base&, EndpointBase *);
|
|
||||||
void UpdateActiveEndpoint();
|
|
||||||
|
|
||||||
rtc::ProxyInfo proxy_info;
|
|
||||||
EndpointBase *active_endpoint;
|
|
||||||
std::unique_ptr<rtc::Thread> thread;
|
|
||||||
rtc::BasicPacketSocketFactory socket_factory;
|
|
||||||
std::unique_ptr<rtc::AsyncPacketSocket> socket;
|
|
||||||
std::unique_ptr<LayerBase> layer;
|
|
||||||
std::map<EndpointBase *, std::unique_ptr<EndpointBase>> endpoints;
|
|
||||||
std::map<EndpointBase *, PingHistory> ping_history;
|
|
||||||
webrtc::RepeatingTaskHandle pinger;
|
|
||||||
uint32_t ping_seq;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //DEMO_CONNECTOR_H
|
#endif //DEMO_CONNECTOR_H
|
||||||
|
@ -1,232 +1,158 @@
|
|||||||
#include "Connector.h"
|
#include "Connector.h"
|
||||||
|
|
||||||
#include "Endpoint.h"
|
|
||||||
#include "Layer92.h"
|
|
||||||
#include "MediaEngineWebrtc.h"
|
#include "MediaEngineWebrtc.h"
|
||||||
#include "Protocol10.h"
|
|
||||||
|
|
||||||
#include "api/packet_socket_factory.h"
|
#include "api/packet_socket_factory.h"
|
||||||
#include "rtc_base/task_utils/to_queued_task.h"
|
#include "rtc_base/task_utils/to_queued_task.h"
|
||||||
|
#include "p2p/base/ice_credentials_iterator.h"
|
||||||
|
#include "api/jsep_ice_candidate.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
const int64_t Connector::tcp_reconnect_delay = 5000;
|
Connector::Connector(bool isOutgoing) {
|
||||||
const int64_t Connector::ping_interval_ms = 10000;
|
networkThread = rtc::Thread::CreateWithSocketServer();
|
||||||
const int64_t Connector::endpoint_ping_diff_ms = 20;
|
|
||||||
const std::set<message::Type> Connector::multicast_types = {
|
|
||||||
message::Type::tInit, message::Type::tInitAck, message::Type::tPing
|
|
||||||
};
|
|
||||||
const size_t Connector::PingHistory::history_length = 5;
|
|
||||||
const int64_t Connector::PingHistory::unavailable_ms = 100000;
|
|
||||||
|
|
||||||
Connector::PingHistory::PingHistory()
|
this->isOutgoing = isOutgoing;
|
||||||
: ping_sum(0)
|
|
||||||
, sent_id(0)
|
|
||||||
, sent_time(0) {
|
|
||||||
for (size_t i = 0; i < history_length; ++i)
|
|
||||||
AppendPing(unavailable_ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connector::PingHistory::AppendPing(int64_t ms) {
|
Connector::~Connector() {
|
||||||
if (history.size() >= history_length) {
|
networkThread->Invoke<void>(RTC_FROM_HERE, [this]() {
|
||||||
ping_sum -= history.front();
|
transportChannel = nullptr;
|
||||||
history.pop();
|
asyncResolverFactory = nullptr;
|
||||||
}
|
portAllocator = nullptr;
|
||||||
if (history.size() < history_length) {
|
networkManager = nullptr;
|
||||||
ping_sum += ms;
|
socketFactory = nullptr;
|
||||||
history.emplace(ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::PingHistory::UpdatePing(int64_t ms) {
|
|
||||||
if (!history.empty()) {
|
|
||||||
ping_sum = ping_sum - history.back() + ms;
|
|
||||||
history.back() = ms;
|
|
||||||
} else
|
|
||||||
AppendPing(ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::PingHistory::Ping(uint32_t id) {
|
|
||||||
sent_id = id;
|
|
||||||
sent_time = rtc::TimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::PingHistory::Pong(uint32_t id) {
|
|
||||||
if (id != sent_id)
|
|
||||||
return;
|
|
||||||
sent_id = 0;
|
|
||||||
UpdatePing(std::min(rtc::TimeMillis() - sent_time, unavailable_ms));
|
|
||||||
sent_time = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Connector::PingHistory::Average() {
|
|
||||||
return static_cast<double>(ping_sum) / history.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
Connector::Connector(std::unique_ptr<LayerBase> layer)
|
|
||||||
: active_endpoint(nullptr)
|
|
||||||
, thread(rtc::Thread::CreateWithSocketServer())
|
|
||||||
, socket_factory(thread.get())
|
|
||||||
, layer(std::move(layer))
|
|
||||||
, ping_seq(0) {
|
|
||||||
pinger = webrtc::RepeatingTaskHandle::Start(thread.get(), [this]() {
|
|
||||||
Connector::UpdateActiveEndpoint();
|
|
||||||
return webrtc::TimeDelta::ms(ping_interval_ms);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connector::Start() {
|
void Connector::Start() {
|
||||||
thread->Start();
|
NSLog(@"Started %d", (int)[[NSDate date] timeIntervalSince1970]);
|
||||||
thread->Invoke<void>(RTC_FROM_HERE, [this]() {
|
networkThread->Start();
|
||||||
socket.reset(socket_factory.CreateUdpSocket(
|
|
||||||
rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0), 0, 0));
|
networkThread->Invoke<void>(RTC_FROM_HERE, [this] {
|
||||||
socket->SignalReadPacket.connect(this, &Connector::RecvPacket);
|
socketFactory.reset(new rtc::BasicPacketSocketFactory(networkThread.get()));
|
||||||
socket->SignalReadyToSend.connect(this, &Connector::Ready);
|
|
||||||
|
networkManager = std::make_unique<rtc::BasicNetworkManager>();
|
||||||
|
portAllocator.reset(new cricket::BasicPortAllocator(networkManager.get(), socketFactory.get(), /*turn_customizer=*/ nullptr, /*relay_port_factory=*/ nullptr));
|
||||||
|
uint32_t flags = cricket::PORTALLOCATOR_DISABLE_TCP;
|
||||||
|
//flags |= cricket::PORTALLOCATOR_DISABLE_UDP;
|
||||||
|
portAllocator->set_flags(portAllocator->flags() | flags);
|
||||||
|
portAllocator->Initialize();
|
||||||
|
|
||||||
|
rtc::SocketAddress defaultStunAddress = rtc::SocketAddress("hlgkfjdrtjfykgulhijkljhulyo.uksouth.cloudapp.azure.com", 3478);
|
||||||
|
cricket::ServerAddresses stunServers;
|
||||||
|
stunServers.insert(defaultStunAddress);
|
||||||
|
std::vector<cricket::RelayServerConfig> turnServers;
|
||||||
|
turnServers.push_back(cricket::RelayServerConfig(
|
||||||
|
rtc::SocketAddress("hlgkfjdrtjfykgulhijkljhulyo.uksouth.cloudapp.azure.com", 3478),
|
||||||
|
"user",
|
||||||
|
"root",
|
||||||
|
cricket::PROTO_UDP
|
||||||
|
));
|
||||||
|
portAllocator->SetConfiguration(stunServers, turnServers, 2, webrtc::NO_PRUNE);
|
||||||
|
|
||||||
|
asyncResolverFactory = std::make_unique<webrtc::BasicAsyncResolverFactory>();
|
||||||
|
transportChannel.reset(new cricket::P2PTransportChannel("transport", 0, portAllocator.get(), asyncResolverFactory.get(), /*event_log=*/ nullptr));
|
||||||
|
|
||||||
|
cricket::IceConfig iceConfig;
|
||||||
|
iceConfig.continual_gathering_policy = cricket::GATHER_CONTINUALLY;
|
||||||
|
transportChannel->SetIceConfig(iceConfig);
|
||||||
|
|
||||||
|
cricket::IceParameters localIceParameters(
|
||||||
|
"gcp3",
|
||||||
|
"zWDKozH8/3JWt8he3M/CMj5R",
|
||||||
|
false
|
||||||
|
);
|
||||||
|
cricket::IceParameters remoteIceParameters(
|
||||||
|
"acp3",
|
||||||
|
"aWDKozH8/3JWt8he3M/CMj5R",
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
transportChannel->SetIceParameters(isOutgoing ? localIceParameters : remoteIceParameters);
|
||||||
|
transportChannel->SetIceRole(isOutgoing ? cricket::ICEROLE_CONTROLLING : cricket::ICEROLE_CONTROLLED);
|
||||||
|
|
||||||
|
transportChannel->SignalCandidateGathered.connect(this, &Connector::CandidateGathered);
|
||||||
|
transportChannel->SignalGatheringState.connect(this, &Connector::CandidateGatheringState);
|
||||||
|
transportChannel->SignalIceTransportStateChanged.connect(this, &Connector::TransportStateChanged);
|
||||||
|
transportChannel->SignalRoleConflict.connect(this, &Connector::TransportRoleConflict);
|
||||||
|
transportChannel->SignalReadPacket.connect(this, &Connector::TransportPacketReceived);
|
||||||
|
|
||||||
|
transportChannel->MaybeStartGathering();
|
||||||
|
|
||||||
|
transportChannel->SetRemoteIceMode(cricket::ICEMODE_FULL);
|
||||||
|
transportChannel->SetRemoteIceParameters((!isOutgoing) ? localIceParameters : remoteIceParameters);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connector::RecvPacket(rtc::AsyncPacketSocket *sock, const char *data, size_t len,
|
void Connector::AddRemoteCandidates(const std::vector<std::string> &candidates) {
|
||||||
const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) {
|
networkThread->Invoke<void>(RTC_FROM_HERE, [this, candidates] {
|
||||||
for (const auto& ep : endpoints) {
|
for (auto &serializedCandidate : candidates) {
|
||||||
auto ep_udp = dynamic_cast<EndpointUdp *>(ep.first);
|
webrtc::JsepIceCandidate parseCandidate("", 0);
|
||||||
if (ep_udp && ep_udp->address == remote_addr) {
|
if (parseCandidate.Initialize(serializedCandidate, nullptr)) {
|
||||||
ep_udp->RecvPacket(sock, data, len, remote_addr, packet_time_us);
|
auto candidate = parseCandidate.candidate();
|
||||||
|
printf("Add remote candidate %s\n", serializedCandidate.c_str());
|
||||||
|
transportChannel->AddRemoteCandidate(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connector::CandidateGathered(cricket::IceTransportInternal *transport, const cricket::Candidate &candidate) {
|
||||||
|
assert(networkThread->IsCurrent());
|
||||||
|
|
||||||
|
webrtc::JsepIceCandidate iceCandidate("", 0);
|
||||||
|
iceCandidate.SetCandidate(candidate);
|
||||||
|
std::string serializedCandidate;
|
||||||
|
if (iceCandidate.ToString(&serializedCandidate)) {
|
||||||
|
std::vector<std::string> arrayOfOne;
|
||||||
|
arrayOfOne.push_back(serializedCandidate);
|
||||||
|
SignalCandidatesGathered(arrayOfOne);
|
||||||
|
|
||||||
|
webrtc::JsepIceCandidate parseCandidate("", 0);
|
||||||
|
if (parseCandidate.Initialize(serializedCandidate, nullptr)) {
|
||||||
|
auto candidate = parseCandidate.candidate();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connector::CandidateGatheringState(cricket::IceTransportInternal *transport) {
|
||||||
|
if (transport->gathering_state() == cricket::IceGatheringState::kIceGatheringComplete) {
|
||||||
|
/*if (collectedLocalCandidates.size() != 0) {
|
||||||
|
SignalCandidatesGathered(collectedLocalCandidates);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connector::TransportStateChanged(cricket::IceTransportInternal *transport) {
|
||||||
|
auto state = transport->GetIceTransportState();
|
||||||
|
switch (state) {
|
||||||
|
case webrtc::IceTransportState::kConnected:
|
||||||
|
case webrtc::IceTransportState::kCompleted:
|
||||||
|
SignalReadyToSendStateChanged(true);
|
||||||
|
printf("===== State: Connected\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SignalReadyToSendStateChanged(false);
|
||||||
|
printf("===== State: Disconnected\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Connector::TransportRoleConflict(cricket::IceTransportInternal *transport) {
|
||||||
|
printf("===== Role conflict\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connector::Ready(rtc::AsyncPacketSocket *) {
|
void Connector::TransportPacketReceived(rtc::PacketTransportInternal *transport, const char *bytes, size_t size, const int64_t ×tamp, __unused int unused) {
|
||||||
SignalMessage(message::Ready());
|
rtc::CopyOnWriteBuffer data;
|
||||||
|
data.AppendData(bytes, size);
|
||||||
|
SignalPacketReceived(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connector::AddEndpointRelayTcpObfuscated(const rtc::SocketAddress& addr, const Relay::PeerTag& peer_tag) {
|
void Connector::SendPacket(const rtc::CopyOnWriteBuffer& data) {
|
||||||
thread->Invoke<void>(RTC_FROM_HERE, [this, addr, peer_tag]() {
|
networkThread->Invoke<void>(RTC_FROM_HERE, [this, data] {
|
||||||
std::unique_ptr<rtc::AsyncPacketSocket> sock(socket_factory.CreateClientTcpSocket(
|
rtc::PacketOptions options;
|
||||||
rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0),
|
transportChannel->SendPacket((const char *)data.data(), data.size(), options, 0);
|
||||||
addr, proxy_info, "", rtc::PacketSocketTcpOptions()));
|
|
||||||
AddEndpoint(std::make_unique<EndpointRelayObfuscatedTcp>(std::move(sock), peer_tag, layer.get()));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connector::AddEndpointRelayUdp(const rtc::SocketAddress& addr, const Relay::PeerTag& peer_tag) {
|
|
||||||
thread->Invoke<void>(RTC_FROM_HERE, [this, addr, peer_tag]() {
|
|
||||||
assert(socket);
|
|
||||||
AddEndpoint(std::make_unique<EndpointRelayUdp>(addr, peer_tag, socket.get(), layer.get()));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::SetEndpointP2p(const rtc::SocketAddress& addr) {
|
|
||||||
thread->Invoke<void>(RTC_FROM_HERE, [this, addr]() {
|
|
||||||
assert(socket);
|
|
||||||
if (auto ep = GetP2pEndpoint())
|
|
||||||
DeleteEndpoint(ep);
|
|
||||||
AddEndpoint(std::make_unique<EndpointP2p>(addr, socket.get(), layer.get()));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Connector::~Connector() {
|
|
||||||
thread->Invoke<void>(RTC_FROM_HERE, [this]() {
|
|
||||||
pinger.Stop();
|
|
||||||
active_endpoint = nullptr;
|
|
||||||
endpoints.clear();
|
|
||||||
ping_history.clear();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::RecvMessage(const message::Base& msg, EndpointBase *endpoint) {
|
|
||||||
if (msg.ID == message::tDisconnected && endpoint->type == EndpointBase::Type::RelayObfuscatedTcp) {
|
|
||||||
thread->PostDelayedTask(webrtc::ToQueuedTask([this, endpoint]() {
|
|
||||||
if (endpoints.find(endpoint) == endpoints.end())
|
|
||||||
return;
|
|
||||||
auto final_ep = dynamic_cast<EndpointRelayObfuscatedTcp *>(endpoint);
|
|
||||||
if (!final_ep)
|
|
||||||
return;
|
|
||||||
std::unique_ptr<rtc::AsyncPacketSocket> sock(socket_factory.CreateClientTcpSocket(
|
|
||||||
rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0),
|
|
||||||
final_ep->address, proxy_info, "", rtc::PacketSocketTcpOptions()));
|
|
||||||
final_ep->Reconnect(std::move(sock));
|
|
||||||
}), tcp_reconnect_delay);
|
|
||||||
if (active_endpoint == endpoint)
|
|
||||||
ResetActiveEndpoint();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (auto msg_ping = dynamic_cast<const message::Ping *>(&msg)) {
|
|
||||||
message::Pong msg_pong;
|
|
||||||
msg_pong.id = msg_ping->id;
|
|
||||||
endpoint->SendMessage(msg_pong);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (auto msg_pong = dynamic_cast<const message::Pong *>(&msg)) {
|
|
||||||
ping_history[endpoint].Pong(msg_pong->id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// fallback if no active endpoint set
|
|
||||||
if (!active_endpoint)
|
|
||||||
active_endpoint = endpoint;
|
|
||||||
SignalMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::SendMessage(const message::Base& msg) {
|
|
||||||
if (!active_endpoint || multicast_types.find(msg.ID) != multicast_types.end()) {
|
|
||||||
for (const auto& ep : endpoints) {
|
|
||||||
ep.first->SendMessage(msg);
|
|
||||||
if (auto msg_ping = dynamic_cast<const message::Ping *>(&msg))
|
|
||||||
ping_history[ep.first].Ping(msg_ping->id);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
active_endpoint->SendMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
EndpointP2p *Connector::GetP2pEndpoint() const {
|
|
||||||
for (const auto& ep : endpoints)
|
|
||||||
if (auto ep_p2p = dynamic_cast<EndpointP2p *>(ep.first))
|
|
||||||
return ep_p2p;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::AddEndpoint(std::unique_ptr<EndpointBase> endpoint) {
|
|
||||||
EndpointBase *ep = endpoint.get();
|
|
||||||
ep->SignalMessage.connect(this, &Connector::RecvMessage);
|
|
||||||
endpoints[ep] = std::move(endpoint);
|
|
||||||
ping_history[ep] = PingHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::DeleteEndpoint(EndpointBase *ep) {
|
|
||||||
// TODO: must be invoked to thread when become public
|
|
||||||
endpoints.erase(ep);
|
|
||||||
ping_history.erase(ep);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::ResetActiveEndpoint() {
|
|
||||||
active_endpoint = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::UpdateActiveEndpoint() {
|
|
||||||
if (ping_history.empty())
|
|
||||||
return;
|
|
||||||
if (ping_history.size() == 1) {
|
|
||||||
active_endpoint = ping_history.begin()->first;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::vector<std::pair<double, EndpointBase*>> times;
|
|
||||||
for (auto ping : ping_history)
|
|
||||||
times.emplace_back(ping.second.Average(), ping.first);
|
|
||||||
std::sort(times.begin(), times.end());
|
|
||||||
EndpointBase *candidate = times.front().second;
|
|
||||||
if (!active_endpoint || (active_endpoint != candidate &&
|
|
||||||
ping_history[active_endpoint].Average() - times.front().first > endpoint_ping_diff_ms))
|
|
||||||
active_endpoint = candidate;
|
|
||||||
message::Ping msg;
|
|
||||||
msg.id = ++ping_seq;
|
|
||||||
SendMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connector::SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username,
|
|
||||||
const std::string& password) {
|
|
||||||
proxy_info.type = type;
|
|
||||||
proxy_info.address = addr;
|
|
||||||
proxy_info.username = username;
|
|
||||||
proxy_info.password = rtc::CryptString();
|
|
||||||
}
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "Connector.h"
|
#include "Connector.h"
|
||||||
#include "MediaEngineWebrtc.h"
|
#include "MediaEngineWebrtc.h"
|
||||||
#include "Layer92.h"
|
|
||||||
|
|
||||||
#include "rtc_base/copy_on_write_buffer.h"
|
#include "rtc_base/copy_on_write_buffer.h"
|
||||||
#include "rtc_base/socket_address.h"
|
#include "rtc_base/socket_address.h"
|
||||||
@ -30,21 +29,21 @@ public:
|
|||||||
Reconnecting,
|
Reconnecting,
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Controller(bool is_outgoing, const EncryptionKey& encryption_key, size_t init_timeout, size_t reconnect_timeout);
|
explicit Controller(bool is_outgoing, size_t init_timeout, size_t reconnect_timeout);
|
||||||
~Controller() override;
|
~Controller() override;
|
||||||
void AddEndpoint(const rtc::SocketAddress& address, const Relay::PeerTag& peer_tag, EndpointType type);
|
|
||||||
void Start();
|
void Start();
|
||||||
void SetNetworkType(message::NetworkType network_type);
|
//void SetNetworkType(message::NetworkType network_type);
|
||||||
void SetDataSaving(bool data_saving);
|
void SetDataSaving(bool data_saving);
|
||||||
void SetMute(bool mute);
|
void SetMute(bool mute);
|
||||||
void AttachVideoView(VideoMetalView *videoView);
|
void AttachVideoView(rtc::VideoSinkInterface<webrtc::VideoFrame> *sink);
|
||||||
void SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username,
|
void SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username, const std::string& password);
|
||||||
const std::string& password);
|
void AddRemoteCandidates(const std::vector<std::string> &candidates);
|
||||||
|
|
||||||
static std::map<message::NetworkType, MediaEngineWebrtc::NetworkParams> network_params;
|
//static std::map<message::NetworkType, MediaEngineWebrtc::NetworkParams> network_params;
|
||||||
static MediaEngineWebrtc::NetworkParams default_network_params;
|
static MediaEngineWebrtc::NetworkParams default_network_params;
|
||||||
static MediaEngineWebrtc::NetworkParams datasaving_network_params;
|
static MediaEngineWebrtc::NetworkParams datasaving_network_params;
|
||||||
sigslot::signal1<State> SignalNewState;
|
sigslot::signal1<State> SignalNewState;
|
||||||
|
sigslot::signal1<const std::vector<std::string>&> SignalCandidatesGathered;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<rtc::Thread> thread;
|
std::unique_ptr<rtc::Thread> thread;
|
||||||
@ -59,17 +58,17 @@ private:
|
|||||||
const size_t reconnect_timeout;
|
const size_t reconnect_timeout;
|
||||||
bool local_datasaving;
|
bool local_datasaving;
|
||||||
bool final_datasaving;
|
bool final_datasaving;
|
||||||
message::NetworkType local_network_type;
|
//message::NetworkType local_network_type;
|
||||||
message::NetworkType final_network_type;
|
//message::NetworkType final_network_type;
|
||||||
|
|
||||||
template <class Closure> void StartRepeating(Closure&& closure);
|
void PacketReceived(const rtc::CopyOnWriteBuffer &);
|
||||||
void StopRepeating();
|
void WriteableStateChanged(bool);
|
||||||
void NewMessage(const message::Base& msg);
|
void CandidatesGathered(const std::vector<std::string> &);
|
||||||
void SetFail();
|
void SetFail();
|
||||||
void Play(const int16_t *data, size_t size);
|
void Play(const int16_t *data, size_t size);
|
||||||
void Record(int16_t *data, size_t size);
|
void Record(int16_t *data, size_t size);
|
||||||
void SendRtp(rtc::CopyOnWriteBuffer packet);
|
void SendRtp(rtc::CopyOnWriteBuffer packet);
|
||||||
void UpdateNetworkParams(const message::RtpStream& rtp);
|
//void UpdateNetworkParams(const message::RtpStream& rtp);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
#include "Controller.h"
|
#include "Controller.h"
|
||||||
|
|
||||||
#include "Layer92.h"
|
|
||||||
|
|
||||||
#include "modules/rtp_rtcp/source/rtp_utility.h"
|
#include "modules/rtp_rtcp/source/rtp_utility.h"
|
||||||
#include "rtc_base/time_utils.h"
|
#include "rtc_base/time_utils.h"
|
||||||
#include "rtc_base/message_handler.h"
|
#include "rtc_base/message_handler.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
std::map<message::NetworkType, MediaEngineWebrtc::NetworkParams> Controller::network_params = {
|
/*std::map<message::NetworkType, MediaEngineWebrtc::NetworkParams> Controller::network_params = {
|
||||||
{message::NetworkType::nGprs, {6, 8, 6, 120, false, false, false}},
|
{message::NetworkType::nGprs, {6, 8, 6, 120, false, false, false}},
|
||||||
{message::NetworkType::nEdge, {6, 16, 6, 120, false, false, false}},
|
{message::NetworkType::nEdge, {6, 16, 6, 120, false, false, false}},
|
||||||
{message::NetworkType::n3gOrAbove, {6, 32, 16, 60, false, false, false}},
|
{message::NetworkType::n3gOrAbove, {6, 32, 16, 60, false, false, false}},
|
||||||
};
|
};
|
||||||
MediaEngineWebrtc::NetworkParams Controller::default_network_params = {6, 32, 16, 30, false, false, false};
|
MediaEngineWebrtc::NetworkParams Controller::default_network_params = {6, 32, 16, 30, false, false, false};
|
||||||
MediaEngineWebrtc::NetworkParams Controller::datasaving_network_params = {6, 8, 6, 120, false, false, true};
|
MediaEngineWebrtc::NetworkParams Controller::datasaving_network_params = {6, 8, 6, 120, false, false, true};*/
|
||||||
|
|
||||||
Controller::Controller(bool is_outgoing, const EncryptionKey& encryption_key, size_t init_timeout, size_t reconnect_timeout)
|
Controller::Controller(bool is_outgoing, size_t init_timeout, size_t reconnect_timeout)
|
||||||
: thread(rtc::Thread::Create())
|
: thread(rtc::Thread::Create())
|
||||||
, connector(std::make_unique<Connector>(std::make_unique<Layer92>(encryption_key, is_outgoing)))
|
, connector(std::make_unique<Connector>(is_outgoing))
|
||||||
, state(State::Starting)
|
, state(State::Starting)
|
||||||
, last_recv_time(rtc::TimeMillis())
|
, last_recv_time(rtc::TimeMillis())
|
||||||
, last_send_time(rtc::TimeMillis())
|
, last_send_time(rtc::TimeMillis())
|
||||||
@ -27,11 +25,16 @@ Controller::Controller(bool is_outgoing, const EncryptionKey& encryption_key, si
|
|||||||
, reconnect_timeout(reconnect_timeout * 1000)
|
, reconnect_timeout(reconnect_timeout * 1000)
|
||||||
, local_datasaving(false)
|
, local_datasaving(false)
|
||||||
, final_datasaving(false)
|
, final_datasaving(false)
|
||||||
, local_network_type(message::NetworkType::nUnknown)
|
|
||||||
, final_network_type(message::NetworkType::nUnknown)
|
|
||||||
{
|
{
|
||||||
connector->SignalMessage.connect(this, &Controller::NewMessage);
|
connector->SignalReadyToSendStateChanged.connect(this, &Controller::WriteableStateChanged);
|
||||||
|
connector->SignalPacketReceived.connect(this, &Controller::PacketReceived);
|
||||||
|
connector->SignalCandidatesGathered.connect(this, &Controller::CandidatesGathered);
|
||||||
thread->Start();
|
thread->Start();
|
||||||
|
|
||||||
|
thread->Invoke<void>(RTC_FROM_HERE, [this, is_outgoing]() {
|
||||||
|
media.reset(new MediaEngineWebrtc(is_outgoing));
|
||||||
|
media->Send.connect(this, &Controller::SendRtp);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller::~Controller() {
|
Controller::~Controller() {
|
||||||
@ -41,121 +44,37 @@ Controller::~Controller() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::AddEndpoint(const rtc::SocketAddress& address, const Relay::PeerTag &peer_tag,
|
|
||||||
Controller::EndpointType type) {
|
|
||||||
if (type == EndpointType::UDP)
|
|
||||||
connector->AddEndpointRelayUdp(address, peer_tag);
|
|
||||||
else if (type == EndpointType::TCP)
|
|
||||||
connector->AddEndpointRelayTcpObfuscated(address, peer_tag);
|
|
||||||
else if (type == EndpointType::P2P)
|
|
||||||
connector->SetEndpointP2p(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::Start() {
|
void Controller::Start() {
|
||||||
last_recv_time = rtc::TimeMillis();
|
last_recv_time = rtc::TimeMillis();
|
||||||
connector->Start();
|
connector->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::NewMessage(const message::Base& msg) {
|
void Controller::PacketReceived(const rtc::CopyOnWriteBuffer &data) {
|
||||||
if (msg.ID == message::tReady && state == State::Starting) {
|
thread->PostTask(RTC_FROM_HERE, [this, data]() {
|
||||||
state = State::WaitInit;
|
|
||||||
SignalNewState(state);
|
|
||||||
StartRepeating([this]() {
|
|
||||||
message::Init msg;
|
|
||||||
msg.minVer = ProtocolBase::minimal_version;
|
|
||||||
msg.ver = ProtocolBase::actual_version;
|
|
||||||
connector->SendMessage(msg);
|
|
||||||
//if (rtc::TimeMillis() - last_recv_time > init_timeout)
|
|
||||||
// SetFail();
|
|
||||||
return webrtc::TimeDelta::seconds(1);
|
|
||||||
});
|
|
||||||
} else if ((msg.ID == message::tInit || msg.ID == message::tInitAck) && state == State::WaitInit) {
|
|
||||||
state = State::WaitInitAck;
|
|
||||||
SignalNewState(state);
|
|
||||||
StartRepeating([this]() {
|
|
||||||
message::InitAck msg;
|
|
||||||
// TODO: version matching
|
|
||||||
msg.minVer = ProtocolBase::minimal_version;
|
|
||||||
msg.ver = ProtocolBase::actual_version;
|
|
||||||
connector->SendMessage(msg);
|
|
||||||
//if (rtc::TimeMillis() - last_recv_time > init_timeout)
|
|
||||||
// SetFail();
|
|
||||||
return webrtc::TimeDelta::seconds(1);
|
|
||||||
});
|
|
||||||
} else if ((msg.ID == message::tInitAck || msg.ID == message::tRtpStream) && state == State::WaitInitAck) {
|
|
||||||
state = State::Established;
|
|
||||||
SignalNewState(state);
|
|
||||||
thread->PostTask(RTC_FROM_HERE, [this]() {
|
|
||||||
media = std::make_unique<MediaEngineWebrtc>(is_outgoing);
|
|
||||||
media->Send.connect(this, &Controller::SendRtp);
|
|
||||||
});
|
|
||||||
StartRepeating([this]() {
|
|
||||||
if (state == State::Established && rtc::TimeMillis() - last_recv_time > 1000) {
|
|
||||||
connector->ResetActiveEndpoint();
|
|
||||||
state = State::Reconnecting;
|
|
||||||
SignalNewState(state);
|
|
||||||
} else if (state == State::Reconnecting && rtc::TimeMillis() - last_recv_time > reconnect_timeout) {
|
|
||||||
//SetFail();
|
|
||||||
}
|
|
||||||
return webrtc::TimeDelta::seconds(1);
|
|
||||||
});
|
|
||||||
} if ((msg.ID == message::tRtpStream) && (state == State::Established || state == State::Reconnecting)) {
|
|
||||||
const auto msg_rtp = *dynamic_cast<const message::RtpStream *>(&msg);
|
|
||||||
thread->PostTask(RTC_FROM_HERE, [this, msg_rtp]() {
|
|
||||||
if (media) {
|
if (media) {
|
||||||
media->Receive(msg_rtp.data);
|
media->Receive(data);
|
||||||
UpdateNetworkParams(msg_rtp);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!webrtc::RtpUtility::RtpHeaderParser(msg_rtp.data.data(), msg_rtp.data.size()).RTCP()) {
|
|
||||||
//printf("rtp received size %d\n", (int)(msg_rtp.data.size()));
|
|
||||||
last_recv_time = rtc::TimeMillis();
|
|
||||||
if (state == State::Reconnecting) {
|
|
||||||
state = State::Established;
|
|
||||||
SignalNewState(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Controller::WriteableStateChanged(bool isWriteable) {
|
||||||
|
if (isWriteable) {
|
||||||
|
SignalNewState(State::Established);
|
||||||
} else {
|
} else {
|
||||||
//printf("rtcp received size %d\n", (int)(msg_rtp.data.size()));
|
SignalNewState(State::Reconnecting);
|
||||||
}
|
}
|
||||||
} else if (msg.ID == message::tBufferOverflow ||
|
thread->PostTask(RTC_FROM_HERE, [this, isWriteable]() {
|
||||||
msg.ID == message::tPacketIncorrect ||
|
if (media) {
|
||||||
msg.ID == message::tWrongProtocol) {
|
media->SetCanSendPackets(isWriteable);
|
||||||
SetFail();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<class Closure>
|
|
||||||
void Controller::StartRepeating(Closure&& closure) {
|
|
||||||
//StopRepeating();
|
|
||||||
repeatable = webrtc::RepeatingTaskHandle::Start(thread.get(), std::forward<Closure>(closure));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::StopRepeating() {
|
|
||||||
thread->Invoke<void>(RTC_FROM_HERE, [this]() {
|
|
||||||
repeatable.Stop();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::SetFail() {
|
|
||||||
thread->PostTask(RTC_FROM_HERE, [this]() {
|
|
||||||
media = nullptr;
|
|
||||||
});
|
|
||||||
if (state != State::Failed) {
|
|
||||||
state = State::Failed;
|
|
||||||
SignalNewState(state);
|
|
||||||
}
|
|
||||||
StopRepeating();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::SendRtp(rtc::CopyOnWriteBuffer packet) {
|
void Controller::SendRtp(rtc::CopyOnWriteBuffer packet) {
|
||||||
message::RtpStream msg;
|
connector->SendPacket(packet);
|
||||||
msg.data = packet;
|
|
||||||
msg.network_type = local_network_type;
|
|
||||||
msg.data_saving = local_datasaving;
|
|
||||||
connector->SendMessage(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::UpdateNetworkParams(const message::RtpStream& rtp) {
|
/*void Controller::UpdateNetworkParams(const message::RtpStream& rtp) {
|
||||||
bool new_datasaving = local_datasaving || rtp.data_saving;
|
bool new_datasaving = local_datasaving || rtp.data_saving;
|
||||||
if (!new_datasaving) {
|
if (!new_datasaving) {
|
||||||
final_datasaving = false;
|
final_datasaving = false;
|
||||||
@ -172,17 +91,17 @@ void Controller::UpdateNetworkParams(const message::RtpStream& rtp) {
|
|||||||
final_datasaving = true;
|
final_datasaving = true;
|
||||||
media->SetNetworkParams(datasaving_network_params);
|
media->SetNetworkParams(datasaving_network_params);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void Controller::AttachVideoView(VideoMetalView *videoView) {
|
void Controller::AttachVideoView(rtc::VideoSinkInterface<webrtc::VideoFrame> *sink) {
|
||||||
thread->PostTask(RTC_FROM_HERE, [this, videoView]() {
|
thread->PostTask(RTC_FROM_HERE, [this, sink]() {
|
||||||
media->AttachVideoView(videoView);
|
media->AttachVideoView(sink);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::SetNetworkType(message::NetworkType network_type) {
|
/*void Controller::SetNetworkType(message::NetworkType network_type) {
|
||||||
local_network_type = network_type;
|
local_network_type = network_type;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void Controller::SetDataSaving(bool data_saving) {
|
void Controller::SetDataSaving(bool data_saving) {
|
||||||
local_datasaving = data_saving;
|
local_datasaving = data_saving;
|
||||||
@ -195,7 +114,13 @@ void Controller::SetMute(bool mute) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username,
|
void Controller::SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username, const std::string& password) {
|
||||||
const std::string& password) {
|
}
|
||||||
connector->SetProxy(type, addr, username, password);
|
|
||||||
|
void Controller::CandidatesGathered(const std::vector<std::string> &candidates) {
|
||||||
|
SignalCandidatesGathered(candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::AddRemoteCandidates(const std::vector<std::string> &candidates) {
|
||||||
|
connector->AddRemoteCandidates(candidates);
|
||||||
}
|
}
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
#ifndef DEMO_ENDPOINT_H
|
|
||||||
#define DEMO_ENDPOINT_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "LayerBase.h"
|
|
||||||
#include "Message.h"
|
|
||||||
|
|
||||||
#include "rtc_base/async_packet_socket.h"
|
|
||||||
#include "rtc_base/buffer_queue.h"
|
|
||||||
#include "rtc_base/socket_address.h"
|
|
||||||
|
|
||||||
class Connector;
|
|
||||||
|
|
||||||
class EndpointBase : public sigslot::has_slots<> {
|
|
||||||
public:
|
|
||||||
enum Type {
|
|
||||||
Unknown,
|
|
||||||
RelayUdp,
|
|
||||||
RelayObfuscatedTcp,
|
|
||||||
P2p,
|
|
||||||
};
|
|
||||||
|
|
||||||
EndpointBase(const EndpointBase&) = delete;
|
|
||||||
virtual void SendMessage(const message::Base&) = 0;
|
|
||||||
sigslot::signal2<const message::Base&, EndpointBase *> SignalMessage;
|
|
||||||
const Type type;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit EndpointBase(LayerBase *layer, Type type);
|
|
||||||
virtual void RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t len,
|
|
||||||
const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us);
|
|
||||||
virtual void SendPacket(const uint8_t *data, size_t size) = 0;
|
|
||||||
|
|
||||||
LayerBase *layer;
|
|
||||||
rtc::PacketOptions packet_options;
|
|
||||||
std::unique_ptr<rtc::ByteBufferReader> in_buffer;
|
|
||||||
size_t in_remains;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Relay {
|
|
||||||
public:
|
|
||||||
typedef unsigned char PeerTag[16];
|
|
||||||
|
|
||||||
virtual ~Relay() = default;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit Relay(const PeerTag& peer_tag);
|
|
||||||
bool CheckPacket(rtc::ByteBufferReader *packet);
|
|
||||||
const rtc::Buffer& PreparePacket(const rtc::Buffer& packet);
|
|
||||||
|
|
||||||
PeerTag peer_tag; // how to initialize it in initializer list?
|
|
||||||
|
|
||||||
private:
|
|
||||||
rtc::Buffer buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
class EndpointUdp : public EndpointBase {
|
|
||||||
public:
|
|
||||||
const rtc::SocketAddress address;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class Connector;
|
|
||||||
// friend void Connector::RecvPacket(rtc::AsyncPacketSocket *, const char *, size_t,
|
|
||||||
// const rtc::SocketAddress&, const int64_t&);
|
|
||||||
|
|
||||||
EndpointUdp(const rtc::SocketAddress& addr, rtc::AsyncPacketSocket *socket, LayerBase *layer, Type type);
|
|
||||||
void SendPacket(const uint8_t *data, size_t size) override;
|
|
||||||
|
|
||||||
rtc::AsyncPacketSocket *socket;
|
|
||||||
};
|
|
||||||
|
|
||||||
class EndpointTcp : public EndpointBase {
|
|
||||||
public:
|
|
||||||
const rtc::SocketAddress address;
|
|
||||||
|
|
||||||
void Reconnect(std::unique_ptr<rtc::AsyncPacketSocket> socket_);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit EndpointTcp(std::unique_ptr<rtc::AsyncPacketSocket> socket, LayerBase *layer, Type type);
|
|
||||||
void SendPacket(const uint8_t *data, size_t size) override;
|
|
||||||
|
|
||||||
virtual void Ready(rtc::AsyncPacketSocket *) = 0;
|
|
||||||
virtual void Close(rtc::AsyncPacketSocket *, int) = 0;
|
|
||||||
|
|
||||||
std::unique_ptr<rtc::AsyncPacketSocket> socket;
|
|
||||||
};
|
|
||||||
|
|
||||||
class EndpointRelayObfuscatedTcp final : public Relay, public EndpointTcp {
|
|
||||||
public:
|
|
||||||
EndpointRelayObfuscatedTcp(std::unique_ptr<rtc::AsyncPacketSocket> socket, const PeerTag& peer_tag,
|
|
||||||
LayerBase *layer);
|
|
||||||
void SendMessage(const message::Base&) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t len,
|
|
||||||
const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) override;
|
|
||||||
void Ready(rtc::AsyncPacketSocket *) override;
|
|
||||||
void Close(rtc::AsyncPacketSocket *, int) override;
|
|
||||||
void SendPacket(const uint8_t *data, size_t size) override;
|
|
||||||
|
|
||||||
TCPO2State recvState;
|
|
||||||
TCPO2State sendState;
|
|
||||||
};
|
|
||||||
|
|
||||||
class EndpointRelayUdp final : public Relay, public EndpointUdp {
|
|
||||||
public:
|
|
||||||
EndpointRelayUdp(const rtc::SocketAddress& addr, const PeerTag& peer_tag,
|
|
||||||
rtc::AsyncPacketSocket *socket, LayerBase *layer);
|
|
||||||
void SendMessage(const message::Base&) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t len,
|
|
||||||
const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class EndpointP2p final : public EndpointUdp {
|
|
||||||
public:
|
|
||||||
EndpointP2p(const rtc::SocketAddress& addr, rtc::AsyncPacketSocket *socket, LayerBase *layer);
|
|
||||||
void SendMessage(const message::Base&) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t len,
|
|
||||||
const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //DEMO_ENDPOINT_H
|
|
@ -1,205 +0,0 @@
|
|||||||
#include "Endpoint.h"
|
|
||||||
|
|
||||||
#include "rtc_base/buffer.h"
|
|
||||||
#include "rtc_base/byte_buffer.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
EndpointBase::EndpointBase(LayerBase *layer, Type type)
|
|
||||||
: type(type)
|
|
||||||
, layer(layer)
|
|
||||||
, in_buffer(std::make_unique<rtc::ByteBufferReader>(nullptr, 0))
|
|
||||||
, in_remains(0) {}
|
|
||||||
|
|
||||||
void EndpointBase::RecvPacket(rtc::AsyncPacketSocket *, const char *data, size_t len,
|
|
||||||
const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) {
|
|
||||||
if (in_buffer && in_buffer->Length() > 0) {
|
|
||||||
rtc::Buffer tmp(in_buffer->Data(), in_buffer->Length() + len);
|
|
||||||
memcpy(tmp.data() + in_buffer->Length(), data, len);
|
|
||||||
in_buffer = std::make_unique<rtc::ByteBufferReader>(reinterpret_cast<const char *>(tmp.data()), tmp.size());
|
|
||||||
} else
|
|
||||||
in_buffer = std::make_unique<rtc::ByteBufferReader>(data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
EndpointUdp::EndpointUdp(const rtc::SocketAddress& addr, rtc::AsyncPacketSocket *socket, LayerBase *layer, Type type)
|
|
||||||
: EndpointBase(layer, type)
|
|
||||||
, address(addr)
|
|
||||||
, socket(socket) {}
|
|
||||||
|
|
||||||
void EndpointUdp::SendPacket(const uint8_t *data, size_t size) {
|
|
||||||
socket->SendTo(data, size, address, packet_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
EndpointTcp::EndpointTcp(std::unique_ptr<rtc::AsyncPacketSocket> socket, LayerBase *layer, Type type)
|
|
||||||
: EndpointBase(layer, type)
|
|
||||||
, address(socket->GetRemoteAddress())
|
|
||||||
, socket(nullptr) {
|
|
||||||
Reconnect(std::move(socket));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndpointTcp::Reconnect(std::unique_ptr<rtc::AsyncPacketSocket> socket_) {
|
|
||||||
socket = std::move(socket_);
|
|
||||||
socket->SignalReadPacket.connect(dynamic_cast<EndpointBase *>(this), &EndpointTcp::RecvPacket);
|
|
||||||
socket->SignalReadyToSend.connect(this, &EndpointTcp::Ready);
|
|
||||||
socket->SignalClose.connect(this, &EndpointTcp::Close);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndpointTcp::SendPacket(const uint8_t *data, size_t size) {
|
|
||||||
socket->Send(data, size, packet_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
Relay::Relay(const PeerTag& peer_tag_) : peer_tag() {
|
|
||||||
memcpy(peer_tag, peer_tag_, sizeof(PeerTag));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Relay::CheckPacket(rtc::ByteBufferReader *packet) {
|
|
||||||
if (packet->Length() >= 16 && memcmp(peer_tag, packet->Data(), 16) == 0) {
|
|
||||||
packet->Consume(16);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rtc::Buffer& Relay::PreparePacket(const rtc::Buffer& packet) {
|
|
||||||
buffer.Clear();
|
|
||||||
if (!packet.empty()) {
|
|
||||||
buffer.AppendData(peer_tag, 16);
|
|
||||||
buffer.AppendData(packet);
|
|
||||||
}
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
EndpointRelayObfuscatedTcp::EndpointRelayObfuscatedTcp(std::unique_ptr<rtc::AsyncPacketSocket> socket,
|
|
||||||
const PeerTag& peer_tag, LayerBase *layer)
|
|
||||||
: Relay(peer_tag)
|
|
||||||
, EndpointTcp(std::move(socket), layer, Type::RelayObfuscatedTcp)
|
|
||||||
, recvState()
|
|
||||||
, sendState() {}
|
|
||||||
|
|
||||||
void EndpointRelayObfuscatedTcp::Ready(rtc::AsyncPacketSocket *) {
|
|
||||||
unsigned char buf[64];
|
|
||||||
layer->GenerateTCPO2States(buf, &recvState, &sendState);
|
|
||||||
EndpointTcp::SendPacket(buf, 64);
|
|
||||||
SignalMessage(message::Connected(), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndpointRelayObfuscatedTcp::Close(rtc::AsyncPacketSocket *, int) {
|
|
||||||
SignalMessage(message::Disconnected(), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndpointRelayObfuscatedTcp::RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t packet_len,
|
|
||||||
const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) {
|
|
||||||
EndpointBase::RecvPacket(socket, data, packet_len, remote_addr, packet_time_us);
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (in_remains > in_buffer->Length())
|
|
||||||
break;
|
|
||||||
if (in_remains > 0 && CheckPacket(in_buffer.get())) {
|
|
||||||
auto msg = layer->DecodePacket(*in_buffer);
|
|
||||||
if (msg)
|
|
||||||
SignalMessage(*msg, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char len1;
|
|
||||||
size_t packetLen = 0;
|
|
||||||
if (!in_buffer->ReadUInt8(&len1))
|
|
||||||
break;
|
|
||||||
layer->EncryptForTCPO2(&len1, 1, &recvState);
|
|
||||||
if (len1 < 0x7F) {
|
|
||||||
packetLen = (size_t) len1 * 4;
|
|
||||||
} else {
|
|
||||||
unsigned char len2[3];
|
|
||||||
if (!in_buffer->ReadBytes(reinterpret_cast<char *>(&len2), 3)) {
|
|
||||||
SignalMessage(message::PacketIncorrect(), this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
layer->EncryptForTCPO2(len2, 3, &recvState);
|
|
||||||
packetLen = ((size_t) len2[0] | ((size_t) len2[1] << 8) | ((size_t) len2[2] << 16)) * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
in_remains = packetLen;
|
|
||||||
if (packetLen > in_buffer->Length()) {
|
|
||||||
in_remains = packetLen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndpointRelayObfuscatedTcp::SendMessage(const message::Base& msg_base) {
|
|
||||||
if (socket->GetState() == rtc::AsyncPacketSocket::State::STATE_CLOSED)
|
|
||||||
return;
|
|
||||||
const rtc::Buffer& out = PreparePacket(layer->EncodePacket(&msg_base));
|
|
||||||
if (!out.empty())
|
|
||||||
SendPacket(out.data(), out.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndpointRelayObfuscatedTcp::SendPacket(const uint8_t *data, size_t size) {
|
|
||||||
rtc::ByteBufferWriter out;
|
|
||||||
size_t len = size / 4;
|
|
||||||
if (len < 0x7F) {
|
|
||||||
out.WriteUInt8(len);
|
|
||||||
} else {
|
|
||||||
out.WriteUInt8(0x7F);
|
|
||||||
out.WriteUInt8(len & 0xFF);
|
|
||||||
out.WriteUInt8((len >> 8) & 0xFF);
|
|
||||||
out.WriteUInt8((len >> 16) & 0xFF);
|
|
||||||
}
|
|
||||||
out.WriteBytes(reinterpret_cast<const char *>(data), size);
|
|
||||||
layer->EncryptForTCPO2(reinterpret_cast<unsigned char *>(out.ReserveWriteBuffer(0)),
|
|
||||||
out.Length(), &sendState);
|
|
||||||
EndpointTcp::SendPacket(reinterpret_cast<const uint8_t *>(out.Data()), out.Length());
|
|
||||||
}
|
|
||||||
|
|
||||||
EndpointRelayUdp::EndpointRelayUdp(const rtc::SocketAddress& addr, const PeerTag& peer_tag,
|
|
||||||
rtc::AsyncPacketSocket *socket, LayerBase *layer)
|
|
||||||
: Relay(peer_tag)
|
|
||||||
, EndpointUdp(addr, socket, layer, Type::RelayUdp) {}
|
|
||||||
|
|
||||||
void EndpointRelayUdp::SendMessage(const message::Base& msg_base) {
|
|
||||||
const rtc::Buffer& out = PreparePacket(layer->EncodePacket(&msg_base));
|
|
||||||
if (!out.empty())
|
|
||||||
SendPacket(out.data(), out.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndpointRelayUdp::RecvPacket(rtc::AsyncPacketSocket *sock, const char *data, size_t len,
|
|
||||||
const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) {
|
|
||||||
bool glued;
|
|
||||||
bool processed = false;
|
|
||||||
do {
|
|
||||||
EndpointBase::RecvPacket(sock, data, len, remote_addr, packet_time_us);
|
|
||||||
glued = in_buffer->Length() > len;
|
|
||||||
std::unique_ptr<message::Base> msg;
|
|
||||||
while (CheckPacket(in_buffer.get()) && (msg = layer->DecodePacket(*in_buffer))) {
|
|
||||||
processed = true;
|
|
||||||
SignalMessage(*msg, this);
|
|
||||||
}
|
|
||||||
if (!processed)
|
|
||||||
in_buffer = std::make_unique<rtc::ByteBufferReader>(nullptr, 0);
|
|
||||||
} while (!processed && glued);
|
|
||||||
}
|
|
||||||
|
|
||||||
EndpointP2p::EndpointP2p(const rtc::SocketAddress& addr, rtc::AsyncPacketSocket *socket, LayerBase *layer)
|
|
||||||
: EndpointUdp(addr, socket, layer, Type::P2p) {}
|
|
||||||
|
|
||||||
void EndpointP2p::SendMessage(const message::Base& msg_base) {
|
|
||||||
rtc::Buffer out = layer->EncodePacket(&msg_base);
|
|
||||||
if (!out.empty())
|
|
||||||
SendPacket(out.data(), out.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndpointP2p::RecvPacket(rtc::AsyncPacketSocket *sock, const char *data, size_t len,
|
|
||||||
const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) {
|
|
||||||
bool glued;
|
|
||||||
bool processed = false;
|
|
||||||
do {
|
|
||||||
EndpointBase::RecvPacket(sock, data, len, remote_addr, packet_time_us);
|
|
||||||
glued = in_buffer->Length() > len;
|
|
||||||
while (auto msg = layer->DecodePacket(*in_buffer)) {
|
|
||||||
processed = true;
|
|
||||||
SignalMessage(*msg, this);
|
|
||||||
}
|
|
||||||
if (!processed)
|
|
||||||
in_buffer = std::make_unique<rtc::ByteBufferReader>(nullptr, 0);
|
|
||||||
} while (!processed && glued);
|
|
||||||
}
|
|
@ -1,238 +0,0 @@
|
|||||||
#include "Layer92.h"
|
|
||||||
|
|
||||||
#include "Message.h"
|
|
||||||
|
|
||||||
#include "rtc_base/byte_buffer.h"
|
|
||||||
#include "rtc_base/byte_order.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
#define TLID_UDP_REFLECTOR_SELF_INFO 0xc01572c7
|
|
||||||
#define TLID_UDP_REFLECTOR_PEER_INFO 0x27D9371C
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define MSC_STACK_FALLBACK(a, b) (b)
|
|
||||||
#else
|
|
||||||
#define MSC_STACK_FALLBACK(a, b) (a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Layer92::Layer92(const EncryptionKey& encryptionKey_, bool isOutgoing)
|
|
||||||
: LayerBase(92)
|
|
||||||
, encryptionKey()
|
|
||||||
, isOutgoing(isOutgoing) {
|
|
||||||
memcpy(encryptionKey, encryptionKey_, sizeof(encryptionKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Layer92::EncryptForTCPO2(unsigned char *buffer, size_t len, TCPO2State *state) {
|
|
||||||
crypto.aes_ctr_encrypt(buffer, len, state->key, state->iv, state->ecount, &state->num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Layer92::GenerateTCPO2States(unsigned char* buffer, TCPO2State* recvState, TCPO2State* sendState) {
|
|
||||||
memset(recvState, 0, sizeof(TCPO2State));
|
|
||||||
memset(sendState, 0, sizeof(TCPO2State));
|
|
||||||
unsigned char nonce[64];
|
|
||||||
uint32_t *first = reinterpret_cast<uint32_t *>(nonce), *second = first + 1;
|
|
||||||
uint32_t first1 = 0x44414548U, first2 = 0x54534f50U, first3 = 0x20544547U, first4 = 0x20544547U, first5 = 0xeeeeeeeeU;
|
|
||||||
uint32_t second1 = 0;
|
|
||||||
do {
|
|
||||||
crypto.rand_bytes(nonce, sizeof(nonce));
|
|
||||||
} while (*first == first1 || *first == first2 || *first == first3 || *first == first4 || *first == first5 ||
|
|
||||||
*second == second1 || *reinterpret_cast<unsigned char *>(nonce) == 0xef);
|
|
||||||
|
|
||||||
// prepare encryption key/iv
|
|
||||||
memcpy(sendState->key, nonce + 8, 32);
|
|
||||||
memcpy(sendState->iv, nonce + 8 + 32, 16);
|
|
||||||
|
|
||||||
// prepare decryption key/iv
|
|
||||||
char reversed[48];
|
|
||||||
memcpy(reversed, nonce + 8, sizeof(reversed));
|
|
||||||
std::reverse(reversed, reversed + sizeof(reversed));
|
|
||||||
memcpy(recvState->key, reversed, 32);
|
|
||||||
memcpy(recvState->iv, reversed + 32, 16);
|
|
||||||
|
|
||||||
// write protocol identifier
|
|
||||||
*reinterpret_cast<uint32_t *>(nonce + 56) = 0xefefefefU;
|
|
||||||
memcpy(buffer, nonce, 56);
|
|
||||||
EncryptForTCPO2(nonce, sizeof(nonce), sendState);
|
|
||||||
memcpy(buffer + 56, nonce + 56, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<message::Base> Layer92::DecodeRelayPacket(rtc::ByteBufferReader& in) {
|
|
||||||
if (in.Length() < 12 + 4 + 16)
|
|
||||||
return nullptr;
|
|
||||||
if (*reinterpret_cast<const uint64_t *>(in.Data()) != 0xFFFFFFFFFFFFFFFFLL)
|
|
||||||
return nullptr;
|
|
||||||
if (*reinterpret_cast<const uint32_t *>(in.Data() + 8) != 0xFFFFFFFF)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// relay special request response
|
|
||||||
in.Consume(12);
|
|
||||||
uint32_t tlid;
|
|
||||||
if (!in.ReadUInt32(&tlid))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (tlid == TLID_UDP_REFLECTOR_SELF_INFO) {
|
|
||||||
if (in.Length() < 32)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto msg = std::make_unique<message::RelayPong>();
|
|
||||||
in.ReadUInt32(&msg->date);
|
|
||||||
in.ReadUInt64(&msg->query_id);
|
|
||||||
in6_addr myIP{};
|
|
||||||
in.ReadBytes(reinterpret_cast<char *>(&myIP), 16);
|
|
||||||
uint32_t myPort; // int32_t in src; why not uint16_t?
|
|
||||||
in.ReadUInt32(&myPort);
|
|
||||||
msg->my_addr = rtc::SocketAddress(rtc::IPAddress(myIP), myPort);
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
if (tlid == TLID_UDP_REFLECTOR_PEER_INFO) {
|
|
||||||
if (in.Length() < 16)
|
|
||||||
return nullptr;
|
|
||||||
auto msg = std::make_unique<message::PeerInfo>();
|
|
||||||
uint32_t myAddr;
|
|
||||||
uint32_t myPort;
|
|
||||||
uint32_t peerAddr;
|
|
||||||
uint32_t peerPort;
|
|
||||||
in.ReadUInt32(&myAddr);
|
|
||||||
in.ReadUInt32(&myPort);
|
|
||||||
in.ReadUInt32(&peerAddr);
|
|
||||||
in.ReadUInt32(&peerPort);
|
|
||||||
msg->my_addr = rtc::SocketAddress(myAddr, myPort);
|
|
||||||
msg->peer_addr = rtc::SocketAddress(peerAddr, peerPort);
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Layer92::KDF2(unsigned char *msgKey, size_t x, unsigned char *aesKey, unsigned char *aesIv) {
|
|
||||||
uint8_t sA[32], sB[32];
|
|
||||||
uint8_t buf[16 + 36];
|
|
||||||
memcpy(buf, msgKey, 16);
|
|
||||||
memcpy(buf + 16, encryptionKey + x, 36);
|
|
||||||
crypto.sha256(buf, 16 + 36, sA);
|
|
||||||
memcpy(buf, encryptionKey + 40 + x, 36);
|
|
||||||
memcpy(buf + 36, msgKey, 16);
|
|
||||||
crypto.sha256(buf, 36 + 16, sB);
|
|
||||||
memcpy(aesKey, sA, 8);
|
|
||||||
memcpy(aesKey + 8, sB + 8, 16);
|
|
||||||
memcpy(aesKey + 8 + 16, sA + 24, 8);
|
|
||||||
memcpy(aesIv, sB, 8);
|
|
||||||
memcpy(aesIv + 8, sA + 8, 16);
|
|
||||||
memcpy(aesIv + 8 + 16, sB + 24, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<message::Base> Layer92::DecodeProtocolPacket(rtc::ByteBufferReader& in) {
|
|
||||||
unsigned char msgKey[16];
|
|
||||||
memcpy(msgKey, in.Data(), 16);
|
|
||||||
|
|
||||||
unsigned char decrypted[1500];
|
|
||||||
unsigned char aesKey[32], aesIv[32];
|
|
||||||
KDF2(msgKey, isOutgoing ? 8 : 0, aesKey, aesIv);
|
|
||||||
size_t decryptedLen = in.Length() - 16;
|
|
||||||
if (decryptedLen > sizeof(decrypted))
|
|
||||||
return nullptr;
|
|
||||||
if (decryptedLen % 16 != 0)
|
|
||||||
return nullptr; // wrong decrypted length
|
|
||||||
|
|
||||||
in.Consume(16);
|
|
||||||
crypto.aes_ige_decrypt((uint8_t *)in.Data(), decrypted, decryptedLen, aesKey, aesIv);
|
|
||||||
in.Consume(decryptedLen);
|
|
||||||
|
|
||||||
rtc::ByteBufferWriter buf;
|
|
||||||
size_t x = isOutgoing ? 8 : 0;
|
|
||||||
buf.WriteBytes((char *)encryptionKey + 88 + x, 32);
|
|
||||||
buf.WriteBytes((char *)decrypted, decryptedLen);
|
|
||||||
unsigned char msgKeyLarge[32];
|
|
||||||
crypto.sha256((uint8_t *)buf.Data(), buf.Length(), msgKeyLarge);
|
|
||||||
if (memcmp(msgKey, msgKeyLarge + 8, 16) != 0)
|
|
||||||
return nullptr; // packet has wrong hash
|
|
||||||
|
|
||||||
uint16_t innerLen;
|
|
||||||
memcpy(&innerLen, decrypted, 2);
|
|
||||||
if (innerLen > decryptedLen)
|
|
||||||
return nullptr; // packet has wrong inner length
|
|
||||||
// if (decryptedLen - innerLen < 16)
|
|
||||||
// return nullptr; // packet has too little padding
|
|
||||||
return protocol->ReadProtocolPacket(decrypted + 2, innerLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<message::Base> Layer92::DecodePacket(rtc::ByteBufferReader& in) {
|
|
||||||
auto msg = DecodeRelayPacket(in);
|
|
||||||
if (msg)
|
|
||||||
return msg;
|
|
||||||
return DecodeProtocolPacket(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Buffer Layer92::EncodePacket(const message::Base *msg_base) {
|
|
||||||
auto buf = EncodeRelayPacket(msg_base);
|
|
||||||
if (!buf.empty())
|
|
||||||
return buf;
|
|
||||||
return EncodeProtocolPacket(msg_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Buffer Layer92::EncodeRelayPacket(const message::Base *msg_base) {
|
|
||||||
if (msg_base->ID == message::tRelayPing) {
|
|
||||||
const auto *msg = dynamic_cast<const message::RelayPing *>(msg_base);
|
|
||||||
if (!msg)
|
|
||||||
return rtc::Buffer();
|
|
||||||
unsigned char buf[16];
|
|
||||||
memset(buf, 0xFF, 16);
|
|
||||||
return rtc::Buffer(buf, 16);
|
|
||||||
}
|
|
||||||
if (msg_base->ID == message::tGetPeerInfo) {
|
|
||||||
const auto *msg = dynamic_cast<const message::GetPeerInfo *>(msg_base);
|
|
||||||
if (!msg)
|
|
||||||
return rtc::Buffer();
|
|
||||||
rtc::ByteBufferWriter out;
|
|
||||||
out.WriteUInt32(-1);
|
|
||||||
out.WriteUInt32(-1);
|
|
||||||
out.WriteUInt32(-1);
|
|
||||||
out.WriteUInt32(-1);
|
|
||||||
int64_t id;
|
|
||||||
crypto.rand_bytes(reinterpret_cast<uint8_t*>(&id), 8);
|
|
||||||
out.WriteUInt64(id);
|
|
||||||
return rtc::Buffer(out.Data(), out.Length());
|
|
||||||
}
|
|
||||||
return rtc::Buffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Buffer Layer92::EncodeProtocolPacket(const message::Base *msg_base) {
|
|
||||||
rtc::Buffer internal = protocol->WriteProtocolPacket(msg_base);
|
|
||||||
if (internal.empty())
|
|
||||||
return rtc::Buffer();
|
|
||||||
|
|
||||||
rtc::ByteBufferWriter out;
|
|
||||||
rtc::ByteBufferWriter inner;
|
|
||||||
uint16_t len = internal.size();
|
|
||||||
inner.WriteBytes((char *)&len, 2); // for backward compatibility
|
|
||||||
inner.WriteBytes((char *)internal.data(), internal.size());
|
|
||||||
|
|
||||||
size_t padLen = 16 - inner.Length() % 16;
|
|
||||||
// if (padLen < 16)
|
|
||||||
// padLen += 16;
|
|
||||||
uint8_t padding[32];
|
|
||||||
crypto.rand_bytes(padding, padLen);
|
|
||||||
inner.WriteBytes((char *)padding, padLen);
|
|
||||||
assert(inner.Length() % 16 == 0);
|
|
||||||
|
|
||||||
unsigned char key[32], iv[32], msgKey[16];
|
|
||||||
rtc::ByteBufferWriter buf;
|
|
||||||
size_t x = isOutgoing ? 0 : 8;
|
|
||||||
buf.WriteBytes((char *)encryptionKey + 88 + x, 32);
|
|
||||||
buf.WriteBytes(inner.Data(), inner.Length());
|
|
||||||
unsigned char msgKeyLarge[32];
|
|
||||||
crypto.sha256((uint8_t *)buf.Data(), buf.Length(), msgKeyLarge);
|
|
||||||
memcpy(msgKey, msgKeyLarge + 8, 16);
|
|
||||||
KDF2(msgKey, isOutgoing ? 0 : 8, key, iv);
|
|
||||||
out.WriteBytes((char *)msgKey, 16);
|
|
||||||
|
|
||||||
unsigned char aesOut[MSC_STACK_FALLBACK(inner.Length(), 1500)];
|
|
||||||
crypto.aes_ige_encrypt((uint8_t *)inner.Data(), aesOut, inner.Length(), key, iv);
|
|
||||||
out.WriteBytes((char *)aesOut, inner.Length());
|
|
||||||
return rtc::Buffer(out.Data(), out.Length());
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
#ifndef DEMO_LAYER92_H
|
|
||||||
#define DEMO_LAYER92_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "LayerBase.h"
|
|
||||||
#include "Message.h"
|
|
||||||
#include "Protocol10.h"
|
|
||||||
|
|
||||||
#include "rtc_base/byte_buffer.h"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
struct CryptoFunctions {
|
|
||||||
void (*rand_bytes)(uint8_t* buffer, size_t length);
|
|
||||||
void (*sha1)(uint8_t* msg, size_t length, uint8_t* output);
|
|
||||||
void (*sha256)(uint8_t* msg, size_t length, uint8_t* output);
|
|
||||||
void (*aes_ige_encrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
|
||||||
void (*aes_ige_decrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
|
||||||
void (*aes_ctr_encrypt)(uint8_t* inout, size_t length, uint8_t* key, uint8_t* iv, uint8_t* ecount, uint32_t* num);
|
|
||||||
void (*aes_cbc_encrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
|
||||||
void (*aes_cbc_decrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef unsigned char EncryptionKey[256];
|
|
||||||
|
|
||||||
class Layer92 : public LayerBase {
|
|
||||||
public:
|
|
||||||
static CryptoFunctions crypto;
|
|
||||||
|
|
||||||
explicit Layer92(const EncryptionKey& encryptionKey, bool isOutgoing);
|
|
||||||
void EncryptForTCPO2(unsigned char *buffer, size_t len, TCPO2State *state) override;
|
|
||||||
void GenerateTCPO2States(unsigned char *buffer, TCPO2State *recvState, TCPO2State *sendState) override;
|
|
||||||
std::unique_ptr<message::Base> DecodePacket(rtc::ByteBufferReader& in) override;
|
|
||||||
rtc::Buffer EncodePacket(const message::Base *msg_base) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void KDF2(unsigned char* msgKey, size_t x, unsigned char *aesKey, unsigned char *aesIv);
|
|
||||||
std::unique_ptr<message::Base> DecodeRelayPacket(rtc::ByteBufferReader& in);
|
|
||||||
std::unique_ptr<message::Base> DecodeProtocolPacket(rtc::ByteBufferReader& in);
|
|
||||||
rtc::Buffer EncodeRelayPacket(const message::Base *msg_base);
|
|
||||||
rtc::Buffer EncodeProtocolPacket(const message::Base *msg_base);
|
|
||||||
|
|
||||||
EncryptionKey encryptionKey;
|
|
||||||
bool isOutgoing;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //DEMO_LAYER92_H
|
|
@ -1,17 +0,0 @@
|
|||||||
#include "LayerBase.h"
|
|
||||||
|
|
||||||
#include "Layer92.h"
|
|
||||||
|
|
||||||
bool LayerBase::ChangeProtocol(uint32_t protocol_version) {
|
|
||||||
if (protocol && protocol->version == protocol_version)
|
|
||||||
return true;
|
|
||||||
auto new_protocol = ProtocolBase::CreateProtocol(protocol_version);
|
|
||||||
if (!new_protocol)
|
|
||||||
return false;
|
|
||||||
protocol = std::move(new_protocol);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerBase::LayerBase(uint32_t version)
|
|
||||||
: version(version)
|
|
||||||
, protocol(ProtocolBase::CreateProtocol(ProtocolBase::actual_version)) {}
|
|
@ -1,38 +0,0 @@
|
|||||||
#ifndef DEMO_LAYERBASE_H
|
|
||||||
#define DEMO_LAYERBASE_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "ProtocolBase.h"
|
|
||||||
|
|
||||||
#include "rtc_base/buffer.h"
|
|
||||||
#include "rtc_base/byte_buffer.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
struct TCPO2State {
|
|
||||||
unsigned char key[32];
|
|
||||||
unsigned char iv[16];
|
|
||||||
unsigned char ecount[16];
|
|
||||||
uint32_t num;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LayerBase {
|
|
||||||
public:
|
|
||||||
bool ChangeProtocol(uint32_t protocol_version);
|
|
||||||
|
|
||||||
virtual ~LayerBase() = default;
|
|
||||||
virtual void EncryptForTCPO2(unsigned char *buffer, size_t len, TCPO2State *state) = 0;
|
|
||||||
virtual void GenerateTCPO2States(unsigned char* buffer, TCPO2State* recvState, TCPO2State* sendState) = 0;
|
|
||||||
virtual std::unique_ptr<message::Base> DecodePacket(rtc::ByteBufferReader& in) = 0;
|
|
||||||
virtual rtc::Buffer EncodePacket(const message::Base *msg_base) = 0;
|
|
||||||
|
|
||||||
const uint32_t version;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit LayerBase(uint32_t version);
|
|
||||||
|
|
||||||
std::unique_ptr<ProtocolBase> protocol;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //DEMO_LAYERBASE_H
|
|
@ -12,7 +12,7 @@ public:
|
|||||||
MediaEngineBase() = default;
|
MediaEngineBase() = default;
|
||||||
virtual ~MediaEngineBase() = default;
|
virtual ~MediaEngineBase() = default;
|
||||||
|
|
||||||
sigslot::signal1<rtc::CopyOnWriteBuffer> Send;
|
|
||||||
virtual void Receive(rtc::CopyOnWriteBuffer) = 0;
|
virtual void Receive(rtc::CopyOnWriteBuffer) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#ifndef DEMO_MEDIAENGINEWEBRTC_H
|
#ifndef DEMO_MEDIAENGINEWEBRTC_H
|
||||||
#define DEMO_MEDIAENGINEWEBRTC_H
|
#define DEMO_MEDIAENGINEWEBRTC_H
|
||||||
|
|
||||||
|
#include "rtc_base/copy_on_write_buffer.h"
|
||||||
#include "MediaEngineBase.h"
|
#include "rtc_base/third_party/sigslot/sigslot.h"
|
||||||
|
|
||||||
#include "api/transport/field_trial_based_config.h"
|
#include "api/transport/field_trial_based_config.h"
|
||||||
#include "call/call.h"
|
#include "call/call.h"
|
||||||
@ -15,7 +15,7 @@
|
|||||||
#import "VideoCameraCapturer.h"
|
#import "VideoCameraCapturer.h"
|
||||||
#import "VideoMetalView.h"
|
#import "VideoMetalView.h"
|
||||||
|
|
||||||
class MediaEngineWebrtc : public MediaEngineBase {
|
class MediaEngineWebrtc : public sigslot::has_slots<> {
|
||||||
public:
|
public:
|
||||||
struct NetworkParams {
|
struct NetworkParams {
|
||||||
uint8_t min_bitrate_kbps;
|
uint8_t min_bitrate_kbps;
|
||||||
@ -27,40 +27,28 @@ public:
|
|||||||
bool noise_suppression;
|
bool noise_suppression;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit MediaEngineWebrtc(bool outgoing, bool send = true, bool recv = true);
|
explicit MediaEngineWebrtc(bool outgoing);
|
||||||
~MediaEngineWebrtc() override;
|
~MediaEngineWebrtc();
|
||||||
void Receive(rtc::CopyOnWriteBuffer) override;
|
void Receive(rtc::CopyOnWriteBuffer);
|
||||||
void OnSentPacket(const rtc::SentPacket& sent_packet);
|
void OnSentPacket(const rtc::SentPacket& sent_packet);
|
||||||
void SetNetworkParams(const NetworkParams& params);
|
void SetNetworkParams(const NetworkParams& params);
|
||||||
void SetMute(bool mute);
|
void SetMute(bool mute);
|
||||||
void AttachVideoView(VideoMetalView *videoView);
|
void SetCanSendPackets(bool);
|
||||||
|
void AttachVideoView(rtc::VideoSinkInterface<webrtc::VideoFrame> *sink);
|
||||||
|
|
||||||
|
sigslot::signal1<rtc::CopyOnWriteBuffer> Send;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Sender final : public cricket::MediaChannel::NetworkInterface {
|
class Sender final : public cricket::MediaChannel::NetworkInterface {
|
||||||
public:
|
public:
|
||||||
explicit Sender(MediaEngineWebrtc&);
|
explicit Sender(MediaEngineWebrtc &engine, bool isVideo);
|
||||||
bool SendPacket(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) override;
|
bool SendPacket(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) override;
|
||||||
bool SendRtcp(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) override;
|
bool SendRtcp(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) override;
|
||||||
int SetOption(SocketType type, rtc::Socket::Option opt, int option) override;
|
int SetOption(SocketType type, rtc::Socket::Option opt, int option) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MediaEngineWebrtc &engine;
|
MediaEngineWebrtc &engine;
|
||||||
};
|
bool isVideo;
|
||||||
|
|
||||||
class AudioProcessor {
|
|
||||||
public:
|
|
||||||
AudioProcessor(webrtc::AudioTransport *transport, webrtc::TaskQueueFactory *task_queue_factory,
|
|
||||||
MediaEngineBase& engine, bool send, bool recv);
|
|
||||||
~AudioProcessor();
|
|
||||||
private:
|
|
||||||
bool send;
|
|
||||||
bool recv;
|
|
||||||
webrtc::AudioTransport *transport;
|
|
||||||
size_t delay_us;
|
|
||||||
int16_t *buf_send;
|
|
||||||
int16_t *buf_recv;
|
|
||||||
MediaEngineBase& engine;
|
|
||||||
std::unique_ptr<rtc::TaskQueue> task_queue_send;
|
|
||||||
std::unique_ptr<rtc::TaskQueue> task_queue_recv;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32_t ssrc_send;
|
const uint32_t ssrc_send;
|
||||||
@ -73,7 +61,8 @@ private:
|
|||||||
std::unique_ptr<webrtc::TaskQueueFactory> task_queue_factory;
|
std::unique_ptr<webrtc::TaskQueueFactory> task_queue_factory;
|
||||||
webrtc::FieldTrialBasedConfig field_trials;
|
webrtc::FieldTrialBasedConfig field_trials;
|
||||||
webrtc::LocalAudioSinkAdapter audio_source;
|
webrtc::LocalAudioSinkAdapter audio_source;
|
||||||
Sender data_sender;
|
Sender audio_sender;
|
||||||
|
Sender video_sender;
|
||||||
std::unique_ptr<cricket::VoiceMediaChannel> voice_channel;
|
std::unique_ptr<cricket::VoiceMediaChannel> voice_channel;
|
||||||
std::unique_ptr<cricket::VideoMediaChannel> video_channel;
|
std::unique_ptr<cricket::VideoMediaChannel> video_channel;
|
||||||
std::unique_ptr<webrtc::VideoBitrateAllocatorFactory> video_bitrate_allocator_factory;
|
std::unique_ptr<webrtc::VideoBitrateAllocatorFactory> video_bitrate_allocator_factory;
|
||||||
|
@ -23,16 +23,11 @@
|
|||||||
#include "sdk/objc/native/api/video_encoder_factory.h"
|
#include "sdk/objc/native/api/video_encoder_factory.h"
|
||||||
#include "sdk/objc/native/api/video_decoder_factory.h"
|
#include "sdk/objc/native/api/video_decoder_factory.h"
|
||||||
|
|
||||||
#if WEBRTC_ENABLE_PROTOBUF
|
|
||||||
#include "modules/audio_coding/audio_network_adaptor/config.pb.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "PlatformCodecs.h"
|
|
||||||
|
|
||||||
#include "sdk/objc/native/src/objc_video_track_source.h"
|
#include "sdk/objc/native/src/objc_video_track_source.h"
|
||||||
#include "api/video_track_source_proxy.h"
|
#include "api/video_track_source_proxy.h"
|
||||||
#include "sdk/objc/api/RTCVideoRendererAdapter.h"
|
#include "sdk/objc/api/RTCVideoRendererAdapter.h"
|
||||||
#include "sdk/objc/native/api/video_frame.h"
|
#include "sdk/objc/native/api/video_frame.h"
|
||||||
|
#include "api/media_types.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const size_t frame_samples = 480;
|
const size_t frame_samples = 480;
|
||||||
@ -45,9 +40,10 @@ const uint8_t sdp_channels = 2;
|
|||||||
const uint32_t sdp_bitrate = 0;
|
const uint32_t sdp_bitrate = 0;
|
||||||
const uint32_t caller_ssrc = 1;
|
const uint32_t caller_ssrc = 1;
|
||||||
const uint32_t called_ssrc = 2;
|
const uint32_t called_ssrc = 2;
|
||||||
const uint32_t caller_ssrc_video = 1;
|
const uint32_t caller_ssrc_video = 3;
|
||||||
const uint32_t called_ssrc_video = 2;
|
const uint32_t called_ssrc_video = 4;
|
||||||
const int extension_sequence = 1;
|
const int extension_sequence = 1;
|
||||||
|
const int extension_sequence_video = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddDefaultFeedbackParams(cricket::VideoCodec* codec) {
|
static void AddDefaultFeedbackParams(cricket::VideoCodec* codec) {
|
||||||
@ -76,7 +72,6 @@ static std::vector<cricket::VideoCodec> AssignPayloadTypesAndDefaultCodecs(std::
|
|||||||
static const int kLastDynamicPayloadType = 127;
|
static const int kLastDynamicPayloadType = 127;
|
||||||
int payload_type = kFirstDynamicPayloadType;
|
int payload_type = kFirstDynamicPayloadType;
|
||||||
|
|
||||||
//input_formats.push_back(webrtc::SdpVideoFormat(cricket::kH264CodecName));
|
|
||||||
input_formats.push_back(webrtc::SdpVideoFormat(cricket::kRedCodecName));
|
input_formats.push_back(webrtc::SdpVideoFormat(cricket::kRedCodecName));
|
||||||
input_formats.push_back(webrtc::SdpVideoFormat(cricket::kUlpfecCodecName));
|
input_formats.push_back(webrtc::SdpVideoFormat(cricket::kUlpfecCodecName));
|
||||||
|
|
||||||
@ -90,6 +85,9 @@ static std::vector<cricket::VideoCodec> AssignPayloadTypesAndDefaultCodecs(std::
|
|||||||
input_formats.push_back(flexfec_format);
|
input_formats.push_back(flexfec_format);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
bool useVP9 = true;
|
||||||
|
|
||||||
std::vector<cricket::VideoCodec> output_codecs;
|
std::vector<cricket::VideoCodec> output_codecs;
|
||||||
for (const webrtc::SdpVideoFormat& format : input_formats) {
|
for (const webrtc::SdpVideoFormat& format : input_formats) {
|
||||||
cricket::VideoCodec codec(format);
|
cricket::VideoCodec codec(format);
|
||||||
@ -97,11 +95,17 @@ static std::vector<cricket::VideoCodec> AssignPayloadTypesAndDefaultCodecs(std::
|
|||||||
AddDefaultFeedbackParams(&codec);
|
AddDefaultFeedbackParams(&codec);
|
||||||
output_codecs.push_back(codec);
|
output_codecs.push_back(codec);
|
||||||
|
|
||||||
if (codec.name == cricket::kVp9CodecName) {
|
if (useVP9 && codec.name == cricket::kVp9CodecName) {
|
||||||
//outCodecId = codec.id;
|
if (!found) {
|
||||||
}
|
|
||||||
if (codec.name == cricket::kH264CodecName) {
|
|
||||||
outCodecId = codec.id;
|
outCodecId = codec.id;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!useVP9 && codec.name == cricket::kH264CodecName) {
|
||||||
|
if (!found) {
|
||||||
|
outCodecId = codec.id;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increment payload type.
|
// Increment payload type.
|
||||||
@ -128,14 +132,15 @@ static std::vector<cricket::VideoCodec> AssignPayloadTypesAndDefaultCodecs(std::
|
|||||||
return output_codecs;
|
return output_codecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv)
|
MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing)
|
||||||
: ssrc_send(outgoing ? caller_ssrc : called_ssrc)
|
: ssrc_send(outgoing ? caller_ssrc : called_ssrc)
|
||||||
, ssrc_recv(outgoing ? called_ssrc : caller_ssrc)
|
, ssrc_recv(outgoing ? called_ssrc : caller_ssrc)
|
||||||
, ssrc_send_video(outgoing ? caller_ssrc_video : called_ssrc_video)
|
, ssrc_send_video(outgoing ? caller_ssrc_video : called_ssrc_video)
|
||||||
, ssrc_recv_video(outgoing ? called_ssrc_video : caller_ssrc_video)
|
, ssrc_recv_video(outgoing ? called_ssrc_video : caller_ssrc_video)
|
||||||
, event_log(std::make_unique<webrtc::RtcEventLogNull>())
|
, event_log(std::make_unique<webrtc::RtcEventLogNull>())
|
||||||
, task_queue_factory(webrtc::CreateDefaultTaskQueueFactory())
|
, task_queue_factory(webrtc::CreateDefaultTaskQueueFactory())
|
||||||
, data_sender(*this)
|
, audio_sender(*this, false)
|
||||||
|
, video_sender(*this, true)
|
||||||
, signaling_thread(rtc::Thread::Create())
|
, signaling_thread(rtc::Thread::Create())
|
||||||
, worker_thread(rtc::Thread::Create()) {
|
, worker_thread(rtc::Thread::Create()) {
|
||||||
signaling_thread->Start();
|
signaling_thread->Start();
|
||||||
@ -172,16 +177,14 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv)
|
|||||||
call.get(), cricket::MediaConfig(), cricket::AudioOptions(), webrtc::CryptoOptions::NoGcm()));
|
call.get(), cricket::MediaConfig(), cricket::AudioOptions(), webrtc::CryptoOptions::NoGcm()));
|
||||||
video_channel.reset(media_engine->video().CreateMediaChannel(call.get(), cricket::MediaConfig(), cricket::VideoOptions(), webrtc::CryptoOptions::NoGcm(), video_bitrate_allocator_factory.get()));
|
video_channel.reset(media_engine->video().CreateMediaChannel(call.get(), cricket::MediaConfig(), cricket::VideoOptions(), webrtc::CryptoOptions::NoGcm(), video_bitrate_allocator_factory.get()));
|
||||||
|
|
||||||
if (false && send) {
|
if (true) {
|
||||||
voice_channel->AddSendStream(cricket::StreamParams::CreateLegacy(ssrc_send));
|
voice_channel->AddSendStream(cricket::StreamParams::CreateLegacy(ssrc_send));
|
||||||
SetNetworkParams({6, 32, 6, 120, false, false, false});
|
SetNetworkParams({6, 32, 6, 120, false, false, false});
|
||||||
SetMute(false);
|
SetMute(false);
|
||||||
voice_channel->SetInterface(&data_sender, webrtc::MediaTransportConfig());
|
voice_channel->SetInterface(&audio_sender, webrtc::MediaTransportConfig());
|
||||||
voice_channel->OnReadyToSend(true);
|
|
||||||
voice_channel->SetSend(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (send) {
|
if (true) {
|
||||||
video_channel->AddSendStream(cricket::StreamParams::CreateLegacy(ssrc_send_video));
|
video_channel->AddSendStream(cricket::StreamParams::CreateLegacy(ssrc_send_video));
|
||||||
|
|
||||||
for (auto codec : videoCodecs) {
|
for (auto codec : videoCodecs) {
|
||||||
@ -189,10 +192,11 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv)
|
|||||||
rtc::scoped_refptr<webrtc::ObjCVideoTrackSource> objCVideoTrackSource(new rtc::RefCountedObject<webrtc::ObjCVideoTrackSource>());
|
rtc::scoped_refptr<webrtc::ObjCVideoTrackSource> objCVideoTrackSource(new rtc::RefCountedObject<webrtc::ObjCVideoTrackSource>());
|
||||||
_nativeVideoSource = webrtc::VideoTrackSourceProxy::Create(signaling_thread.get(), worker_thread.get(), objCVideoTrackSource);
|
_nativeVideoSource = webrtc::VideoTrackSourceProxy::Create(signaling_thread.get(), worker_thread.get(), objCVideoTrackSource);
|
||||||
|
|
||||||
codec.SetParam(cricket::kCodecParamMinBitrate, 32);
|
codec.SetParam(cricket::kCodecParamMinBitrate, 64);
|
||||||
codec.SetParam(cricket::kCodecParamStartBitrate, 100);
|
codec.SetParam(cricket::kCodecParamStartBitrate, 256);
|
||||||
codec.SetParam(cricket::kCodecParamMaxBitrate, 1500);
|
codec.SetParam(cricket::kCodecParamMaxBitrate, 2500);
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
#if TARGET_IPHONE_SIMULATOR
|
#if TARGET_IPHONE_SIMULATOR
|
||||||
#else
|
#else
|
||||||
_videoCapturer = [[VideoCameraCapturer alloc] initWithSource:_nativeVideoSource];
|
_videoCapturer = [[VideoCameraCapturer alloc] initWithSource:_nativeVideoSource];
|
||||||
@ -245,10 +249,11 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv)
|
|||||||
|
|
||||||
[_videoCapturer startCaptureWithDevice:frontCamera format:bestFormat fps:27];
|
[_videoCapturer startCaptureWithDevice:frontCamera format:bestFormat fps:27];
|
||||||
#endif
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
cricket::VideoSendParameters send_parameters;
|
cricket::VideoSendParameters send_parameters;
|
||||||
send_parameters.codecs.push_back(codec);
|
send_parameters.codecs.push_back(codec);
|
||||||
send_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence);
|
send_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence_video);
|
||||||
//send_parameters.options.echo_cancellation = params.echo_cancellation;
|
//send_parameters.options.echo_cancellation = params.echo_cancellation;
|
||||||
//send_parameters.options.noise_suppression = params.noise_suppression;
|
//send_parameters.options.noise_suppression = params.noise_suppression;
|
||||||
//send_parameters.options.auto_gain_control = params.auto_gain_control;
|
//send_parameters.options.auto_gain_control = params.auto_gain_control;
|
||||||
@ -261,15 +266,13 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv)
|
|||||||
|
|
||||||
video_channel->SetVideoSend(ssrc_send_video, NULL, _nativeVideoSource.get());
|
video_channel->SetVideoSend(ssrc_send_video, NULL, _nativeVideoSource.get());
|
||||||
|
|
||||||
video_channel->SetInterface(&data_sender, webrtc::MediaTransportConfig());
|
video_channel->SetInterface(&video_sender, webrtc::MediaTransportConfig());
|
||||||
video_channel->OnReadyToSend(true);
|
|
||||||
video_channel->SetSend(true);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (false && recv) {
|
if (true) {
|
||||||
cricket::AudioRecvParameters recv_parameters;
|
cricket::AudioRecvParameters recv_parameters;
|
||||||
recv_parameters.codecs.emplace_back(sdp_payload, sdp_name, clockrate, sdp_bitrate, sdp_channels);
|
recv_parameters.codecs.emplace_back(sdp_payload, sdp_name, clockrate, sdp_bitrate, sdp_channels);
|
||||||
recv_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence);
|
recv_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence);
|
||||||
@ -279,7 +282,7 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv)
|
|||||||
voice_channel->SetRecvParameters(recv_parameters);
|
voice_channel->SetRecvParameters(recv_parameters);
|
||||||
voice_channel->SetPlayout(true);
|
voice_channel->SetPlayout(true);
|
||||||
}
|
}
|
||||||
if (recv) {
|
if (true) {
|
||||||
for (auto codec : videoCodecs) {
|
for (auto codec : videoCodecs) {
|
||||||
if (codec.id == outCodecId) {
|
if (codec.id == outCodecId) {
|
||||||
codec.SetParam(cricket::kCodecParamMinBitrate, 32);
|
codec.SetParam(cricket::kCodecParamMinBitrate, 32);
|
||||||
@ -288,7 +291,7 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv)
|
|||||||
|
|
||||||
cricket::VideoRecvParameters recv_parameters;
|
cricket::VideoRecvParameters recv_parameters;
|
||||||
recv_parameters.codecs.emplace_back(codec);
|
recv_parameters.codecs.emplace_back(codec);
|
||||||
recv_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence);
|
recv_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence_video);
|
||||||
//recv_parameters.rtcp.reduced_size = true;
|
//recv_parameters.rtcp.reduced_size = true;
|
||||||
recv_parameters.rtcp.remote_estimate = true;
|
recv_parameters.rtcp.remote_estimate = true;
|
||||||
video_channel->AddRecvStream(cricket::StreamParams::CreateLegacy(ssrc_recv_video));
|
video_channel->AddRecvStream(cricket::StreamParams::CreateLegacy(ssrc_recv_video));
|
||||||
@ -300,14 +303,35 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaEngineWebrtc::~MediaEngineWebrtc() = default;
|
MediaEngineWebrtc::~MediaEngineWebrtc() {
|
||||||
|
[_videoCapturer stopCapture];
|
||||||
|
video_channel->SetSink(ssrc_recv_video, nullptr);
|
||||||
|
video_channel->RemoveSendStream(ssrc_send_video);
|
||||||
|
video_channel->RemoveRecvStream(ssrc_recv_video);
|
||||||
|
|
||||||
|
voice_channel->SetPlayout(false);
|
||||||
|
voice_channel->RemoveSendStream(ssrc_send);
|
||||||
|
voice_channel->RemoveRecvStream(ssrc_recv);
|
||||||
|
};
|
||||||
|
|
||||||
void MediaEngineWebrtc::Receive(rtc::CopyOnWriteBuffer packet) {
|
void MediaEngineWebrtc::Receive(rtc::CopyOnWriteBuffer packet) {
|
||||||
if (voice_channel) {
|
if (packet.size() < 1) {
|
||||||
//voice_channel->OnPacketReceived(packet, -1);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t header = ((uint8_t *)packet.data())[0];
|
||||||
|
rtc::CopyOnWriteBuffer unwrappedPacket = packet.Slice(1, packet.size() - 1);
|
||||||
|
|
||||||
|
if (header == 0xba) {
|
||||||
|
if (voice_channel) {
|
||||||
|
voice_channel->OnPacketReceived(unwrappedPacket, -1);
|
||||||
|
}
|
||||||
|
} else if (header == 0xbf) {
|
||||||
if (video_channel) {
|
if (video_channel) {
|
||||||
video_channel->OnPacketReceived(packet, -1);
|
video_channel->OnPacketReceived(unwrappedPacket, -1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("----- Unknown packet header");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,29 +360,55 @@ void MediaEngineWebrtc::SetNetworkParams(const MediaEngineWebrtc::NetworkParams&
|
|||||||
// send_parameters.max_bandwidth_bps = 16000;
|
// send_parameters.max_bandwidth_bps = 16000;
|
||||||
send_parameters.rtcp.reduced_size = true;
|
send_parameters.rtcp.reduced_size = true;
|
||||||
send_parameters.rtcp.remote_estimate = true;
|
send_parameters.rtcp.remote_estimate = true;
|
||||||
//voice_channel->SetSendParameters(send_parameters);
|
voice_channel->SetSendParameters(send_parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaEngineWebrtc::SetMute(bool mute) {
|
void MediaEngineWebrtc::SetMute(bool mute) {
|
||||||
//voice_channel->SetAudioSend(ssrc_send, !mute, nullptr, &audio_source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaEngineWebrtc::AttachVideoView(VideoMetalView *videoView) {
|
void MediaEngineWebrtc::SetCanSendPackets(bool canSendPackets) {
|
||||||
//VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 240.0f)];
|
if (canSendPackets) {
|
||||||
//remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
call->SignalChannelNetworkState(webrtc::MediaType::AUDIO, webrtc::kNetworkUp);
|
||||||
|
call->SignalChannelNetworkState(webrtc::MediaType::VIDEO, webrtc::kNetworkUp);
|
||||||
|
} else {
|
||||||
|
call->SignalChannelNetworkState(webrtc::MediaType::AUDIO, webrtc::kNetworkDown);
|
||||||
|
call->SignalChannelNetworkState(webrtc::MediaType::VIDEO, webrtc::kNetworkDown);
|
||||||
|
}
|
||||||
|
if (voice_channel) {
|
||||||
|
voice_channel->OnReadyToSend(canSendPackets);
|
||||||
|
voice_channel->SetSend(canSendPackets);
|
||||||
|
voice_channel->SetAudioSend(ssrc_send, true, nullptr, &audio_source);
|
||||||
|
}
|
||||||
|
if (video_channel) {
|
||||||
|
video_channel->OnReadyToSend(canSendPackets);
|
||||||
|
video_channel->SetSend(canSendPackets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
video_channel->SetSink(ssrc_recv_video, [videoView getSink]);
|
void MediaEngineWebrtc::AttachVideoView(rtc::VideoSinkInterface<webrtc::VideoFrame> *sink) {
|
||||||
|
video_channel->SetSink(ssrc_recv_video, sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MediaEngineWebrtc::Sender::SendPacket(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) {
|
bool MediaEngineWebrtc::Sender::SendPacket(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) {
|
||||||
engine.Send(*packet);
|
rtc::CopyOnWriteBuffer wrappedPacket;
|
||||||
|
uint8_t header = isVideo ? 0xbf : 0xba;
|
||||||
|
wrappedPacket.AppendData(&header, 1);
|
||||||
|
wrappedPacket.AppendData(*packet);
|
||||||
|
|
||||||
|
engine.Send(wrappedPacket);
|
||||||
rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(), options.info_signaled_after_sent);
|
rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(), options.info_signaled_after_sent);
|
||||||
engine.OnSentPacket(sent_packet);
|
engine.OnSentPacket(sent_packet);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MediaEngineWebrtc::Sender::SendRtcp(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) {
|
bool MediaEngineWebrtc::Sender::SendRtcp(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) {
|
||||||
engine.Send(*packet);
|
rtc::CopyOnWriteBuffer wrappedPacket;
|
||||||
|
uint8_t header = isVideo ? 0xbf : 0xba;
|
||||||
|
wrappedPacket.AppendData(&header, 1);
|
||||||
|
wrappedPacket.AppendData(*packet);
|
||||||
|
|
||||||
|
engine.Send(wrappedPacket);
|
||||||
rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(), options.info_signaled_after_sent);
|
rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(), options.info_signaled_after_sent);
|
||||||
engine.OnSentPacket(sent_packet);
|
engine.OnSentPacket(sent_packet);
|
||||||
return true;
|
return true;
|
||||||
@ -368,4 +418,8 @@ int MediaEngineWebrtc::Sender::SetOption(cricket::MediaChannel::NetworkInterface
|
|||||||
return -1; // in general, the result is not important yet
|
return -1; // in general, the result is not important yet
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaEngineWebrtc::Sender::Sender(MediaEngineWebrtc& engine) : engine(engine) {}
|
MediaEngineWebrtc::Sender::Sender(MediaEngineWebrtc &engine, bool isVideo) :
|
||||||
|
engine(engine),
|
||||||
|
isVideo(isVideo) {
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,134 +0,0 @@
|
|||||||
#ifndef DEMO_MESSAGE_H
|
|
||||||
#define DEMO_MESSAGE_H
|
|
||||||
|
|
||||||
#include "rtc_base/copy_on_write_buffer.h"
|
|
||||||
#include "rtc_base/socket_address.h"
|
|
||||||
|
|
||||||
namespace message {
|
|
||||||
|
|
||||||
enum Type {
|
|
||||||
tUnknown,
|
|
||||||
tReady,
|
|
||||||
tConnected,
|
|
||||||
tDisconnected,
|
|
||||||
tRelayPing,
|
|
||||||
tRelayPong,
|
|
||||||
tGetPeerInfo,
|
|
||||||
tPeerInfo,
|
|
||||||
tSelfIPv6,
|
|
||||||
tSelfLocalIP,
|
|
||||||
tInit,
|
|
||||||
tInitAck,
|
|
||||||
tPing,
|
|
||||||
tPong,
|
|
||||||
tBufferOverflow,
|
|
||||||
tPacketIncorrect,
|
|
||||||
tWrongProtocol,
|
|
||||||
tRtpStream,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum NetworkType {
|
|
||||||
nGprs,
|
|
||||||
nEdge,
|
|
||||||
n3gOrAbove,
|
|
||||||
nHighSpeed,
|
|
||||||
nUnknown,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Base {
|
|
||||||
virtual ~Base() = default;
|
|
||||||
explicit Base(Type ID) : ID(ID) {}
|
|
||||||
const Type ID;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Unknown : Base {
|
|
||||||
Unknown() : Base(Type::tUnknown) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Ready : Base {
|
|
||||||
Ready() : Base(Type::tReady) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Connected : Base {
|
|
||||||
Connected() : Base(Type::tConnected) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Disconnected : Base {
|
|
||||||
Disconnected() : Base(Type::tDisconnected) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RelayPing : Base {
|
|
||||||
RelayPing() : Base(Type::tRelayPing) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RelayPong : Base {
|
|
||||||
RelayPong() : Base(Type::tRelayPong) {}
|
|
||||||
uint32_t date{}; // int32_t in src
|
|
||||||
uint64_t query_id{}; //int64_t in src
|
|
||||||
rtc::SocketAddress my_addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GetPeerInfo : Base {
|
|
||||||
GetPeerInfo() : Base(Type::tGetPeerInfo) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PeerInfo : Base {
|
|
||||||
PeerInfo() : Base(Type::tPeerInfo) {}
|
|
||||||
rtc::SocketAddress my_addr;
|
|
||||||
rtc::SocketAddress peer_addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SelfIPv6 : Base {
|
|
||||||
SelfIPv6() : Base(Type::tSelfIPv6) {}
|
|
||||||
rtc::SocketAddress my_addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SelfLocalIP : Base {
|
|
||||||
SelfLocalIP() : Base(Type::tSelfLocalIP) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Init : Base {
|
|
||||||
Init() : Base(Type::tInit) {}
|
|
||||||
uint32_t ver{};
|
|
||||||
uint32_t minVer{};
|
|
||||||
uint32_t flags{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InitAck : Base {
|
|
||||||
InitAck() : Base(Type::tInitAck) {}
|
|
||||||
uint32_t ver{};
|
|
||||||
uint32_t minVer{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Ping : Base {
|
|
||||||
Ping() : Base(Type::tPing) {}
|
|
||||||
uint32_t id{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Pong : Base {
|
|
||||||
Pong() : Base(Type::tPong) {}
|
|
||||||
uint32_t id{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BufferOverflow : Base {
|
|
||||||
BufferOverflow() : Base(Type::tBufferOverflow) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PacketIncorrect : Base {
|
|
||||||
PacketIncorrect() : Base(Type::tPacketIncorrect) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WrongProtocol : Base {
|
|
||||||
WrongProtocol() : Base(Type::tWrongProtocol) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RtpStream : Base {
|
|
||||||
RtpStream() : Base(Type::tRtpStream) {}
|
|
||||||
bool data_saving{false};
|
|
||||||
NetworkType network_type{NetworkType::nUnknown};
|
|
||||||
rtc::CopyOnWriteBuffer data;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //DEMO_MESSAGE_H
|
|
@ -1,6 +0,0 @@
|
|||||||
#ifndef PLATFORM_CODECS_H
|
|
||||||
#define PLATFORM_CODECS_H
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif //PLATFORM_CODECS_H
|
|
@ -1,2 +0,0 @@
|
|||||||
#include "PlatformCodecs.h"
|
|
||||||
|
|
@ -1,159 +0,0 @@
|
|||||||
#include "Protocol10.h"
|
|
||||||
|
|
||||||
#include "rtc_base/byte_buffer.h"
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
const std::map<uint8_t, Protocol10::Deserializer> Protocol10::decoders = {
|
|
||||||
{Protocol10::PacketType::tInit, Protocol10::InitDecode}, // back compatibility
|
|
||||||
{Protocol10::PacketType::tInitAck, Protocol10::InitAckDecode}, // back compatibility
|
|
||||||
{Protocol10::PacketType::tRtpStream, Protocol10::RtpStreamDecode},
|
|
||||||
{Protocol10::PacketType::tPing, Protocol10::PingDecode},
|
|
||||||
{Protocol10::PacketType::tPong, Protocol10::PongDecode},
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::map<uint8_t, Protocol10::Serializer> Protocol10::encoders = {
|
|
||||||
{message::tInit, Protocol10::InitEncode},
|
|
||||||
{message::tInitAck, Protocol10::InitAckEncode},
|
|
||||||
{message::tRtpStream, Protocol10::RtpStreamEncode},
|
|
||||||
{message::tPing, Protocol10::PingEncode},
|
|
||||||
{message::tPong, Protocol10::PongEncode},
|
|
||||||
};
|
|
||||||
|
|
||||||
Protocol10::Protocol10() : ProtocolBase(10) {}
|
|
||||||
|
|
||||||
std::unique_ptr<message::Base> Protocol10::ReadProtocolPacket(const uint8_t *buffer, size_t size) {
|
|
||||||
uint8_t type = buffer[0];
|
|
||||||
auto deserializer = decoders.find(type);
|
|
||||||
if (deserializer == decoders.end())
|
|
||||||
return nullptr;
|
|
||||||
return deserializer->second(buffer + 1, size - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Buffer Protocol10::WriteProtocolPacket(const message::Base *msg) {
|
|
||||||
auto serializer = encoders.find(msg->ID);
|
|
||||||
if (serializer == encoders.end())
|
|
||||||
return rtc::Buffer();
|
|
||||||
return serializer->second(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Buffer Protocol10::InitEncode(const message::Base *msg_base) {
|
|
||||||
const auto *msg = dynamic_cast<const message::Init *>(msg_base);
|
|
||||||
if (!msg)
|
|
||||||
return rtc::Buffer();
|
|
||||||
rtc::ByteBufferWriter out;
|
|
||||||
out.WriteUInt8(PacketType::tInit);
|
|
||||||
out.Resize(14);
|
|
||||||
out.WriteUInt32(rtc::NetworkToHost32(msg->ver));
|
|
||||||
out.WriteUInt32(rtc::NetworkToHost32(msg->minVer));
|
|
||||||
out.WriteUInt32(rtc::NetworkToHost32(msg->flags));
|
|
||||||
return rtc::Buffer(out.Data(), out.Length());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<message::Base> Protocol10::InitDecode(const uint8_t *buffer, size_t size) {
|
|
||||||
rtc::ByteBufferReader in(reinterpret_cast<const char *>(buffer), size);
|
|
||||||
uint32_t ackId = 0, pseq = 0, acks = 0;
|
|
||||||
unsigned char pflags = 0;
|
|
||||||
in.ReadUInt32(&ackId);
|
|
||||||
in.ReadUInt32(&pseq);
|
|
||||||
in.ReadUInt32(&acks);
|
|
||||||
in.ReadUInt8(&pflags);
|
|
||||||
auto msg = std::make_unique<message::Init>();
|
|
||||||
in.ReadUInt32(&msg->ver);
|
|
||||||
in.ReadUInt32(&msg->minVer);
|
|
||||||
in.ReadUInt32(&msg->flags);
|
|
||||||
msg->ver = rtc::HostToNetwork32(msg->ver);
|
|
||||||
msg->minVer = rtc::HostToNetwork32(msg->minVer);
|
|
||||||
msg->flags = rtc::HostToNetwork32(msg->flags);
|
|
||||||
if (ProtocolBase::IsSupported(msg->ver))
|
|
||||||
return msg;
|
|
||||||
// TODO: support matching of lower supported versions
|
|
||||||
return std::make_unique<message::WrongProtocol>();
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Buffer Protocol10::InitAckEncode(const message::Base *msg_base) {
|
|
||||||
const auto *msg = dynamic_cast<const message::InitAck *>(msg_base);
|
|
||||||
if (!msg)
|
|
||||||
return rtc::Buffer();
|
|
||||||
rtc::ByteBufferWriter out;
|
|
||||||
out.WriteUInt8(PacketType::tInitAck);
|
|
||||||
out.Resize(14);
|
|
||||||
out.WriteUInt32(rtc::NetworkToHost32(msg->ver));
|
|
||||||
out.WriteUInt32(rtc::NetworkToHost32(msg->minVer));
|
|
||||||
return rtc::Buffer(out.Data(), out.Length());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<message::Base> Protocol10::InitAckDecode(const uint8_t *buffer, size_t size) {
|
|
||||||
rtc::ByteBufferReader in(reinterpret_cast<const char *>(buffer), size);
|
|
||||||
uint32_t ackId = 0, pseq = 0, acks = 0;
|
|
||||||
unsigned char pflags = 0;
|
|
||||||
in.ReadUInt32(&ackId);
|
|
||||||
in.ReadUInt32(&pseq);
|
|
||||||
in.ReadUInt32(&acks);
|
|
||||||
in.ReadUInt8(&pflags);
|
|
||||||
auto msg = std::make_unique<message::InitAck>();
|
|
||||||
in.ReadUInt32(&msg->ver);
|
|
||||||
in.ReadUInt32(&msg->minVer);
|
|
||||||
msg->ver = rtc::HostToNetwork32(msg->ver);
|
|
||||||
msg->minVer = rtc::HostToNetwork32(msg->minVer);
|
|
||||||
if (ProtocolBase::IsSupported(msg->ver))
|
|
||||||
return msg;
|
|
||||||
// TODO: support matching of lower supported versions
|
|
||||||
return std::make_unique<message::WrongProtocol>();
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Buffer Protocol10::RtpStreamEncode(const message::Base *msg_base) {
|
|
||||||
const auto *msg = dynamic_cast<const message::RtpStream *>(msg_base);
|
|
||||||
if (!msg)
|
|
||||||
return rtc::Buffer();
|
|
||||||
rtc::ByteBufferWriter out;
|
|
||||||
out.WriteUInt8(PacketType::tRtpStream);
|
|
||||||
uint8_t meta = (msg->network_type & 0b111) | (msg->data_saving << 3);
|
|
||||||
out.WriteUInt8(meta);
|
|
||||||
out.WriteBytes(reinterpret_cast<const char *>(msg->data.data()), msg->data.size());
|
|
||||||
return rtc::Buffer(out.Data(), out.Length());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<message::Base> Protocol10::RtpStreamDecode(const uint8_t *buffer, size_t size) {
|
|
||||||
auto msg = std::make_unique<message::RtpStream>();
|
|
||||||
uint8_t meta = buffer[0];
|
|
||||||
msg->network_type = (message::NetworkType) (meta & 0b111);
|
|
||||||
msg->data_saving = (meta >> 3) & 0b1;
|
|
||||||
msg->data = rtc::CopyOnWriteBuffer(buffer + 1, size - 1);
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Buffer Protocol10::PingEncode(const message::Base *msg_base) {
|
|
||||||
const auto *msg = dynamic_cast<const message::Ping *>(msg_base);
|
|
||||||
if (!msg)
|
|
||||||
return rtc::Buffer();
|
|
||||||
rtc::ByteBufferWriter out;
|
|
||||||
out.WriteUInt8(PacketType::tPing);
|
|
||||||
out.WriteUInt32(msg->id);
|
|
||||||
return rtc::Buffer(out.Data(), out.Length());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<message::Base> Protocol10::PingDecode(const uint8_t *buffer, size_t size) {
|
|
||||||
rtc::ByteBufferReader in(reinterpret_cast<const char *>(buffer), size);
|
|
||||||
auto msg = std::make_unique<message::Ping>();
|
|
||||||
in.ReadUInt32(&msg->id);
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Buffer Protocol10::PongEncode(const message::Base *msg_base) {
|
|
||||||
const auto *msg = dynamic_cast<const message::Pong *>(msg_base);
|
|
||||||
if (!msg)
|
|
||||||
return rtc::Buffer();
|
|
||||||
rtc::ByteBufferWriter out;
|
|
||||||
out.WriteUInt8(PacketType::tPong);
|
|
||||||
out.WriteUInt32(msg->id);
|
|
||||||
return rtc::Buffer(out.Data(), out.Length());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<message::Base> Protocol10::PongDecode(const uint8_t *buffer, size_t size) {
|
|
||||||
rtc::ByteBufferReader in(reinterpret_cast<const char *>(buffer), size);
|
|
||||||
auto msg = std::make_unique<message::Pong>();
|
|
||||||
in.ReadUInt32(&msg->id);
|
|
||||||
return msg;
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
#ifndef DEMO_PROTOCOL10_H
|
|
||||||
#define DEMO_PROTOCOL10_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "Message.h"
|
|
||||||
#include "ProtocolBase.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class Protocol10 : public ProtocolBase {
|
|
||||||
public:
|
|
||||||
enum PacketType {
|
|
||||||
tInit = 1,
|
|
||||||
tInitAck,
|
|
||||||
tRtpStream,
|
|
||||||
tPing,
|
|
||||||
tPong,
|
|
||||||
};
|
|
||||||
|
|
||||||
Protocol10();
|
|
||||||
std::unique_ptr<message::Base> ReadProtocolPacket(const uint8_t *buffer, size_t size) override;
|
|
||||||
rtc::Buffer WriteProtocolPacket(const message::Base *msg) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::function<std::unique_ptr<message::Base>(const uint8_t *, size_t)> Deserializer;
|
|
||||||
typedef std::function<rtc::Buffer(const message::Base *)> Serializer;
|
|
||||||
|
|
||||||
static const std::map<uint8_t, Deserializer> decoders;
|
|
||||||
static const std::map<uint8_t, Serializer> encoders;
|
|
||||||
|
|
||||||
static rtc::Buffer InitEncode(const message::Base *msg_base);
|
|
||||||
static std::unique_ptr<message::Base> InitDecode(const uint8_t *buffer, size_t size);
|
|
||||||
static rtc::Buffer InitAckEncode(const message::Base *msg_base);
|
|
||||||
static std::unique_ptr<message::Base> InitAckDecode(const uint8_t *buffer, size_t size);
|
|
||||||
static rtc::Buffer RtpStreamEncode(const message::Base *msg_base);
|
|
||||||
static std::unique_ptr<message::Base> RtpStreamDecode(const uint8_t *buffer, size_t size);
|
|
||||||
static rtc::Buffer PingEncode(const message::Base *msg_base);
|
|
||||||
static std::unique_ptr<message::Base> PingDecode(const uint8_t *buffer, size_t size);
|
|
||||||
static rtc::Buffer PongEncode(const message::Base *msg_base);
|
|
||||||
static std::unique_ptr<message::Base> PongDecode(const uint8_t *buffer, size_t size);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //DEMO_PROTOCOL10_H
|
|
@ -1,23 +0,0 @@
|
|||||||
#include "ProtocolBase.h"
|
|
||||||
|
|
||||||
#include "Protocol10.h"
|
|
||||||
|
|
||||||
const std::map<uint8_t, ProtocolBase::Constructor> ProtocolBase::constructors = {
|
|
||||||
{10, std::make_unique<Protocol10>},
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint32_t ProtocolBase::actual_version = 10;
|
|
||||||
const uint32_t ProtocolBase::minimal_version = 10;
|
|
||||||
|
|
||||||
std::unique_ptr<ProtocolBase> ProtocolBase::CreateProtocol(uint32_t version) {
|
|
||||||
auto protocol = constructors.find(version);
|
|
||||||
if (protocol == constructors.end())
|
|
||||||
return nullptr;
|
|
||||||
return protocol->second();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProtocolBase::IsSupported(uint32_t version) {
|
|
||||||
return constructors.find(version) != constructors.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
ProtocolBase::ProtocolBase(uint32_t version) : version(version) {}
|
|
@ -1,33 +0,0 @@
|
|||||||
#ifndef DEMO_PROTOCOLBASE_H
|
|
||||||
#define DEMO_PROTOCOLBASE_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "Message.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
class ProtocolBase {
|
|
||||||
public:
|
|
||||||
static const uint32_t actual_version;
|
|
||||||
static const uint32_t minimal_version;
|
|
||||||
static std::unique_ptr<ProtocolBase> CreateProtocol(uint32_t version);
|
|
||||||
static bool IsSupported(uint32_t version);
|
|
||||||
|
|
||||||
virtual ~ProtocolBase() = default;
|
|
||||||
virtual std::unique_ptr<message::Base> ReadProtocolPacket(const uint8_t *buffer, size_t size) = 0;
|
|
||||||
virtual rtc::Buffer WriteProtocolPacket(const message::Base *msg) = 0;
|
|
||||||
|
|
||||||
const uint32_t version;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit ProtocolBase(uint32_t version);
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::function<std::unique_ptr<ProtocolBase>()> Constructor;
|
|
||||||
static const std::map<uint8_t, Constructor> constructors;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //DEMO_PROTOCOLBASE_H
|
|
@ -66,19 +66,6 @@ struct TgVoipPersistentState {
|
|||||||
std::vector<uint8_t> value;
|
std::vector<uint8_t> value;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef TGVOIP_USE_CUSTOM_CRYPTO
|
|
||||||
struct TgVoipCrypto {
|
|
||||||
void (*rand_bytes)(uint8_t* buffer, size_t length);
|
|
||||||
void (*sha1)(uint8_t* msg, size_t length, uint8_t* output);
|
|
||||||
void (*sha256)(uint8_t* msg, size_t length, uint8_t* output);
|
|
||||||
void (*aes_ige_encrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
|
||||||
void (*aes_ige_decrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
|
||||||
void (*aes_ctr_encrypt)(uint8_t* inout, size_t length, uint8_t* key, uint8_t* iv, uint8_t* ecount, uint32_t* num);
|
|
||||||
void (*aes_cbc_encrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
|
||||||
void (*aes_cbc_decrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct TgVoipConfig {
|
struct TgVoipConfig {
|
||||||
double initializationTimeout;
|
double initializationTimeout;
|
||||||
double receiveTimeout;
|
double receiveTimeout;
|
||||||
@ -145,14 +132,6 @@ public:
|
|||||||
std::unique_ptr<TgVoipProxy> const &proxy,
|
std::unique_ptr<TgVoipProxy> const &proxy,
|
||||||
TgVoipNetworkType initialNetworkType,
|
TgVoipNetworkType initialNetworkType,
|
||||||
TgVoipEncryptionKey const &encryptionKey
|
TgVoipEncryptionKey const &encryptionKey
|
||||||
#ifdef TGVOIP_USE_CUSTOM_CRYPTO
|
|
||||||
,
|
|
||||||
TgVoipCrypto const &crypto
|
|
||||||
#endif
|
|
||||||
#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO
|
|
||||||
,
|
|
||||||
TgVoipAudioDataCallbacks const &audioDataCallbacks
|
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
|
|
||||||
virtual ~TgVoip();
|
virtual ~TgVoip();
|
||||||
@ -172,6 +151,9 @@ public:
|
|||||||
|
|
||||||
virtual void setOnStateUpdated(std::function<void(TgVoipState)> onStateUpdated) = 0;
|
virtual void setOnStateUpdated(std::function<void(TgVoipState)> onStateUpdated) = 0;
|
||||||
virtual void setOnSignalBarsUpdated(std::function<void(int)> onSignalBarsUpdated) = 0;
|
virtual void setOnSignalBarsUpdated(std::function<void(int)> onSignalBarsUpdated) = 0;
|
||||||
|
virtual void setOnCandidatesGathered(std::function<void(const std::vector<std::string> &)> onCandidatesGathered) = 0;
|
||||||
|
|
||||||
|
virtual void addRemoteCandidates(const std::vector<std::string> &candidates) = 0;
|
||||||
|
|
||||||
virtual TgVoipFinalState stop() = 0;
|
virtual TgVoipFinalState stop() = 0;
|
||||||
};
|
};
|
||||||
|
@ -3,14 +3,12 @@
|
|||||||
#include "TgVoip.h"
|
#include "TgVoip.h"
|
||||||
|
|
||||||
#include "Controller.h"
|
#include "Controller.h"
|
||||||
#include "Layer92.h"
|
|
||||||
#include "Message.h"
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#ifndef TGVOIP_USE_CUSTOM_CRYPTO
|
#ifndef TGVOIP_USE_CUSTOM_CRYPTO
|
||||||
extern "C" {
|
/*extern "C" {
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
#include <openssl/modes.h>
|
#include <openssl/modes.h>
|
||||||
@ -18,52 +16,48 @@ extern "C" {
|
|||||||
#include <openssl/crypto.h>
|
#include <openssl/crypto.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgvoip_openssl_aes_ige_encrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
|
static void tgvoip_openssl_aes_ige_encrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
|
||||||
AES_KEY akey;
|
AES_KEY akey;
|
||||||
AES_set_encrypt_key(key, 32*8, &akey);
|
AES_set_encrypt_key(key, 32*8, &akey);
|
||||||
AES_ige_encrypt(in, out, length, &akey, iv, AES_ENCRYPT);
|
AES_ige_encrypt(in, out, length, &akey, iv, AES_ENCRYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgvoip_openssl_aes_ige_decrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
|
static void tgvoip_openssl_aes_ige_decrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
|
||||||
AES_KEY akey;
|
AES_KEY akey;
|
||||||
AES_set_decrypt_key(key, 32*8, &akey);
|
AES_set_decrypt_key(key, 32*8, &akey);
|
||||||
AES_ige_encrypt(in, out, length, &akey, iv, AES_DECRYPT);
|
AES_ige_encrypt(in, out, length, &akey, iv, AES_DECRYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgvoip_openssl_rand_bytes(uint8_t* buffer, size_t len){
|
static void tgvoip_openssl_rand_bytes(uint8_t* buffer, size_t len){
|
||||||
RAND_bytes(buffer, (int)len);
|
RAND_bytes(buffer, (int)len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgvoip_openssl_sha1(uint8_t* msg, size_t len, uint8_t* output){
|
static void tgvoip_openssl_sha1(uint8_t* msg, size_t len, uint8_t* output){
|
||||||
SHA1(msg, len, output);
|
SHA1(msg, len, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgvoip_openssl_sha256(uint8_t* msg, size_t len, uint8_t* output){
|
static void tgvoip_openssl_sha256(uint8_t* msg, size_t len, uint8_t* output){
|
||||||
SHA256(msg, len, output);
|
SHA256(msg, len, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgvoip_openssl_aes_ctr_encrypt(uint8_t* inout, size_t length, uint8_t* key, uint8_t* iv, uint8_t* ecount, uint32_t* num){
|
static void tgvoip_openssl_aes_ctr_encrypt(uint8_t* inout, size_t length, uint8_t* key, uint8_t* iv, uint8_t* ecount, uint32_t* num){
|
||||||
AES_KEY akey;
|
AES_KEY akey;
|
||||||
AES_set_encrypt_key(key, 32*8, &akey);
|
AES_set_encrypt_key(key, 32*8, &akey);
|
||||||
CRYPTO_ctr128_encrypt(inout, inout, length, &akey, iv, ecount, num, (block128_f) AES_encrypt);
|
CRYPTO_ctr128_encrypt(inout, inout, length, &akey, iv, ecount, num, (block128_f) AES_encrypt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgvoip_openssl_aes_cbc_encrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
|
static void tgvoip_openssl_aes_cbc_encrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
|
||||||
AES_KEY akey;
|
AES_KEY akey;
|
||||||
AES_set_encrypt_key(key, 256, &akey);
|
AES_set_encrypt_key(key, 256, &akey);
|
||||||
AES_cbc_encrypt(in, out, length, &akey, iv, AES_ENCRYPT);
|
AES_cbc_encrypt(in, out, length, &akey, iv, AES_ENCRYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgvoip_openssl_aes_cbc_decrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
|
static void tgvoip_openssl_aes_cbc_decrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
|
||||||
AES_KEY akey;
|
AES_KEY akey;
|
||||||
AES_set_decrypt_key(key, 256, &akey);
|
AES_set_decrypt_key(key, 256, &akey);
|
||||||
AES_cbc_encrypt(in, out, length, &akey, iv, AES_DECRYPT);
|
AES_cbc_encrypt(in, out, length, &akey, iv, AES_DECRYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * openssl_version() {
|
|
||||||
return SSLeay_version(SSLEAY_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
CryptoFunctions Layer92::crypto={
|
CryptoFunctions Layer92::crypto={
|
||||||
tgvoip_openssl_rand_bytes,
|
tgvoip_openssl_rand_bytes,
|
||||||
tgvoip_openssl_sha1,
|
tgvoip_openssl_sha1,
|
||||||
@ -73,7 +67,7 @@ CryptoFunctions Layer92::crypto={
|
|||||||
tgvoip_openssl_aes_ctr_encrypt,
|
tgvoip_openssl_aes_ctr_encrypt,
|
||||||
tgvoip_openssl_aes_cbc_encrypt,
|
tgvoip_openssl_aes_cbc_encrypt,
|
||||||
tgvoip_openssl_aes_cbc_decrypt
|
tgvoip_openssl_aes_cbc_decrypt
|
||||||
};
|
};*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -82,6 +76,9 @@ namespace TGVOIP_NAMESPACE {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
class TgVoipImpl : public TgVoip, public sigslot::has_slots<> {
|
class TgVoipImpl : public TgVoip, public sigslot::has_slots<> {
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TgVoipImpl(
|
TgVoipImpl(
|
||||||
std::vector<TgVoipEndpoint> const &endpoints,
|
std::vector<TgVoipEndpoint> const &endpoints,
|
||||||
@ -90,38 +87,17 @@ public:
|
|||||||
TgVoipConfig const &config,
|
TgVoipConfig const &config,
|
||||||
TgVoipEncryptionKey const &encryptionKey,
|
TgVoipEncryptionKey const &encryptionKey,
|
||||||
TgVoipNetworkType initialNetworkType
|
TgVoipNetworkType initialNetworkType
|
||||||
#ifdef TGVOIP_USE_CUSTOM_CRYPTO
|
|
||||||
,
|
|
||||||
TgVoipCrypto const &crypto
|
|
||||||
#endif
|
|
||||||
#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO
|
|
||||||
,
|
|
||||||
TgVoipAudioDataCallbacks const &audioDataCallbacks
|
|
||||||
#endif
|
|
||||||
) {
|
) {
|
||||||
#ifdef TGVOIP_USE_CUSTOM_CRYPTO
|
|
||||||
tgvoip::VoIPController::crypto.sha1 = crypto.sha1;
|
|
||||||
tgvoip::VoIPController::crypto.sha256 = crypto.sha256;
|
|
||||||
tgvoip::VoIPController::crypto.rand_bytes = crypto.rand_bytes;
|
|
||||||
tgvoip::VoIPController::crypto.aes_ige_encrypt = crypto.aes_ige_encrypt;
|
|
||||||
tgvoip::VoIPController::crypto.aes_ige_decrypt = crypto.aes_ige_decrypt;
|
|
||||||
tgvoip::VoIPController::crypto.aes_ctr_encrypt = crypto.aes_ctr_encrypt;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// std::cerr << "OpenSSL version: " << openssl_version() << std::endl; // to verify because of WebRTC BoringSSL
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
rtc::LogMessage::LogToDebug(rtc::LS_INFO);
|
||||||
|
rtc::LogMessage::SetLogToStderr(true);
|
||||||
|
});
|
||||||
|
|
||||||
EncryptionKey encryptionKeyValue;
|
/*EncryptionKey encryptionKeyValue;
|
||||||
memcpy(encryptionKeyValue, encryptionKey.value.data(), 256);
|
memcpy(encryptionKeyValue, encryptionKey.value.data(), 256);*/
|
||||||
controller_ = new Controller(encryptionKey.isOutgoing, encryptionKeyValue, 5, 3);
|
controller_ = new Controller(encryptionKey.isOutgoing, 5, 3);
|
||||||
|
|
||||||
#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO
|
|
||||||
audioCallbacks = audioDataCallbacks;
|
|
||||||
controller_->SignalRecord.connect(this, &TgVoipImpl::record);
|
|
||||||
controller_->SignalPlay.connect(this, &TgVoipImpl::play);
|
|
||||||
#ifdef TGVOIP_PREPROCESSED_OUTPUT
|
|
||||||
controller_->SignalPreprocessed.connect(this, &TgVoipImpl::preprocessed);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (proxy != nullptr) {
|
if (proxy != nullptr) {
|
||||||
controller_->SetProxy(rtc::ProxyType::PROXY_SOCKS5, rtc::SocketAddress(proxy->host, proxy->port),
|
controller_->SetProxy(rtc::ProxyType::PROXY_SOCKS5, rtc::SocketAddress(proxy->host, proxy->port),
|
||||||
@ -129,6 +105,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
controller_->SignalNewState.connect(this, &TgVoipImpl::controllerStateCallback);
|
controller_->SignalNewState.connect(this, &TgVoipImpl::controllerStateCallback);
|
||||||
|
controller_->SignalCandidatesGathered.connect(this, &TgVoipImpl::candidatesGathered);
|
||||||
controller_->Start();
|
controller_->Start();
|
||||||
|
|
||||||
for (const auto &endpoint : endpoints) {
|
for (const auto &endpoint : endpoints) {
|
||||||
@ -149,7 +126,7 @@ public:
|
|||||||
type = Controller::EndpointType::UDP;
|
type = Controller::EndpointType::UDP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
controller_->AddEndpoint(addr, endpoint.peerTag, type);
|
//controller_->AddEndpoint(addr, endpoint.peerTag, type);
|
||||||
}
|
}
|
||||||
/*rtc::SocketAddress addr("192.168.8.118", 7325);
|
/*rtc::SocketAddress addr("192.168.8.118", 7325);
|
||||||
unsigned char peerTag[16];
|
unsigned char peerTag[16];
|
||||||
@ -184,8 +161,16 @@ public:
|
|||||||
onSignalBarsUpdated_ = onSignalBarsUpdated;
|
onSignalBarsUpdated_ = onSignalBarsUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setOnCandidatesGathered(std::function<void(const std::vector<std::string> &)> onCandidatesGathered) override {
|
||||||
|
onCandidatesGathered_ = onCandidatesGathered;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addRemoteCandidates(const std::vector<std::string> &candidates) override {
|
||||||
|
controller_->AddRemoteCandidates(candidates);
|
||||||
|
}
|
||||||
|
|
||||||
void setNetworkType(TgVoipNetworkType networkType) override {
|
void setNetworkType(TgVoipNetworkType networkType) override {
|
||||||
message::NetworkType mappedType;
|
/*message::NetworkType mappedType;
|
||||||
|
|
||||||
switch (networkType) {
|
switch (networkType) {
|
||||||
case TgVoipNetworkType::Unknown:
|
case TgVoipNetworkType::Unknown:
|
||||||
@ -229,7 +214,7 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
controller_->SetNetworkType(mappedType);
|
controller_->SetNetworkType(mappedType);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMuteMicrophone(bool muteMicrophone) override {
|
void setMuteMicrophone(bool muteMicrophone) override {
|
||||||
@ -237,7 +222,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AttachVideoView(VideoMetalView *videoView) override {
|
void AttachVideoView(VideoMetalView *videoView) override {
|
||||||
controller_->AttachVideoView(videoView);
|
controller_->AttachVideoView([videoView getSink]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAudioOutputGainControlEnabled(bool enabled) override {
|
void setAudioOutputGainControlEnabled(bool enabled) override {
|
||||||
@ -304,6 +289,10 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void candidatesGathered(const std::vector<std::string> &candidates) {
|
||||||
|
onCandidatesGathered_(candidates);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO
|
#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO
|
||||||
TgVoipAudioDataCallbacks audioCallbacks;
|
TgVoipAudioDataCallbacks audioCallbacks;
|
||||||
@ -334,6 +323,7 @@ private:
|
|||||||
Controller *controller_;
|
Controller *controller_;
|
||||||
std::function<void(TgVoipState)> onStateUpdated_;
|
std::function<void(TgVoipState)> onStateUpdated_;
|
||||||
std::function<void(int)> onSignalBarsUpdated_;
|
std::function<void(int)> onSignalBarsUpdated_;
|
||||||
|
std::function<void(const std::vector<std::string> &)> onCandidatesGathered_;
|
||||||
std::mutex m_onStateUpdated, m_onSignalBarsUpdated;
|
std::mutex m_onStateUpdated, m_onSignalBarsUpdated;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -379,14 +369,6 @@ TgVoip *TgVoip::makeInstance(
|
|||||||
std::unique_ptr<TgVoipProxy> const &proxy,
|
std::unique_ptr<TgVoipProxy> const &proxy,
|
||||||
TgVoipNetworkType initialNetworkType,
|
TgVoipNetworkType initialNetworkType,
|
||||||
TgVoipEncryptionKey const &encryptionKey
|
TgVoipEncryptionKey const &encryptionKey
|
||||||
#ifdef TGVOIP_USE_CUSTOM_CRYPTO
|
|
||||||
,
|
|
||||||
TgVoipCrypto const &crypto
|
|
||||||
#endif
|
|
||||||
#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO
|
|
||||||
,
|
|
||||||
TgVoipAudioDataCallbacks const &audioDataCallbacks
|
|
||||||
#endif
|
|
||||||
) {
|
) {
|
||||||
return new TgVoipImpl(
|
return new TgVoipImpl(
|
||||||
endpoints,
|
endpoints,
|
||||||
@ -395,14 +377,6 @@ TgVoip *TgVoip::makeInstance(
|
|||||||
config,
|
config,
|
||||||
encryptionKey,
|
encryptionKey,
|
||||||
initialNetworkType
|
initialNetworkType
|
||||||
#ifdef TGVOIP_USE_CUSTOM_CRYPTO
|
|
||||||
,
|
|
||||||
crypto
|
|
||||||
#endif
|
|
||||||
#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO
|
|
||||||
,
|
|
||||||
audioDataCallbacks
|
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) {
|
|||||||
@property (nonatomic, copy) void (^ _Nullable stateChanged)(OngoingCallStateWebrtc);
|
@property (nonatomic, copy) void (^ _Nullable stateChanged)(OngoingCallStateWebrtc);
|
||||||
@property (nonatomic, copy) void (^ _Nullable signalBarsChanged)(int32_t);
|
@property (nonatomic, copy) void (^ _Nullable signalBarsChanged)(int32_t);
|
||||||
|
|
||||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath;
|
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^)(NSData * _Nonnull))sendSignalingData;
|
||||||
- (void)stop:(void (^_Nullable)(NSString * _Nullable debugLog, int64_t bytesSentWifi, int64_t bytesReceivedWifi, int64_t bytesSentMobile, int64_t bytesReceivedMobile))completion;
|
- (void)stop:(void (^_Nullable)(NSString * _Nullable debugLog, int64_t bytesSentWifi, int64_t bytesReceivedWifi, int64_t bytesSentMobile, int64_t bytesReceivedMobile))completion;
|
||||||
|
|
||||||
- (bool)needRate;
|
- (bool)needRate;
|
||||||
@ -77,6 +77,7 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) {
|
|||||||
- (void)setIsMuted:(bool)isMuted;
|
- (void)setIsMuted:(bool)isMuted;
|
||||||
- (void)setNetworkType:(OngoingCallNetworkTypeWebrtc)networkType;
|
- (void)setNetworkType:(OngoingCallNetworkTypeWebrtc)networkType;
|
||||||
- (void)getRemoteCameraView:(void (^_Nonnull)(UIView * _Nullable))completion;
|
- (void)getRemoteCameraView:(void (^_Nonnull)(UIView * _Nullable))completion;
|
||||||
|
- (void)addSignalingData:(NSData * _Nonnull)data;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ using namespace TGVOIP_NAMESPACE;
|
|||||||
OngoingCallStateWebrtc _state;
|
OngoingCallStateWebrtc _state;
|
||||||
int32_t _signalBars;
|
int32_t _signalBars;
|
||||||
NSData *_lastDerivedState;
|
NSData *_lastDerivedState;
|
||||||
|
|
||||||
|
void (^_sendSignalingData)(NSData *);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)controllerStateChanged:(TgVoipState)state;
|
- (void)controllerStateChanged:(TgVoipState)state;
|
||||||
@ -112,7 +114,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
|||||||
return @"2.7.7";
|
return @"2.7.7";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath {
|
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^)(NSData * _Nonnull))sendSignalingData; {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self != nil) {
|
if (self != nil) {
|
||||||
_queue = queue;
|
_queue = queue;
|
||||||
@ -123,6 +125,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
|||||||
_callConnectTimeout = 30.0;
|
_callConnectTimeout = 30.0;
|
||||||
_callPacketTimeout = 10.0;
|
_callPacketTimeout = 10.0;
|
||||||
_networkType = networkType;
|
_networkType = networkType;
|
||||||
|
_sendSignalingData = [sendSignalingData copy];
|
||||||
|
|
||||||
std::vector<uint8_t> derivedStateValue;
|
std::vector<uint8_t> derivedStateValue;
|
||||||
derivedStateValue.resize(derivedState.length);
|
derivedStateValue.resize(derivedState.length);
|
||||||
@ -211,6 +214,16 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
|||||||
[strongSelf signalBarsChanged:signalBars];
|
[strongSelf signalBarsChanged:signalBars];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
_tgVoip->setOnCandidatesGathered([weakSelf](const std::vector<std::string> &candidates) {
|
||||||
|
__strong OngoingCallThreadLocalContextWebrtc *strongSelf = weakSelf;
|
||||||
|
if (strongSelf) {
|
||||||
|
NSMutableArray *mappedCandidates = [[NSMutableArray alloc] init];
|
||||||
|
for (auto &candidate : candidates) {
|
||||||
|
[mappedCandidates addObject:[[NSString alloc] initWithCString:candidate.c_str() encoding:NSUTF8StringEncoding]];
|
||||||
|
}
|
||||||
|
[strongSelf candidatesGathered:mappedCandidates];
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -307,6 +320,30 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)candidatesGathered:(NSArray<NSString *> *)candidates {
|
||||||
|
if (_sendSignalingData) {
|
||||||
|
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:@{
|
||||||
|
@"type": @"candidates",
|
||||||
|
@"data": candidates
|
||||||
|
}];
|
||||||
|
_sendSignalingData(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addSignalingData:(NSData *)data {
|
||||||
|
NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:data];
|
||||||
|
NSString *type = dict[@"type"];
|
||||||
|
if ([type isEqualToString:@"candidates"]) {
|
||||||
|
if (_tgVoip) {
|
||||||
|
std::vector<std::string> candidates;
|
||||||
|
for (NSString *string in dict[@"data"]) {
|
||||||
|
candidates.push_back([string UTF8String]);
|
||||||
|
}
|
||||||
|
_tgVoip->addRemoteCandidates(candidates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setIsMuted:(bool)isMuted {
|
- (void)setIsMuted:(bool)isMuted {
|
||||||
if (_tgVoip) {
|
if (_tgVoip) {
|
||||||
_tgVoip->setMuteMicrophone(isMuted);
|
_tgVoip->setMuteMicrophone(isMuted);
|
||||||
@ -324,7 +361,8 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
|||||||
|
|
||||||
- (void)getRemoteCameraView:(void (^_Nonnull)(UIView * _Nullable))completion {
|
- (void)getRemoteCameraView:(void (^_Nonnull)(UIView * _Nullable))completion {
|
||||||
if (_tgVoip) {
|
if (_tgVoip) {
|
||||||
VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 240.0f)];
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectZero];
|
||||||
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
||||||
|
|
||||||
_tgVoip->AttachVideoView(remoteRenderer);
|
_tgVoip->AttachVideoView(remoteRenderer);
|
||||||
@ -332,6 +370,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
|||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
completion(remoteRenderer);
|
completion(remoteRenderer);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
third-party/webrtc/build-webrtc-bazel.sh
vendored
2
third-party/webrtc/build-webrtc-bazel.sh
vendored
@ -23,7 +23,7 @@ if [ "$ARCH" == "x64" ]; then
|
|||||||
OUT_DIR="ios_sim"
|
OUT_DIR="ios_sim"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
gn gen out/$OUT_DIR --args="use_xcode_clang=true "" target_cpu=\"$ARCH\""' target_os="ios" is_debug=true is_component_build=false rtc_include_tests=false use_rtti=true rtc_use_x11=false use_custom_libcxx=false use_custom_libcxx_for_host=false rtc_build_ssl=false rtc_build_examples=false rtc_build_tools=false ios_deployment_target="9.0" ios_enable_code_signing=false is_unsafe_developer_build=false rtc_enable_protobuf=false rtc_include_builtin_video_codecs=true rtc_build_libvpx=true rtc_libvpx_build_vp9=true rtc_use_gtk=false rtc_use_metal_rendering=true rtc_ssl_root="//openssl"'
|
gn gen out/$OUT_DIR --args="use_xcode_clang=true "" target_cpu=\"$ARCH\""' target_os="ios" is_debug=false is_component_build=false rtc_include_tests=false use_rtti=true rtc_use_x11=false use_custom_libcxx=false use_custom_libcxx_for_host=false rtc_build_ssl=false rtc_build_examples=false rtc_build_tools=false ios_deployment_target="9.0" ios_enable_code_signing=false is_unsafe_developer_build=false rtc_enable_protobuf=false rtc_include_builtin_video_codecs=true rtc_build_libvpx=true rtc_libvpx_build_vp9=true rtc_use_gtk=false rtc_use_metal_rendering=true rtc_ssl_root="//openssl"'
|
||||||
ninja -C out/$OUT_DIR framework_objc_static
|
ninja -C out/$OUT_DIR framework_objc_static
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
Loading…
x
Reference in New Issue
Block a user