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); } }