• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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/impl/tls_connection_posix.h"
6 
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <netinet/in.h>
10 #include <netinet/ip.h>
11 #include <openssl/ssl.h>
12 #include <sys/ioctl.h>
13 #include <sys/socket.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 
17 #include <cstring>
18 #include <memory>
19 #include <utility>
20 #include <vector>
21 
22 #include "absl/types/optional.h"
23 #include "absl/types/span.h"
24 #include "platform/api/task_runner.h"
25 #include "platform/base/error.h"
26 #include "platform/impl/stream_socket.h"
27 #include "util/crypto/openssl_util.h"
28 #include "util/osp_logging.h"
29 
30 namespace openscreen {
31 
32 // TODO(jophba, rwkeane): implement write blocking/unblocking
TlsConnectionPosix(IPEndpoint local_address,TaskRunner * task_runner)33 TlsConnectionPosix::TlsConnectionPosix(IPEndpoint local_address,
34                                        TaskRunner* task_runner)
35     : task_runner_(task_runner),
36       socket_(std::make_unique<StreamSocketPosix>(local_address)) {
37   OSP_DCHECK(task_runner_);
38 }
39 
TlsConnectionPosix(IPAddress::Version version,TaskRunner * task_runner)40 TlsConnectionPosix::TlsConnectionPosix(IPAddress::Version version,
41                                        TaskRunner* task_runner)
42     : task_runner_(task_runner),
43       socket_(std::make_unique<StreamSocketPosix>(version)) {
44   OSP_DCHECK(task_runner_);
45 }
46 
TlsConnectionPosix(std::unique_ptr<StreamSocket> socket,TaskRunner * task_runner)47 TlsConnectionPosix::TlsConnectionPosix(std::unique_ptr<StreamSocket> socket,
48                                        TaskRunner* task_runner)
49     : task_runner_(task_runner), socket_(std::move(socket)) {
50   OSP_DCHECK(task_runner_);
51 }
52 
~TlsConnectionPosix()53 TlsConnectionPosix::~TlsConnectionPosix() {
54   if (platform_client_) {
55     platform_client_->tls_data_router()->DeregisterConnection(this);
56   }
57   // TODO(issuetracker.google.com/169966671): This is only tested by CastSocket
58   // E2E tests at the moment.
59   if (ssl_) {
60     SSL_shutdown(ssl_.get());
61   }
62 }
63 
TryReceiveMessage()64 void TlsConnectionPosix::TryReceiveMessage() {
65   OSP_DCHECK(ssl_);
66   constexpr int kMaxApplicationDataBytes = 4096;
67   std::vector<uint8_t> block(kMaxApplicationDataBytes);
68   ClearOpenSSLERRStack(CURRENT_LOCATION);
69   const int bytes_read =
70       SSL_read(ssl_.get(), block.data(), kMaxApplicationDataBytes);
71 
72   // Read operator was not successful, either due to a closed connection,
73   // no application data available, an error occurred, or we have to take an
74   // action.
75   if (bytes_read <= 0) {
76     const Error error = GetSSLError(ssl_.get(), bytes_read);
77     if (!error.ok() && (error != Error::Code::kAgain)) {
78       DispatchError(error);
79     }
80     return;
81   }
82 
83   block.resize(bytes_read);
84 
85   task_runner_->PostTask([weak_this = weak_factory_.GetWeakPtr(),
86                           moved_block = std::move(block)]() mutable {
87     if (auto* self = weak_this.get()) {
88       if (auto* client = self->client_) {
89         client->OnRead(self, std::move(moved_block));
90       }
91     }
92   });
93 }
94 
SetClient(Client * client)95 void TlsConnectionPosix::SetClient(Client* client) {
96   OSP_DCHECK(task_runner_->IsRunningOnTaskRunner());
97   client_ = client;
98 }
99 
Send(const void * data,size_t len)100 bool TlsConnectionPosix::Send(const void* data, size_t len) {
101   OSP_DCHECK(task_runner_->IsRunningOnTaskRunner());
102   return buffer_.Push(data, len);
103 }
104 
GetRemoteEndpoint() const105 IPEndpoint TlsConnectionPosix::GetRemoteEndpoint() const {
106   OSP_DCHECK(task_runner_->IsRunningOnTaskRunner());
107 
108   absl::optional<IPEndpoint> endpoint = socket_->remote_address();
109   OSP_DCHECK(endpoint.has_value());
110   return endpoint.value();
111 }
112 
RegisterConnectionWithDataRouter(PlatformClientPosix * platform_client)113 void TlsConnectionPosix::RegisterConnectionWithDataRouter(
114     PlatformClientPosix* platform_client) {
115   OSP_DCHECK(!platform_client_);
116   platform_client_ = platform_client;
117   platform_client_->tls_data_router()->RegisterConnection(this);
118 }
119 
SendAvailableBytes()120 void TlsConnectionPosix::SendAvailableBytes() {
121   absl::Span<const uint8_t> sendable_bytes = buffer_.GetReadableRegion();
122   if (sendable_bytes.empty()) {
123     return;
124   }
125 
126   ClearOpenSSLERRStack(CURRENT_LOCATION);
127   const int result =
128       SSL_write(ssl_.get(), sendable_bytes.data(), sendable_bytes.size());
129   if (result <= 0) {
130     const Error result_error = GetSSLError(ssl_.get(), result);
131     if (!result_error.ok() && (result_error.code() != Error::Code::kAgain)) {
132       DispatchError(result_error);
133     }
134   } else {
135     buffer_.Consume(static_cast<size_t>(result));
136   }
137 }
138 
DispatchError(Error error)139 void TlsConnectionPosix::DispatchError(Error error) {
140   task_runner_->PostTask([weak_this = weak_factory_.GetWeakPtr(),
141                           moved_error = std::move(error)]() mutable {
142     if (auto* self = weak_this.get()) {
143       if (auto* client = self->client_) {
144         client->OnError(self, std::move(moved_error));
145       }
146     }
147   });
148 }
149 
150 }  // namespace openscreen
151