/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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.
*/
#include <folly/io/async/AsyncSocket.h>
#include <sys/types.h>
#include <cerrno>
#include <climits>
#include <sstream>
#include <thread>
#include <boost/preprocessor/control/if.hpp>
#include <folly/ExceptionWrapper.h>
#include <folly/Format.h>
#include <folly/Portability.h>
#include <folly/SocketAddress.h>
#include <folly/String.h>
#include <folly/io/Cursor.h>
#include <folly/io/IOBuf.h>
#include <folly/io/IOBufQueue.h>
#include <folly/io/SocketOptionMap.h>
#include <folly/portability/Fcntl.h>
#include <folly/portability/Sockets.h>
#include <folly/portability/SysUio.h>
#include <folly/portability/Unistd.h>
#if defined(__linux__)
#include <linux/if_packet.h>
#include <linux/sockios.h>
#include <sys/ioctl.h>
#endif
#if FOLLY_HAVE_VLA
#define FOLLY_HAVE_VLA_01 1
#else
#define FOLLY_HAVE_VLA_01 0
#endif
using std::string;
using std::unique_ptr;
namespace fsp = folly::portability::sockets;
namespace folly {
static constexpr bool msgErrQueueSupported =
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
true;
#else
false;
#endif // FOLLY_HAVE_MSG_ERRQUEUE
static AsyncSocketException const& getSocketClosedLocallyEx() {
static auto& ex = *new AsyncSocketException(
AsyncSocketException::END_OF_FILE, "socket closed locally");
return ex;
}
static AsyncSocketException const& getSocketShutdownForWritesEx() {
static auto& ex = *new AsyncSocketException(
AsyncSocketException::END_OF_FILE, "socket shutdown for writes");
return ex;
}
namespace {
#if FOLLY_HAVE_SO_TIMESTAMPING
const sock_extended_err* FOLLY_NULLABLE
cmsgToSockExtendedErr(const cmsghdr& cmsg) {
if ((cmsg.cmsg_level == SOL_IP && cmsg.cmsg_type == IP_RECVERR) ||
(cmsg.cmsg_level == SOL_IPV6 && cmsg.cmsg_type == IPV6_RECVERR) ||
(cmsg.cmsg_level == SOL_PACKET &&
cmsg.cmsg_type == PACKET_TX_TIMESTAMP)) {
return reinterpret_cast<const sock_extended_err*>(CMSG_DATA(&cmsg));
}
(void)cmsg;
return nullptr;
}
const sock_extended_err* FOLLY_NULLABLE
cmsgToSockExtendedErrTimestamping(const cmsghdr& cmsg) {
const auto serr = cmsgToSockExtendedErr(cmsg);
if (serr && serr->ee_errno == ENOMSG &&
serr->ee_origin == SO_EE_ORIGIN_TIMESTAMPING) {
return serr;
}
(void)cmsg;
return nullptr;
}
const scm_timestamping* FOLLY_NULLABLE
cmsgToScmTimestamping(const cmsghdr& cmsg) {
if (cmsg.cmsg_level == SOL_SOCKET && cmsg.cmsg_type == SCM_TIMESTAMPING) {
return reinterpret_cast<const struct scm_timestamping*>(CMSG_DATA(&cmsg));
}
(void)cmsg;
return nullptr;
}
#endif // FOLLY_HAVE_SO_TIMESTAMPING
} // namespace
// TODO: It might help performance to provide a version of BytesWriteRequest
// that users could derive from, so we can avoid the extra allocation for each
// call to write()/writev().
//
// We would need the version for external users where they provide the iovec
// storage space, and only our internal version would allocate it at the end of
// the WriteRequest.
/* The default WriteRequest implementation, used for write(), writev() and
* writeChain()
*
* A new BytesWriteRequest operation is allocated on the heap for all write
* operations that cannot be completed immediately.
*/
class AsyncSocket::BytesWriteRequest : public AsyncSocket::WriteRequest {
public:
static BytesWriteRequest* newRequest(
AsyncSocket* socket,
WriteCallback* callback,
const iovec* ops,
uint32_t opCount,
uint32_t partialWritten,
uint32_t bytesWritten,
unique_ptr<IOBuf>&& ioBuf,
WriteFlags flags) {
assert(opCount > 0);
// Since we put a variable size iovec array at the end
// of each BytesWriteRequest, we have to manually allocate the memory.
void* buf =
malloc(sizeof(BytesWriteRequest) + (opCount * sizeof(struct iovec)));
if (buf == nullptr) {
throw std::bad_alloc();
}
return new (buf) BytesWriteRequest(
socket,
callback,
ops,
opCount,
partialWritten,
bytesWritten,
std::move(ioBuf),
flags);
}
void destroy() override {
if (ioBuf_ && releaseIOBufCallback_) {
releaseIOBufCallback_->releaseIOBuf(std::move(ioBuf_));
}
this->~BytesWriteRequest();
free(this);
}
WriteResult performWrite() override {
WriteFlags writeFlags = flags_;
if (getNext() != nullptr) {
writeFlags |= WriteFlags::CORK;
}
socket_->adjustZeroCopyFlags(writeFlags);
auto writeResult = socket_->performWrite(
getOps(), getOpCount(), writeFlags, &opsWritten_, &partialBytes_);
bytesWritten_ = writeResult.writeReturn > 0 ? writeResult.writeReturn : 0;
if (bytesWritten_) {
if (socket_->isZeroCopyRequest(writeFlags)) {
if (isComplete()) {
socket_->addZeroCopyBuf(std::move(ioBuf_), releaseIOBufCallback_);
} else {
socket_->addZeroCopyBuf(ioBuf_.get());
}
} else {
// this happens if at least one of the prev requests were sent
// with zero copy but not the last one
if (isComplete() && zeroCopyRequest_ &&
socket_->containsZeroCopyBuf(ioBuf_.get())) {
socket_->setZeroCopyBuf(std::move(ioBuf_), releaseIOBufCallback_);
}
}
}
return writeResult;
}
bool isComplete() override { return opsWritten_ == getOpCount(); }
void consume() override {
// Advance opIndex_ forward by opsWritten_
opIndex_ += opsWritten_;
assert(opIndex_ < opCount_);
bool zeroCopyReq = socket_->isZeroCopyRequest(flags_);
if (zeroCopyReq) {
zeroCopyRequest_ = true;
}
if (!zeroCopyRequest_) {
// If we've finished writing any IOBufs, release them
// but only if we did not send any of them via zerocopy
if (ioBuf_) {
for (uint32_t i = opsWritten_; i != 0; --i) {
assert(ioBuf_);
auto next = ioBuf_->pop();
if (releaseIOBufCallback_) {
releaseIOBufCallback_->releaseIOBuf(std::move(ioBuf_));
}
ioBuf_ = std::move(next);
}
}
}
// Move partialBytes_ forward into the current iovec buffer
struct iovec* currentOp = writeOps_ + opIndex_;
assert((partialBytes_ < currentOp->iov_len) || (currentOp->iov_len == 0));
currentOp->iov_base =
reinterpret_cast<uint8_t*>(currentOp->iov_base) + partialBytes_;
currentOp->iov_len -= partialBytes_;
// Increment the totalBytesWritten_ count by bytesWritten_;
assert(bytesWritten_ >= 0);
totalBytesWritten_ += uint32_t(bytesWritten_);
}
private:
BytesWriteRequest(
AsyncSocket* socket,
WriteCallback* callback,
const struct iovec* ops,
uint32_t opCount,
uint32_t partialBytes,
uint32_t bytesWritten,
unique_ptr<IOBuf>&& ioBuf,
WriteFlags flags)
: AsyncSocket::WriteRequest(socket, callback),
opCount_(opCount),
opIndex_(0),
flags_(flags),
ioBuf_(std::move(ioBuf)),
opsWritten_(0),
partialBytes_(partialBytes),
bytesWritten_(bytesWritten) {
memcpy(writeOps_, ops, sizeof(*ops) * opCount_);
zeroCopyRequest_ = socket_->isZeroCopyRequest(flags_);
}
// private destructor, to ensure callers use destroy()
~BytesWriteRequest() override = default;
const struct iovec* getOps() const {
assert(opCount_ > opIndex_);
return writeOps_ + opIndex_;
}
uint32_t getOpCoun
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
Workreap React Native v2.6求职招聘软件app Java JavaScript项目源码ios android Workreap React Native移动的APP是一个优秀的跨平台原生应用程序,旨在与Workreap - Freelance Marketplace WordPress主题一起使用。它有一些令人兴奋的特性和优秀的代码质量。它是在经过深入研究后设计和开发的,以满足有兴趣建立自由职业者市场或其他类似项目的人的要求。该设计是现代的,但同时,它侧重于可用性,视觉层次和美学,以确保最终用户轻松导航。 应用程序功能 强大的搜索工作,自由职业者,微服务和雇主 工作、自由职业者、微服务和雇主的详细页面 雇主和自由职业者配置文件设置 精选自由职业者 特色服务 发送建议 购买服务 WooCommerce支付服务 分类列表 最新发布的职位 张贴一份工作 发布服务
资源推荐
资源详情
资源评论
收起资源包目录
Workreap React Native v2.6求职软件app Java JavaScript项目源码ios android (2001个子文件)
AsyncSocket.cpp 115KB
AsyncSSLSocket.cpp 70KB
Dwarf.cpp 44KB
IOBuf.cpp 41KB
RSocketStateMachine.cpp 39KB
AsyncServerSocket.cpp 37KB
AsyncUDPSocket.cpp 34KB
json.cpp 30KB
Subprocess.cpp 30KB
EventBase.cpp 26KB
LoggerDB.cpp 26KB
Conv.cpp 25KB
SSLContext.cpp 25KB
FrameSerializer_v1_0.cpp 23KB
SocketAddress.cpp 22KB
String.cpp 22KB
LogConfigParser.cpp 19KB
NetOps.cpp 19KB
Request.cpp 19KB
Benchmark.cpp 18KB
Core.cpp 17KB
PThread.cpp 17KB
ThreadPoolExecutor.cpp 16KB
FlipperConnectionManagerImpl.cpp 16KB
Symbolizer.cpp 15KB
IPAddressV6.cpp 15KB
SignalHandler.cpp 14KB
Singleton.cpp 14KB
IPAddress.cpp 14KB
ThreadLocalDetail.cpp 14KB
dynamic.cpp 14KB
dynamic.cpp 14KB
CacheLocality.cpp 13KB
EDFThreadPoolExecutor.cpp 13KB
SafeAssert.cpp 13KB
SafeAssert.cpp 13KB
Exception.cpp 13KB
Exception.cpp 13KB
Elf.cpp 13KB
OpenSSL.cpp 12KB
HHWheelTimer.cpp 12KB
MemoryMapping.cpp 12KB
Format.cpp 12KB
FiberManager.cpp 11KB
CustomLogFormatter.cpp 11KB
FlipperClient.cpp 11KB
OpenSSLUtils.cpp 10KB
CPUThreadPoolExecutor.cpp 10KB
IOBufQueue.cpp 10KB
json_patch.cpp 10KB
StackTrace.cpp 10KB
GuardPageAllocator.cpp 10KB
CertificateUtils.cpp 10KB
Time.cpp 10KB
SpookyHashV2.cpp 10KB
SpookyHashV1.cpp 9KB
RSocketServer.cpp 9KB
BaselinesAsyncSocket.cpp 9KB
IPAddressV4.cpp 9KB
OpenSSLCertUtils.cpp 9KB
FileUtil.cpp 8KB
AsyncLogWriter.cpp 8KB
ThreadName.cpp 8KB
AsyncPipe.cpp 8KB
IOThreadPoolExecutor.cpp 8KB
RSocketClient.cpp 8KB
LogCategory.cpp 8KB
CancellationToken.cpp 8KB
Futex.cpp 8KB
LogStreamProcessor.cpp 8KB
SymbolizePrinter.cpp 7KB
StreamsWriter.cpp 7KB
Fiber.cpp 7KB
RecordIO.cpp 7KB
MemoryIdler.cpp 7KB
ObserverManager.cpp 7KB
StrandExecutor.cpp 7KB
GlobalExecutor.cpp 7KB
SetupResumeAcceptor.cpp 7KB
Sockets.cpp 6KB
Unistd.cpp 6KB
FlipperRSocket.cpp 6KB
Frame.cpp 6KB
ConnectionContextStore.cpp 6KB
RSocketRequester.cpp 6KB
RSocketResponder.cpp 6KB
FramedReader.cpp 6KB
RangeSse42.cpp 6KB
Semaphore.cpp 6KB
TcpDuplexConnection.cpp 6KB
Framer.cpp 6KB
SemaphoreBase.cpp 6KB
EventHandler.cpp 6KB
SysMman.cpp 6KB
SanitizeThread.cpp 6KB
StandardLogHandlerFactory.cpp 6KB
Unicode.cpp 6KB
MacAddress.cpp 6KB
GlobalThreadPoolList.cpp 5KB
RSocket.cpp 5KB
共 2001 条
- 1
- 2
- 3
- 4
- 5
- 6
- 21
资源评论
小云同志你好
- 粉丝: 1047
- 资源: 931
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功