* Added an LLUUID.Combine() function

* Added NetworkManager.SecureSessionID
* Added a missing SendPacket function for raw payloads to non-current sims
* Documented a few things in NetworkManager

git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@910 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
John Hurliman
2007-01-27 09:57:29 +00:00
parent 245597788d
commit 76fdbc7f80
5 changed files with 240 additions and 178 deletions

View File

@@ -102,6 +102,11 @@ namespace libsecondlife
Transfer = 0x00002000
}
/// <summary>Provide a single instance of the MD5 class to avoid making
/// duplicate copies</summary>
public static System.Security.Cryptography.MD5 MD5Builder =
new System.Security.Cryptography.MD5CryptoServiceProvider();
/// <summary>
/// Converts an unsigned integer to a hexadecimal string
/// </summary>
@@ -824,8 +829,7 @@ namespace libsecondlife
public static string MD5(string password)
{
StringBuilder digest = new StringBuilder();
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] hash = md5.ComputeHash(Encoding.ASCII.GetBytes(password));
byte[] hash = MD5Builder.ComputeHash(ASCIIEncoding.Default.GetBytes(password));
// Convert the hash to a hex string
foreach (byte b in hash)

View File

@@ -804,6 +804,7 @@ namespace libsecondlife
/// <param name="PreviousSimulator">A reference to the old value of CurrentSim</param>
public delegate void CurrentSimChangedCallback(Simulator PreviousSimulator);
/// <summary>
/// Explains why a simulator or the grid disconnected from us
/// </summary>
@@ -817,40 +818,6 @@ namespace libsecondlife
NetworkTimeout
}
/// <summary>
/// The permanent UUID for the logged in avatar
/// </summary>
public LLUUID AgentID;
/// <summary>
/// A temporary UUID assigned to this session, used for secure
/// transactions
/// </summary>
public LLUUID SessionID;
/// <summary>
/// A string holding a descriptive error on login failure, empty
/// otherwise
/// </summary>
public string LoginError;
/// <summary>
/// The simulator that the logged in avatar is currently occupying
/// </summary>
public Simulator CurrentSim;
/// <summary>
/// The capabilities for the current simulator
/// </summary>
public Caps CurrentCaps;
/// <summary>
/// The complete dictionary of all the login values returned by the
/// RPC login server, converted to native data types wherever possible
/// </summary>
public Dictionary<string, object> LoginValues = new Dictionary<string, object>();
/// <summary>
/// Shows whether the network layer is logged in to the grid or not
/// </summary>
public bool Connected
{
get { return connected; }
}
/// <summary>
/// An event for the connection to a simulator other than the currently
@@ -867,22 +834,57 @@ namespace libsecondlife
/// </summary>
public event CurrentSimChangedCallback OnCurrentSimChanged;
/// <summary>
/// The permanent UUID for the logged in avatar
/// </summary>
public LLUUID AgentID = LLUUID.Zero;
/// <summary>
/// Temporary UUID assigned to this session, used for verifying
/// our identity in packets
/// </summary>
public LLUUID SessionID = LLUUID.Zero;
/// <summary>
/// Shared secret UUID that is never sent over the wire
/// </summary>
public LLUUID SecureSessionID = LLUUID.Zero;
/// <summary>
/// String holding a descriptive error on login failure, empty
/// otherwise
/// </summary>
public string LoginError = String.Empty;
/// <summary>
/// The simulator that the logged in avatar is currently occupying
/// </summary>
public Simulator CurrentSim = null;
/// <summary>
/// The capabilities for the current simulator
/// </summary>
public Caps CurrentCaps = null;
/// <summary>
/// The complete dictionary of all the login values returned by the
/// RPC login server, converted to native data types wherever possible
/// </summary>
public Dictionary<string, object> LoginValues = new Dictionary<string, object>();
/// <summary>
/// Shows whether the network layer is logged in to the grid or not
/// </summary>
public bool Connected { get { return connected; } }
private SecondLife Client;
private Dictionary<PacketType, List<PacketCallback>> Callbacks = new Dictionary<PacketType, List<PacketCallback>>();
private List<Simulator> Simulators = new List<Simulator>();
private System.Timers.Timer DisconnectTimer;
private System.Timers.Timer LogoutTimer;
private bool connected;
private bool connected = false;
private List<Caps.EventQueueCallback> EventQueueCallbacks = new List<Caps.EventQueueCallback>();
private const int NetworkTrafficTimeout = 15000;
ManualResetEvent LogoutReplyEvent = new ManualResetEvent(false);
/// <summary>
///
/// Default constructor
/// </summary>
/// <param name="client"></param>
/// <param name="client">Reference to the SecondLife client</param>
public NetworkManager(SecondLife client)
{
Client = client;
@@ -896,16 +898,20 @@ namespace libsecondlife
RegisterCallback(PacketType.KickUser, new PacketCallback(KickUserHandler));
RegisterCallback(PacketType.LogoutReply, new PacketCallback(LogoutReplyHandler));
// Disconnect a sim if we exceed our threshold
DisconnectTimer = new System.Timers.Timer(NetworkTrafficTimeout);
// The proper timeout for this will get set at Login
DisconnectTimer = new System.Timers.Timer();
DisconnectTimer.AutoReset = false;
DisconnectTimer.Elapsed += new ElapsedEventHandler(DisconnectTimer_Elapsed);
}
/// <summary>
///
/// Register an event handler for a packet. This is a low level event
/// interface and should only be used if you are doing something not
/// supported in libsecondlife
/// </summary>
/// <param name="type"></param>
/// <param name="callback"></param>
/// <param name="type">Packet type to trigger events for</param>
/// <param name="callback">Callback to fire when a packet of this type
/// is received</param>
public void RegisterCallback(PacketType type, PacketCallback callback)
{
if (!Callbacks.ContainsKey(type))
@@ -918,10 +924,12 @@ namespace libsecondlife
}
/// <summary>
///
/// Unregister an event handler for a packet. This is a low level event
/// interface and should only be used if you are doing something not
/// supported in libsecondlife
/// </summary>
/// <param name="type"></param>
/// <param name="callback"></param>
/// <param name="type">Packet type this callback is registered with</param>
/// <param name="callback">Callback to stop firing events for</param>
public void UnregisterCallback(PacketType type, PacketCallback callback)
{
if (!Callbacks.ContainsKey(type))
@@ -945,69 +953,72 @@ namespace libsecondlife
}
/// <summary>
///
/// Register a CAPS event handler
/// </summary>
/// <param name="callback"></param>
/// <param name="callback">Callback to fire when a CAPS event is received</param>
public void RegisterEventCallback(Caps.EventQueueCallback callback)
{
EventQueueCallbacks.Add(callback);
}
/// <summary>
///
/// Send a packet to the simulator the avatar is currently occupying
/// </summary>
/// <param name="packet"></param>
/// <param name="packet">Packet to send</param>
public void SendPacket(Packet packet)
{
if (CurrentSim != null && CurrentSim.Connected)
{
CurrentSim.SendPacket(packet, true);
}
}
/// <summary>
///
/// Send a packet to a specified simulator
/// </summary>
/// <param name="packet"></param>
/// <param name="simulator"></param>
/// <param name="packet">Packet to send</param>
/// <param name="simulator">Simulator to send the packet to</param>
public void SendPacket(Packet packet, Simulator simulator)
{
if (simulator != null && simulator.Connected)
{
simulator.SendPacket(packet, true);
}
}
/// <summary>
///
/// Send a raw byte array as a packet to the current simulator
/// </summary>
/// <param name="payload"></param>
/// <param name="payload">Byte array containing a packet</param>
/// <param name="setSequence">Whether to set the second, third, and fourth
/// bytes of the payload to the current sequence number</param>
public void SendPacket(byte[] payload, bool setSequence)
{
if (connected && CurrentSim != null)
{
CurrentSim.SendPacket(payload, setSequence);
}
else
{
Client.Log("Trying to send a " + payload.Length + " payload " +
"when we're not connected", Helpers.LogLevel.Warning);
}
}
/// <summary>
/// Use this if you want to login to a specific location
/// Send a raw byte array as a packet to the specified simulator
/// </summary>
/// <param name="sim"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="z"></param>
/// <returns>string with a value that can be used in the start field in .DefaultLoginValues()</returns>
/// <param name="payload">Byte array containing a packet</param>
/// <param name="simulator">Simulator to send the packet to</param>
/// <param name="setSequence">Whether to set the second, third, and fourth
/// bytes of the payload to the current sequence number</param>
public void SendPacket(byte[] payload, Simulator simulator, bool setSequence)
{
if (connected && simulator != null)
simulator.SendPacket(payload, setSequence);
}
/// <summary>
/// Build a start location URI for passing to the Login function
/// </summary>
/// <param name="sim">Name of the simulator to start in</param>
/// <param name="x">X coordinate to start at</param>
/// <param name="y">Y coordinate to start at</param>
/// <param name="z">Z coordinate to start at</param>
/// <returns>String with a URI that can be used to login to a specified
/// location</returns>
public static string StartLocation(string sim, int x, int y, int z)
{
//uri:sim&x&y&z
// uri:sim name&x&y&z
return "uri:" + sim.ToLower() + "&" + x + "&" + y + "&" + z;
}
@@ -1232,6 +1243,9 @@ namespace libsecondlife
XmlRpcRequest xmlrpc;
Hashtable loginValues;
// Re-read the timeout value for the DisconnectTimer
DisconnectTimer.Interval = Client.Settings.SIMULATOR_TIMEOUT;
// Clear possible old values from the last login
LoginValues.Clear();
@@ -1386,6 +1400,7 @@ namespace libsecondlife
{
this.AgentID = new LLUUID((string)LoginValues["agent_id"]);
this.SessionID = new LLUUID((string)LoginValues["session_id"]);
this.SecureSessionID = new LLUUID((string)LoginValues["secure_session_id"]);
Client.Self.ID = this.AgentID;
// Names are wrapped in quotes now, have to strip those
Client.Self.FirstName = ((string)LoginValues["first_name"]).Trim(new char[] { '"' });
@@ -1558,6 +1573,10 @@ namespace libsecondlife
/// </summary>
public void ForceLogout()
{
Client.Log("Forcing a logout", Helpers.LogLevel.Info);
DisconnectTimer.Stop();
// Insist on shutdown
LogoutDemandPacket logoutDemand = new LogoutDemandPacket();
logoutDemand.LogoutBlock.SessionID = SessionID;

View File

@@ -1,102 +1,102 @@
/*
* Copyright (c) 2006, Second Life Reverse Engineering Team
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the Second Life Reverse Engineering Team nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using libsecondlife.Packets;
namespace libsecondlife
{
/// <summary>
/// Class for controlling various system settings.
/// </summary>
public class Settings
{
/// <summary>The version of libsecondlife (not the SL protocol itself)</summary>
public string VERSION = "libsecondlife 0.0.9";
/// <summary>XML-RPC login server to connect to</summary>
public string LOGIN_SERVER = "https://login.agni.lindenlab.com/cgi-bin/login.cgi";
/// <summary>Millisecond interval between ticks, where all ACKs are
/// sent out and the age of unACKed packets is checked</summary>
public readonly int NETWORK_TICK_LENGTH = 500;
/// <summary>The maximum value of a packet sequence number. After that
/// we assume the sequence number just rolls over? Or maybe the
/// protocol isn't able to sustain a connection past that</summary>
public readonly int MAX_SEQUENCE = 0xFFFFFF;
/// <summary>Number of milliseconds before a teleport attempt will time
/// out</summary>
public readonly int TELEPORT_TIMEOUT = 18 * 1000;
/// <summary>Number of milliseconds before NetworkManager.Logout() will time out</summary>
public int LOGOUT_TIMEOUT = 5 * 1000;
/// <summary>Number of milliseconds for xml-rpc to timeout</summary>
public int LOGIN_TIMEOUT = 30 * 1000;
/// <summary>The maximum size of the sequence number inbox, used to
/// check for resent and/or duplicate packets</summary>
public int INBOX_SIZE = 100;
/// <summary>Milliseconds before a packet is assumed lost and resent</summary>
public int RESEND_TIMEOUT = 4000;
/// <summary>Milliseconds before the connection to a simulator is
/// assumed lost</summary>
public int SIMULATOR_TIMEOUT = 15000;
/// <summary>Maximum number of queued ACKs to be sent before SendAcks()
/// is forced</summary>
public int MAX_PENDING_ACKS = 10;
/// <summary>Maximum number of ACKs to append to a packet</summary>
public int MAX_APPENDED_ACKS = 10;
/// <summary>Cost of uploading an asset</summary>
/*
* Copyright (c) 2006, Second Life Reverse Engineering Team
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the Second Life Reverse Engineering Team nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using libsecondlife.Packets;
namespace libsecondlife
{
/// <summary>
/// Class for controlling various system settings.
/// </summary>
public class Settings
{
/// <summary>The version of libsecondlife (not the SL protocol itself)</summary>
public string VERSION = "libsecondlife 0.0.9";
/// <summary>XML-RPC login server to connect to</summary>
public string LOGIN_SERVER = "https://login.agni.lindenlab.com/cgi-bin/login.cgi";
/// <summary>Millisecond interval between ticks, where all ACKs are
/// sent out and the age of unACKed packets is checked</summary>
public readonly int NETWORK_TICK_LENGTH = 500;
/// <summary>The maximum value of a packet sequence number. After that
/// we assume the sequence number just rolls over? Or maybe the
/// protocol isn't able to sustain a connection past that</summary>
public readonly int MAX_SEQUENCE = 0xFFFFFF;
/// <summary>Number of milliseconds before a teleport attempt will time
/// out</summary>
public readonly int TELEPORT_TIMEOUT = 18 * 1000;
/// <summary>Number of milliseconds before NetworkManager.Logout() will time out</summary>
public int LOGOUT_TIMEOUT = 5 * 1000;
/// <summary>Number of milliseconds for xml-rpc to timeout</summary>
public int LOGIN_TIMEOUT = 30 * 1000;
/// <summary>The maximum size of the sequence number inbox, used to
/// check for resent and/or duplicate packets</summary>
public int INBOX_SIZE = 100;
/// <summary>Milliseconds before a packet is assumed lost and resent</summary>
public int RESEND_TIMEOUT = 4000;
/// <summary>Milliseconds without receiving a packet before the
/// connection to a simulator is assumed lost</summary>
public int SIMULATOR_TIMEOUT = 15 * 1000;
/// <summary>Maximum number of queued ACKs to be sent before SendAcks()
/// is forced</summary>
public int MAX_PENDING_ACKS = 10;
/// <summary>Maximum number of ACKs to append to a packet</summary>
public int MAX_APPENDED_ACKS = 10;
/// <summary>Cost of uploading an asset</summary>
public int UPLOAD_COST { get { return priceUpload; } }
/// <summary>Enable/disable debugging log messages</summary>
public bool DEBUG = true;
private SecondLife Client;
private int priceUpload = 0;
/// <summary>
/// Constructor
/// </summary>
/// <param name="client">Client connection Object to use</param>
public Settings(SecondLife client)
{
Client = client;
Client.Network.RegisterCallback(Packets.PacketType.EconomyData, new NetworkManager.PacketCallback(EconomyDataHandler));
}
/// <summary>
/// Presumably for outputting asset upload costs.
/// </summary>
/// <param name="packet"></param>
/// <param name="simulator"></param>
private void EconomyDataHandler(Packet packet, Simulator simulator)
{
EconomyDataPacket econ = (EconomyDataPacket)packet;
priceUpload = econ.Info.PriceUpload;
}
}
}
public bool DEBUG = true;
private SecondLife Client;
private int priceUpload = 0;
/// <summary>
/// Constructor
/// </summary>
/// <param name="client">Client connection Object to use</param>
public Settings(SecondLife client)
{
Client = client;
Client.Network.RegisterCallback(Packets.PacketType.EconomyData, new NetworkManager.PacketCallback(EconomyDataHandler));
}
/// <summary>
/// Presumably for outputting asset upload costs.
/// </summary>
/// <param name="packet"></param>
/// <param name="simulator"></param>
private void EconomyDataHandler(Packet packet, Simulator simulator)
{
EconomyDataPacket econ = (EconomyDataPacket)packet;
priceUpload = econ.Info.PriceUpload;
}
}
}

View File

@@ -104,6 +104,22 @@ namespace libsecondlife
return retval;
}
/// <summary>
/// Combine two UUIDs together by taking the MD5 hash of a byte array
/// containing both UUIDs
/// </summary>
/// <param name="other">The UUID to combine with this one</param>
/// <returns>The UUID product of the combination</returns>
public LLUUID Combine(LLUUID other)
{
// Build the buffer to MD5
byte[] input = new byte[32];
Array.Copy(data, input, 16);
Array.Copy(other.Data, 0, input, 16, 16);
return new LLUUID(Helpers.MD5Builder.ComputeHash(input), 0);
}
/// <summary>
/// Parse the bytes for a LLUUID from a string
/// </summary>

View File

@@ -206,8 +206,8 @@ namespace libsecondlife.Utilities.Assets
Client.Network.RegisterCallback(PacketType.TransferPacket, new NetworkManager.PacketCallback(TransferPacketHandler));
// Xfer packets for uploading large assets
//Client.Network.RegisterCallback(PacketType.AssetUploadComplete, new NetworkManager.PacketCallback(AssetUploadCompleteHandler));
//Client.Network.RegisterCallback(PacketType.ConfirmXferPacket, new NetworkManager.PacketCallback(ConfirmXferPacketHandler));
Client.Network.RegisterCallback(PacketType.AssetUploadComplete, new NetworkManager.PacketCallback(AssetUploadCompleteHandler));
Client.Network.RegisterCallback(PacketType.ConfirmXferPacket, new NetworkManager.PacketCallback(ConfirmXferPacketHandler));
//Client.Network.RegisterCallback(PacketType.RequestXfer, new NetworkManager.PacketCallback(RequestXferHandler));
}
@@ -289,6 +289,19 @@ namespace libsecondlife.Utilities.Assets
}
public void RequestEstateAsset()
{
throw new Exception("This function is not implemented yet!");
}
/// <summary>
///
/// </summary>
/// <param name="transactionID"></param>
/// <param name="type"></param>
/// <param name="data"></param>
/// <param name="tempFile"></param>
/// <param name="isPriority"></param>
public void RequestUpload(LLUUID transactionID, AssetType type, byte[] data, bool tempFile, bool isPriority)
{
;
}
@@ -424,6 +437,16 @@ namespace libsecondlife.Utilities.Assets
}
}
}
private void AssetUploadCompleteHandler(Packet packet, Simulator simulator)
{
;
}
private void ConfirmXferPacketHandler(Packet packet, Simulator simulator)
{
;
}
}
public class ImageManager