Index: webrtc/p2p/base/udptransportchannel.cc |
diff --git a/webrtc/p2p/base/udptransportchannel.cc b/webrtc/p2p/base/udptransportchannel.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..73aa02352656c519333ce3612fe273a366805b51 |
--- /dev/null |
+++ b/webrtc/p2p/base/udptransportchannel.cc |
@@ -0,0 +1,178 @@ |
+/* |
+ * 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/base/udptransportchannel.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" |
+#include "webrtc/base/thread_checker.h" |
+ |
+namespace cricket { |
+ |
+UdpTransportChannel::UdpTransportChannel(const std::string& transport_name, |
+ int component) |
+ : UdpTransportChannel(transport_name, |
+ component, |
+ rtc::Thread::Current()->socketserver()) {} |
+ |
+UdpTransportChannel::UdpTransportChannel(const std::string& transport_name, |
+ int component, |
+ rtc::SocketServer* socket_server) |
+ : TransportChannelImpl(transport_name, component), |
+ socket_server_(socket_server) { |
+ RTC_DCHECK_RUN_ON(&network_thread_checker_); |
+} |
+ |
+UdpTransportChannel::~UdpTransportChannel() { |
+ RTC_DCHECK_RUN_ON(&network_thread_checker_); |
+} |
+ |
+void UdpTransportChannel::OnSocketReadPacket( |
+ rtc::AsyncPacketSocket* socket, |
+ const char* data, |
+ size_t len, |
+ const rtc::SocketAddress& remote_addr, |
+ const rtc::PacketTime& packet_time) { |
+ // No thread_checker in high frequency network function. |
+ SignalReadPacket(this, data, len, packet_time, 0); |
+} |
+ |
+int UdpTransportChannel::SendPacket(const char* data, |
+ size_t len, |
+ const rtc::PacketOptions& options, |
+ int flags) { |
+ // No thread_checker in high frequency network function. |
+ if (!remote_parameters_) { |
+ LOG(LS_WARNING) << "Remote parameters not set."; |
+ send_error_ = ENOTCONN; |
+ return -1; |
+ } |
+ const rtc::SocketAddress& remote_addr_ = remote_parameters_->address(); |
+ int result = socket_->SendTo((const void*)data, len, remote_addr_, options); |
+ LOG(LS_VERBOSE) << "SendPacket() " << result; |
+ return result; |
+} |
+ |
+bool UdpTransportChannel::TryAllocateSockets() { |
+ RTC_DCHECK_RUN_ON(&network_thread_checker_); |
+ static constexpr uint16_t kMaxTries = 100; |
+ static constexpr uint16_t kMinPortNumber = 2000; |
+ // TODO(johan) provide configuration option for kMinPortNumber. |
+ rtc::SocketAddress socket_addr("0.0.0.0", 0); |
+ // TODO(johan): use rtc::PacketSocketFactory. |
+ for (uint16_t count = 0; count < kMaxTries; ++count) { |
+ uint16_t rtpport = kMinPortNumber + (2 * count); |
+ socket_addr.SetPort(rtpport); |
+ socket_.reset(rtc::AsyncUDPSocket::Create(socket_server_, socket_addr)); |
+ if (!socket_) { |
+ continue; |
+ } |
+ if (socket_) { |
+ LOG(INFO) << "Allocated Rtp socket with local port " << rtpport; |
+ socket_->SignalReadPacket.connect( |
+ this, &UdpTransportChannel::OnSocketReadPacket); |
+ local_parameters_ = rtc::Optional<Candidate>(Candidate()); |
+ local_parameters_->set_address(socket_addr); |
+ return true; |
+ } |
+ } |
+ socket_.reset(); |
+ LOG(INFO) << "Local socket allocation failure"; |
+ return false; |
+} |
+ |
+void UdpTransportChannel::MaybeStartGathering() { |
+ RTC_DCHECK_RUN_ON(&network_thread_checker_); |
+ if (gathering_state_ != kIceGatheringNew) { |
+ LOG(INFO) << "candidates gathering already done, early return"; |
+ return; |
+ } |
+ SetGatheringState(kIceGatheringGathering); |
+ bool gathering_success = TryAllocateSockets(); |
+ if (gathering_success) { |
+ SignalCandidateGathered(this, *local_parameters_); |
+ SetGatheringState(kIceGatheringComplete); |
+ } else { |
+ SetGatheringState(kIceGatheringNew); |
+ } |
+ UpdateState(); |
+} |
+ |
+bool UdpTransportChannel::IsLocalConsistent() { |
+ if (!local_parameters_) { |
+ return true; |
+ } |
+ if (!socket_) { |
+ LOG(INFO) << "socket_ is false"; |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+bool UdpTransportChannel::IsRemoteConsistent() { |
+ if (!remote_parameters_) { |
+ return true; |
+ } |
+ if (!remote_parameters_->address().IsComplete()) { |
+ LOG(INFO) << "remote_addr_ not complete"; |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+void UdpTransportChannel::UpdateState() { |
+ RTC_DCHECK_RUN_ON(&network_thread_checker_); |
+ TransportChannelState state; |
+ if (!IsLocalConsistent()) { |
+ state = STATE_FAILED; |
+ } else if (!IsRemoteConsistent()) { |
+ state = STATE_FAILED; |
+ } else if (!local_parameters_ && !remote_parameters_) { |
+ state = STATE_INIT; |
+ } else if (local_parameters_ && !remote_parameters_) { |
+ state = STATE_CONNECTING; |
+ } else if (local_parameters_ && remote_parameters_) { |
+ state = STATE_COMPLETED; |
+ } else { |
+ state = STATE_FAILED; |
+ } |
+ set_writable(state == STATE_COMPLETED); |
+ SetTransportChannelState(state); |
+} |
+ |
+void UdpTransportChannel::AddRemoteCandidate(const Candidate& candidate) { |
+ RTC_DCHECK_RUN_ON(&network_thread_checker_); |
+ // TODO(johan) check for ipv4, other settings. |
+ remote_parameters_ = rtc::Optional<Candidate>(candidate); |
+ UpdateState(); |
+} |
+ |
+void UdpTransportChannel::SetGatheringState(IceGatheringState gathering_state) { |
+ RTC_DCHECK_RUN_ON(&network_thread_checker_); |
+ if (gathering_state_ != gathering_state) { |
+ gathering_state_ = gathering_state; |
+ SignalGatheringState(this); |
+ } |
+} |
+ |
+void UdpTransportChannel::SetTransportChannelState( |
+ TransportChannelState state) { |
+ RTC_DCHECK_RUN_ON(&network_thread_checker_); |
+ if (state_ != state) { |
+ state_ = state; |
+ SignalStateChanged(this); |
+ } |
+} |
+} // namespace cricket |