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();
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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);
    }
  }
}
Example #6
0
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());
}
Example #7
0
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;
}
Example #8
0
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;
}