void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry> entry) { if (isSynchronous()) { m_synchronousLoadData->response = entry->response(); sendReplyToSynchronousRequest(*m_synchronousLoadData, entry->buffer()); } else { bool needsContinueDidReceiveResponseMessage = isMainResource(); sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveResponse(entry->response(), needsContinueDidReceiveResponseMessage)); #if ENABLE(SHAREABLE_RESOURCE) if (!entry->shareableResourceHandle().isNull()) send(Messages::WebResourceLoader::DidReceiveResource(entry->shareableResourceHandle(), currentTime())); else { #endif bool shouldContinue = sendBufferMaybeAborting(*entry->buffer(), entry->buffer()->size()); if (!shouldContinue) return; send(Messages::WebResourceLoader::DidFinishResourceLoad(currentTime())); #if ENABLE(SHAREABLE_RESOURCE) } #endif } cleanup(); }
void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry> entry) { if (isSynchronous()) { m_synchronousLoadData->response = entry->response(); sendReplyToSynchronousRequest(*m_synchronousLoadData, entry->buffer()); } else { if (entry->response().url() != originalRequest().url()) { // This is a cached redirect. Synthesize a minimal redirect so we get things like referer header right. // FIXME: We should cache the actual redirects. ResourceRequest syntheticRedirectRequest(entry->response().url()); ResourceResponse syntheticRedirectResponse(originalRequest().url(), { }, 0, { }); sendAbortingOnFailure(Messages::WebResourceLoader::WillSendRequest(syntheticRedirectRequest, syntheticRedirectResponse)); } bool needsContinueDidReceiveResponseMessage = originalRequest().requester() == ResourceRequest::Requester::Main; sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveResponse(entry->response(), needsContinueDidReceiveResponseMessage)); #if ENABLE(SHAREABLE_RESOURCE) if (!entry->shareableResourceHandle().isNull()) send(Messages::WebResourceLoader::DidReceiveResource(entry->shareableResourceHandle(), currentTime())); else { #endif bool shouldContinue = sendBufferMaybeAborting(*entry->buffer(), entry->buffer()->size()); if (!shouldContinue) return; send(Messages::WebResourceLoader::DidFinishResourceLoad(currentTime())); #if ENABLE(SHAREABLE_RESOURCE) } #endif } cleanup(); }
bool NetResMgr::AsyncTcpAccept(TcpHandle handle, const TcpSocketPtr& socket, std::unique_ptr<tcp::AcceptBuffer> buffer) { auto accept_socket = std::make_unique<tcp::Socket>(); if (!accept_socket) { LOG(kError, "AsyncTcpAccept failed: can not new tcp socket."); return false; } if (!accept_socket->Create()) { return false; } if (!buffer) { buffer = std::make_unique<tcp::AcceptBuffer>(); if (!buffer) { LOG(kError, "AsyncTcpAccept failed: can not new accept buffer."); return false; } } auto async_sock = accept_socket->socket(); buffer->Reset(); buffer->set_handle(handle); buffer->set_accept_socket(std::move(accept_socket)); if (!socket->AsyncAccept(async_sock, buffer->buffer(), buffer->buffer_size(), buffer->ovlp())) { return false; } buffer.release(); return true; }
bool NetResMgr::AsyncTcpRecv(TcpHandle handle, const TcpSocketPtr& socket, std::unique_ptr<tcp::RecvBuffer> buffer) { if (!buffer) { buffer = std::make_unique<tcp::RecvBuffer>(); if (!buffer) { LOG(kError, "AsyncTcpRecv failed: can not new recv buffer."); return false; } } buffer->Reset(); buffer->set_handle(handle); if (!socket->AsyncRecv(buffer->buffer(), buffer->buffer_size(), buffer->ovlp())) { return false; } buffer.release(); return true; }
void NetResMgr::OnTcpRecv(std::unique_ptr<tcp::RecvBuffer> buffer, int size) { auto recv_handle = buffer->handle(); auto recv_socket = GetTcpSocket(recv_handle); if (!recv_socket) { return; } if (size == 0) { RemoveTcpSocket(recv_handle); callback_->OnTcpDisconnected(recv_handle); } else { callback_->OnTcpReceived(recv_handle, buffer->buffer(), size); if (!AsyncTcpRecv(recv_handle, recv_socket, std::move(buffer))) { RemoveTcpSocket(recv_handle); callback_->OnTcpError(recv_handle, 2); } } }
void assert_shape(const std::unique_ptr<io_buff_t>& b, size_t headroom, size_t data_size, size_t tailroom) { if(b->empty()) { ASSERT_EQ(0, b->length()); } else { ASSERT_NE(0, b->length()); } ASSERT_EQ(headroom, b->headroom()); ASSERT_EQ(headroom, b->data() - b->buffer()); ASSERT_EQ(data_size, b->length()); ASSERT_EQ(data_size, b->tail() - b->data()); ASSERT_EQ(tailroom, b->tailroom()); ASSERT_EQ(tailroom, b->buffer_end() - b->tail()); ASSERT_EQ(headroom + data_size + tailroom, b->capacity()); }
bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder) { COMPILE_ASSERT(sizeof(MessageInfo) + attachmentMaxAmount * sizeof(size_t) <= messageMaxSize, AttachmentsFitToMessageInline); Vector<Attachment> attachments = encoder->releaseAttachments(); AttachmentResourceGuard<Vector<Attachment>, Vector<Attachment>::iterator> attachementDisposer(attachments); if (attachments.size() > (attachmentMaxAmount - 1)) { ASSERT_NOT_REACHED(); return false; } MessageInfo messageInfo(encoder->bufferSize(), attachments.size()); size_t messageSizeWithBodyInline = sizeof(messageInfo) + (attachments.size() * sizeof(AttachmentInfo)) + encoder->bufferSize(); if (messageSizeWithBodyInline > messageMaxSize && encoder->bufferSize()) { RefPtr<WebKit::SharedMemory> oolMessageBody = WebKit::SharedMemory::create(encoder->bufferSize()); if (!oolMessageBody) return false; WebKit::SharedMemory::Handle handle; if (!oolMessageBody->createHandle(handle, WebKit::SharedMemory::ReadOnly)) return false; messageInfo.setMessageBodyIsOutOfLine(); memcpy(oolMessageBody->data(), encoder->buffer(), encoder->bufferSize()); attachments.append(handle.releaseToAttachment()); } struct msghdr message; memset(&message, 0, sizeof(message)); struct iovec iov[3]; memset(&iov, 0, sizeof(iov)); message.msg_iov = iov; int iovLength = 1; iov[0].iov_base = reinterpret_cast<void*>(&messageInfo); iov[0].iov_len = sizeof(messageInfo); auto attachmentInfo = std::make_unique<AttachmentInfo[]>(attachments.size()); size_t attachmentFDBufferLength = 0; if (!attachments.isEmpty()) { for (size_t i = 0; i < attachments.size(); ++i) { if (attachments[i].fileDescriptor() != -1) attachmentFDBufferLength++; } } auto attachmentFDBuffer = std::make_unique<char[]>(CMSG_SPACE(sizeof(int) * attachmentFDBufferLength)); if (!attachments.isEmpty()) { int* fdPtr = 0; if (attachmentFDBufferLength) { message.msg_control = attachmentFDBuffer.get(); message.msg_controllen = CMSG_SPACE(sizeof(int) * attachmentFDBufferLength); memset(message.msg_control, 0, message.msg_controllen); struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int) * attachmentFDBufferLength); fdPtr = reinterpret_cast<int*>(CMSG_DATA(cmsg)); } int fdIndex = 0; for (size_t i = 0; i < attachments.size(); ++i) { attachmentInfo[i].setType(attachments[i].type()); switch (attachments[i].type()) { case Attachment::MappedMemoryType: attachmentInfo[i].setSize(attachments[i].size()); // Fall trhough, set file descriptor or null. case Attachment::SocketType: if (attachments[i].fileDescriptor() != -1) { ASSERT(fdPtr); fdPtr[fdIndex++] = attachments[i].fileDescriptor(); } else attachmentInfo[i].setNull(); break; case Attachment::Uninitialized: default: break; } } iov[iovLength].iov_base = attachmentInfo.get(); iov[iovLength].iov_len = sizeof(AttachmentInfo) * attachments.size(); ++iovLength; } if (!messageInfo.isMessageBodyIsOutOfLine() && encoder->bufferSize()) { iov[iovLength].iov_base = reinterpret_cast<void*>(encoder->buffer()); iov[iovLength].iov_len = encoder->bufferSize(); ++iovLength; } message.msg_iovlen = iovLength; int bytesSent = 0; while ((bytesSent = sendmsg(m_socketDescriptor, &message, 0)) == -1) { if (errno != EINTR) return false; } return true; }
bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder) { COMPILE_ASSERT(sizeof(MessageInfo) + attachmentMaxAmount * sizeof(size_t) <= messageMaxSize, AttachmentsFitToMessageInline); Vector<Attachment> attachments = encoder->releaseAttachments(); if (attachments.size() > (attachmentMaxAmount - 1)) { ASSERT_NOT_REACHED(); return false; } MessageInfo messageInfo(encoder->bufferSize(), attachments.size()); size_t messageSizeWithBodyInline = sizeof(messageInfo) + (attachments.size() * sizeof(AttachmentInfo)) + encoder->bufferSize(); if (messageSizeWithBodyInline > messageMaxSize && encoder->bufferSize()) { RefPtr<WebKit::SharedMemory> oolMessageBody = WebKit::SharedMemory::allocate(encoder->bufferSize()); if (!oolMessageBody) return false; WebKit::SharedMemory::Handle handle; if (!oolMessageBody->createHandle(handle, WebKit::SharedMemory::Protection::ReadOnly)) return false; messageInfo.setMessageBodyIsOutOfLine(); memcpy(oolMessageBody->data(), encoder->buffer(), encoder->bufferSize()); attachments.append(handle.releaseAttachment()); } struct msghdr message; memset(&message, 0, sizeof(message)); struct iovec iov[3]; memset(&iov, 0, sizeof(iov)); message.msg_iov = iov; int iovLength = 1; iov[0].iov_base = reinterpret_cast<void*>(&messageInfo); iov[0].iov_len = sizeof(messageInfo); std::unique_ptr<AttachmentInfo[]> attachmentInfo; MallocPtr<char> attachmentFDBuffer; if (!attachments.isEmpty()) { int* fdPtr = 0; size_t attachmentFDBufferLength = std::count_if(attachments.begin(), attachments.end(), [](const Attachment& attachment) { return attachment.fileDescriptor() != -1; }); if (attachmentFDBufferLength) { attachmentFDBuffer = MallocPtr<char>::malloc(sizeof(char) * CMSG_SPACE(sizeof(int) * attachmentFDBufferLength)); message.msg_control = attachmentFDBuffer.get(); message.msg_controllen = CMSG_SPACE(sizeof(int) * attachmentFDBufferLength); memset(message.msg_control, 0, message.msg_controllen); struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int) * attachmentFDBufferLength); fdPtr = reinterpret_cast<int*>(CMSG_DATA(cmsg)); } attachmentInfo = std::make_unique<AttachmentInfo[]>(attachments.size()); int fdIndex = 0; for (size_t i = 0; i < attachments.size(); ++i) { attachmentInfo[i].setType(attachments[i].type()); switch (attachments[i].type()) { case Attachment::MappedMemoryType: attachmentInfo[i].setSize(attachments[i].size()); // Fall trhough, set file descriptor or null. case Attachment::SocketType: if (attachments[i].fileDescriptor() != -1) { ASSERT(fdPtr); fdPtr[fdIndex++] = attachments[i].fileDescriptor(); } else attachmentInfo[i].setNull(); break; case Attachment::Uninitialized: default: break; } } iov[iovLength].iov_base = attachmentInfo.get(); iov[iovLength].iov_len = sizeof(AttachmentInfo) * attachments.size(); ++iovLength; } if (!messageInfo.isMessageBodyIsOutOfLine() && encoder->bufferSize()) { iov[iovLength].iov_base = reinterpret_cast<void*>(encoder->buffer()); iov[iovLength].iov_len = encoder->bufferSize(); ++iovLength; } message.msg_iovlen = iovLength; while (sendmsg(m_socketDescriptor, &message, 0) == -1) { if (errno == EINTR) continue; if (errno == EAGAIN || errno == EWOULDBLOCK) { struct pollfd pollfd; pollfd.fd = m_socketDescriptor; pollfd.events = POLLOUT; pollfd.revents = 0; poll(&pollfd, 1, -1); continue; } WTFLogAlways("Error sending IPC message: %s", strerror(errno)); return false; } return true; }