2 * Copyright 2016 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <folly/Optional.h>
19 #include <folly/io/async/SSLContext.h>
20 #include <folly/io/async/AsyncSocket.h>
21 #include <folly/io/async/AsyncSSLSocket.h>
23 class BlockingSocket : public folly::AsyncSocket::ConnectCallback,
24 public folly::AsyncTransportWrapper::ReadCallback,
25 public folly::AsyncTransportWrapper::WriteCallback
28 explicit BlockingSocket(int fd)
29 : sock_(new folly::AsyncSocket(&eventBase_, fd)) {
32 BlockingSocket(folly::SocketAddress address,
33 std::shared_ptr<folly::SSLContext> sslContext)
34 : sock_(sslContext ? new folly::AsyncSSLSocket(sslContext, &eventBase_) :
35 new folly::AsyncSocket(&eventBase_)),
38 explicit BlockingSocket(folly::AsyncSocket::UniquePtr socket)
39 : sock_(std::move(socket)) {
40 sock_->attachEventBase(&eventBase_);
44 sock_->connect(this, address_);
46 if (err_.hasValue()) {
53 void closeWithReset() { sock_->closeWithReset(); }
55 int32_t write(uint8_t const* buf, size_t len) {
56 sock_->write(this, buf, len);
58 if (err_.hasValue()) {
66 int32_t readAll(uint8_t *buf, size_t len) {
67 return readHelper(buf, len, true);
70 int32_t read(uint8_t *buf, size_t len) {
71 return readHelper(buf, len, false);
74 int getSocketFD() const {
75 return sock_->getFd();
79 folly::EventBase eventBase_;
80 folly::AsyncSocket::UniquePtr sock_;
81 folly::Optional<folly::AsyncSocketException> err_;
82 uint8_t *readBuf_{nullptr};
84 folly::SocketAddress address_;
86 void connectSuccess() noexcept override {}
87 void connectErr(const folly::AsyncSocketException& ex) noexcept override {
90 void getReadBuffer(void** bufReturn, size_t* lenReturn) override {
91 *bufReturn = readBuf_;
92 *lenReturn = readLen_;
94 void readDataAvailable(size_t len) noexcept override {
98 sock_->setReadCB(nullptr);
101 void readEOF() noexcept override {
103 void readErr(const folly::AsyncSocketException& ex) noexcept override {
106 void writeSuccess() noexcept override {}
107 void writeErr(size_t /* bytesWritten */,
108 const folly::AsyncSocketException& ex) noexcept override {
112 int32_t readHelper(uint8_t *buf, size_t len, bool all) {
115 sock_->setReadCB(this);
116 while (!err_ && sock_->good() && readLen_ > 0) {
122 sock_->setReadCB(nullptr);
123 if (err_.hasValue()) {
126 if (all && readLen_ > 0) {
127 throw folly::AsyncSocketException(folly::AsyncSocketException::UNKNOWN,
130 return len - readLen_;