Move SSLStream into separate file Change-Id: If5f2ec10d5f0455b748a2b86968ac28b2a8da1b6 Reviewed-on: https://weave-review.googlesource.com/1115 Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/libweave/examples/ubuntu/network_manager.cc b/libweave/examples/ubuntu/network_manager.cc index 6217f25..2414d7d 100644 --- a/libweave/examples/ubuntu/network_manager.cc +++ b/libweave/examples/ubuntu/network_manager.cc
@@ -5,20 +5,17 @@ #include "libweave/examples/ubuntu/network_manager.h" #include <arpa/inet.h> -#include <fcntl.h> #include <linux/wireless.h> -#include <netdb.h> -#include <openssl/ssl.h> #include <sys/ioctl.h> -#include <sys/socket.h> #include <sys/wait.h> -#include <cstdlib> #include <fstream> #include <base/bind.h> #include <weave/task_runner.h> +#include "libweave/examples/ubuntu/ssl_stream.h" + namespace weave { namespace examples { @@ -39,150 +36,6 @@ NOTREACHED(); } -class SSLStream : public Stream { - public: - explicit SSLStream(TaskRunner* task_runner) : task_runner_{task_runner} {} - - ~SSLStream() { CancelPendingAsyncOperations(); } - - void RunDelayedTask(const base::Closure& success_callback) { - success_callback.Run(); - } - - void ReadAsync(void* buffer, - size_t size_to_read, - const base::Callback<void(size_t)>& success_callback, - const base::Callback<void(const Error*)>& error_callback) { - int res = SSL_read(ssl_.get(), buffer, size_to_read); - if (res > 0) { - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), - base::Bind(success_callback, res)), - {}); - return; - } - - int err = SSL_get_error(ssl_.get(), res); - - if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&SSLStream::ReadAsync, weak_ptr_factory_.GetWeakPtr(), - buffer, size_to_read, success_callback, error_callback), - base::TimeDelta::FromSeconds(1)); - return; - } - - ErrorPtr weave_error; - Error::AddTo(&weave_error, FROM_HERE, "ssl", "socket_read_failed", - "SSL error"); - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind( - &SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), - base::Bind(error_callback, base::Owned(weave_error.release()))), - {}); - return; - } - - void WriteAllAsync(const void* buffer, - size_t size_to_write, - const base::Closure& success_callback, - const base::Callback<void(const Error*)>& error_callback) { - int res = SSL_write(ssl_.get(), buffer, size_to_write); - if (res > 0) { - buffer = static_cast<const char*>(buffer) + res; - size_to_write -= res; - if (size_to_write == 0) { - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&SSLStream::RunDelayedTask, - weak_ptr_factory_.GetWeakPtr(), success_callback), - {}); - return; - } - - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&SSLStream::WriteAllAsync, weak_ptr_factory_.GetWeakPtr(), - buffer, size_to_write, success_callback, error_callback), - base::TimeDelta::FromSeconds(1)); - - return; - } - - int err = SSL_get_error(ssl_.get(), res); - - if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&SSLStream::WriteAllAsync, weak_ptr_factory_.GetWeakPtr(), - buffer, size_to_write, success_callback, error_callback), - base::TimeDelta::FromSeconds(1)); - return; - } - - ErrorPtr weave_error; - Error::AddTo(&weave_error, FROM_HERE, "ssl", "socket_write_failed", - "SSL error"); - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind( - &SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), - base::Bind(error_callback, base::Owned(weave_error.release()))), - {}); - return; - } - - void CancelPendingAsyncOperations() { - weak_ptr_factory_.InvalidateWeakPtrs(); - } - - bool Init(const std::string& host, uint16_t port) { - ctx_.reset(SSL_CTX_new(TLSv1_2_client_method())); - CHECK(ctx_); - ssl_.reset(SSL_new(ctx_.get())); - - char end_point[255]; - snprintf(end_point, sizeof(end_point), "%s:%u", host.c_str(), port); - BIO* stream_bio = BIO_new_connect(end_point); - CHECK(stream_bio); - BIO_set_nbio(stream_bio, 1); - - while (BIO_do_connect(stream_bio) != 1) { - CHECK(BIO_should_retry(stream_bio)); - sleep(1); - } - - SSL_set_bio(ssl_.get(), stream_bio, stream_bio); - SSL_set_connect_state(ssl_.get()); - - for (;;) { - int res = SSL_do_handshake(ssl_.get()); - if (res) { - return true; - } - - res = SSL_get_error(ssl_.get(), res); - - if (res != SSL_ERROR_WANT_READ || res != SSL_ERROR_WANT_WRITE) { - return false; - } - - sleep(1); - } - return false; - } - - private: - TaskRunner* task_runner_{nullptr}; - std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> ctx_{nullptr, SSL_CTX_free}; - std::unique_ptr<SSL, decltype(&SSL_free)> ssl_{nullptr, SSL_free}; - - base::WeakPtrFactory<SSLStream> weak_ptr_factory_{this}; -}; - } // namespace NetworkImpl::NetworkImpl(TaskRunner* task_runner, bool force_bootstrapping)
diff --git a/libweave/examples/ubuntu/ssl_stream.cc b/libweave/examples/ubuntu/ssl_stream.cc new file mode 100644 index 0000000..e383f01 --- /dev/null +++ b/libweave/examples/ubuntu/ssl_stream.cc
@@ -0,0 +1,152 @@ +// 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 "libweave/examples/ubuntu/ssl_stream.h" + +#include <base/bind.h> +#include <weave/task_runner.h> + +namespace weave { +namespace examples { + +SSLStream::SSLStream(TaskRunner* task_runner) : task_runner_{task_runner} {} + +SSLStream::~SSLStream() { + CancelPendingAsyncOperations(); +} + +void SSLStream::RunDelayedTask(const base::Closure& success_callback) { + success_callback.Run(); +} + +void SSLStream::ReadAsync( + void* buffer, + size_t size_to_read, + const base::Callback<void(size_t)>& success_callback, + const base::Callback<void(const Error*)>& error_callback) { + int res = SSL_read(ssl_.get(), buffer, size_to_read); + if (res > 0) { + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), + base::Bind(success_callback, res)), + {}); + return; + } + + int err = SSL_get_error(ssl_.get(), res); + + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&SSLStream::ReadAsync, weak_ptr_factory_.GetWeakPtr(), + buffer, size_to_read, success_callback, error_callback), + base::TimeDelta::FromSeconds(1)); + return; + } + + ErrorPtr weave_error; + Error::AddTo(&weave_error, FROM_HERE, "ssl", "socket_read_failed", + "SSL error"); + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind( + &SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), + base::Bind(error_callback, base::Owned(weave_error.release()))), + {}); + return; +} + +void SSLStream::WriteAllAsync( + const void* buffer, + size_t size_to_write, + const base::Closure& success_callback, + const base::Callback<void(const Error*)>& error_callback) { + int res = SSL_write(ssl_.get(), buffer, size_to_write); + if (res > 0) { + buffer = static_cast<const char*>(buffer) + res; + size_to_write -= res; + if (size_to_write == 0) { + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), + success_callback), + {}); + return; + } + + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&SSLStream::WriteAllAsync, weak_ptr_factory_.GetWeakPtr(), + buffer, size_to_write, success_callback, error_callback), + base::TimeDelta::FromSeconds(1)); + + return; + } + + int err = SSL_get_error(ssl_.get(), res); + + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&SSLStream::WriteAllAsync, weak_ptr_factory_.GetWeakPtr(), + buffer, size_to_write, success_callback, error_callback), + base::TimeDelta::FromSeconds(1)); + return; + } + + ErrorPtr weave_error; + Error::AddTo(&weave_error, FROM_HERE, "ssl", "socket_write_failed", + "SSL error"); + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind( + &SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), + base::Bind(error_callback, base::Owned(weave_error.release()))), + {}); + return; +} + +void SSLStream::CancelPendingAsyncOperations() { + weak_ptr_factory_.InvalidateWeakPtrs(); +} + +bool SSLStream::Init(const std::string& host, uint16_t port) { + ctx_.reset(SSL_CTX_new(TLSv1_2_client_method())); + CHECK(ctx_); + ssl_.reset(SSL_new(ctx_.get())); + + char end_point[255]; + snprintf(end_point, sizeof(end_point), "%s:%u", host.c_str(), port); + BIO* stream_bio = BIO_new_connect(end_point); + CHECK(stream_bio); + BIO_set_nbio(stream_bio, 1); + + while (BIO_do_connect(stream_bio) != 1) { + CHECK(BIO_should_retry(stream_bio)); + sleep(1); + } + + SSL_set_bio(ssl_.get(), stream_bio, stream_bio); + SSL_set_connect_state(ssl_.get()); + + for (;;) { + int res = SSL_do_handshake(ssl_.get()); + if (res) { + return true; + } + + res = SSL_get_error(ssl_.get(), res); + + if (res != SSL_ERROR_WANT_READ || res != SSL_ERROR_WANT_WRITE) { + return false; + } + + sleep(1); + } + return false; +} + +} // namespace examples +} // namespace weave
diff --git a/libweave/examples/ubuntu/ssl_stream.h b/libweave/examples/ubuntu/ssl_stream.h new file mode 100644 index 0000000..5530cce --- /dev/null +++ b/libweave/examples/ubuntu/ssl_stream.h
@@ -0,0 +1,54 @@ +// 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 LIBWEAVE_EXAMPLES_UBUNTU_SSL_STREAM_H_ +#define LIBWEAVE_EXAMPLES_UBUNTU_SSL_STREAM_H_ + +#include <openssl/ssl.h> + +#include <base/memory/weak_ptr.h> +#include <weave/stream.h> + +namespace weave { + +class TaskRunner; + +namespace examples { + +class SSLStream : public Stream { + public: + explicit SSLStream(TaskRunner* task_runner); + + ~SSLStream() override; + + void ReadAsync( + void* buffer, + size_t size_to_read, + const base::Callback<void(size_t)>& success_callback, + const base::Callback<void(const Error*)>& error_callback) override; + + void WriteAllAsync( + const void* buffer, + size_t size_to_write, + const base::Closure& success_callback, + const base::Callback<void(const Error*)>& error_callback) override; + + void CancelPendingAsyncOperations() override; + + bool Init(const std::string& host, uint16_t port); + + private: + void RunDelayedTask(const base::Closure& success_callback); + + TaskRunner* task_runner_{nullptr}; + std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> ctx_{nullptr, SSL_CTX_free}; + std::unique_ptr<SSL, decltype(&SSL_free)> ssl_{nullptr, SSL_free}; + + base::WeakPtrFactory<SSLStream> weak_ptr_factory_{this}; +}; + +} // namespace examples +} // namespace weave + +#endif // LIBWEAVE_EXAMPLES_UBUNTU_SSL_STREAM_H_
diff --git a/libweave/examples/ubuntu/weave.gyp b/libweave/examples/ubuntu/weave.gyp index e8abc5e..a4df01d 100644 --- a/libweave/examples/ubuntu/weave.gyp +++ b/libweave/examples/ubuntu/weave.gyp
@@ -5,14 +5,15 @@ 'type': 'executable', 'cflags': ['-pthread'], 'sources': [ - 'main.cc', - 'file_config_store.cc', - 'event_task_runner.cc', - 'curl_http_client.cc', - 'network_manager.cc', 'avahi_client.cc', - 'event_http_server.cc', 'bluez_client.cc', + 'curl_http_client.cc', + 'event_http_server.cc', + 'event_task_runner.cc', + 'file_config_store.cc', + 'main.cc', + 'network_manager.cc', + 'ssl_stream.cc', ], 'dependencies': [ '../../libweave_standalone.gyp:libweave',