/* Copyright (c) 2014-2017 DataStax Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef DATASTAX_INTERNAL_CONNECTOR_HPP #define DATASTAX_INTERNAL_CONNECTOR_HPP #include #include "address.hpp" #include "callback.hpp" #include "ref_counted.hpp" namespace datastax { namespace internal { namespace core { /** * A wrapper for uv_connect that handles connecting a TCP connection. */ class TcpConnector : public RefCounted { public: typedef SharedRefPtr Ptr; typedef internal::Callback Callback; enum Status { NEW, CONNECTING, FAILED_BAD_PARAM, FAILED_TO_CONNECT, CANCELED, SUCCESS }; /** * Constructor * * @param address The address to connect to. */ TcpConnector(const Address& address) : address_(address) , status_(NEW) , uv_status_(-1) { req_.data = this; } /** * Connect the given TCP handle. * * @param handle The handle to connect. * @param callback A callback that's called when the handle is connected or * an error occurs. */ void connect(uv_tcp_t* handle, const Callback& callback) { int rc = 0; inc_ref(); // For the event loop callback_ = callback; status_ = CONNECTING; Address::SocketStorage storage; rc = uv_tcp_connect(&req_, handle, address_.to_sockaddr(&storage), on_connect); if (rc != 0) { status_ = FAILED_BAD_PARAM; uv_status_ = rc; callback_(this); dec_ref(); } } /** * Cancel the connection process. */ void cancel() { if (status_ == CONNECTING) { uv_cancel(reinterpret_cast(&req_)); status_ = CANCELED; } } public: uv_loop_t* loop() { return req_.handle->loop; } bool is_success() { return status_ == SUCCESS; } bool is_canceled() { return status_ == CANCELED; } Status status() { return status_; } int uv_status() { return uv_status_; } const Address& address() { return address_; } private: static void on_connect(uv_connect_t* req, int status) { TcpConnector* connector = static_cast(req->data); if (connector->status_ == CONNECTING) { if (status == 0) { connector->status_ = SUCCESS; } else { connector->status_ = FAILED_TO_CONNECT; } } connector->uv_status_ = status; connector->callback_(connector); connector->dec_ref(); } private: uv_connect_t req_; Address address_; Callback callback_; Status status_; int uv_status_; }; }}} // namespace datastax::internal::core #endif