bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments) { ASSERT(m_socket); // We put the message ID last. arguments->encodeUInt32(messageID.toInt()); size_t bufferSize = arguments->bufferSize(); // Write message size first // FIXME: Should just do a single write. qint64 bytesWrittenForSize = m_socket->write(reinterpret_cast<char*>(&bufferSize), sizeof(bufferSize)); if (bytesWrittenForSize != sizeof(bufferSize)) { connectionDidClose(); return false; } qint64 bytesWrittenForBuffer = m_socket->write(reinterpret_cast<char*>(arguments->buffer()), arguments->bufferSize()); if (bytesWrittenForBuffer != arguments->bufferSize()) { connectionDidClose(); return false; } m_socket->flush(); return true; }
std::auto_ptr<ArgumentDecoder> Connection::waitForMessage(MessageID messageID, uint64_t destinationID, double timeout) { // First, check if this message is already in the incoming messages queue. { MutexLocker locker(m_incomingMessagesLock); for (size_t i = 0; i < m_incomingMessages.size(); ++i) { const IncomingMessage& message = m_incomingMessages[i]; if (equalIgnoringFlags(message.messageID(), messageID) && message.arguments()->destinationID() == destinationID) { std::auto_ptr<ArgumentDecoder> arguments(message.arguments()); // Erase the incoming message. m_incomingMessages.remove(i); return arguments; } } } double absoluteTime = currentTime() + timeout; std::pair<unsigned, uint64_t> messageAndDestination(std::make_pair(messageID.toInt(), destinationID)); { MutexLocker locker(m_waitForMessageMutex); // We don't support having multiple clients wait for the same message. ASSERT(!m_waitForMessageMap.contains(messageAndDestination)); // Insert our pending wait. m_waitForMessageMap.set(messageAndDestination, 0); } bool timedOut = false; // Now wait for it to be set. while (!timedOut) { MutexLocker locker(m_waitForMessageMutex); HashMap<std::pair<unsigned, uint64_t>, ArgumentDecoder*>::iterator it = m_waitForMessageMap.find(messageAndDestination); if (it->second) { std::auto_ptr<ArgumentDecoder> arguments(it->second); m_waitForMessageMap.remove(it); return arguments; } // We didn't find it, keep waiting. timedOut = !m_waitForMessageCondition.timedWait(m_waitForMessageMutex, absoluteTime); } // We timed out, now remove the pending wait. { MutexLocker locker(m_waitForMessageMutex); m_waitForMessageMap.remove(messageAndDestination); } return std::auto_ptr<ArgumentDecoder>(); }
bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments) { ASSERT(m_socket); // We put the message ID last. arguments->encodeUInt32(messageID.toInt()); size_t bufferSize = arguments->bufferSize(); // Write message size first // FIXME: Should just do a single write. m_socket->write(reinterpret_cast<char*>(&bufferSize), sizeof(bufferSize)); qint64 bytesWritten = m_socket->write(reinterpret_cast<char*>(arguments->buffer()), arguments->bufferSize()); ASSERT_UNUSED(bytesWritten, bytesWritten == arguments->bufferSize()); return true; }
bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments) { if (m_socket < 0) return false; // We put the message ID last. arguments->encodeUInt32(messageID.toInt()); size_t bufferSize = arguments->bufferSize(); // Send the message size first. if (!writeBytesToSocket(m_socket, reinterpret_cast<uint8_t*>(&bufferSize), sizeof(size_t))) return false; if (!writeBytesToSocket(m_socket, arguments->buffer(), arguments->bufferSize())) return false; return true; }
bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<MessageEncoder> encoder) { ASSERT(!m_pendingWriteEncoder); // Just bail if the handle has been closed. if (m_connectionPipe == INVALID_HANDLE_VALUE) return false; // We put the message ID last. encoder->encode(static_cast<uint32_t>(messageID.toInt())); // Write the outgoing message. if (::WriteFile(m_connectionPipe, encoder->buffer(), encoder->bufferSize(), 0, &m_writeState)) { // We successfully sent this message. return true; } DWORD error = ::GetLastError(); if (error == ERROR_NO_DATA) { // The pipe is being closed. connectionDidClose(); return false; } if (error != ERROR_IO_PENDING) { ASSERT_NOT_REACHED(); return false; } // The message will be sent soon. Hold onto the encoder so that it won't be destroyed // before the write completes. m_pendingWriteEncoder = encoder; // We can only send one asynchronous message at a time (see comment in platformCanSendOutgoingMessages). return false; }
void Connection::processIncomingMessage(MessageID messageID, std::auto_ptr<ArgumentDecoder> arguments) { // First, check if we're waiting for this message. { MutexLocker locker(m_waitForMessageMutex); HashMap<std::pair<unsigned, uint64_t>, ArgumentDecoder*>::iterator it = m_waitForMessageMap.find(std::make_pair(messageID.toInt(), arguments->destinationID())); if (it != m_waitForMessageMap.end()) { it->second = arguments.release(); m_waitForMessageCondition.signal(); return; } } if (messageID == MessageID(CoreIPCMessage::SyncMessageReply)) { // FIXME: We got a reply for another sync message someone sent, handle this. ASSERT_NOT_REACHED(); } MutexLocker locker(m_incomingMessagesLock); m_incomingMessages.append(IncomingMessage(messageID, arguments)); m_clientRunLoop->scheduleWork(WorkItem::create(this, &Connection::dispatchMessages)); }
bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments) { Vector<Attachment> attachments = arguments->releaseAttachments(); size_t numberOfPortDescriptors = 0; size_t numberOfOOLMemoryDescriptors = 0; for (size_t i = 0; i < attachments.size(); ++i) { Attachment::Type type = attachments[i].type(); if (type == Attachment::MachPortType) numberOfPortDescriptors++; else if (type == Attachment::MachOOLMemoryType) numberOfOOLMemoryDescriptors++; } size_t messageSize = machMessageSize(arguments->bufferSize(), numberOfPortDescriptors, numberOfOOLMemoryDescriptors); char buffer[inlineMessageMaxSize]; bool messageBodyIsOOL = false; if (messageSize > sizeof(buffer)) { messageBodyIsOOL = true; attachments.append(Attachment(arguments->buffer(), arguments->bufferSize(), MACH_MSG_VIRTUAL_COPY, false)); numberOfOOLMemoryDescriptors++; messageSize = machMessageSize(0, numberOfPortDescriptors, numberOfOOLMemoryDescriptors); } bool isComplex = (numberOfPortDescriptors + numberOfOOLMemoryDescriptors > 0); mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(&buffer); header->msgh_bits = isComplex ? MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND | MACH_MSGH_BITS_COMPLEX, 0) : MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); header->msgh_size = messageSize; header->msgh_remote_port = m_sendPort; header->msgh_local_port = MACH_PORT_NULL; header->msgh_id = messageID.toInt(); if (messageBodyIsOOL) header->msgh_id |= MessageBodyIsOOL; uint8_t* messageData; if (isComplex) { mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1); body->msgh_descriptor_count = numberOfPortDescriptors + numberOfOOLMemoryDescriptors; uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1); for (size_t i = 0; i < attachments.size(); ++i) { Attachment attachment = attachments[i]; mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData); switch (attachment.type()) { case Attachment::MachPortType: descriptor->port.name = attachment.port(); descriptor->port.disposition = attachment.disposition(); descriptor->port.type = MACH_MSG_PORT_DESCRIPTOR; descriptorData += sizeof(mach_msg_port_descriptor_t); break; case Attachment::MachOOLMemoryType: descriptor->out_of_line.address = attachment.address(); descriptor->out_of_line.size = attachment.size(); descriptor->out_of_line.copy = attachment.copyOptions(); descriptor->out_of_line.deallocate = attachment.deallocate(); descriptor->out_of_line.type = MACH_MSG_OOL_DESCRIPTOR; descriptorData += sizeof(mach_msg_ool_descriptor_t); break; default: ASSERT_NOT_REACHED(); } } messageData = descriptorData; } else messageData = (uint8_t*)(header + 1); // Copy the data if it is not being sent out-of-line. if (!messageBodyIsOOL) memcpy(messageData, arguments->buffer(), arguments->bufferSize()); ASSERT(m_sendPort); // Send the message. kern_return_t kr = mach_msg(header, MACH_SEND_MSG, messageSize, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (kr != KERN_SUCCESS) { // FIXME: What should we do here? } return true; }
void Connection::processIncomingMessage(MessageID messageID, PassOwnPtr<ArgumentDecoder> arguments) { // Check if this is a sync reply. if (messageID == MessageID(CoreIPCMessage::SyncMessageReply)) { MutexLocker locker(m_pendingSyncRepliesMutex); ASSERT(!m_pendingSyncReplies.isEmpty()); PendingSyncReply& pendingSyncReply = m_pendingSyncReplies.last(); ASSERT(pendingSyncReply.syncRequestID == arguments->destinationID()); pendingSyncReply.replyDecoder = arguments.leakPtr(); pendingSyncReply.didReceiveReply = true; m_waitForSyncReplySemaphore.signal(); return; } // Check if we're waiting for this message. { MutexLocker locker(m_waitForMessageMutex); HashMap<std::pair<unsigned, uint64_t>, ArgumentDecoder*>::iterator it = m_waitForMessageMap.find(std::make_pair(messageID.toInt(), arguments->destinationID())); if (it != m_waitForMessageMap.end()) { it->second = arguments.leakPtr(); m_waitForMessageCondition.signal(); return; } } MutexLocker locker(m_incomingMessagesLock); m_incomingMessages.append(IncomingMessage(messageID, arguments)); m_clientRunLoop->scheduleWork(WorkItem::create(this, &Connection::dispatchMessages)); }
void Connection::processIncomingMessage(MessageID messageID, PassOwnPtr<ArgumentDecoder> arguments) { // Check if this is a sync reply. if (messageID == MessageID(CoreIPCMessage::SyncMessageReply)) { MutexLocker locker(m_syncReplyStateMutex); ASSERT(!m_pendingSyncReplies.isEmpty()); PendingSyncReply& pendingSyncReply = m_pendingSyncReplies.last(); ASSERT(pendingSyncReply.syncRequestID == arguments->destinationID()); pendingSyncReply.replyDecoder = arguments.leakPtr(); pendingSyncReply.didReceiveReply = true; m_waitForSyncReplySemaphore.signal(); return; } // Check if this is a sync message. If it is, and we're waiting for a sync reply this message // needs to be dispatched. If we don't we'll end up with a deadlock where both sync message senders are // stuck waiting for a reply. if (messageID.isSync()) { MutexLocker locker(m_syncReplyStateMutex); if (!m_pendingSyncReplies.isEmpty()) { m_syncMessagesReceivedWhileWaitingForSyncReply.append(IncomingMessage(messageID, arguments)); // The message has been added, now wake up the client thread. m_waitForSyncReplySemaphore.signal(); return; } } // Check if we're waiting for this message. { MutexLocker locker(m_waitForMessageMutex); HashMap<std::pair<unsigned, uint64_t>, ArgumentDecoder*>::iterator it = m_waitForMessageMap.find(std::make_pair(messageID.toInt(), arguments->destinationID())); if (it != m_waitForMessageMap.end()) { it->second = arguments.leakPtr(); m_waitForMessageCondition.signal(); return; } } MutexLocker locker(m_incomingMessagesLock); m_incomingMessages.append(IncomingMessage(messageID, arguments)); m_clientRunLoop->scheduleWork(WorkItem::create(this, &Connection::dispatchMessages)); }