Chromium Code Reviews| Index: webrtc/p2p/rawudp/rawudptransportchannel.cc |
| diff --git a/webrtc/p2p/rawudp/rawudptransportchannel.cc b/webrtc/p2p/rawudp/rawudptransportchannel.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..20835c2d15e30f5a5515fa1dcb1f5ba9c9e479fa |
| --- /dev/null |
| +++ b/webrtc/p2p/rawudp/rawudptransportchannel.cc |
| @@ -0,0 +1,224 @@ |
| +/* |
| + * Copyright 2016 The WebRTC project authors. All Rights Reserved. |
| + * |
| + * Use of this source code is governed by a BSD-style license |
| + * that can be found in the LICENSE file in the root of the source |
| + * tree. An additional intellectual property rights grant can be found |
| + * in the file PATENTS. All contributing project authors may |
| + * be found in the AUTHORS file in the root of the source tree. |
| + */ |
| + |
| +#include "webrtc/p2p/rawudp/rawudptransportchannel.h" |
| + |
| +#include <string> |
| + |
| +#include "webrtc/base/asyncudpsocket.h" |
| +#include "webrtc/base/logging.h" |
| +#include "webrtc/base/physicalsocketserver.h" |
| +#include "webrtc/base/socketaddress.h" |
| +#include "webrtc/base/thread.h" |
| + |
| + |
| +namespace cricket { |
| + |
| +RawUdpTransportChannel::RawUdpTransportChannel( |
| + const std::string& transport_name, |
| + int component) |
| + : RawUdpTransportChannel(transport_name, |
| + component, |
| + rtc::Thread::Current(), |
| + rtc::Thread::Current()->socketserver()) {} |
| + |
| +RawUdpTransportChannel::RawUdpTransportChannel( |
| + const std::string& transport_name, |
| + int component, |
| + rtc::Thread* network_thread, |
| + rtc::SocketServer* ss) |
| + : TransportChannelImpl(transport_name, component), |
| + tch_state_(STATE_INIT), |
| + gathering_state_(kIceGatheringNew), |
| + local_candidate_(), |
| + remote_candidate_() { |
|
sprang_webrtc
2016/10/07 09:56:21
We usually omit default constructors in the initia
johan
2016/10/07 12:24:26
Acknowledged.
|
| + network_thread_ = network_thread; |
|
sprang_webrtc
2016/10/07 09:56:21
Why not in the initializer list?
johan
2016/10/07 12:24:26
Leftover from a different implementation approach.
|
| +} |
| + |
| +RawUdpTransportChannel::~RawUdpTransportChannel() { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
|
sprang_webrtc
2016/10/07 09:56:21
Please use ThreadChecker utility, here and elsewhe
|
| +} |
| + |
| +void RawUdpTransportChannel::OnSocketReadPacket( |
| + rtc::AsyncPacketSocket* socket, |
| + const char* data, |
| + size_t len, |
| + const rtc::SocketAddress& remote_addr, |
| + const rtc::PacketTime& packet_time, |
| + bool is_rtcp) { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + // serialisation of processing RTP and RTCP socket is implicit done by event |
| + // loop. |
| + SignalReadPacket(this, data, len, packet_time, 0); |
| +} |
| + |
| +void RawUdpTransportChannel::OnRtpSocketReadPacket( |
| + rtc::AsyncPacketSocket* socket, |
| + const char* data, |
| + size_t len, |
| + const rtc::SocketAddress& remote_addr, |
| + const rtc::PacketTime& packet_time) { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + // TODO(johan) check, if remote_addr is valid and legit |
| + LOG(LS_VERBOSE) << "received rtp packet"; |
|
sprang_webrtc
2016/10/07 09:56:21
This looks extremely verbose. Will it be useful ou
johan
2016/10/07 12:24:26
Only useful for debug. Removing it.
|
| + OnSocketReadPacket(socket, data, len, remote_addr, packet_time, |
| + false /*rtcp*/); |
| +} |
| + |
| +void RawUdpTransportChannel::OnRtcpSocketReadPacket( |
| + rtc::AsyncPacketSocket* socket, |
| + const char* data, |
| + size_t len, |
| + const rtc::SocketAddress& remote_addr, |
| + const rtc::PacketTime& packet_time) { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + // TODO(johan) check, if remote_addr is valid and legit |
| + LOG(LS_VERBOSE) << "received rtcp packet"; |
| + OnSocketReadPacket(socket, data, len, remote_addr, packet_time, |
| + true /*rtcp*/); |
| +} |
| + |
| +int RawUdpTransportChannel::SendPacket(const char* data, |
| + size_t len, |
| + const rtc::PacketOptions& options, |
| + int flags) { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + int32_t is_rtcp = 0; |
| + // TODO(johan): add logic to send rtcp packets over rtcp socket |
| + int result = -1; |
| + if (is_rtcp) { |
|
sprang_webrtc
2016/10/07 09:56:21
Just do
if (!is_rtcp) { result = ... }
Add the if/
johan
2016/10/07 12:24:25
Acknowledged.
|
| + } else { |
| + result = rtp_socket_->SendTo((const void*)data, len, remote_addr_, options); |
| + } |
| + LOG(LS_VERBOSE) << "SendPacket() " << result; |
| + return result; |
| +} |
| + |
| +bool RawUdpTransportChannel::TryAllocateSockets() { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + const uint16_t maxTry = 100; |
|
sprang_webrtc
2016/10/07 09:56:21
I'd do
static constexpr uint16_t kMaxTries = 100;
johan
2016/10/07 12:24:25
Acknowledged.
|
| + rtc::SocketAddress rtp_socket_addr("0.0.0.0", 0); |
| + rtc::SocketAddress rtcp_socket_addr("0.0.0.0", 1); |
| + // TODO(johan) allocate sockets only once, and loop over |
| + // rtc::AsyncSocketAdapter::bind() |
| + for (uint16_t count = 0; count < maxTry; ++count) { |
| + uint16_t rtpport = 2000 + (2 * count); |
|
sprang_webrtc
2016/10/07 09:56:21
Why 2000? Named constant?
johan
2016/10/07 12:24:26
Changing this to a constant. Will probably change
|
| + rtp_socket_addr.SetPort(rtpport); |
| + rtp_socket_.reset(rtc::AsyncUDPSocket::Create( |
| + network_thread_->socketserver(), rtp_socket_addr)); |
| + if (!rtp_socket_) { |
| + continue; |
| + } |
| + rtcp_socket_addr.SetPort(rtpport + 1); |
| + rtcp_socket_.reset(rtc::AsyncUDPSocket::Create( |
| + network_thread_->socketserver(), rtcp_socket_addr)); |
| + if (rtp_socket_ && rtcp_socket_) { |
| + LOG(INFO) << "Allocated Rtp socket with local port " << rtpport; |
| + rtp_socket_->SignalReadPacket.connect( |
| + this, &RawUdpTransportChannel::OnRtpSocketReadPacket); |
| + rtcp_socket_->SignalReadPacket.connect( |
| + this, &RawUdpTransportChannel::OnRtcpSocketReadPacket); |
| + local_candidate_.set_address(rtp_socket_addr); |
| + return true; |
| + } |
| + } |
| + rtp_socket_.reset(); |
| + rtcp_socket_.reset(); |
| + return false; |
| +} |
| + |
| +void RawUdpTransportChannel::MaybeStartGathering() { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + if (gathering_state_ != kIceGatheringNew) { |
| + LOG(INFO) << "candidates gathering already done, early return"; |
| + return; |
| + } |
| + SetGatheringState(kIceGatheringGathering); |
| + TryAllocateSockets(); |
| + SignalCandidateGathered(this, local_candidate_); |
| + SetGatheringState(kIceGatheringComplete); |
| +} |
| + |
| +void RawUdpTransportChannel::UpdateWritableState() { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + bool writable = true; |
| + if (!rtp_socket_) { |
| + writable = false; |
| + LOG(INFO) << "rtp_socket_ is false"; |
| + } |
| + if (!remote_addr_.IsComplete()) { |
| + writable = false; |
| + LOG(INFO) << "remote_addr_ not complete"; |
| + } |
| + if (gathering_state_ != kIceGatheringComplete) { |
| + writable = false; |
| + LOG(INFO) << "gathering_state_ " << gathering_state_; |
| + } |
| + set_writable(writable); |
| +} |
| + |
| +void RawUdpTransportChannel::AddRemoteCandidate(const Candidate& candidate) { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + // TODO(johan) check for ipv4, other settings |
| + remote_candidate_ = candidate; |
| + remote_addr_ = candidate.address(); |
| + // TODO(johan) - only set STATE_COMPLETED if *both* local and remote addr are |
| + // set. Maybe use an rtc::Optional to indicate unset addr? |
| + SetTransportChannelState(STATE_COMPLETED); |
| + // TODO(johan) - set STATE_FAILED, if remote addr is invalid |
| + UpdateWritableState(); |
| +} |
| + |
| +IceGatheringState RawUdpTransportChannel::gathering_state() const { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + return gathering_state_; |
| +} |
| + |
| +bool RawUdpTransportChannel::SetRemoteAddrAndPorts(const char* ip_addr, |
| + int rtp_port) { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + remote_addr_ = rtc::SocketAddress(ip_addr, rtp_port); |
| + return true; |
| +} |
| + |
| +TransportChannelState RawUdpTransportChannel::GetState() const { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + return tch_state_; |
| +} |
| + |
| +void RawUdpTransportChannel::SetGatheringState( |
| + IceGatheringState new_gathering_state) { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + /* |
| + kIceGatheringNew = 0, |
| + kIceGatheringGathering, |
| + kIceGatheringComplete, |
| + */ |
|
sprang_webrtc
2016/10/07 09:56:21
Remove this comment
johan
2016/10/07 12:24:26
Acknowledged.
|
| + if (gathering_state_ != new_gathering_state) { |
| + gathering_state_ = new_gathering_state; |
| + SignalGatheringState(this); |
| + } |
| +} |
| + |
| +void RawUdpTransportChannel::SetTransportChannelState( |
| + TransportChannelState new_tch_state) { |
| + RTC_DCHECK_EQ(network_thread_, rtc::Thread::Current()); |
| + /* |
| + STATE_INIT, |
| + STATE_CONNECTING, // Will enter this state once a connection is created |
| + STATE_COMPLETED, |
| + STATE_FAILED |
| + */ |
|
sprang_webrtc
2016/10/07 09:56:21
Remove this comment.
johan
2016/10/07 12:24:26
Acknowledged.
|
| + if (tch_state_ != new_tch_state) { |
| + tch_state_ = new_tch_state; |
| + SignalStateChanged(this); |
| + } |
| +} |
| +} // namespace cricket |