// This is the viewer process (the parent process) // // This function is called to send a message to the plugin. void LLPluginProcessParent::sendMessage(const LLPluginMessage &message) { if(message.hasValue("blocking_response")) { mBlocked = false; // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); } if (message.hasValue("gorgon")) { // After this message it is expected that the plugin will not send any more messages for a long time. mBlocked = true; } std::string buffer = message.generate(); #if LL_DEBUG if (message.getName() == "mouse_event") { LL_DEBUGS("PluginMouseEvent") << "Sending: " << buffer << LL_ENDL; } else { LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; } #endif writeMessageRaw(buffer); // Try to send message immediately. if(mMessagePipe) { mMessagePipe->pumpOutput(); } }
void LLPluginProcessParent::sendMessage(const LLPluginMessage &message) { std::string buffer = message.generate(); LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; writeMessageRaw(buffer); }
// This is the SLPlugin process (the child process). // This is not part of a DSO. // // This function is called by SLPlugin to send 'message' to the viewer (the parent process). void LLPluginProcessChild::sendMessageToParent(const LLPluginMessage &message) { std::string buffer = message.generate(); LL_DEBUGS("Plugin") << "Sending to parent: " << buffer << LL_ENDL; // Write the serialized message to the pipe. writeMessageRaw(buffer); }
void LLPluginProcessParent::sendMessage(const LLPluginMessage &message) { if(message.hasValue("blocking_response")) { mBlocked = false; // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); } std::string buffer = message.generate(); LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; writeMessageRaw(buffer); // Try to send message immediately. if(mMessagePipe) { mMessagePipe->pumpOutput(); } }
/* virtual */ void LLPluginProcessChild::receivePluginMessage(const std::string &message) { LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL; if(mBlockingRequest) { // LL_ERRS("Plugin") << "Can't send a message while already waiting on a blocking request -- aborting!" << LL_ENDL; } // Incoming message from the plugin instance bool passMessage = true; // FIXME: how should we handle queueing here? // Intercept certain base messages (responses to ones sent by this class) { // Decode this message LLPluginMessage parsed; parsed.parse(message); if(parsed.hasValue("blocking_request")) { mBlockingRequest = true; } std::string message_class = parsed.getClass(); if(message_class == "base") { std::string message_name = parsed.getName(); if(message_name == "init_response") { // The plugin has finished initializing. setState(STATE_RUNNING); // Don't pass this message up to the parent passMessage = false; LLPluginMessage new_message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin_response"); LLSD versions = parsed.getValueLLSD("versions"); new_message.setValueLLSD("versions", versions); if(parsed.hasValue("plugin_version")) { std::string plugin_version = parsed.getValue("plugin_version"); new_message.setValueLLSD("plugin_version", plugin_version); } // Let the parent know it's loaded and initialized. sendMessageToParent(new_message); } else if(message_name == "shm_remove_response") { // Don't pass this message up to the parent passMessage = false; std::string name = parsed.getValue("name"); sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); if(iter != mSharedMemoryRegions.end()) { // detach the shared memory region iter->second->detach(); // and remove it from our map mSharedMemoryRegions.erase(iter); // Finally, send the response to the parent. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove_response"); message.setValue("name", name); sendMessageToParent(message); } else { LL_WARNS("Plugin") << "shm_remove_response for unknown memory segment!" << LL_ENDL; } } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) { bool flush = false; std::string message_name = parsed.getName(); if(message_name == "shutdown") { // The plugin is finished. setState(STATE_UNLOADING); flush = true; } else if (message_name == "flush") { flush = true; passMessage = false; } if (flush) { flushMessages(); } } } if(passMessage) { LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL; writeMessageRaw(message); } while(mBlockingRequest) { // The plugin wants to block and wait for a response to this message. sleep(mSleepTime); // this will pump the message pipe and process messages if(mBlockingResponseReceived || mSocketError != APR_SUCCESS || (mMessagePipe == NULL)) { // Response has been received, or we've hit an error state. Stop waiting. mBlockingRequest = false; mBlockingResponseReceived = false; } } }
/* virtual */ void LLPluginProcessChild::receivePluginMessage(const std::string &message) { LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL; // Incoming message from the plugin instance bool passMessage = true; // FIXME: how should we handle queueing here? // Intercept certain base messages (responses to ones sent by this class) { // Decode this message LLPluginMessage parsed; parsed.parse(message); std::string message_class = parsed.getClass(); if(message_class == "base") { std::string message_name = parsed.getName(); if(message_name == "init_response") { // The plugin has finished initializing. setState(STATE_RUNNING); // Don't pass this message up to the parent passMessage = false; LLPluginMessage new_message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin_response"); LLSD versions = parsed.getValueLLSD("versions"); new_message.setValueLLSD("versions", versions); if(parsed.hasValue("plugin_version")) { std::string plugin_version = parsed.getValue("plugin_version"); new_message.setValueLLSD("plugin_version", plugin_version); } // Let the parent know it's loaded and initialized. sendMessageToParent(new_message); } else if(message_name == "shm_remove_response") { // Don't pass this message up to the parent passMessage = false; std::string name = parsed.getValue("name"); sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); if(iter != mSharedMemoryRegions.end()) { // detach the shared memory region iter->second->detach(); // and remove it from our map mSharedMemoryRegions.erase(iter); // Finally, send the response to the parent. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove_response"); message.setValue("name", name); sendMessageToParent(message); } else { LL_WARNS("Plugin") << "shm_remove_response for unknown memory segment!" << LL_ENDL; } } } } if(passMessage) { LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL; writeMessageRaw(message); } }