bool Host::Invoke(IPC::Message* msg) { #pragma TODO("Unpack the invoker and interface name from the message data") const char* invokerName = NULL; const char* interfaceName = NULL; // find the interface Interface* interface = GetInterface(interfaceName); if (interface == NULL) { printf("RPC::Unable to find interface '%s'\n", interfaceName); delete msg; return true; } // find the invoker Invoker* invoker = interface->GetInvoker(invokerName); if (invoker == NULL) { printf("RPC::Unable to find invoker '%s' in interface '%s'\n", invokerName, interfaceName); delete msg; return true; } // get our frame from the top of the stack Frame* frame = m_Stack.Top(); HELIUM_ASSERT(frame->m_Message == NULL); frame->m_Message = msg; // call the function frame->m_MessageTaken = false; invoker->Invoke(msg->GetData(), msg->GetSize()); HELIUM_ASSERT(frame->m_Message != NULL); frame->m_Message = NULL; Args* args = (Args*)msg->GetData(); if (args->m_Flags & RPC::Flags::NonBlocking) { if (!frame->m_MessageTaken) { delete msg; } return true; // async call, we are done } // our reply IPC::Message* reply = NULL; // if we have data, and a reference args or payload if (msg->GetSize() > 0 && args->m_Flags & (RPC::Flags::ReplyWithArgs | RPC::Flags::ReplyWithPayload)) { // total size of reply uint32_t size = 0; // size of args section uint32_t argSize = invoker->GetArgsSize(); // size of payload section uint32_t payload_size = msg->GetSize() - argSize; // if we have a ref args if (args->m_Flags & RPC::Flags::ReplyWithArgs) { // alloc for args block size += argSize; } // if we have a ref payload if (args->m_Flags & RPC::Flags::ReplyWithPayload) { // alloc for payload block size += payload_size; } // create message reply = Create(invoker, size, msg->GetTransaction()); // where to write uint8_t* ptr = reply->GetData(); // if we have a ref args if (args->m_Flags & RPC::Flags::ReplyWithArgs) { if (Swizzle()) { invoker->Swizzle( msg->GetData() ); } // write to ptr memcpy(ptr, msg->GetData(), argSize); // incr ptr by amount written ptr += argSize; } // if we have a ref payload if (args->m_Flags & RPC::Flags::ReplyWithPayload) { // write to ptr memcpy(ptr, msg->GetData() + argSize, payload_size); // incr ptr by amount written ptr += payload_size; } // assert we did not overrun message size HELIUM_ASSERT((uint32_t)(ptr - reply->GetData()) == size); } else // no data, or no ref args or payload { // just create an empty reply, the other side is blocking reply = Create(invoker, 0, msg->GetTransaction()); } if (m_Connection->Send(reply)!= IPC::ConnectionStates::Active) { delete reply; } #ifdef RPC_DEBUG_MSG printf("RPC::Put message id 0x%08x, size %d, transaction %d\n", reply->GetID(), reply->GetSize(), reply->GetTransaction()); #endif if (!frame->m_MessageTaken) { delete msg; } return true; }