protected void ParseFault(XmlNode faultNode) { Parameters = new XmlRpcParameterArray(); if (faultNode.Name != "fault") { throw new Exception($"WARN XmlRpcResponse.ParseFault: Unexpected node name, expected \"fault\" found \"{faultNode.Name}\"."); } if (faultNode.ChildNodes.Count != 1) { throw new Exception("WARN XmlRpcResponse.ParseFault: Unexpected number of nodes in fault."); } XmlNode valueNode = faultNode.FirstChild; if (valueNode.Name != "value") { throw new Exception($"WARN XmlRpcResponse.ParseFault: Unexpected node name, expected \"value\" found \"{valueNode.Name}\"."); } if (valueNode.ChildNodes.Count != 1) { throw new Exception("WARN XmlRpcResponse.ParseFault: Unexpected number of nodes in value."); } XmlRpcValue faultValue = XmlRpcValue.FromXmlNode(valueNode.FirstChild); if (faultValue is XmlRpcStruct == false) { throw new Exception("WARN XmlRpcResponse.ParseFault: Unexpected value type."); } XmlRpcStruct fault = (XmlRpcStruct)faultValue; if (fault.Has("faultCode") == false) { throw new Exception("WARN XmlRpcResponse.ParseFault: Fault response has no faultCode."); } if (fault["faultCode"] is XmlRpcInteger == false) { throw new Exception("WARN XmlRpcResponse.ParseFault: faultCode is not an integer."); } FaultCode = ((XmlRpcInteger)fault["faultCode"]).Value; if (fault.Has("faultString") == false) { throw new Exception("WARN XmlRpcResponse.ParseFault: Fault response has no faultString."); } if (fault["faultString"] is XmlRpcString == false) { throw new Exception("WARN XmlRpcResponse.ParseFault: faultString is not a string."); } FaultString = ((XmlRpcString)fault["faultString"]).Value; }
public async Task <LoginResponse> Connect(string uri, Credential credential, Slurl slurl = null, bool getInventoryLibrary = true, bool godMode = false) { if (slurl == null) { slurl = new Slurl(Slurl.SIM_LOCATION_LAST); } Logger.LogDebug($"INFO Login.Connect: Connecting {credential.First} {credential.Last} using {uri}."); XmlRpcParameterArray parameters = CreateLoginParameters(credential, slurl, getInventoryLibrary, godMode); XmlRpcResponse response = await XmlRpcClient.Call(uri, "login_to_simulator", parameters); LoginResponse loginResponse = new LoginResponse(); if (response.FaultCode != 0) { loginResponse.LoginSucceeded = false; loginResponse.LoginFailReason = response.FaultCode.ToString(); loginResponse.Message = response.FaultString; loginResponse.MessageId = "XmlRpcError"; return(loginResponse); } if (response.Parameters.Count != 1 || (response.Parameters[0] is XmlRpcStruct == false)) { loginResponse.LoginSucceeded = false; loginResponse.LoginFailReason = "500"; loginResponse.Message = "Login response contained incorrect parameters."; loginResponse.MessageId = "XmlRpcError"; return(loginResponse); } XmlRpcStruct responseData = (XmlRpcStruct)response.Parameters[0]; if (responseData.Has("login") == false || (responseData["login"] is XmlRpcString == false) || ((XmlRpcString)responseData["login"]).Value != "true") { loginResponse.LoginSucceeded = false; loginResponse.LoginFailReason = responseData["reason"]?.AsString; loginResponse.Message = responseData["message"]?.AsString; loginResponse.MessageId = responseData["message_id"]?.AsString; return(loginResponse); } Logger.LogInfo("Login.Connect: Connection was successful."); if (ProcessLoginSuccessResponse(responseData, loginResponse)) { loginResponse.LoginSucceeded = true; return(loginResponse); } else { // Yet another error } return(loginResponse); }
protected bool ProcessLoginSuccessResponse(XmlRpcStruct responseData, LoginResponse loginResponse) { // TODO: Parse benefits // TODO: Parse "udp_blacklist" loginResponse.SessionId = Guid.Empty; if (responseData.Has("session_id")) { loginResponse.SessionId = Guid.Parse(responseData["session_id"].AsString); } if (loginResponse.SessionId == Guid.Empty) { return(false); } #region Agent loginResponse.AgentId = Guid.Empty; if (responseData.Has("agent_id")) { loginResponse.AgentId = Guid.Parse(responseData["agent_id"].AsString); } if (loginResponse.AgentId == Guid.Empty) { return(false); } // TODO: Send agentId and agentSessionId to the LLUrlEntryParcel //Guid agentSecureSessionId = Guid.Empty; //if (responseData.Has("secure_session_id")) //{ // agentSecureSessionId = Guid.Parse(responseData["secure_session_id"].AsString); //} string agentUserName = ""; if (responseData.Has("first_name")) { agentUserName = responseData["first_name"].AsString.Replace('"', ' ').Trim(); // NOTE: login.cgi sends " to force names that look like numbers into strings loginResponse.FirstName = agentUserName; } if (responseData.Has("last_name")) { string lastName = responseData["last_name"].AsString.Replace('"', ' ').Trim(); // NOTE: login.cgi sends " to force names that look like numbers into strings loginResponse.LastName = lastName; if (lastName != "Resident") { agentUserName += $" {lastName}"; } } string displayName = ""; if (responseData.Has("display_name")) { displayName = responseData["display_name"].AsString.Replace('"', ' ').Trim(); // NOTE: login.cgi sends " to force names that look like numbers into strings } else if (agentUserName != "") { displayName = agentUserName; } else { // TODO: Construct display name from request credentials } loginResponse.DisplayName = displayName; //RegionMaturityLevel regionMaturityLevel = RegionMaturityLevel.A; // TODO: Get from settings //if (responseData.Has("agent_access_max")) //{ // Enum.TryParse<RegionMaturityLevel>(responseData["agent_access_max"].AsString, out regionMaturityLevel); //} //RegionMaturityLevel preferredMaturityLevel = RegionMaturityLevel.A; // TODO: Get from settings //if (responseData.Has("agent_region_access")) //{ // Enum.TryParse<RegionMaturityLevel>(responseData["agent_region_access"].AsString, out preferredMaturityLevel); //} //string agentStartLocation = ""; //if (responseData.Has("start_location")) //{ // agentStartLocation = responseData["start_location"].AsString; //} //Vector3 agentStartLookAt = Vector3.forward; //if (responseData.Has("look_at")) //{ // // TODO: Decode "[r0.75787899999999996936,r0.65239599999999997593,r0]" //} #endregion Agent #region Region if (responseData.Has("region_x") && responseData.Has("region_y")) { UInt32 x = UInt32.Parse(responseData["region_x"].AsString); UInt32 y = UInt32.Parse(responseData["region_y"].AsString); loginResponse.RegionHandle = new RegionHandle(x, y); } loginResponse.CircuitCode = 0; loginResponse.SimIp = ""; loginResponse.SimPort = 0; if (responseData.Has("circuit_code")) { loginResponse.CircuitCode = UInt32.Parse(responseData["circuit_code"].AsString); } if (responseData.Has("sim_ip")) { loginResponse.SimIp = responseData["sim_ip"].AsString; } if (responseData.Has("sim_port")) { loginResponse.SimPort = int.Parse(responseData["sim_port"].AsString); } if (loginResponse.CircuitCode == 0 || string.IsNullOrEmpty(loginResponse.SimIp) || loginResponse.SimPort == 0) { return(false); } if (responseData.Has("seed_capability")) { loginResponse.SeedCapability = responseData["seed_capability"]?.AsString; } #endregion Region #region BuddyList if (responseData.Has("buddy-list") && responseData["buddy-list"] is XmlRpcArray) { loginResponse.BuddyList.Clear(); foreach (XmlRpcValue value in (XmlRpcArray)responseData["buddy-list"]) { if (value is XmlRpcStruct == false || ((XmlRpcStruct)value).Has("buddy_id") == false || ((XmlRpcStruct)value)["buddy_id"] is XmlRpcString == false || ((XmlRpcStruct)value).Has("buddy_rights_given") == false || ((XmlRpcStruct)value)["buddy_rights_given"] is XmlRpcInteger == false || ((XmlRpcStruct)value).Has("buddy_rights_has") == false || ((XmlRpcStruct)value)["buddy_rights_has"] is XmlRpcInteger == false ) { continue; } XmlRpcStruct data = (XmlRpcStruct)value; Guid buddyId = Guid.Parse(data["buddy_id"].AsString); Relationship.Rights toAgent = (Relationship.Rights)((XmlRpcInteger)data["buddy_rights_given"]).Value; Relationship.Rights fromAgent = (Relationship.Rights)((XmlRpcInteger)data["buddy_rights_has"]).Value; loginResponse.BuddyList[buddyId] = new Relationship(toAgent, fromAgent, false); } } #endregion BuddyList // TODO: Parse more things, see llstartup.cpp line 3439 and onwards // TODO: Non-existent Inventory.RootFolderId is a fail return(true); }