blob: 378b6872666e5ffc3a16430594dcde040cc13bbd [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
Yves Gerey665174f2018-06-19 15:03:05 +020027AsyncUDPSocket* AsyncUDPSocket::Create(AsyncSocket* socket,
28 const SocketAddress& bind_address) {
jbauch555604a2016-04-26 03:13:22 -070029 std::unique_ptr<AsyncSocket> 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) {
39 AsyncSocket* socket =
40 factory->CreateAsyncSocket(bind_address.family(), SOCK_DGRAM);
41 if (!socket)
deadbeef37f5ecf2017-02-27 14:06:41 -080042 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000043 return Create(socket, bind_address);
44}
45
Yves Gerey665174f2018-06-19 15:03:05 +020046AsyncUDPSocket::AsyncUDPSocket(AsyncSocket* socket) : socket_(socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000047 size_ = BUF_SIZE;
48 buf_ = new char[size_];
49
50 // 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
55AsyncUDPSocket::~AsyncUDPSocket() {
Yves Gerey665174f2018-06-19 15:03:05 +020056 delete[] buf_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000057}
58
59SocketAddress AsyncUDPSocket::GetLocalAddress() const {
60 return socket_->GetLocalAddress();
61}
62
63SocketAddress AsyncUDPSocket::GetRemoteAddress() const {
64 return socket_->GetRemoteAddress();
65}
66
Yves Gerey665174f2018-06-19 15:03:05 +020067int AsyncUDPSocket::Send(const void* pv,
68 size_t cb,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000069 const rtc::PacketOptions& options) {
Qingsi Wang6e641e62018-04-11 20:14:17 -070070 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(),
71 options.info_signaled_after_sent);
Qingsi Wang4ea53b32018-04-16 18:22:31 -070072 CopySocketInformationToPacketInfo(cb, *this, false, &sent_packet.info);
stefanc1aeaf02015-10-15 07:26:07 -070073 int ret = socket_->Send(pv, cb);
74 SignalSentPacket(this, sent_packet);
75 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000076}
77
Yves Gerey665174f2018-06-19 15:03:05 +020078int AsyncUDPSocket::SendTo(const void* pv,
79 size_t cb,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000080 const SocketAddress& addr,
81 const rtc::PacketOptions& options) {
Qingsi Wang6e641e62018-04-11 20:14:17 -070082 rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(),
83 options.info_signaled_after_sent);
Qingsi Wang4ea53b32018-04-16 18:22:31 -070084 CopySocketInformationToPacketInfo(cb, *this, true, &sent_packet.info);
stefanc1aeaf02015-10-15 07:26:07 -070085 int ret = socket_->SendTo(pv, cb, addr);
86 SignalSentPacket(this, sent_packet);
87 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000088}
89
90int AsyncUDPSocket::Close() {
91 return socket_->Close();
92}
93
94AsyncUDPSocket::State AsyncUDPSocket::GetState() const {
95 return STATE_BOUND;
96}
97
98int AsyncUDPSocket::GetOption(Socket::Option opt, int* value) {
99 return socket_->GetOption(opt, value);
100}
101
102int AsyncUDPSocket::SetOption(Socket::Option opt, int value) {
103 return socket_->SetOption(opt, value);
104}
105
106int AsyncUDPSocket::GetError() const {
107 return socket_->GetError();
108}
109
110void AsyncUDPSocket::SetError(int error) {
111 return socket_->SetError(error);
112}
113
114void AsyncUDPSocket::OnReadEvent(AsyncSocket* socket) {
nisseede5da42017-01-12 05:15:36 -0800115 RTC_DCHECK(socket_.get() == socket);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000116
117 SocketAddress remote_addr;
Stefan Holmer9131efd2016-05-23 18:19:26 +0200118 int64_t timestamp;
119 int len = socket_->RecvFrom(buf_, size_, &remote_addr, &timestamp);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000120 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 11:09:25 +0100126 RTC_LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString()
Yves Gerey665174f2018-06-19 15:03:05 +0200127 << "] receive failed with error " << socket_->GetError();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000128 return;
129 }
130
131 // TODO: Make sure that we got all of the packet.
132 // If we did not, then we should resize our buffer to be large enough.
Niels Möller15ca5a92018-11-01 14:32:47 +0100133 SignalReadPacket(this, buf_, static_cast<size_t>(len), remote_addr,
134 (timestamp > -1 ? timestamp : TimeMicros()));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000135}
136
137void AsyncUDPSocket::OnWriteEvent(AsyncSocket* socket) {
138 SignalReadyToSend(this);
139}
140
141} // namespace rtc