blob: 3d258bcb262263b820a511069cc1346b76ec7d0f [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:261/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 17:11:0011#include "rtc_base/async_udp_socket.h"
Yves Gerey3e707812018-11-28 15:47:4912
Per Kf81af2f2023-12-22 12:24:4013#include "absl/types/optional.h"
14#include "api/units/time_delta.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3115#include "rtc_base/checks.h"
16#include "rtc_base/logging.h"
Per Kf81af2f2023-12-22 12:24:4017#include "rtc_base/network/received_packet.h"
Yves Gerey3e707812018-11-28 15:47:4918#include "rtc_base/network/sent_packet.h"
Steve Anton10542f22019-01-11 17:11:0019#include "rtc_base/time_utils.h"
Per Kjellander3daf6962022-11-08 17:23:4320#include "system_wrappers/include/field_trial.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2621
22namespace rtc {
23
Per K7efd3722023-03-21 13:10:4424// Returns true if the experiement "WebRTC-SCM-Timestamp" is explicitly
25// disabled.
26static bool IsScmTimeStampExperimentDisabled() {
27 return webrtc::field_trial::IsDisabled("WebRTC-SCM-Timestamp");
Per Kjellander3daf6962022-11-08 17:23:4328}
henrike@webrtc.orgf0488722014-05-13 18:00:2629
Niels Möllerd0b88792021-08-12 08:32:3030AsyncUDPSocket* AsyncUDPSocket::Create(Socket* socket,
Yves Gerey665174f2018-06-19 13:03:0531 const SocketAddress& bind_address) {
Niels Möllerd0b88792021-08-12 08:32:3032 std::unique_ptr<Socket> owned_socket(socket);
henrike@webrtc.orgf0488722014-05-13 18:00:2633 if (socket->Bind(bind_address) < 0) {
Mirko Bonadei675513b2017-11-09 10:09:2534 RTC_LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError();
deadbeef37f5ecf2017-02-27 22:06:4135 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:2636 }
37 return new AsyncUDPSocket(owned_socket.release());
38}
39
40AsyncUDPSocket* AsyncUDPSocket::Create(SocketFactory* factory,
41 const SocketAddress& bind_address) {
Niels Möllerd0b88792021-08-12 08:32:3042 Socket* socket = factory->CreateSocket(bind_address.family(), SOCK_DGRAM);
henrike@webrtc.orgf0488722014-05-13 18:00:2643 if (!socket)
deadbeef37f5ecf2017-02-27 22:06:4144 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:2645 return Create(socket, bind_address);
46}
47
Niels Möllerd0b88792021-08-12 08:32:3048AsyncUDPSocket::AsyncUDPSocket(Socket* socket) : socket_(socket) {
Per Kjellander3daf6962022-11-08 17:23:4349 sequence_checker_.Detach();
henrike@webrtc.orgf0488722014-05-13 18:00:2650 // The socket should start out readable but not writable.
51 socket_->SignalReadEvent.connect(this, &AsyncUDPSocket::OnReadEvent);
52 socket_->SignalWriteEvent.connect(this, &AsyncUDPSocket::OnWriteEvent);
53}
54
henrike@webrtc.orgf0488722014-05-13 18:00:2655SocketAddress AsyncUDPSocket::GetLocalAddress() const {
56 return socket_->GetLocalAddress();
57}
58
59SocketAddress AsyncUDPSocket::GetRemoteAddress() const {
60 return socket_->GetRemoteAddress();
61}
62
Yves Gerey665174f2018-06-19 13:03:0563int AsyncUDPSocket::Send(const void* pv,
64 size_t cb,
henrike@webrtc.orgf0488722014-05-13 18:00:2665 const rtc::PacketOptions& options) {
Qingsi Wang6e641e62018-04-12 03:14:1766 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(),
67 options.info_signaled_after_sent);
Qingsi Wang4ea53b32018-04-17 01:22:3168 CopySocketInformationToPacketInfo(cb, *this, false, &sent_packet.info);
stefanc1aeaf02015-10-15 14:26:0769 int ret = socket_->Send(pv, cb);
70 SignalSentPacket(this, sent_packet);
71 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:2672}
73
Yves Gerey665174f2018-06-19 13:03:0574int AsyncUDPSocket::SendTo(const void* pv,
75 size_t cb,
henrike@webrtc.orgf0488722014-05-13 18:00:2676 const SocketAddress& addr,
77 const rtc::PacketOptions& options) {
Qingsi Wang6e641e62018-04-12 03:14:1778 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(),
79 options.info_signaled_after_sent);
Qingsi Wang4ea53b32018-04-17 01:22:3180 CopySocketInformationToPacketInfo(cb, *this, true, &sent_packet.info);
stefanc1aeaf02015-10-15 14:26:0781 int ret = socket_->SendTo(pv, cb, addr);
82 SignalSentPacket(this, sent_packet);
83 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:2684}
85
86int AsyncUDPSocket::Close() {
87 return socket_->Close();
88}
89
90AsyncUDPSocket::State AsyncUDPSocket::GetState() const {
91 return STATE_BOUND;
92}
93
94int AsyncUDPSocket::GetOption(Socket::Option opt, int* value) {
95 return socket_->GetOption(opt, value);
96}
97
98int AsyncUDPSocket::SetOption(Socket::Option opt, int value) {
99 return socket_->SetOption(opt, value);
100}
101
102int AsyncUDPSocket::GetError() const {
103 return socket_->GetError();
104}
105
106void AsyncUDPSocket::SetError(int error) {
107 return socket_->SetError(error);
108}
109
Niels Möllerd0b88792021-08-12 08:32:30110void AsyncUDPSocket::OnReadEvent(Socket* socket) {
nisseede5da42017-01-12 13:15:36111 RTC_DCHECK(socket_.get() == socket);
Per Kjellander3daf6962022-11-08 17:23:43112 RTC_DCHECK_RUN_ON(&sequence_checker_);
henrike@webrtc.orgf0488722014-05-13 18:00:26113
Per Kf81af2f2023-12-22 12:24:40114 Socket::ReceiveBuffer receive_buffer(buffer_);
115 int len = socket_->RecvFrom(receive_buffer);
henrike@webrtc.orgf0488722014-05-13 18:00:26116 if (len < 0) {
117 // An error here typically means we got an ICMP error in response to our
118 // send datagram, indicating the remote address was unreachable.
119 // When doing ICE, this kind of thing will often happen.
120 // TODO: Do something better like forwarding the error to the user.
121 SocketAddress local_addr = socket_->GetLocalAddress();
Mirko Bonadei675513b2017-11-09 10:09:25122 RTC_LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString()
Yves Gerey665174f2018-06-19 13:03:05123 << "] receive failed with error " << socket_->GetError();
henrike@webrtc.orgf0488722014-05-13 18:00:26124 return;
125 }
Per Kf81af2f2023-12-22 12:24:40126 if (len == 0) {
127 // Spurios wakeup.
128 return;
Per Kjellander3daf6962022-11-08 17:23:43129 }
henrike@webrtc.orgf0488722014-05-13 18:00:26130
Per Kf81af2f2023-12-22 12:24:40131 if (!receive_buffer.arrival_time) {
132 // Timestamp from socket is not available.
133 receive_buffer.arrival_time = webrtc::Timestamp::Micros(rtc::TimeMicros());
134 } else {
135 if (!socket_time_offset_) {
136 // Estimate timestamp offset from first packet arrival time unless
137 // disabled
138 bool estimate_time_offset = !IsScmTimeStampExperimentDisabled();
139 if (estimate_time_offset) {
140 socket_time_offset_ = webrtc::Timestamp::Micros(rtc::TimeMicros()) -
141 *receive_buffer.arrival_time;
142 } else {
143 socket_time_offset_ = webrtc::TimeDelta::Micros(0);
144 }
145 }
146 *receive_buffer.arrival_time += *socket_time_offset_;
147 }
148 NotifyPacketReceived(ReceivedPacket(receive_buffer.payload,
149 receive_buffer.source_address,
150 receive_buffer.arrival_time));
henrike@webrtc.orgf0488722014-05-13 18:00:26151}
152
Niels Möllerd0b88792021-08-12 08:32:30153void AsyncUDPSocket::OnWriteEvent(Socket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26154 SignalReadyToSend(this);
155}
156
157} // namespace rtc