public void Parse(OSDMap reply)
{
try
{
AgentID = ParseUUID("agent_id", reply);
SessionID = ParseUUID("session_id", reply);
SecureSessionID = ParseUUID("secure_session_id", reply);
FirstName = ParseString("first_name", reply).Trim('"');
LastName = ParseString("last_name", reply).Trim('"');
StartLocation = ParseString("start_location", reply);
AgentAccess = ParseString("agent_access", reply);
LookAt = ParseVector3("look_at", reply);
AssetServerUri = ParseString("asset_server_address", reply);
}
catch (OSDException e)
{
Logger.DebugLog("Login server returned (some) invalid data: " + e.Message);
}
// Home
OSDMap home = null;
OSD osdHome = OSDParser.DeserializeLLSDNotation(reply["home"].AsString());
if (osdHome.Type == OSDType.Map)
{
home = (OSDMap)osdHome;
OSD homeRegion;
if (home.TryGetValue("region_handle", out homeRegion) && homeRegion.Type == OSDType.Array)
{
OSDArray homeArray = (OSDArray)homeRegion;
if (homeArray.Count == 2)
HomeRegion = Utils.UIntsToLong((uint)homeArray[0].AsInteger(), (uint)homeArray[1].AsInteger());
else
HomeRegion = 0;
}
HomePosition = ParseVector3("position", home);
HomeLookAt = ParseVector3("look_at", home);
}
else
{
HomeRegion = 0;
HomePosition = Vector3.Zero;
HomeLookAt = Vector3.Zero;
}
CircuitCode = ParseUInt("circuit_code", reply);
RegionX = ParseUInt("region_x", reply);
RegionY = ParseUInt("region_y", reply);
SimPort = (ushort)ParseUInt("sim_port", reply);
string simIP = ParseString("sim_ip", reply);
IPAddress.TryParse(simIP, out SimIP);
SeedCapability = ParseString("seed_capability", reply);
// Buddy list
OSD buddyLLSD;
if (reply.TryGetValue("buddy-list", out buddyLLSD) && buddyLLSD.Type == OSDType.Array)
{
OSDArray buddyArray = (OSDArray)buddyLLSD;
BuddyList = new FriendInfo[buddyArray.Count];
for (int i = 0; i < buddyArray.Count; i++)
{
if (buddyArray[i].Type == OSDType.Map)
{
OSDMap buddy = (OSDMap)buddyArray[i];
BuddyList[i] = new FriendInfo(
ParseUUID("buddy_id", buddy),
(FriendRights)ParseUInt("buddy_rights_given", buddy),
(FriendRights)ParseUInt("buddy_rights_has", buddy));
}
}
}
SecondsSinceEpoch = Utils.UnixTimeToDateTime(ParseUInt("seconds_since_epoch", reply));
InventoryRoot = ParseMappedUUID("inventory-root", "folder_id", reply);
InventorySkeleton = ParseInventoryFolders("inventory-skeleton", AgentID, reply);
LibraryRoot = ParseMappedUUID("inventory-lib-root", "folder_id", reply);
LibraryOwner = ParseMappedUUID("inventory-lib-owner", "agent_id", reply);
LibrarySkeleton = ParseInventoryFolders("inventory-skel-lib", LibraryOwner, reply);
}
/// <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); } }