diff --git a/libsecondlife-cs/Helpers.cs b/libsecondlife-cs/Helpers.cs
index 4d4308f0..99f0ef62 100644
--- a/libsecondlife-cs/Helpers.cs
+++ b/libsecondlife-cs/Helpers.cs
@@ -102,6 +102,11 @@ namespace libsecondlife
Transfer = 0x00002000
}
+ /// Provide a single instance of the MD5 class to avoid making
+ /// duplicate copies
+ public static System.Security.Cryptography.MD5 MD5Builder =
+ new System.Security.Cryptography.MD5CryptoServiceProvider();
+
///
/// Converts an unsigned integer to a hexadecimal string
///
@@ -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)
diff --git a/libsecondlife-cs/NetworkManager.cs b/libsecondlife-cs/NetworkManager.cs
index d4ddf618..c81674e6 100644
--- a/libsecondlife-cs/NetworkManager.cs
+++ b/libsecondlife-cs/NetworkManager.cs
@@ -804,6 +804,7 @@ namespace libsecondlife
/// A reference to the old value of CurrentSim
public delegate void CurrentSimChangedCallback(Simulator PreviousSimulator);
+
///
/// Explains why a simulator or the grid disconnected from us
///
@@ -817,40 +818,6 @@ namespace libsecondlife
NetworkTimeout
}
- ///
- /// The permanent UUID for the logged in avatar
- ///
- public LLUUID AgentID;
- ///
- /// A temporary UUID assigned to this session, used for secure
- /// transactions
- ///
- public LLUUID SessionID;
- ///
- /// A string holding a descriptive error on login failure, empty
- /// otherwise
- ///
- public string LoginError;
- ///
- /// The simulator that the logged in avatar is currently occupying
- ///
- public Simulator CurrentSim;
- ///
- /// The capabilities for the current simulator
- ///
- public Caps CurrentCaps;
- ///
- /// The complete dictionary of all the login values returned by the
- /// RPC login server, converted to native data types wherever possible
- ///
- public Dictionary LoginValues = new Dictionary();
- ///
- /// Shows whether the network layer is logged in to the grid or not
- ///
- public bool Connected
- {
- get { return connected; }
- }
///
/// An event for the connection to a simulator other than the currently
@@ -867,22 +834,57 @@ namespace libsecondlife
///
public event CurrentSimChangedCallback OnCurrentSimChanged;
+ ///
+ /// The permanent UUID for the logged in avatar
+ ///
+ public LLUUID AgentID = LLUUID.Zero;
+ ///
+ /// Temporary UUID assigned to this session, used for verifying
+ /// our identity in packets
+ ///
+ public LLUUID SessionID = LLUUID.Zero;
+ ///
+ /// Shared secret UUID that is never sent over the wire
+ ///
+ public LLUUID SecureSessionID = LLUUID.Zero;
+ ///
+ /// String holding a descriptive error on login failure, empty
+ /// otherwise
+ ///
+ public string LoginError = String.Empty;
+ ///
+ /// The simulator that the logged in avatar is currently occupying
+ ///
+ public Simulator CurrentSim = null;
+ ///
+ /// The capabilities for the current simulator
+ ///
+ public Caps CurrentCaps = null;
+ ///
+ /// The complete dictionary of all the login values returned by the
+ /// RPC login server, converted to native data types wherever possible
+ ///
+ public Dictionary LoginValues = new Dictionary();
+
+ ///
+ /// Shows whether the network layer is logged in to the grid or not
+ ///
+ public bool Connected { get { return connected; } }
+
private SecondLife Client;
private Dictionary> Callbacks = new Dictionary>();
private List Simulators = new List();
private System.Timers.Timer DisconnectTimer;
private System.Timers.Timer LogoutTimer;
- private bool connected;
+ private bool connected = false;
private List EventQueueCallbacks = new List();
- private const int NetworkTrafficTimeout = 15000;
-
ManualResetEvent LogoutReplyEvent = new ManualResetEvent(false);
///
- ///
+ /// Default constructor
///
- ///
+ /// Reference to the SecondLife client
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);
}
///
- ///
+ /// 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
///
- ///
- ///
+ /// Packet type to trigger events for
+ /// Callback to fire when a packet of this type
+ /// is received
public void RegisterCallback(PacketType type, PacketCallback callback)
{
if (!Callbacks.ContainsKey(type))
@@ -918,10 +924,12 @@ namespace libsecondlife
}
///
- ///
+ /// 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
///
- ///
- ///
+ /// Packet type this callback is registered with
+ /// Callback to stop firing events for
public void UnregisterCallback(PacketType type, PacketCallback callback)
{
if (!Callbacks.ContainsKey(type))
@@ -945,69 +953,72 @@ namespace libsecondlife
}
///
- ///
+ /// Register a CAPS event handler
///
- ///
+ /// Callback to fire when a CAPS event is received
public void RegisterEventCallback(Caps.EventQueueCallback callback)
{
EventQueueCallbacks.Add(callback);
}
///
- ///
+ /// Send a packet to the simulator the avatar is currently occupying
///
- ///
+ /// Packet to send
public void SendPacket(Packet packet)
{
if (CurrentSim != null && CurrentSim.Connected)
- {
CurrentSim.SendPacket(packet, true);
- }
}
///
- ///
+ /// Send a packet to a specified simulator
///
- ///
- ///
+ /// Packet to send
+ /// Simulator to send the packet to
public void SendPacket(Packet packet, Simulator simulator)
{
if (simulator != null && simulator.Connected)
- {
simulator.SendPacket(packet, true);
- }
}
///
- ///
+ /// Send a raw byte array as a packet to the current simulator
///
- ///
+ /// Byte array containing a packet
/// Whether to set the second, third, and fourth
/// bytes of the payload to the current sequence number
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);
- }
}
///
- /// Use this if you want to login to a specific location
+ /// Send a raw byte array as a packet to the specified simulator
///
- ///
- ///
- ///
- ///
- /// string with a value that can be used in the start field in .DefaultLoginValues()
+ /// Byte array containing a packet
+ /// Simulator to send the packet to
+ /// Whether to set the second, third, and fourth
+ /// bytes of the payload to the current sequence number
+ public void SendPacket(byte[] payload, Simulator simulator, bool setSequence)
+ {
+ if (connected && simulator != null)
+ simulator.SendPacket(payload, setSequence);
+ }
+
+ ///
+ /// Build a start location URI for passing to the Login function
+ ///
+ /// Name of the simulator to start in
+ /// X coordinate to start at
+ /// Y coordinate to start at
+ /// Z coordinate to start at
+ /// String with a URI that can be used to login to a specified
+ /// location
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
///
public void ForceLogout()
{
+ Client.Log("Forcing a logout", Helpers.LogLevel.Info);
+
+ DisconnectTimer.Stop();
+
// Insist on shutdown
LogoutDemandPacket logoutDemand = new LogoutDemandPacket();
logoutDemand.LogoutBlock.SessionID = SessionID;
diff --git a/libsecondlife-cs/Settings.cs b/libsecondlife-cs/Settings.cs
index 80a5297e..0d459bd4 100644
--- a/libsecondlife-cs/Settings.cs
+++ b/libsecondlife-cs/Settings.cs
@@ -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
-{
- ///
- /// Class for controlling various system settings.
- ///
- public class Settings
- {
- /// The version of libsecondlife (not the SL protocol itself)
- public string VERSION = "libsecondlife 0.0.9";
- /// XML-RPC login server to connect to
- public string LOGIN_SERVER = "https://login.agni.lindenlab.com/cgi-bin/login.cgi";
-
- /// Millisecond interval between ticks, where all ACKs are
- /// sent out and the age of unACKed packets is checked
- public readonly int NETWORK_TICK_LENGTH = 500;
- /// 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
- public readonly int MAX_SEQUENCE = 0xFFFFFF;
- /// Number of milliseconds before a teleport attempt will time
- /// out
- public readonly int TELEPORT_TIMEOUT = 18 * 1000;
-
- /// Number of milliseconds before NetworkManager.Logout() will time out
- public int LOGOUT_TIMEOUT = 5 * 1000;
- /// Number of milliseconds for xml-rpc to timeout
- public int LOGIN_TIMEOUT = 30 * 1000;
- /// The maximum size of the sequence number inbox, used to
- /// check for resent and/or duplicate packets
- public int INBOX_SIZE = 100;
- /// Milliseconds before a packet is assumed lost and resent
- public int RESEND_TIMEOUT = 4000;
- /// Milliseconds before the connection to a simulator is
- /// assumed lost
- public int SIMULATOR_TIMEOUT = 15000;
- /// Maximum number of queued ACKs to be sent before SendAcks()
- /// is forced
- public int MAX_PENDING_ACKS = 10;
- /// Maximum number of ACKs to append to a packet
- public int MAX_APPENDED_ACKS = 10;
- /// Cost of uploading an asset
+/*
+ * 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
+{
+ ///
+ /// Class for controlling various system settings.
+ ///
+ public class Settings
+ {
+ /// The version of libsecondlife (not the SL protocol itself)
+ public string VERSION = "libsecondlife 0.0.9";
+ /// XML-RPC login server to connect to
+ public string LOGIN_SERVER = "https://login.agni.lindenlab.com/cgi-bin/login.cgi";
+
+ /// Millisecond interval between ticks, where all ACKs are
+ /// sent out and the age of unACKed packets is checked
+ public readonly int NETWORK_TICK_LENGTH = 500;
+ /// 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
+ public readonly int MAX_SEQUENCE = 0xFFFFFF;
+ /// Number of milliseconds before a teleport attempt will time
+ /// out
+ public readonly int TELEPORT_TIMEOUT = 18 * 1000;
+
+ /// Number of milliseconds before NetworkManager.Logout() will time out
+ public int LOGOUT_TIMEOUT = 5 * 1000;
+ /// Number of milliseconds for xml-rpc to timeout
+ public int LOGIN_TIMEOUT = 30 * 1000;
+ /// The maximum size of the sequence number inbox, used to
+ /// check for resent and/or duplicate packets
+ public int INBOX_SIZE = 100;
+ /// Milliseconds before a packet is assumed lost and resent
+ public int RESEND_TIMEOUT = 4000;
+ /// Milliseconds without receiving a packet before the
+ /// connection to a simulator is assumed lost
+ public int SIMULATOR_TIMEOUT = 15 * 1000;
+ /// Maximum number of queued ACKs to be sent before SendAcks()
+ /// is forced
+ public int MAX_PENDING_ACKS = 10;
+ /// Maximum number of ACKs to append to a packet
+ public int MAX_APPENDED_ACKS = 10;
+ /// Cost of uploading an asset
public int UPLOAD_COST { get { return priceUpload; } }
/// Enable/disable debugging log messages
- public bool DEBUG = true;
-
- private SecondLife Client;
- private int priceUpload = 0;
-
- ///
- /// Constructor
- ///
- /// Client connection Object to use
- public Settings(SecondLife client)
- {
- Client = client;
-
- Client.Network.RegisterCallback(Packets.PacketType.EconomyData, new NetworkManager.PacketCallback(EconomyDataHandler));
- }
-
- ///
- /// Presumably for outputting asset upload costs.
- ///
- ///
- ///
- 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;
+
+ ///
+ /// Constructor
+ ///
+ /// Client connection Object to use
+ public Settings(SecondLife client)
+ {
+ Client = client;
+
+ Client.Network.RegisterCallback(Packets.PacketType.EconomyData, new NetworkManager.PacketCallback(EconomyDataHandler));
+ }
+
+ ///
+ /// Presumably for outputting asset upload costs.
+ ///
+ ///
+ ///
+ private void EconomyDataHandler(Packet packet, Simulator simulator)
+ {
+ EconomyDataPacket econ = (EconomyDataPacket)packet;
+
+ priceUpload = econ.Info.PriceUpload;
+ }
+ }
+}
diff --git a/libsecondlife-cs/Types.cs b/libsecondlife-cs/Types.cs
index 65fadae2..4d48bb2b 100644
--- a/libsecondlife-cs/Types.cs
+++ b/libsecondlife-cs/Types.cs
@@ -104,6 +104,22 @@ namespace libsecondlife
return retval;
}
+ ///
+ /// Combine two UUIDs together by taking the MD5 hash of a byte array
+ /// containing both UUIDs
+ ///
+ /// The UUID to combine with this one
+ /// The UUID product of the combination
+ 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);
+ }
+
///
/// Parse the bytes for a LLUUID from a string
///
diff --git a/libsecondlife-cs/libsecondlife.Utilities/Assets.cs b/libsecondlife-cs/libsecondlife.Utilities/Assets.cs
index 4c46b1f2..e0f27c1a 100644
--- a/libsecondlife-cs/libsecondlife.Utilities/Assets.cs
+++ b/libsecondlife-cs/libsecondlife.Utilities/Assets.cs
@@ -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!");
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ 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