blob: e9c16dc73648c98ec14cb64fa383ef4810ebd323 [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
Niels Möllerd0b88792021-08-12 08:32:3024AsyncUDPSocket* AsyncUDPSocket::Create(Socket* socket,
Yves Gerey665174f2018-06-19 13:03:0525 const SocketAddress& bind_address) {
Niels Möllerd0b88792021-08-12 08:32:3026 std::unique_ptr<Socket> owned_socket(socket);
henrike@webrtc.orgf0488722014-05-13 18:00:2627 if (socket->Bind(bind_address) < 0) {
Mirko Bonadei675513b2017-11-09 10:09:2528 RTC_LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError();
deadbeef37f5ecf2017-02-27 22:06:4129 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:2630 }
31 return new AsyncUDPSocket(owned_socket.release());
32}
33
34AsyncUDPSocket* AsyncUDPSocket::Create(SocketFactory* factory,
35 const SocketAddress& bind_address) {
Niels Möllerd0b88792021-08-12 08:32:3036 Socket* socket = factory->CreateSocket(bind_address.family(), SOCK_DGRAM);
henrike@webrtc.orgf0488722014-05-13 18:00:2637 if (!socket)
deadbeef37f5ecf2017-02-27 22:06:4138 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:2639 return Create(socket, bind_address);
40}
41
Niels Möllerd0b88792021-08-12 08:32:3042AsyncUDPSocket::AsyncUDPSocket(Socket* socket) : socket_(socket) {
Per Kjellander3daf6962022-11-08 17:23:4343 sequence_checker_.Detach();
henrike@webrtc.orgf0488722014-05-13 18:00:2644 // The socket should start out readable but not writable.
45 socket_->SignalReadEvent.connect(this, &AsyncUDPSocket::OnReadEvent);
46 socket_->SignalWriteEvent.connect(this, &AsyncUDPSocket::OnWriteEvent);
47}
48
henrike@webrtc.orgf0488722014-05-13 18:00:2649SocketAddress AsyncUDPSocket::GetLocalAddress() const {
50 return socket_->GetLocalAddress();
51}
52
53SocketAddress AsyncUDPSocket::GetRemoteAddress() const {
54 return socket_->GetRemoteAddress();
55}
56
Yves Gerey665174f2018-06-19 13:03:0557int AsyncUDPSocket::Send(const void* pv,
58 size_t cb,
henrike@webrtc.orgf0488722014-05-13 18:00:2659 const rtc::PacketOptions& options) {
Qingsi Wang6e641e62018-04-12 03:14:1760 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(),
61 options.info_signaled_after_sent);
Qingsi Wang4ea53b32018-04-17 01:22:3162 CopySocketInformationToPacketInfo(cb, *this, false, &sent_packet.info);
stefanc1aeaf02015-10-15 14:26:0763 int ret = socket_->Send(pv, cb);
64 SignalSentPacket(this, sent_packet);
65 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:2666}
67
Yves Gerey665174f2018-06-19 13:03:0568int AsyncUDPSocket::SendTo(const void* pv,
69 size_t cb,
henrike@webrtc.orgf0488722014-05-13 18:00:2670 const SocketAddress& addr,
71 const rtc::PacketOptions& options) {
Qingsi Wang6e641e62018-04-12 03:14:1772 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(),
73 options.info_signaled_after_sent);
Qingsi Wang4ea53b32018-04-17 01:22:3174 CopySocketInformationToPacketInfo(cb, *this, true, &sent_packet.info);
stefanc1aeaf02015-10-15 14:26:0775 int ret = socket_->SendTo(pv, cb, addr);
76 SignalSentPacket(this, sent_packet);
77 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:2678}
79
80int AsyncUDPSocket::Close() {
81 return socket_->Close();
82}
83
84AsyncUDPSocket::State AsyncUDPSocket::GetState() const {
85 return STATE_BOUND;
86}
87
88int AsyncUDPSocket::GetOption(Socket::Option opt, int* value) {
89 return socket_->GetOption(opt, value);
90}
91
92int AsyncUDPSocket::SetOption(Socket::Option opt, int value) {
93 return socket_->SetOption(opt, value);
94}
95
96int AsyncUDPSocket::GetError() const {
97 return socket_->GetError();
98}
99
100void AsyncUDPSocket::SetError(int error) {
101 return socket_->SetError(error);
102}
103
Niels Möllerd0b88792021-08-12 08:32:30104void AsyncUDPSocket::OnReadEvent(Socket* socket) {
nisseede5da42017-01-12 13:15:36105 RTC_DCHECK(socket_.get() == socket);
Per Kjellander3daf6962022-11-08 17:23:43106 RTC_DCHECK_RUN_ON(&sequence_checker_);
henrike@webrtc.orgf0488722014-05-13 18:00:26107
Per Kf81af2f2023-12-22 12:24:40108 Socket::ReceiveBuffer receive_buffer(buffer_);
109 int len = socket_->RecvFrom(receive_buffer);
henrike@webrtc.orgf0488722014-05-13 18:00:26110 if (len < 0) {
111 // An error here typically means we got an ICMP error in response to our
112 // send datagram, indicating the remote address was unreachable.
113 // When doing ICE, this kind of thing will often happen.
114 // TODO: Do something better like forwarding the error to the user.
115 SocketAddress local_addr = socket_->GetLocalAddress();
Mirko Bonadei675513b2017-11-09 10:09:25116 RTC_LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString()
Yves Gerey665174f2018-06-19 13:03:05117 << "] receive failed with error " << socket_->GetError();
henrike@webrtc.orgf0488722014-05-13 18:00:26118 return;
119 }
Per Kf81af2f2023-12-22 12:24:40120 if (len == 0) {
121 // Spurios wakeup.
122 return;
Per Kjellander3daf6962022-11-08 17:23:43123 }
henrike@webrtc.orgf0488722014-05-13 18:00:26124
Per Kf81af2f2023-12-22 12:24:40125 if (!receive_buffer.arrival_time) {
126 // Timestamp from socket is not available.
127 receive_buffer.arrival_time = webrtc::Timestamp::Micros(rtc::TimeMicros());
128 } else {
129 if (!socket_time_offset_) {
Per K58cccc62024-04-19 06:31:23130 // Estimate timestamp offset from first packet arrival time.
131 socket_time_offset_ = webrtc::Timestamp::Micros(rtc::TimeMicros()) -
132 *receive_buffer.arrival_time;
Per Kf81af2f2023-12-22 12:24:40133 }
134 *receive_buffer.arrival_time += *socket_time_offset_;
135 }
Per K8df31c92024-03-11 09:21:48136 NotifyPacketReceived(
137 ReceivedPacket(receive_buffer.payload, receive_buffer.source_address,
138 receive_buffer.arrival_time, receive_buffer.ecn));
henrike@webrtc.orgf0488722014-05-13 18:00:26139}
140
Niels Möllerd0b88792021-08-12 08:32:30141void AsyncUDPSocket::OnWriteEvent(Socket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26142 SignalReadyToSend(this);
143}
144
145} // namespace rtc