/// <summary> /// Handle response from LLSD login replies /// </summary> /// <param name="client"></param> /// <param name="result"></param> /// <param name="error"></param> private void LoginReplyLLSDHandler(CapsClient client, OSD result, Exception error) { if (error == null) { if (result != null && result.Type == OSDType.Map) { OSDMap map = (OSDMap)result; OSD osd; LoginResponseData data = new LoginResponseData(); data.Parse(map); if (map.TryGetValue("login", out osd)) { bool loginSuccess = osd.AsBoolean(); bool redirect = (osd.AsString() == "indeterminate"); if (redirect) { // Login redirected // Make the next login URL jump UpdateLoginStatus(LoginStatus.Redirecting, data.Message); LoginParams loginParams = CurrentContext.Value; loginParams.URI = LoginResponseData.ParseString("next_url", map); //CurrentContext.Params.MethodName = LoginResponseData.ParseString("next_method", map); // Sleep for some amount of time while the servers work int seconds = (int)LoginResponseData.ParseUInt("next_duration", map); Logger.Log("Sleeping for " + seconds + " seconds during a login redirect", Helpers.LogLevel.Info); Thread.Sleep(seconds * 1000); // Ignore next_options for now CurrentContext = loginParams; BeginLogin(); } else if (loginSuccess) { // Login succeeded // Fire the login callback if (OnLoginResponse != null) { try { OnLoginResponse(loginSuccess, redirect, data.Message, data.Reason, data); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex); } } // These parameters are stored in NetworkManager, so instead of registering // another callback for them we just set the values here CircuitCode = (uint)data.CircuitCode; LoginSeedCapability = data.SeedCapability; UpdateLoginStatus(LoginStatus.ConnectingToSim, "Connecting to simulator..."); ulong handle = Utils.UIntsToLong((uint)data.RegionX, (uint)data.RegionY); if (data.SimIP != null && data.SimPort != 0) { // Connect to the sim given in the login reply if (Connect(data.SimIP, (ushort)data.SimPort, handle, true, LoginSeedCapability) != null) { // Request the economy data right after login SendPacket(new EconomyDataRequestPacket()); // Update the login message with the MOTD returned from the server UpdateLoginStatus(LoginStatus.Success, data.Message); } else { UpdateLoginStatus(LoginStatus.Failed, "Unable to establish a UDP connection to the simulator"); } } else { UpdateLoginStatus(LoginStatus.Failed, "Login server did not return a simulator address"); } } else { // Login failed // Make sure a usable error key is set if (data.Reason != String.Empty) InternalErrorKey = data.Reason; else InternalErrorKey = "unknown"; UpdateLoginStatus(LoginStatus.Failed, data.Message); } } else { // Got an LLSD map but no login value UpdateLoginStatus(LoginStatus.Failed, "login parameter missing in the response"); } } else { // No LLSD response InternalErrorKey = "bad response"; UpdateLoginStatus(LoginStatus.Failed, "Empty or unparseable login response"); } } else { // Connection error InternalErrorKey = "no connection"; UpdateLoginStatus(LoginStatus.Failed, error.Message); } }
/// <summary> /// Handles response from XML-RPC login replies /// </summary> private void LoginReplyXmlRpcHandler(XmlRpcResponse response, LoginParams context) { LoginResponseData reply = new LoginResponseData(); // Fetch the login response if (response == null || !(response.Value is Hashtable)) { UpdateLoginStatus(LoginStatus.Failed, "Invalid or missing login response from the server"); Logger.Log("Invalid or missing login response from the server", Helpers.LogLevel.Warning); return; } try { reply.Parse((Hashtable)response.Value); if (context.LoginID != CurrentContext.LoginID) { Logger.Log("Login response does not match login request. Only one login can be attempted at a time", Helpers.LogLevel.Error); return; } } catch (Exception e) { UpdateLoginStatus(LoginStatus.Failed, "Error retrieving the login response from the server: " + e.Message); Logger.Log("Login response failure: " + e.Message + " " + e.StackTrace, Helpers.LogLevel.Warning); return; } LoginReplyXmlRpcHandler(reply, context); }
/// <summary> /// Handles response from XML-RPC login replies /// </summary> private void LoginReplyXmlRpcHandler(XmlRpcResponse response, LoginParams context) { LoginResponseData reply = new LoginResponseData(); ushort simPort = 0; uint regionX = 0; uint regionY = 0; // Fetch the login response if (response == null || !(response.Value is Hashtable)) { UpdateLoginStatus(LoginStatus.Failed, "Invalid or missing login response from the server"); Logger.Log("Invalid or missing login response from the server", Helpers.LogLevel.Warning); return; } try { reply.Parse((Hashtable)response.Value); if (context.LoginID != CurrentContext.Value.LoginID) { Logger.Log("Login response does not match login request. Only one login can be attempted at a time", Helpers.LogLevel.Error); return; } } catch (Exception e) { UpdateLoginStatus(LoginStatus.Failed, "Error retrieving the login response from the server: " + e.Message); Logger.Log("Login response failure: " + e.Message + " " + e.StackTrace, Helpers.LogLevel.Warning); return; } string reason = reply.Reason; string message = reply.Message; if (reply.Login == "true") { // Remove the quotes around our first name. if (reply.FirstName[0] == '"') reply.FirstName = reply.FirstName.Remove(0, 1); if (reply.FirstName[reply.FirstName.Length - 1] == '"') reply.FirstName = reply.FirstName.Remove(reply.FirstName.Length - 1); #region Critical Information try { // Networking Client.Network.CircuitCode = (uint)reply.CircuitCode; regionX = (uint)reply.RegionX; regionY = (uint)reply.RegionY; simPort = (ushort)reply.SimPort; LoginSeedCapability = reply.SeedCapability; } catch (Exception) { UpdateLoginStatus(LoginStatus.Failed, "Login server failed to return critical information"); return; } #endregion Critical Information /* Add any blacklisted UDP packets to the blacklist * for exclusion from packet processing */ if (reply.UDPBlacklist != null) UDPBlacklist.AddRange(reply.UDPBlacklist.Split(',')); // Misc: //uint timestamp = (uint)reply.seconds_since_epoch; //DateTime time = Helpers.UnixTimeToDateTime(timestamp); // TODO: Do something with this? // Unhandled: // reply.gestures // reply.event_categories // reply.classified_categories // reply.event_notifications // reply.ui_config // reply.login_flags // reply.global_textures // reply.inventory_lib_root // reply.inventory_lib_owner // reply.inventory_skeleton // reply.inventory_skel_lib // reply.initial_outfit } bool redirect = (reply.Login == "indeterminate"); try { if (OnLoginResponse != null) { try { OnLoginResponse(reply.Success, redirect, message, reason, reply); } catch (Exception ex) { Logger.Log(ex.ToString(), Helpers.LogLevel.Error); } } } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, ex); } // Make the next network jump, if needed if (redirect) { UpdateLoginStatus(LoginStatus.Redirecting, "Redirecting login..."); LoginParams loginParams = CurrentContext.Value; loginParams.URI = reply.NextUrl; loginParams.MethodName = reply.NextMethod; loginParams.Options = reply.NextOptions; // Sleep for some amount of time while the servers work int seconds = reply.NextDuration; Logger.Log("Sleeping for " + seconds + " seconds during a login redirect", Helpers.LogLevel.Info); Thread.Sleep(seconds * 1000); CurrentContext = loginParams; BeginLogin(); } else if (reply.Success) { UpdateLoginStatus(LoginStatus.ConnectingToSim, "Connecting to simulator..."); ulong handle = Utils.UIntsToLong(regionX, regionY); // Connect to the sim given in the login reply if (Connect(reply.SimIP, simPort, handle, true, LoginSeedCapability) != null) { // Request the economy data right after login SendPacket(new EconomyDataRequestPacket()); // Update the login message with the MOTD returned from the server UpdateLoginStatus(LoginStatus.Success, message); } else { UpdateLoginStatus(LoginStatus.Failed, "Unable to connect to simulator"); } } else { // Make sure a usable error key is set if (!String.IsNullOrEmpty(reason)) InternalErrorKey = reason; else InternalErrorKey = "unknown"; UpdateLoginStatus(LoginStatus.Failed, message); } }
private void LoginReplyHandler(CapsClient client, OSD result, Exception error) { if (error == null) { if (result != null && result.Type == OSDType.Map) { OSDMap map = (OSDMap)result; OSD osd; string reason, message; if (map.TryGetValue("reason", out osd)) { reason = osd.AsString(); } else { reason = String.Empty; } if (map.TryGetValue("message", out osd)) { message = osd.AsString(); } else { message = String.Empty; } if (map.TryGetValue("login", out osd)) { bool loginSuccess = osd.AsBoolean(); bool redirect = (osd.AsString() == "indeterminate"); LoginResponseData data = new LoginResponseData(); data.Reason = reason; data.Message = message; if (redirect) { // Login redirected // Make the next login URL jump UpdateLoginStatus(LoginStatus.Redirecting, message); LoginParams loginParams = CurrentContext.Value; loginParams.URI = LoginResponseData.ParseString("next_url", map); //CurrentContext.Params.MethodName = LoginResponseData.ParseString("next_method", map); // Sleep for some amount of time while the servers work int seconds = (int)LoginResponseData.ParseUInt("next_duration", map); Logger.Log("Sleeping for " + seconds + " seconds during a login redirect", Helpers.LogLevel.Info); Thread.Sleep(seconds * 1000); // Ignore next_options for now CurrentContext = loginParams; BeginLogin(); } else if (loginSuccess) { // Login succeeded // Parse successful login replies into LoginResponseData structs data.Parse(map); // Fire the login callback if (OnLoginResponse != null) { try { OnLoginResponse(loginSuccess, redirect, message, reason, data); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex); } } // These parameters are stored in NetworkManager, so instead of registering // another callback for them we just set the values here CircuitCode = data.CircuitCode; LoginSeedCapability = data.SeedCapability; UpdateLoginStatus(LoginStatus.ConnectingToSim, "Connecting to simulator..."); ulong handle = Utils.UIntsToLong(data.RegionX, data.RegionY); if (data.SimIP != null && data.SimPort != 0) { // Connect to the sim given in the login reply if (Connect(data.SimIP, data.SimPort, handle, true, LoginSeedCapability) != null) { // Request the economy data right after login SendPacket(new EconomyDataRequestPacket()); // Update the login message with the MOTD returned from the server UpdateLoginStatus(LoginStatus.Success, message); // Fire an event for connecting to the grid if (OnConnected != null) { try { OnConnected(this.Client); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } else { UpdateLoginStatus(LoginStatus.Failed, "Unable to establish a UDP connection to the simulator"); } } else { UpdateLoginStatus(LoginStatus.Failed, "Login server did not return a simulator address"); } } else { // Login failed // Make sure a usable error key is set if (reason != String.Empty) { InternalErrorKey = reason; } else { InternalErrorKey = "unknown"; } UpdateLoginStatus(LoginStatus.Failed, message); } } else { // Got an LLSD map but no login value UpdateLoginStatus(LoginStatus.Failed, "login parameter missing in the response"); } } else { // No LLSD response InternalErrorKey = "bad response"; UpdateLoginStatus(LoginStatus.Failed, "Empty or unparseable login response"); } } else { // Connection error InternalErrorKey = "no connection"; UpdateLoginStatus(LoginStatus.Failed, error.Message); } }