blob: b4aefd683770a075a4c87431d821624d3c233877 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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 09:11:00 -080011#include "rtc_base/async_udp_socket.h"
Yves Gerey3e707812018-11-28 16:47:49 +010012
13#include <stdint.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <string>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/checks.h"
18#include "rtc_base/logging.h"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "rtc_base/network/sent_packet.h"
20#include "rtc_base/third_party/sigslot/sigslot.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "rtc_base/time_utils.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000022
23namespace rtc {
24
25static const int BUF_SIZE = 64 * 1024;
26
Niels Möllerd0b88792021-08-12 10:32:30 +020027AsyncUDPSocket* AsyncUDPSocket::Create(Socket* socket,
Yves Gerey665174f2018-06-19 15:03:05 +020028 const SocketAddress& bind_address) {
Niels Möllerd0b88792021-08-12 10:32:30 +020029 std::unique_ptr<Socket> owned_socket(socket);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000030 if (socket->Bind(bind_address) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010031 RTC_LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError();
deadbeef37f5ecf2017-02-27 14:06:41 -080032 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000033 }
34 return new AsyncUDPSocket(owned_socket.release());
35}
36
37AsyncUDPSocket* AsyncUDPSocket::Create(SocketFactory* factory,
38 const SocketAddress& bind_address) {
Niels Möllerd0b88792021-08-12 10:32:30 +020039 Socket* socket = factory->CreateSocket(bind_address.family(), SOCK_DGRAM);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000040 if (!socket)
deadbeef37f5ecf2017-02-27 14:06:41 -080041 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000042 return Create(socket, bind_address);
43}
44
Niels Möllerd0b88792021-08-12 10:32:30 +020045AsyncUDPSocket::AsyncUDPSocket(Socket* socket) : socket_(socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000046 size_ = BUF_SIZE;
47 buf_ = new char[size_];
48
49 // The socket should start out readable but not writable.
50 socket_->SignalReadEvent.connect(this, &AsyncUDPSocket::OnReadEvent);
51 socket_->SignalWriteEvent.connect(this, &AsyncUDPSocket::OnWriteEvent);
52}
53
54AsyncUDPSocket::~AsyncUDPSocket() {
Yves Gerey665174f2018-06-19 15:03:05 +020055 delete[] buf_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000056}
57
58SocketAddress AsyncUDPSocket::GetLocalAddress() const {
59 return socket_->GetLocalAddress();
60}
61
62SocketAddress AsyncUDPSocket::GetRemoteAddress() const {
63 return socket_->GetRemoteAddress();
64}
65
Yves Gerey665174f2018-06-19 15:03:05 +020066int AsyncUDPSocket::Send(const void* pv,
67 size_t cb,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000068 const rtc::PacketOptions& options) {
Qingsi Wang6e641e62018-04-11 20:14:17 -070069 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(),
70 options.info_signaled_after_sent);
Qingsi Wang4ea53b32018-04-16 18:22:31 -070071 CopySocketInformationToPacketInfo(cb, *this, false, &sent_packet.info);
stefanc1aeaf02015-10-15 07:26:07 -070072 int ret = socket_->Send(pv, cb);
73 SignalSentPacket(this, sent_packet);
74 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000075}
76
Yves Gerey665174f2018-06-19 15:03:05 +020077int AsyncUDPSocket::SendTo(const void* pv,
78 size_t cb,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000079 const SocketAddress& addr,
80 const rtc::PacketOptions& options) {
Qingsi Wang6e641e62018-04-11 20:14:17 -070081 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(),
82 options.info_signaled_after_sent);
Qingsi Wang4ea53b32018-04-16 18:22:31 -070083 CopySocketInformationToPacketInfo(cb, *this, true, &sent_packet.info);
stefanc1aeaf02015-10-15 07:26:07 -070084 int ret = socket_->SendTo(pv, cb, addr);
85 SignalSentPacket(this, sent_packet);
86 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000087}
88
89int AsyncUDPSocket::Close() {
90 return socket_->Close();
91}
92
93AsyncUDPSocket::State AsyncUDPSocket::GetState() const {
94 return STATE_BOUND;
95}
96
97int AsyncUDPSocket::GetOption(Socket::Option opt, int* value) {
98 return socket_->GetOption(opt, value);
99}
100
101int AsyncUDPSocket::SetOption(Socket::Option opt, int value) {
102 return socket_->SetOption(opt, value);
103}
104
105int AsyncUDPSocket::GetError() const {
106 return socket_->GetError();
107}
108
109void AsyncUDPSocket::SetError(int error) {
110 return socket_->SetError(error);
111}
112
Niels Möllerd0b88792021-08-12 10:32:30 +0200113void AsyncUDPSocket::OnReadEvent(Socket* socket) {
nisseede5da42017-01-12 05:15:36 -0800114 RTC_DCHECK(socket_.get() == socket);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000115
116 SocketAddress remote_addr;
Stefan Holmer9131efd2016-05-23 18:19:26 +0200117 int64_t timestamp;
118 int len = socket_->RecvFrom(buf_, size_, &remote_addr, &timestamp);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000119 if (len < 0) {
120 // An error here typically means we got an ICMP error in response to our
121 // send datagram, indicating the remote address was unreachable.
122 // When doing ICE, this kind of thing will often happen.
123 // TODO: Do something better like forwarding the error to the user.
124 SocketAddress local_addr = socket_->GetLocalAddress();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100125 RTC_LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString()
Yves Gerey665174f2018-06-19 15:03:05 +0200126 << "] receive failed with error " << socket_->GetError();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000127 return;
128 }
129
130 // TODO: Make sure that we got all of the packet.
131 // If we did not, then we should resize our buffer to be large enough.
Niels Möller15ca5a92018-11-01 14:32:47 +0100132 SignalReadPacket(this, buf_, static_cast<size_t>(len), remote_addr,
133 (timestamp > -1 ? timestamp : TimeMicros()));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000134}
135
Niels Möllerd0b88792021-08-12 10:32:30 +0200136void AsyncUDPSocket::OnWriteEvent(Socket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000137 SignalReadyToSend(this);
138}
139
140} // namespace rtc