Esempio n. 1
0
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());
}    
Esempio n. 2
0
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));
}
Esempio n. 3
0
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));
}
Esempio n. 4
0
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);
    }
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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));
}
Esempio n. 8
0
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);
}    
Esempio n. 9
0
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);
    }
}
Esempio n. 10
0
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();
    }
}
Esempio n. 11
0
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;
}