// This is the SLPlugin process (the child process). // This is not part of a DSO. // // This function is called when the serialized message 'message' was received from the viewer. // It parses the message and handles LLPLUGIN_MESSAGE_CLASS_INTERNAL. // Other message classes are passed on to LLPluginInstance::sendMessage. void LLPluginProcessChild::receiveMessageRaw(const std::string &message) { // Incoming message from the TCP Socket LL_DEBUGS("Plugin") << "Received from parent: " << message << LL_ENDL; // Decode this message LLPluginMessage parsed; parsed.parse(message); if(mBlockingRequest) { // We're blocking the plugin waiting for a response. if(parsed.hasValue("blocking_response")) { // This is the message we've been waiting for -- fall through and send it immediately. mBlockingResponseReceived = true; } else { // Still waiting. Queue this message and don't process it yet. mMessageQueue.push(message); return; } } bool passMessage = true; // FIXME: how should we handle queueing here? { std::string message_class = parsed.getClass(); if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) { passMessage = false; std::string message_name = parsed.getName(); if(message_name == "load_plugin") { mPluginFile = parsed.getValue("file"); mPluginDir = parsed.getValue("dir"); } else if(message_name == "shm_add") { std::string name = parsed.getValue("name"); size_t size = (size_t)parsed.getValueS32("size"); sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); if(iter != mSharedMemoryRegions.end()) { // Need to remove the old region first LL_WARNS("Plugin") << "Adding a duplicate shared memory segment!" << LL_ENDL; } else { // This is a new region LLPluginSharedMemory *region = new LLPluginSharedMemory; if(region->attach(name, size)) { mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region)); std::stringstream addr; addr << region->getMappedAddress(); // Send the add notification to the plugin LLPluginMessage message("base", "shm_added"); message.setValue("name", name); message.setValueS32("size", (S32)size); message.setValuePointer("address", region->getMappedAddress()); sendMessageToPlugin(message); // and send the response to the parent message.setMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add_response"); message.setValue("name", name); sendMessageToParent(message); } else { LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL; delete region; } } } else if(message_name == "shm_remove") { std::string name = parsed.getValue("name"); sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); if(iter != mSharedMemoryRegions.end()) { // forward the remove request to the plugin -- its response will trigger us to detach the segment. LLPluginMessage message("base", "shm_remove"); message.setValue("name", name); sendMessageToPlugin(message); } else { LL_WARNS("Plugin") << "shm_remove for unknown memory segment!" << LL_ENDL; } } else if(message_name == "sleep_time") { mSleepTime = llmax(parsed.getValueReal("time"), 1.0 / 100.0); // clamp to maximum of 100Hz } else if(message_name == "crash") { // Crash the plugin LL_ERRS("Plugin") << "Plugin crash requested." << LL_ENDL; } else if(message_name == "hang") { // Hang the plugin LL_WARNS("Plugin") << "Plugin hang requested." << LL_ENDL; while(1) { // wheeeeeeeee...... } } else { LL_WARNS("Plugin") << "Unknown internal message from parent: " << message_name << LL_ENDL; } } } if(passMessage && mInstance != NULL) { LLTimer elapsed; mInstance->sendMessage(message); mCPUElapsed += elapsed.getElapsedTimeF64(); } }