blob: 7276a230b9aed009203eb5cf501eecec3704a44a [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
13#include <stdint.h>
Jonas Olssona4d87372019-07-05 17:08:3314
Yves Gerey3e707812018-11-28 15:47:4915#include <string>
16
Mirko Bonadei92ea95e2017-09-15 04:47:3117#include "rtc_base/checks.h"
18#include "rtc_base/logging.h"
Yves Gerey3e707812018-11-28 15:47:4919#include "rtc_base/network/sent_packet.h"
20#include "rtc_base/third_party/sigslot/sigslot.h"
Steve Anton10542f22019-01-11 17:11:0021#include "rtc_base/time_utils.h"
Per Kjellander3daf6962022-11-08 17:23:4322#include "system_wrappers/include/field_trial.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2623
24namespace rtc {
25
Per K7efd3722023-03-21 13:10:4426// Returns true if the experiement "WebRTC-SCM-Timestamp" is explicitly
27// disabled.
28static bool IsScmTimeStampExperimentDisabled() {
29 return webrtc::field_trial::IsDisabled("WebRTC-SCM-Timestamp");
Per Kjellander3daf6962022-11-08 17:23:4330}
henrike@webrtc.orgf0488722014-05-13 18:00:2631
Niels Möllerd0b88792021-08-12 08:32:3032AsyncUDPSocket* AsyncUDPSocket::Create(Socket* socket,
Yves Gerey665174f2018-06-19 13:03:0533 const SocketAddress& bind_address) {
Niels Möllerd0b88792021-08-12 08:32:3034 std::unique_ptr<Socket> owned_socket(socket);
henrike@webrtc.orgf0488722014-05-13 18:00:2635 if (socket->Bind(bind_address) < 0) {
Mirko Bonadei675513b2017-11-09 10:09:2536 RTC_LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError();
deadbeef37f5ecf2017-02-27 22:06:4137 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:2638 }
39 return new AsyncUDPSocket(owned_socket.release());
40}
41
42AsyncUDPSocket* AsyncUDPSocket::Create(SocketFactory* factory,
43 const SocketAddress& bind_address) {
Niels Möllerd0b88792021-08-12 08:32:3044 Socket* socket = factory->CreateSocket(bind_address.family(), SOCK_DGRAM);
henrike@webrtc.orgf0488722014-05-13 18:00:2645 if (!socket)
deadbeef37f5ecf2017-02-27 22:06:4146 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:2647 return Create(socket, bind_address);
48}
49
Niels Möllerd0b88792021-08-12 08:32:3050AsyncUDPSocket::AsyncUDPSocket(Socket* socket) : socket_(socket) {
Per Kjellander3daf6962022-11-08 17:23:4351 sequence_checker_.Detach();
henrike@webrtc.orgf0488722014-05-13 18:00:2652 // The socket should start out readable but not writable.
53 socket_->SignalReadEvent.connect(this, &AsyncUDPSocket::OnReadEvent);
54 socket_->SignalWriteEvent.connect(this, &AsyncUDPSocket::OnWriteEvent);
55}
56
henrike@webrtc.orgf0488722014-05-13 18:00:2657SocketAddress AsyncUDPSocket::GetLocalAddress() const {
58 return socket_->GetLocalAddress();
59}
60
61SocketAddress AsyncUDPSocket::GetRemoteAddress() const {
62 return socket_->GetRemoteAddress();
63}
64
Yves Gerey665174f2018-06-19 13:03:0565int AsyncUDPSocket::Send(const void* pv,
66 size_t cb,
henrike@webrtc.orgf0488722014-05-13 18:00:2667 const rtc::PacketOptions& options) {
Qingsi Wang6e641e62018-04-12 03:14:1768 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(),
69 options.info_signaled_after_sent);
Qingsi Wang4ea53b32018-04-17 01:22:3170 CopySocketInformationToPacketInfo(cb, *this, false, &sent_packet.info);
stefanc1aeaf02015-10-15 14:26:0771 int ret = socket_->Send(pv, cb);
72 SignalSentPacket(this, sent_packet);
73 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:2674}
75
Yves Gerey665174f2018-06-19 13:03:0576int AsyncUDPSocket::SendTo(const void* pv,
77 size_t cb,
henrike@webrtc.orgf0488722014-05-13 18:00:2678 const SocketAddress& addr,
79 const rtc::PacketOptions& options) {
Qingsi Wang6e641e62018-04-12 03:14:1780 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(),
81 options.info_signaled_after_sent);
Qingsi Wang4ea53b32018-04-17 01:22:3182 CopySocketInformationToPacketInfo(cb, *this, true, &sent_packet.info);
stefanc1aeaf02015-10-15 14:26:0783 int ret = socket_->SendTo(pv, cb, addr);
84 SignalSentPacket(this, sent_packet);
85 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:2686}
87
88int AsyncUDPSocket::Close() {
89 return socket_->Close();
90}
91
92AsyncUDPSocket::State AsyncUDPSocket::GetState() const {
93 return STATE_BOUND;
94}
95
96int AsyncUDPSocket::GetOption(Socket::Option opt, int* value) {
97 return socket_->GetOption(opt, value);
98}
99
100int AsyncUDPSocket::SetOption(Socket::Option opt, int value) {
101 return socket_->SetOption(opt, value);
102}
103
104int AsyncUDPSocket::GetError() const {
105 return socket_->GetError();
106}
107
108void AsyncUDPSocket::SetError(int error) {
109 return socket_->SetError(error);
110}
111
Niels Möllerd0b88792021-08-12 08:32:30112void AsyncUDPSocket::OnReadEvent(Socket* socket) {
nisseede5da42017-01-12 13:15:36113 RTC_DCHECK(socket_.get() == socket);
Per Kjellander3daf6962022-11-08 17:23:43114 RTC_DCHECK_RUN_ON(&sequence_checker_);
henrike@webrtc.orgf0488722014-05-13 18:00:26115
116 SocketAddress remote_addr;
Per Kjellander3daf6962022-11-08 17:23:43117 int64_t timestamp = -1;
118 int len = socket_->RecvFrom(buf_, BUF_SIZE, &remote_addr, &timestamp);
119
henrike@webrtc.orgf0488722014-05-13 18:00:26120 if (len < 0) {
121 // An error here typically means we got an ICMP error in response to our
122 // send datagram, indicating the remote address was unreachable.
123 // When doing ICE, this kind of thing will often happen.
124 // TODO: Do something better like forwarding the error to the user.
125 SocketAddress local_addr = socket_->GetLocalAddress();
Mirko Bonadei675513b2017-11-09 10:09:25126 RTC_LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString()
Yves Gerey665174f2018-06-19 13:03:05127 << "] receive failed with error " << socket_->GetError();
henrike@webrtc.orgf0488722014-05-13 18:00:26128 return;
129 }
Per Kjellander3daf6962022-11-08 17:23:43130 if (timestamp == -1) {
131 // Timestamp from socket is not available.
132 timestamp = TimeMicros();
133 } else {
134 if (!socket_time_offset_) {
135 socket_time_offset_ =
Per K7efd3722023-03-21 13:10:44136 !IsScmTimeStampExperimentDisabled() ? TimeMicros() - timestamp : 0;
Per Kjellander3daf6962022-11-08 17:23:43137 }
138 timestamp += *socket_time_offset_;
139 }
henrike@webrtc.orgf0488722014-05-13 18:00:26140
141 // TODO: Make sure that we got all of the packet.
142 // If we did not, then we should resize our buffer to be large enough.
Niels Möller15ca5a92018-11-01 13:32:47143 SignalReadPacket(this, buf_, static_cast<size_t>(len), remote_addr,
Per Kjellander3daf6962022-11-08 17:23:43144 timestamp);
henrike@webrtc.orgf0488722014-05-13 18:00:26145}
146
Niels Möllerd0b88792021-08-12 08:32:30147void AsyncUDPSocket::OnWriteEvent(Socket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26148 SignalReadyToSend(this);
149}
150
151} // namespace rtc