blob: 263d300dfdc92e150b99eb4fce0c310d244fcba2 [file] [log] [blame]
Ryan Keanedeb48b32019-06-28 16:24:40 -07001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file
4
5#include "platform/api/udp_socket.h"
6
Ryan Keanea4dfaa12019-08-19 10:30:20 -07007#include "platform/api/task_runner.h"
8
Ryan Keanedeb48b32019-06-28 16:24:40 -07009namespace openscreen {
10namespace platform {
11
Ryan Keanea4dfaa12019-08-19 10:30:20 -070012UdpSocket::UdpSocket(TaskRunner* task_runner, Client* client)
13 : client_(client), task_runner_(task_runner) {
14 OSP_CHECK(task_runner_);
Ryan Keane9222e042019-08-27 10:44:13 -070015 if (lifetime_observer_.load()) {
16 lifetime_observer_.load()->OnCreate(this);
17 }
Ryan Keanedeb48b32019-06-28 16:24:40 -070018}
19
20UdpSocket::~UdpSocket() {
Ryan Keane83050af2019-08-26 08:58:09 -070021 OSP_DCHECK(is_closed_);
Ryan Keanedeb48b32019-06-28 16:24:40 -070022}
23
Ryan Keane9222e042019-08-27 10:44:13 -070024// static
25void UdpSocket::SetLifetimeObserver(LifetimeObserver* observer) {
26 lifetime_observer_.store(observer);
Ryan Keanedeb48b32019-06-28 16:24:40 -070027}
28
Ryan Keane9222e042019-08-27 10:44:13 -070029// static
30std::atomic<UdpSocket::LifetimeObserver*> UdpSocket::lifetime_observer_{
31 nullptr};
32
Ryan Keane63fbedd2019-08-19 12:33:41 -070033void UdpSocket::OnError(Error error) {
Ryan Keane83050af2019-08-26 08:58:09 -070034 CloseIfError(error);
35
Ryan Keane63fbedd2019-08-19 12:33:41 -070036 if (!client_) {
37 return;
38 }
39
40 task_runner_->PostTask([e = std::move(error), this]() mutable {
Yuri Wiitalaaf9eadb2019-09-04 14:45:54 -070041 // TODO(issues/71): |this| may be invalid at this point.
Ryan Keane63fbedd2019-08-19 12:33:41 -070042 this->client_->OnError(this, std::move(e));
43 });
44}
Yuri Wiitalaaf9eadb2019-09-04 14:45:54 -070045
Ryan Keane63fbedd2019-08-19 12:33:41 -070046void UdpSocket::OnSendError(Error error) {
47 if (!client_) {
48 return;
49 }
50
51 task_runner_->PostTask([e = std::move(error), this]() mutable {
Yuri Wiitalaaf9eadb2019-09-04 14:45:54 -070052 // TODO(issues/71): |this| may be invalid at this point.
Ryan Keane63fbedd2019-08-19 12:33:41 -070053 this->client_->OnSendError(this, std::move(e));
54 });
55}
Yuri Wiitalaaf9eadb2019-09-04 14:45:54 -070056
Ryan Keane63fbedd2019-08-19 12:33:41 -070057void UdpSocket::OnRead(ErrorOr<UdpPacket> read_data) {
58 if (!client_) {
59 return;
60 }
61
62 task_runner_->PostTask([data = std::move(read_data), this]() mutable {
Yuri Wiitalaaf9eadb2019-09-04 14:45:54 -070063 // TODO(issues/71): |this| may be invalid at this point.
Ryan Keane63fbedd2019-08-19 12:33:41 -070064 this->client_->OnRead(this, std::move(data));
65 });
66}
67
Ryan Keane83050af2019-08-26 08:58:09 -070068void UdpSocket::CloseIfError(const Error& error) {
69 if (error.code() != Error::Code::kNone &&
70 error.code() != Error::Code::kAgain) {
71 CloseIfOpen();
72 }
73}
74
75void UdpSocket::CloseIfOpen() {
76 if (!is_closed_.exchange(true)) {
Ryan Keane9222e042019-08-27 10:44:13 -070077 if (lifetime_observer_.load()) {
78 lifetime_observer_.load()->OnDestroy(this);
79 }
Ryan Keane83050af2019-08-26 08:58:09 -070080 Close();
81 }
82}
83
Ryan Keanedeb48b32019-06-28 16:24:40 -070084} // namespace platform
85} // namespace openscreen