libweave: Extract weave::Stream interface

Interface is implemented in buffet using ChromeOS streams.
This breaks libweave dependency on chromeos/streams/.

BUG=brillo:1257
TEST=`FEATURES=test emerge-gizmo libweave buffet`

Change-Id: I9fa73d40810f39d5608b3cbe320bc9eca0dff4ef
Reviewed-on: https://chromium-review.googlesource.com/293321
Trybot-Ready: Vitaly Buka <vitalybuka@chromium.org>
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp
index 5b229b6..026b341 100644
--- a/buffet/buffet.gyp
+++ b/buffet/buffet.gyp
@@ -41,6 +41,7 @@
         'http_transport_client.cc',
         'manager.cc',
         'shill_client.cc',
+        'socket_stream.cc',
       ],
       'conditions': [
         ['USE_wifi_bootstrapping == 1', {
diff --git a/buffet/shill_client.cc b/buffet/shill_client.cc
index c549fd4..0d733c8 100644
--- a/buffet/shill_client.cc
+++ b/buffet/shill_client.cc
@@ -15,6 +15,7 @@
 #include <weave/enum_to_string.h>
 
 #include "buffet/ap_manager_client.h"
+#include "buffet/socket_stream.h"
 
 using chromeos::Any;
 using chromeos::VariantDictionary;
@@ -496,4 +497,20 @@
   connecting_service_reset_pending_ = false;
 }
 
+std::unique_ptr<weave::Stream> ShillClient::OpenSocketBlocking(
+    const std::string& host,
+    uint16_t port) {
+  return SocketStream::ConnectBlocking(host, port);
+}
+
+void ShillClient::CreateTlsStream(
+    std::unique_ptr<weave::Stream> socket,
+    const std::string& host,
+    const base::Callback<void(std::unique_ptr<weave::Stream>)>&
+        success_callback,
+    const base::Callback<void(const chromeos::Error*)>& error_callback) {
+  SocketStream::TlsConnect(std::move(socket), host, success_callback,
+                           error_callback);
+}
+
 }  // namespace buffet
diff --git a/buffet/shill_client.h b/buffet/shill_client.h
index 4d54d60..0aad908 100644
--- a/buffet/shill_client.h
+++ b/buffet/shill_client.h
@@ -42,6 +42,15 @@
   weave::NetworkState GetConnectionState() const override;
   void EnableAccessPoint(const std::string& ssid) override;
   void DisableAccessPoint() override;
+  std::unique_ptr<weave::Stream> OpenSocketBlocking(const std::string& host,
+                                                    uint16_t port) override;
+  void CreateTlsStream(
+      std::unique_ptr<weave::Stream> socket,
+      const std::string& host,
+      const base::Callback<void(std::unique_ptr<weave::Stream>)>&
+          success_callback,
+      const base::Callback<void(const chromeos::Error*)>& error_callback)
+      override;
 
  private:
   struct DeviceState {
diff --git a/buffet/socket_stream.cc b/buffet/socket_stream.cc
new file mode 100644
index 0000000..4b4bbbe
--- /dev/null
+++ b/buffet/socket_stream.cc
@@ -0,0 +1,122 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <arpa/inet.h>
+#include <map>
+#include <netdb.h>
+#include <string>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <base/bind.h>
+#include <base/files/file_util.h>
+#include <chromeos/streams/file_stream.h>
+#include <chromeos/streams/tls_stream.h>
+
+#include "buffet/socket_stream.h"
+
+namespace buffet {
+
+namespace {
+
+int ConnectSocket(const std::string& host, uint16_t port) {
+  std::string service = std::to_string(port);
+  addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM};
+  addrinfo* result = nullptr;
+  if (getaddrinfo(host.c_str(), service.c_str(), &hints, &result)) {
+    PLOG(WARNING) << "Failed to resolve host name: " << host;
+    return -1;
+  }
+
+  int socket_fd = -1;
+  for (const addrinfo* info = result; info != nullptr; info = info->ai_next) {
+    socket_fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
+    if (socket_fd < 0)
+      continue;
+
+    char str[INET6_ADDRSTRLEN] = {};
+    inet_ntop(info->ai_family, info->ai_addr, str, info->ai_addrlen);
+    LOG(INFO) << "Connecting to address: " << str;
+    if (connect(socket_fd, info->ai_addr, info->ai_addrlen) == 0)
+      break;  // Success.
+
+    PLOG(WARNING) << "Failed to connect to address: " << str;
+    close(socket_fd);
+    socket_fd = -1;
+  }
+
+  freeaddrinfo(result);
+  return socket_fd;
+}
+
+void OnSuccess(const base::Callback<void(std::unique_ptr<weave::Stream>)>&
+                   success_callback,
+               chromeos::StreamPtr tls_stream) {
+  success_callback.Run(
+      std::unique_ptr<weave::Stream>{new SocketStream{std::move(tls_stream)}});
+}
+
+}  // namespace
+
+bool SocketStream::ReadAsync(
+    void* buffer,
+    size_t size_to_read,
+    const base::Callback<void(size_t)>& success_callback,
+    const base::Callback<void(const chromeos::Error*)>& error_callback,
+    chromeos::ErrorPtr* error) {
+  return ptr_->ReadAsync(buffer, size_to_read, success_callback, error_callback,
+                         error);
+}
+
+bool SocketStream::WriteAllAsync(
+    const void* buffer,
+    size_t size_to_write,
+    const base::Closure& success_callback,
+    const base::Callback<void(const chromeos::Error*)>& error_callback,
+    chromeos::ErrorPtr* error) {
+  return ptr_->WriteAllAsync(buffer, size_to_write, success_callback,
+                             error_callback, error);
+}
+
+bool SocketStream::FlushBlocking(chromeos::ErrorPtr* error) {
+  return ptr_->FlushBlocking(error);
+}
+
+bool SocketStream::CloseBlocking(chromeos::ErrorPtr* error) {
+  return ptr_->CloseBlocking(error);
+}
+
+void SocketStream::CancelPendingAsyncOperations() {
+  return ptr_->CancelPendingAsyncOperations();
+}
+
+std::unique_ptr<weave::Stream> SocketStream::ConnectBlocking(
+    const std::string& host,
+    uint16_t port) {
+  int socket_fd = ConnectSocket(host, port);
+  if (socket_fd <= 0)
+    return nullptr;
+
+  auto ptr_ =
+      chromeos::FileStream::FromFileDescriptor(socket_fd, true, nullptr);
+  if (ptr_)
+    return std::unique_ptr<Stream>{new SocketStream{std::move(ptr_)}};
+
+  close(socket_fd);
+  return nullptr;
+}
+
+void SocketStream::TlsConnect(
+    std::unique_ptr<Stream> socket,
+    const std::string& host,
+    const base::Callback<void(std::unique_ptr<Stream>)>& success_callback,
+    const base::Callback<void(const chromeos::Error*)>& error_callback) {
+  SocketStream* stream = static_cast<SocketStream*>(socket.get());
+  chromeos::TlsStream::Connect(std::move(stream->ptr_), host,
+                               base::Bind(&OnSuccess, success_callback),
+                               error_callback);
+}
+
+}  // namespace buffet
diff --git a/buffet/socket_stream.h b/buffet/socket_stream.h
new file mode 100644
index 0000000..2e06099
--- /dev/null
+++ b/buffet/socket_stream.h
@@ -0,0 +1,60 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BUFFET_SOCKET_STREAM_H_
+#define BUFFET_SOCKET_STREAM_H_
+
+#include <string>
+
+#include <base/callback.h>
+#include <base/macros.h>
+#include <chromeos/streams/stream.h>
+#include <weave/stream.h>
+
+namespace buffet {
+
+class SocketStream : public weave::Stream {
+ public:
+  explicit SocketStream(chromeos::StreamPtr ptr) : ptr_{std::move(ptr)} {}
+
+  ~SocketStream() override = default;
+
+  bool ReadAsync(
+      void* buffer,
+      size_t size_to_read,
+      const base::Callback<void(size_t)>& success_callback,
+      const base::Callback<void(const chromeos::Error*)>& error_callback,
+      chromeos::ErrorPtr* error) override;
+
+  bool WriteAllAsync(
+      const void* buffer,
+      size_t size_to_write,
+      const base::Closure& success_callback,
+      const base::Callback<void(const chromeos::Error*)>& error_callback,
+      chromeos::ErrorPtr* error) override;
+
+  bool FlushBlocking(chromeos::ErrorPtr* error) override;
+
+  bool CloseBlocking(chromeos::ErrorPtr* error) override;
+
+  void CancelPendingAsyncOperations() override;
+
+  static std::unique_ptr<weave::Stream> ConnectBlocking(const std::string& host,
+                                                        uint16_t port);
+
+  static void TlsConnect(
+      std::unique_ptr<weave::Stream> socket,
+      const std::string& host,
+      const base::Callback<void(std::unique_ptr<weave::Stream>)>&
+          success_callback,
+      const base::Callback<void(const chromeos::Error*)>& error_callback);
+
+ private:
+  chromeos::StreamPtr ptr_;
+  DISALLOW_COPY_AND_ASSIGN(SocketStream);
+};
+
+}  // namespace buffet
+
+#endif  // BUFFET_SOCKET_STREAM_H_