void Connection::receiveSourceEventHandler() { ReceiveBuffer buffer; mach_msg_header_t* header = readFromMachPort(m_receivePort, buffer); if (!header) return; MessageID messageID = MessageID::fromInt(header->msgh_id); OwnPtr<ArgumentDecoder> arguments = createArgumentDecoder(header); ASSERT(arguments); if (messageID == MessageID(CoreIPCMessage::InitializeConnection)) { ASSERT(m_isServer); ASSERT(!m_isConnected); ASSERT(!m_sendPort); MachPort port; if (!arguments->decode(port)) { // FIXME: Disconnect. return; } m_sendPort = port.port(); // Set the dead name source if needed. if (m_sendPort) initializeDeadNameSource(); m_isConnected = true; // Send any pending outgoing messages. sendOutgoingMessages(); return; } if (messageID == MessageID(CoreIPCMessage::SetExceptionPort)) { MachPort exceptionPort; if (!arguments->decode(exceptionPort)) return; setMachExceptionPort(exceptionPort.port()); return; } processIncomingMessage(messageID, arguments.release()); }
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)); }
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 MessageQueue::append(In& stream) { unsigned usedSize, numberOfMessages; stream >> usedSize >> numberOfMessages; // Trying a direct copy. This is hacked, but fast. char* dest = numberOfMessages == (unsigned) -1 ? 0 : queue.reserve(usedSize - MessageQueueBase::headerSize); if(dest) { stream.read(dest - MessageQueueBase::headerSize, usedSize); queue.numberOfMessages += numberOfMessages; queue.usedSize += usedSize; queue.writePosition = 0; } else // Not all messages fit in there, so try step by step (some will be missing). for(unsigned i = 0; numberOfMessages == (unsigned) -1 ? !stream.eof() : i < numberOfMessages ; ++i) { unsigned char id = 0; unsigned int size = 0; stream >> id; stream.read(&size, 3); char* dest = numberOfMessages != (unsigned) -1 || id < numOfDataMessageIDs ? queue.reserve(size) : 0; if(dest) { stream.read(dest, size); out.finishMessage(MessageID(id)); } else stream.skip(size); } }
std::auto_ptr<ArgumentDecoder> Connection::sendSyncMessage(MessageID messageID, uint64_t syncRequestID, std::auto_ptr<ArgumentEncoder> encoder, double timeout) { // First send the message. if (!sendMessage(messageID, encoder)) return std::auto_ptr<ArgumentDecoder>(); // Now wait for a reply and return it. return waitForMessage(MessageID(CoreIPCMessage::SyncMessageReply), syncRequestID, timeout); }
bool Connection::open() { if (m_isServer) { ASSERT(m_receivePort); ASSERT(!m_sendPort); } else { ASSERT(!m_receivePort); ASSERT(m_sendPort); // Create the receive port. mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &m_receivePort); m_isConnected = true; // Send the initialize message, which contains a send right for the server to use. OwnPtr<MessageEncoder> encoder = MessageEncoder::create("IPC", "InitializeConnection", 0); encoder->encode(MachPort(m_receivePort, MACH_MSG_TYPE_MAKE_SEND)); sendMessage(MessageID(), encoder.release()); // Set the dead name handler for our send port. initializeDeadNameSource(); } // Change the message queue length for the receive port. setMachPortQueueLength(m_receivePort, MACH_PORT_QLIMIT_LARGE); // Register the data available handler. m_connectionQueue.registerMachPortEventHandler(m_receivePort, WorkQueue::MachPortDataAvailable, bind(&Connection::receiveSourceEventHandler, this)); // If we have an exception port, register the data available handler and send over the port to the other end. if (m_exceptionPort) { m_connectionQueue.registerMachPortEventHandler(m_exceptionPort, WorkQueue::MachPortDataAvailable, bind(&Connection::exceptionSourceEventHandler, this)); OwnPtr<MessageEncoder> encoder = MessageEncoder::create("IPC", "SetExceptionPort", 0); encoder->encode(MachPort(m_exceptionPort, MACH_MSG_TYPE_MAKE_SEND)); sendMessage(MessageID(), encoder.release()); } 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_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)); }
void Connection::receiveSourceEventHandler() { char buffer[inlineMessageMaxSize]; mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(&buffer); kern_return_t kr = mach_msg(header, MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT, 0, sizeof(buffer), m_receivePort, 0, MACH_PORT_NULL); if (kr == MACH_RCV_TIMED_OUT) return; if (kr != MACH_MSG_SUCCESS) { ASSERT_NOT_REACHED(); // FIXME: Handle MACH_RCV_MSG_TOO_LARGE. return; } MessageID messageID = MessageID::fromInt(header->msgh_id); std::auto_ptr<ArgumentDecoder> arguments = createArgumentDecoder(header); ASSERT(arguments.get()); if (messageID == MessageID(CoreIPCMessage::InitializeConnection)) { ASSERT(m_isServer); ASSERT(!m_isConnected); ASSERT(!m_sendPort); MachPort port; if (!arguments->decode(port)) { // FIXME: Disconnect. return; } m_sendPort = port.port(); // Set the dead name source if needed. if (m_sendPort) initializeDeadNameSource(); m_isConnected = true; // Send any pending outgoing messages. sendOutgoingMessages(); return; } processIncomingMessage(messageID, arguments); }
void MessageQueue::append(In& stream) { unsigned usedSize, numberOfMessages; stream >> usedSize >> numberOfMessages; // Trying a direct copy. This is hacked, but fast. char* dest = numberOfMessages == (unsigned) -1 ? 0 : queue.reserve(usedSize - MessageQueueBase::headerSize); if(dest) { stream.read(dest - MessageQueueBase::headerSize, usedSize); queue.numberOfMessages += numberOfMessages; queue.usedSize += usedSize; queue.writePosition = 0; } else // Not all messages fit in there, so try step by step (some will be missing). for(unsigned i = 0; numberOfMessages == (unsigned) -1 ? !stream.eof() : i < numberOfMessages ; ++i) { unsigned char id = 0; unsigned int size = 0; stream >> id; stream.read(&size, 3); if((id >= numOfDataMessageIDs || size == 0) && numberOfMessages == (unsigned) -1) { OUTPUT(idText, text, "MessageQueue: Logfile appears to be broken. Skipping rest of file. Read messages: " << queue.numberOfMessages << " read size:" << queue.usedSize); break; } char* dest = numberOfMessages != (unsigned) -1 || id < numOfDataMessageIDs ? queue.reserve(size) : 0; if(dest) { stream.read(dest, size); out.finishMessage(MessageID(id)); } else stream.skip(size); } }
void Connection::dispatchMessages() { Vector<IncomingMessage> incomingMessages; { MutexLocker locker(m_incomingMessagesLock); m_incomingMessages.swap(incomingMessages); } // Dispatch messages. for (size_t i = 0; i < incomingMessages.size(); ++i) { IncomingMessage& message = incomingMessages[i]; ArgumentDecoder* arguments = message.arguments(); if (message.messageID().isSync()) { // Decode the sync request ID. uint64_t syncRequestID = 0; if (!arguments->decodeUInt64(syncRequestID)) { // FIXME: Handle this case. ASSERT_NOT_REACHED(); } // Create our reply encoder. std::auto_ptr<ArgumentEncoder> replyEncoder(new ArgumentEncoder(syncRequestID)); // Hand off both the decoder and encoder to the client.. m_client->didReceiveSyncMessage(this, message.messageID(), arguments, replyEncoder.get()); // Send the reply. sendMessage(MessageID(CoreIPCMessage::SyncMessageReply), replyEncoder); } else m_client->didReceiveMessage(this, message.messageID(), arguments); message.destroy(); } }
bool Connection::sendSyncReply(PassOwnPtr<ArgumentEncoder> arguments) { return sendMessage(MessageID(CoreIPCMessage::SyncMessageReply), arguments); }
MessageID MessageQueueBase::getMessageID() const { MessageID id = MessageID(buf[selectedMessageForReadingPosition]); return id < numOfMappedIDs ? mappedIDs[id] : id; }