Add simple reading to TlsConnection

This patch implements a ReceiveMessage method for TlsConnectionPosix,
that simply checks if bytes are pending and then reads them if so,
reporting any errors that occur.

Change-Id: If9c453cd466c235c502ed16deedac3b7538a6a46
Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/1816287
Reviewed-by: Jordan Bayles <jophba@chromium.org>
Reviewed-by: Yuri Wiitala <miu@chromium.org>
Reviewed-by: Ryan Keane <rwkeane@google.com>
Commit-Queue: Jordan Bayles <jophba@chromium.org>
diff --git a/platform/api/tls_connection.cc b/platform/api/tls_connection.cc
index 0696e4f..ee0258c 100644
--- a/platform/api/tls_connection.cc
+++ b/platform/api/tls_connection.cc
@@ -42,14 +42,14 @@
   });
 }
 
-void TlsConnection::OnRead(std::vector<uint8_t> message) {
+void TlsConnection::OnRead(std::vector<uint8_t> block) {
   if (!client_) {
     return;
   }
 
-  task_runner_->PostTask([m = std::move(message), this]() mutable {
+  task_runner_->PostTask([b = std::move(block), this]() mutable {
     // TODO(issues/71): |this| may be invalid at this point.
-    this->client_->OnRead(this, std::move(m));
+    this->client_->OnRead(this, std::move(b));
   });
 }
 
diff --git a/platform/api/tls_connection.h b/platform/api/tls_connection.h
index 1126265..de7faff 100644
--- a/platform/api/tls_connection.h
+++ b/platform/api/tls_connection.h
@@ -33,11 +33,11 @@
     virtual void OnWriteUnblocked(TlsConnection* connection) = 0;
 
     // Called when |connection| experiences an error, such as a read error.
-    virtual void OnError(TlsConnection* socket, Error error) = 0;
+    virtual void OnError(TlsConnection* connection, Error error) = 0;
 
-    // Called when a |packet| arrives on |socket|.
-    virtual void OnRead(TlsConnection* socket,
-                        std::vector<uint8_t> message) = 0;
+    // Called when a |block| arrives on |connection|.
+    virtual void OnRead(TlsConnection* connection,
+                        std::vector<uint8_t> block) = 0;
 
    protected:
     virtual ~Client() = default;
diff --git a/platform/impl/tls_connection_posix.cc b/platform/impl/tls_connection_posix.cc
index e11b85b..6a0f435 100644
--- a/platform/impl/tls_connection_posix.cc
+++ b/platform/impl/tls_connection_posix.cc
@@ -16,6 +16,7 @@
 
 #include <cstring>
 #include <memory>
+#include <utility>
 
 #include "absl/types/optional.h"
 #include "absl/types/span.h"
@@ -27,7 +28,6 @@
 namespace openscreen {
 namespace platform {
 
-// TODO(jophba, rwkeane): implement reading
 // TODO(jophba, rwkeane): implement write blocking/unblocking
 TlsConnectionPosix::TlsConnectionPosix(IPEndpoint local_address,
                                        TaskRunner* task_runner)
@@ -47,6 +47,31 @@
 
 TlsConnectionPosix::~TlsConnectionPosix() = default;
 
+void TlsConnectionPosix::TryReceiveMessage() {
+  const int bytes_available = SSL_pending(ssl_.get());
+  if (bytes_available > 0) {
+    // NOTE: the pending size of the data block available is not a guarantee
+    // that it will receive only bytes_available or even
+    // any data, since not all pending bytes are application data.
+    std::vector<uint8_t> block(bytes_available);
+
+    const int bytes_read = SSL_read(ssl_.get(), block.data(), bytes_available);
+
+    // Read operator was not successful, either due to a closed connection,
+    // an error occurred, or we have to take an action.
+    if (bytes_read <= 0) {
+      const Error error = GetSSLError(ssl_.get(), bytes_read);
+      if (!error.ok() && (error != Error::Code::kAgain)) {
+        OnError(error);
+      }
+      return;
+    }
+
+    block.resize(bytes_read);
+    OnRead(std::move(block));
+  }
+}
+
 void TlsConnectionPosix::Write(const void* data, size_t len) {
   // TODO(jophba, rwkeane): implement this method.
   OSP_UNIMPLEMENTED();
diff --git a/platform/impl/tls_connection_posix.h b/platform/impl/tls_connection_posix.h
index dd58354..cf8c1a7 100644
--- a/platform/impl/tls_connection_posix.h
+++ b/platform/impl/tls_connection_posix.h
@@ -33,6 +33,10 @@
   // Sends any available bytes from this connection's buffer_.
   void SendAvailableBytes();
 
+  // Read out a block/message, if one is available, and notify this instance's
+  // TlsConnection::Client.
+  virtual void TryReceiveMessage();
+
   // TlsConnection overrides.
   void Write(const void* data, size_t len) override;
   const IPEndpoint& local_address() const override;
diff --git a/platform/impl/tls_data_router_posix.cc b/platform/impl/tls_data_router_posix.cc
index b65210b..466e506 100644
--- a/platform/impl/tls_data_router_posix.cc
+++ b/platform/impl/tls_data_router_posix.cc
@@ -41,8 +41,10 @@
 }
 
 void TlsDataRouterPosix::ReadAll() {
-  // TODO(jophba, rwkeane): implement this method.
-  OSP_UNIMPLEMENTED();
+  std::lock_guard<std::mutex> lock(connections_mutex_);
+  for (TlsConnectionPosix* connection : connections_) {
+    connection->TryReceiveMessage();
+  }
 }
 
 void TlsDataRouterPosix::WriteAll() {