diff options
| -rw-r--r-- | indra/newview/llscripteditorws.cpp | 75 | ||||
| -rw-r--r-- | indra/newview/llscripteditorws.h | 8 |
2 files changed, 76 insertions, 7 deletions
diff --git a/indra/newview/llscripteditorws.cpp b/indra/newview/llscripteditorws.cpp index 9f829f430e..2df4c73cd9 100644 --- a/indra/newview/llscripteditorws.cpp +++ b/indra/newview/llscripteditorws.cpp @@ -134,6 +134,18 @@ void LLScriptEditorWSServer::unsubscribeEditor(const std::string &script_id) if (it != mSubscriptions.end()) { mSubscriptions.erase(it); + S32 connection_id = it->second.mConnectionID; + ptrdiff_t count = std::count_if(mSubscriptions.begin(), mSubscriptions.end(), [connection_id](const auto& pair) { + return pair.second.mConnectionID == connection_id; + }); + auto connection = it->second.mConnection.lock(); + if (connection && !count) + { // We have removed the last subscription, close the connection + LL_DEBUGS("ScriptEditorWS") << "Closing connection ID " << it->second.mConnectionID << + " as last subscription was removed" << LL_ENDL; + connection->sendDisconnect(LLScriptEditorWSConnection::REASON_EDITOR_CLOSED, "Editor closed"); + } + } } @@ -512,7 +524,11 @@ void LLScriptEditorWSConnection::onOpen() handshake["agent_id"] = gAgent.getID(); handshake["agent_name"] = "todo"; - // handshake["challenge"] = ... TODO: simple challenge, write to a file and have the client echo it back? + std::string challenge_file = generateChallenge(); + if (!challenge_file.empty()) + { + handshake["challenge"] = challenge_file; + } LLSD languages = LLSD::emptyArray(); languages.append("lsl"); @@ -564,6 +580,16 @@ void LLScriptEditorWSConnection::onClose() mFeatures.clear(); } +void LLScriptEditorWSConnection::sendDisconnect(S32 reason, const std::string& message) +{ + LL_INFOS("ScriptEditorWS") << "Sending disconnect to client: " << message << LL_ENDL; + LLSD params; + params["reason"] = reason; + params["message"] = message; + notify("session.disconnect", params); + closeConnection(1000, message); +} + void LLScriptEditorWSConnection::handleHandshakeResponse(const LLSD& result) { LL_INFOS("ScriptEditorWS") << "Processing handshake response from client" << LL_ENDL; @@ -573,7 +599,23 @@ void LLScriptEditorWSConnection::handleHandshakeResponse(const LLSD& result) mClientVersion = result["client_version"].asString(); mProtocolVersion = result["protocol_version"].asString(); - // TODO: Validate challenge_response if implemented + if (mChallenge.notNull()) + { + // Validate challenge response + bool valid_response = (result.has("challenge_response") && + (result["challenge_response"].asUUID() == mChallenge)); + + LLFile::remove(mChallengeFile); + mChallengeFile.clear(); + mChallenge.setNull(); + if (!valid_response) + { + LL_WARNS("ScriptEditorWS") << "Invalid or missing challenge response from client" << LL_ENDL; + sendDisconnect(REASON_PROTOCOL_ERROR, "Invalid challenge response"); + return; + } + } + LLUUID challenge_response = result["challenge_response"].asUUID(); // Validate protocol compatibility if (mProtocolVersion != "1.0") @@ -603,7 +645,36 @@ void LLScriptEditorWSConnection::handleHandshakeResponse(const LLSD& result) } } + if (mChallenge.notNull()) + { + // Remove temporary challenge file + LLFile::remove(mChallengeFile); + mChallenge.setNull(); + mChallengeFile.clear(); + } + notify("session.ok"); LL_INFOS("ScriptEditorWS") << "Handshake completed successfully." << LL_ENDL; } + +std::string LLScriptEditorWSConnection::generateChallenge() +{ + mChallenge.generate(); + + mChallengeFile = std::string(LLFile::tmpdir()) + "sl_script_challenge.tmp"; + + llofstream file(mChallengeFile.c_str()); + if (!file.is_open()) + { + LL_WARNS() << "Unable to open challenge file: " << mChallengeFile << LL_ENDL; + mChallenge.setNull(); + mChallengeFile.clear(); + return std::string(); + } + + file << mChallenge; + file.close(); + + return mChallengeFile; +} diff --git a/indra/newview/llscripteditorws.h b/indra/newview/llscripteditorws.h index 7112320c57..2c3ae31e8d 100644 --- a/indra/newview/llscripteditorws.h +++ b/indra/newview/llscripteditorws.h @@ -71,11 +71,6 @@ public: void onOpen() override; void onClose() override; - /** - * @brief Send session disconnect message to the external editor - * @param reason Numeric reason code for the disconnect (default 0 for normal closure) - * @param message Human-readable disconnect message (default "Goodbye") - */ void sendDisconnect(S32 reason = 0, const std::string& message = "Goodbye"); private: @@ -85,6 +80,7 @@ private: * @param result The response data from the client containing client information */ void handleHandshakeResponse(const LLSD& result); + std::string generateChallenge(); LLScriptEdContainer* getEditor() const; std::shared_ptr<LLScriptEditorWSServer> getServer() const; @@ -99,6 +95,8 @@ private: std::string mScriptLanguage; ///< Programming language of the script (lsl, luau, etc.) string_set_t mLanguages; ///< Set of supported scripting languages string_set_t mFeatures; ///< Active client features (live_sync, compilation, etc.) + LLUUID mChallenge; + std::string mChallengeFile; ///< Temporary file used for challenge-response verification static U32 sNextConnectionID; }; |
