blob: 852191060ef51e53258357c05586dc77a06d139f [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>
14#include <string>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "rtc_base/checks.h"
17#include "rtc_base/logging.h"
Yves Gerey3e707812018-11-28 16:47:49 +010018#include "rtc_base/network/sent_packet.h"
19#include "rtc_base/third_party/sigslot/sigslot.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "rtc_base/time_utils.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000021
22namespace rtc {
23
24static const int BUF_SIZE = 64 * 1024;
25
Yves Gerey665174f2018-06-19 15:03:05 +020026AsyncUDPSocket* AsyncUDPSocket::Create(AsyncSocket* socket,
27 const SocketAddress& bind_address) {
jbauch555604a2016-04-26 03:13:22 -070028 std::unique_ptr<AsyncSocket> owned_socket(socket);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000029 if (socket->Bind(bind_address) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010030 RTC_LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError();
deadbeef37f5ecf2017-02-27 14:06:41 -080031 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000032 }
33 return new AsyncUDPSocket(owned_socket.release());
34}
35
36AsyncUDPSocket* AsyncUDPSocket::Create(SocketFactory* factory,
37 const SocketAddress& bind_address) {
38 AsyncSocket* socket =
39 factory->CreateAsyncSocket(bind_address.family(), SOCK_DGRAM);
40 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
Yves Gerey665174f2018-06-19 15:03:05 +020045AsyncUDPSocket::AsyncUDPSocket(AsyncSocket* 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
113void AsyncUDPSocket::OnReadEvent(AsyncSocket* 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
136void AsyncUDPSocket::OnWriteEvent(AsyncSocket* socket) {
137 SignalReadyToSend(this);
138}
139
140} // namespace rtc