socket_stream.cc revision 35d119ab40cdfd317c46abe08472e2981adf90b5
1// Copyright 2015 The Chromium OS 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 <arpa/inet.h> 6#include <map> 7#include <netdb.h> 8#include <string> 9#include <sys/socket.h> 10#include <sys/types.h> 11#include <unistd.h> 12 13#include <base/bind.h> 14#include <base/files/file_util.h> 15#include <chromeos/streams/file_stream.h> 16#include <chromeos/streams/tls_stream.h> 17 18#include "buffet/socket_stream.h" 19#include "buffet/weave_error_conversion.h" 20 21namespace buffet { 22 23namespace { 24 25int ConnectSocket(const std::string& host, uint16_t port) { 26 std::string service = std::to_string(port); 27 addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM}; 28 addrinfo* result = nullptr; 29 if (getaddrinfo(host.c_str(), service.c_str(), &hints, &result)) { 30 PLOG(WARNING) << "Failed to resolve host name: " << host; 31 return -1; 32 } 33 34 int socket_fd = -1; 35 for (const addrinfo* info = result; info != nullptr; info = info->ai_next) { 36 socket_fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol); 37 if (socket_fd < 0) 38 continue; 39 40 char str[INET6_ADDRSTRLEN] = {}; 41 inet_ntop(info->ai_family, info->ai_addr, str, info->ai_addrlen); 42 LOG(INFO) << "Connecting to address: " << str; 43 if (connect(socket_fd, info->ai_addr, info->ai_addrlen) == 0) 44 break; // Success. 45 46 PLOG(WARNING) << "Failed to connect to address: " << str; 47 close(socket_fd); 48 socket_fd = -1; 49 } 50 51 freeaddrinfo(result); 52 return socket_fd; 53} 54 55void OnSuccess(const base::Callback<void(std::unique_ptr<weave::Stream>)>& 56 success_callback, 57 chromeos::StreamPtr tls_stream) { 58 success_callback.Run( 59 std::unique_ptr<weave::Stream>{new SocketStream{std::move(tls_stream)}}); 60} 61 62void OnError(const base::Callback<void(const weave::Error*)>& error_callback, 63 const chromeos::Error* chromeos_error) { 64 weave::ErrorPtr error; 65 ConvertError(*chromeos_error, &error); 66 error_callback.Run(error.get()); 67} 68 69} // namespace 70 71bool SocketStream::ReadAsync( 72 void* buffer, 73 size_t size_to_read, 74 const base::Callback<void(size_t)>& success_callback, 75 const base::Callback<void(const weave::Error*)>& error_callback, 76 weave::ErrorPtr* error) { 77 chromeos::ErrorPtr chromeos_error; 78 if (!ptr_->ReadAsync(buffer, size_to_read, success_callback, 79 base::Bind(&OnError, error_callback), &chromeos_error)) { 80 ConvertError(*chromeos_error, error); 81 return false; 82 } 83 return true; 84} 85 86bool SocketStream::WriteAllAsync( 87 const void* buffer, 88 size_t size_to_write, 89 const base::Closure& success_callback, 90 const base::Callback<void(const weave::Error*)>& error_callback, 91 weave::ErrorPtr* error) { 92 chromeos::ErrorPtr chromeos_error; 93 if (!ptr_->WriteAllAsync(buffer, size_to_write, success_callback, 94 base::Bind(&OnError, error_callback), 95 &chromeos_error)) { 96 ConvertError(*chromeos_error, error); 97 return false; 98 } 99 return true; 100} 101 102void SocketStream::CancelPendingAsyncOperations() { 103 ptr_->CancelPendingAsyncOperations(); 104} 105 106std::unique_ptr<weave::Stream> SocketStream::ConnectBlocking( 107 const std::string& host, 108 uint16_t port) { 109 int socket_fd = ConnectSocket(host, port); 110 if (socket_fd <= 0) 111 return nullptr; 112 113 auto ptr_ = 114 chromeos::FileStream::FromFileDescriptor(socket_fd, true, nullptr); 115 if (ptr_) 116 return std::unique_ptr<Stream>{new SocketStream{std::move(ptr_)}}; 117 118 close(socket_fd); 119 return nullptr; 120} 121 122void SocketStream::TlsConnect( 123 std::unique_ptr<Stream> socket, 124 const std::string& host, 125 const base::Callback<void(std::unique_ptr<Stream>)>& success_callback, 126 const base::Callback<void(const weave::Error*)>& error_callback) { 127 SocketStream* stream = static_cast<SocketStream*>(socket.get()); 128 chromeos::TlsStream::Connect(std::move(stream->ptr_), host, 129 base::Bind(&OnSuccess, success_callback), 130 base::Bind(&OnError, error_callback)); 131} 132 133} // namespace buffet 134