2007-03-22 10:11:15 +00:00
/ *
Copyright ( c ) OpenSim project , http : //osgrid.org/
*
* 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 .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* * Neither the name of the < organization > 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 < copyright holder > ` ` 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 < copyright holder > 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 ;
using System.Collections.Generic ;
using libsecondlife ;
using libsecondlife.Packets ;
2007-04-17 12:03:52 +00:00
using Nwc.XmlRpc ;
2007-03-22 10:11:15 +00:00
using System.Net ;
using System.Net.Sockets ;
using System.IO ;
using System.Threading ;
using System.Timers ;
using OpenSim.Framework.Interfaces ;
2007-04-25 13:03:48 +00:00
using OpenSim.Framework.Types ;
2007-03-22 10:11:15 +00:00
using OpenSim.Framework.Inventory ;
using OpenSim.Framework.Utilities ;
using OpenSim.world ;
using OpenSim.Assets ;
namespace OpenSim
{
2007-03-31 21:18:05 +00:00
public delegate bool PacketMethod ( SimClient simClient , Packet packet ) ;
2007-03-22 10:11:15 +00:00
/// <summary>
/// Handles new client connections
/// Constructor takes a single Packet and authenticates everything
/// </summary>
2007-05-15 15:05:13 +00:00
public partial class SimClient
2007-03-22 10:11:15 +00:00
{
public LLUUID AgentID ;
public LLUUID SessionID ;
public LLUUID SecureSessionID = LLUUID . Zero ;
2007-04-17 12:03:52 +00:00
public bool m_child ;
2007-03-22 10:11:15 +00:00
public uint CircuitCode ;
public world . Avatar ClientAvatar ;
private UseCircuitCodePacket cirpack ;
2007-04-17 01:38:20 +00:00
public Thread ClientThread ;
2007-04-17 12:03:52 +00:00
public EndPoint userEP ;
public LLVector3 startpos ;
2007-03-22 10:11:15 +00:00
private BlockingQueue < QueItem > PacketQueue ;
private Dictionary < uint , uint > PendingAcks = new Dictionary < uint , uint > ( ) ;
private Dictionary < uint , Packet > NeedAck = new Dictionary < uint , Packet > ( ) ;
//private Dictionary<LLUUID, AssetBase> UploadedAssets = new Dictionary<LLUUID, AssetBase>();
private System . Timers . Timer AckTimer ;
private uint Sequence = 0 ;
private object SequenceLock = new object ( ) ;
private const int MAX_APPENDED_ACKS = 10 ;
private const int RESEND_TIMEOUT = 4000 ;
private const int MAX_SEQUENCE = 0xFFFFFF ;
2007-03-25 17:34:58 +00:00
private AgentAssetUpload UploadAssets ;
2007-03-22 10:11:15 +00:00
private LLUUID newAssetFolder = LLUUID . Zero ;
2007-03-30 15:51:38 +00:00
private bool debug = false ;
2007-03-27 21:42:14 +00:00
private World m_world ;
private Dictionary < uint , SimClient > m_clientThreads ;
private AssetCache m_assetCache ;
private IGridServer m_gridServer ;
2007-03-28 18:10:52 +00:00
private IUserServer m_userServer = null ;
2007-05-16 15:46:22 +00:00
private OpenSimNetworkHandler m_networkServer ;
2007-03-27 21:42:14 +00:00
private InventoryCache m_inventoryCache ;
2007-04-17 12:03:52 +00:00
public bool m_sandboxMode ;
2007-03-30 12:12:33 +00:00
private int cachedtextureserial = 0 ;
2007-04-17 12:03:52 +00:00
private RegionInfo m_regionData ;
2007-03-22 10:11:15 +00:00
2007-04-01 10:19:21 +00:00
protected static Dictionary < PacketType , PacketMethod > PacketHandlers = new Dictionary < PacketType , PacketMethod > ( ) ; //Global/static handlers for all clients
2007-03-28 18:10:52 +00:00
2007-04-01 10:19:21 +00:00
protected Dictionary < PacketType , PacketMethod > m_packetHandlers = new Dictionary < PacketType , PacketMethod > ( ) ; //local handlers for this instance
2007-04-10 10:45:46 +00:00
2007-03-28 18:10:52 +00:00
public IUserServer UserServer
{
set
{
this . m_userServer = value ;
}
}
2007-04-17 12:03:52 +00:00
public SimClient ( EndPoint remoteEP , UseCircuitCodePacket initialcirpack , World world , Dictionary < uint , SimClient > clientThreads , AssetCache assetCache , IGridServer gridServer , OpenSimNetworkHandler application , InventoryCache inventoryCache , bool sandboxMode , bool child , RegionInfo regionDat )
2007-04-01 10:19:21 +00:00
{
m_world = world ;
m_clientThreads = clientThreads ;
m_assetCache = assetCache ;
m_gridServer = gridServer ;
2007-05-16 15:46:22 +00:00
m_networkServer = application ;
2007-04-01 10:19:21 +00:00
m_inventoryCache = inventoryCache ;
m_sandboxMode = sandboxMode ;
2007-04-17 12:03:52 +00:00
m_child = child ;
m_regionData = regionDat ;
2007-05-16 16:01:01 +00:00
OpenSim . Framework . Console . MainConsole . Instance . WriteLine ( OpenSim . Framework . Console . LogPriority . LOW , "OpenSimClient.cs - Started up new client thread to handle incoming request" ) ;
2007-04-01 10:19:21 +00:00
cirpack = initialcirpack ;
userEP = remoteEP ;
2007-04-17 12:03:52 +00:00
if ( m_gridServer . GetName ( ) = = "Remote" )
{
this . startpos = ( ( RemoteGridBase ) m_gridServer ) . agentcircuits [ initialcirpack . CircuitCode . Code ] . startpos ;
}
else
{
2007-04-22 04:49:12 +00:00
this . startpos = new LLVector3 ( 128 , 128 , m_world . Terrain [ ( int ) 128 , ( int ) 128 ] + 15.0f ) ; // new LLVector3(128.0f, 128.0f, 60f);
2007-04-17 12:03:52 +00:00
}
2007-04-01 10:19:21 +00:00
PacketQueue = new BlockingQueue < QueItem > ( ) ;
this . UploadAssets = new AgentAssetUpload ( this , m_assetCache , m_inventoryCache ) ;
AckTimer = new System . Timers . Timer ( 500 ) ;
AckTimer . Elapsed + = new ElapsedEventHandler ( AckTimer_Elapsed ) ;
AckTimer . Start ( ) ;
this . RegisterLocalPacketHandlers ( ) ;
ClientThread = new Thread ( new ThreadStart ( AuthUser ) ) ;
ClientThread . IsBackground = true ;
ClientThread . Start ( ) ;
}
2007-05-16 16:01:01 +00:00
# region Client Methods
2007-04-17 12:03:52 +00:00
public void UpgradeClient ( )
{
2007-05-16 16:01:01 +00:00
OpenSim . Framework . Console . MainConsole . Instance . WriteLine ( OpenSim . Framework . Console . LogPriority . LOW , "SimClient.cs:UpgradeClient() - upgrading child to full agent" ) ;
2007-04-17 12:03:52 +00:00
this . m_child = false ;
this . m_world . RemoveViewerAgent ( this ) ;
if ( ! this . m_sandboxMode )
{
this . startpos = ( ( RemoteGridBase ) m_gridServer ) . agentcircuits [ CircuitCode ] . startpos ;
( ( RemoteGridBase ) m_gridServer ) . agentcircuits [ CircuitCode ] . child = false ;
}
this . InitNewClient ( ) ;
}
public void DowngradeClient ( )
{
2007-05-16 16:01:01 +00:00
OpenSim . Framework . Console . MainConsole . Instance . WriteLine ( OpenSim . Framework . Console . LogPriority . LOW , "SimClient.cs:UpgradeClient() - changing full agent to child" ) ;
2007-04-17 12:03:52 +00:00
this . m_child = true ;
this . m_world . RemoveViewerAgent ( this ) ;
this . m_world . AddViewerAgent ( this ) ;
}
public void KillClient ( )
{
KillObjectPacket kill = new KillObjectPacket ( ) ;
kill . ObjectData = new KillObjectPacket . ObjectDataBlock [ 1 ] ;
kill . ObjectData [ 0 ] = new KillObjectPacket . ObjectDataBlock ( ) ;
kill . ObjectData [ 0 ] . ID = this . ClientAvatar . localid ;
foreach ( SimClient client in m_clientThreads . Values )
{
client . OutPacket ( kill ) ;
}
if ( this . m_userServer ! = null )
{
this . m_inventoryCache . ClientLeaving ( this . AgentID , this . m_userServer ) ;
}
else
{
this . m_inventoryCache . ClientLeaving ( this . AgentID , null ) ;
}
m_world . RemoveViewerAgent ( this ) ;
m_clientThreads . Remove ( this . CircuitCode ) ;
2007-05-16 15:46:22 +00:00
m_networkServer . RemoveClientCircuit ( this . CircuitCode ) ;
2007-04-17 12:03:52 +00:00
this . ClientThread . Abort ( ) ;
}
2007-05-16 16:01:01 +00:00
# endregion
2007-04-17 12:03:52 +00:00
2007-05-16 16:01:01 +00:00
# region Packet Handling
2007-03-31 21:18:05 +00:00
public static bool AddPacketHandler ( PacketType packetType , PacketMethod handler )
{
bool result = false ;
lock ( PacketHandlers )
{
if ( ! PacketHandlers . ContainsKey ( packetType ) )
{
PacketHandlers . Add ( packetType , handler ) ;
result = true ;
}
}
return result ;
}
2007-04-01 10:19:21 +00:00
public bool AddLocalPacketHandler ( PacketType packetType , PacketMethod handler )
{
bool result = false ;
lock ( m_packetHandlers )
{
if ( ! m_packetHandlers . ContainsKey ( packetType ) )
{
m_packetHandlers . Add ( packetType , handler ) ;
result = true ;
}
}
return result ;
}
2007-03-31 21:18:05 +00:00
protected virtual bool ProcessPacketMethod ( Packet packet )
{
bool result = false ;
bool found = false ;
PacketMethod method ;
2007-04-01 10:19:21 +00:00
if ( m_packetHandlers . TryGetValue ( packet . Type , out method ) )
2007-03-31 21:18:05 +00:00
{
2007-04-01 10:19:21 +00:00
//there is a local handler for this packet type
result = method ( this , packet ) ;
2007-03-31 21:18:05 +00:00
}
2007-04-01 10:19:21 +00:00
else
2007-03-31 21:18:05 +00:00
{
2007-04-01 10:19:21 +00:00
//there is not a local handler so see if there is a Global handler
lock ( PacketHandlers )
{
found = PacketHandlers . TryGetValue ( packet . Type , out method ) ;
}
if ( found )
{
result = method ( this , packet ) ;
}
2007-03-31 21:18:05 +00:00
}
return result ;
}
2007-05-16 16:01:01 +00:00
# endregion
# region Low Level Packet Methods
2007-03-22 10:11:15 +00:00
private void ack_pack ( Packet Pack )
{
2007-04-03 18:47:10 +00:00
if ( Pack . Header . Reliable )
{
libsecondlife . Packets . PacketAckPacket ack_it = new PacketAckPacket ( ) ;
ack_it . Packets = new PacketAckPacket . PacketsBlock [ 1 ] ;
ack_it . Packets [ 0 ] = new PacketAckPacket . PacketsBlock ( ) ;
ack_it . Packets [ 0 ] . ID = Pack . Header . Sequence ;
ack_it . Header . Reliable = false ;
2007-03-22 10:11:15 +00:00
2007-04-03 18:47:10 +00:00
OutPacket ( ack_it ) ;
2007-03-22 10:11:15 +00:00
2007-04-03 18:47:10 +00:00
}
/ *
2007-03-22 10:11:15 +00:00
if ( Pack . Header . Reliable )
{
lock ( PendingAcks )
{
uint sequence = ( uint ) Pack . Header . Sequence ;
if ( ! PendingAcks . ContainsKey ( sequence ) ) { PendingAcks [ sequence ] = sequence ; }
}
2007-04-03 18:47:10 +00:00
} * /
2007-03-22 10:11:15 +00:00
}
private void ResendUnacked ( )
{
int now = Environment . TickCount ;
lock ( NeedAck )
{
foreach ( Packet packet in NeedAck . Values )
{
if ( ( now - packet . TickCount > RESEND_TIMEOUT ) & & ( ! packet . Header . Resent ) )
{
2007-05-16 16:01:01 +00:00
OpenSim . Framework . Console . MainConsole . Instance . WriteLine ( OpenSim . Framework . Console . LogPriority . VERBOSE , "Resending " + packet . Type . ToString ( ) + " packet, " +
2007-03-22 10:11:15 +00:00
( now - packet . TickCount ) + "ms have passed" ) ;
packet . Header . Resent = true ;
OutPacket ( packet ) ;
}
}
}
}
private void SendAcks ( )
{
lock ( PendingAcks )
{
if ( PendingAcks . Count > 0 )
{
if ( PendingAcks . Count > 250 )
{
// FIXME: Handle the odd case where we have too many pending ACKs queued up
2007-05-16 16:01:01 +00:00
OpenSim . Framework . Console . MainConsole . Instance . WriteLine ( OpenSim . Framework . Console . LogPriority . VERBOSE , "Too many ACKs queued up!" ) ;
2007-03-22 10:11:15 +00:00
return ;
}
2007-04-04 11:06:39 +00:00
//OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Sending PacketAck");
2007-03-22 10:11:15 +00:00
int i = 0 ;
PacketAckPacket acks = new PacketAckPacket ( ) ;
acks . Packets = new PacketAckPacket . PacketsBlock [ PendingAcks . Count ] ;
foreach ( uint ack in PendingAcks . Values )
{
acks . Packets [ i ] = new PacketAckPacket . PacketsBlock ( ) ;
acks . Packets [ i ] . ID = ack ;
i + + ;
}
acks . Header . Reliable = false ;
OutPacket ( acks ) ;
PendingAcks . Clear ( ) ;
}
}
}
private void AckTimer_Elapsed ( object sender , ElapsedEventArgs ea )
{
SendAcks ( ) ;
ResendUnacked ( ) ;
}
2007-05-16 16:01:01 +00:00
# endregion
#region Packet Queue Processing
2007-03-22 10:11:15 +00:00
protected virtual void ProcessOutPacket ( Packet Pack )
{
// Keep track of when this packet was sent out
Pack . TickCount = Environment . TickCount ;
if ( ! Pack . Header . Resent )
{
// Set the sequence number
lock ( SequenceLock )
{
if ( Sequence > = MAX_SEQUENCE )
Sequence = 1 ;
else
Sequence + + ;
Pack . Header . Sequence = Sequence ;
}
if ( Pack . Header . Reliable ) //DIRTY HACK
{
lock ( NeedAck )
{
if ( ! NeedAck . ContainsKey ( Pack . Header . Sequence ) )
{
2007-04-22 17:31:51 +00:00
try
{
NeedAck . Add ( Pack . Header . Sequence , Pack ) ;
}
2007-04-22 18:48:45 +00:00
catch ( Exception e ) // HACKY
2007-04-22 17:31:51 +00:00
{
2007-04-22 18:48:45 +00:00
e . ToString ( ) ;
2007-04-22 17:31:51 +00:00
// Ignore
// Seems to throw a exception here occasionally
// of 'duplicate key' despite being locked.
// !?!?!?
}
2007-03-22 10:11:15 +00:00
}
else
{
// Client.Log("Attempted to add a duplicate sequence number (" +
// packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
// packet.Type.ToString(), Helpers.LogLevel.Warning);
}
}
// Don't append ACKs to resent packets, in case that's what was causing the
// delivery to fail
if ( ! Pack . Header . Resent )
{
// Append any ACKs that need to be sent out to this packet
lock ( PendingAcks )
{
if ( PendingAcks . Count > 0 & & PendingAcks . Count < MAX_APPENDED_ACKS & &
Pack . Type ! = PacketType . PacketAck & &
Pack . Type ! = PacketType . LogoutRequest )
{
Pack . Header . AckList = new uint [ PendingAcks . Count ] ;
int i = 0 ;
foreach ( uint ack in PendingAcks . Values )
{
Pack . Header . AckList [ i ] = ack ;
i + + ;
}
PendingAcks . Clear ( ) ;
Pack . Header . AppendedAcks = true ;
}
}
}
}
}
byte [ ] ZeroOutBuffer = new byte [ 4096 ] ;
byte [ ] sendbuffer ;
sendbuffer = Pack . ToBytes ( ) ;
try
{
if ( Pack . Header . Zerocoded )
{
int packetsize = Helpers . ZeroEncode ( sendbuffer , sendbuffer . Length , ZeroOutBuffer ) ;
2007-05-16 15:46:22 +00:00
m_networkServer . SendPacketTo ( ZeroOutBuffer , packetsize , SocketFlags . None , CircuitCode ) ; //userEP);
2007-03-22 10:11:15 +00:00
}
else
{
2007-05-16 15:46:22 +00:00
m_networkServer . SendPacketTo ( sendbuffer , sendbuffer . Length , SocketFlags . None , CircuitCode ) ; //userEP);
2007-03-22 10:11:15 +00:00
}
}
catch ( Exception )
{
2007-05-16 16:01:01 +00:00
OpenSim . Framework . Console . MainConsole . Instance . WriteLine ( OpenSim . Framework . Console . LogPriority . MEDIUM , "OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP . ToString ( ) + " - killing thread" ) ;
2007-03-22 10:11:15 +00:00
ClientThread . Abort ( ) ;
}
}
2007-03-31 21:18:05 +00:00
public virtual void InPacket ( Packet NewPack )
2007-03-22 10:11:15 +00:00
{
// Handle appended ACKs
if ( NewPack . Header . AppendedAcks )
{
lock ( NeedAck )
{
foreach ( uint ack in NewPack . Header . AckList )
{
NeedAck . Remove ( ack ) ;
}
}
}
// Handle PacketAck packets
if ( NewPack . Type = = PacketType . PacketAck )
{
PacketAckPacket ackPacket = ( PacketAckPacket ) NewPack ;
lock ( NeedAck )
{
foreach ( PacketAckPacket . PacketsBlock block in ackPacket . Packets )
{
NeedAck . Remove ( block . ID ) ;
}
}
}
else if ( ( NewPack . Type = = PacketType . StartPingCheck ) )
{
//reply to pingcheck
libsecondlife . Packets . StartPingCheckPacket startPing = ( libsecondlife . Packets . StartPingCheckPacket ) NewPack ;
libsecondlife . Packets . CompletePingCheckPacket endPing = new CompletePingCheckPacket ( ) ;
endPing . PingID . PingID = startPing . PingID . PingID ;
OutPacket ( endPing ) ;
}
else
{
QueItem item = new QueItem ( ) ;
item . Packet = NewPack ;
item . Incoming = true ;
this . PacketQueue . Enqueue ( item ) ;
}
}
public virtual void OutPacket ( Packet NewPack )
{
QueItem item = new QueItem ( ) ;
item . Packet = NewPack ;
item . Incoming = false ;
this . PacketQueue . Enqueue ( item ) ;
}
protected virtual void ClientLoop ( )
{
2007-05-16 16:01:01 +00:00
OpenSim . Framework . Console . MainConsole . Instance . WriteLine ( OpenSim . Framework . Console . LogPriority . LOW , "OpenSimClient.cs:ClientLoop() - Entered loop" ) ;
2007-03-22 10:11:15 +00:00
while ( true )
{
QueItem nextPacket = PacketQueue . Dequeue ( ) ;
if ( nextPacket . Incoming )
{
//is a incoming packet
ProcessInPacket ( nextPacket . Packet ) ;
}
else
{
//is a out going packet
ProcessOutPacket ( nextPacket . Packet ) ;
}
}
}
2007-05-16 16:01:01 +00:00
# endregion
# region Setup
2007-03-22 10:11:15 +00:00
protected virtual void InitNewClient ( )
{
2007-05-16 16:01:01 +00:00
OpenSim . Framework . Console . MainConsole . Instance . WriteLine ( OpenSim . Framework . Console . LogPriority . LOW , "OpenSimClient.cs:InitNewClient() - Adding viewer agent to world" ) ;
2007-03-31 21:18:05 +00:00
2007-03-27 21:42:14 +00:00
m_world . AddViewerAgent ( this ) ;
world . Entity tempent = m_world . Entities [ this . AgentID ] ;
2007-03-31 21:18:05 +00:00
2007-03-22 10:11:15 +00:00
this . ClientAvatar = ( world . Avatar ) tempent ;
}
protected virtual void AuthUser ( )
{
2007-05-16 16:01:01 +00:00
// AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
2007-05-16 15:46:22 +00:00
AuthenticateResponse sessionInfo = this . m_networkServer . AuthenticateSession ( cirpack . CircuitCode . SessionID , cirpack . CircuitCode . ID , cirpack . CircuitCode . Code ) ;
2007-03-22 10:11:15 +00:00
if ( ! sessionInfo . Authorised )
{
//session/circuit not authorised
2007-05-16 16:01:01 +00:00
OpenSim . Framework . Console . MainConsole . Instance . WriteLine ( OpenSim . Framework . Console . LogPriority . NORMAL , "OpenSimClient.cs:AuthUser() - New user request denied to " + userEP . ToString ( ) ) ;
2007-03-22 10:11:15 +00:00
ClientThread . Abort ( ) ;
}
else
{
2007-05-16 16:01:01 +00:00
OpenSim . Framework . Console . MainConsole . Instance . WriteLine ( OpenSim . Framework . Console . LogPriority . NORMAL , "OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP . ToString ( ) ) ;
2007-03-22 10:11:15 +00:00
//session is authorised
this . AgentID = cirpack . CircuitCode . ID ;
this . SessionID = cirpack . CircuitCode . SessionID ;
this . CircuitCode = cirpack . CircuitCode . Code ;
InitNewClient ( ) ; //shouldn't be called here as we might be a child agent and not want a full avatar
this . ClientAvatar . firstname = sessionInfo . LoginInfo . First ;
this . ClientAvatar . lastname = sessionInfo . LoginInfo . Last ;
if ( sessionInfo . LoginInfo . SecureSession ! = LLUUID . Zero )
{
this . SecureSessionID = sessionInfo . LoginInfo . SecureSession ;
}
// Create Inventory, currently only works for sandbox mode
2007-03-27 21:42:14 +00:00
if ( m_sandboxMode )
2007-03-22 10:11:15 +00:00
{
2007-05-16 15:46:22 +00:00
this . SetupInventory ( sessionInfo ) ;
}
ClientLoop ( ) ;
}
}
2007-05-16 16:01:01 +00:00
# endregion
2007-05-16 15:46:22 +00:00
#region Inventory Creation
2007-05-16 16:01:01 +00:00
private void SetupInventory ( AuthenticateResponse sessionInfo )
2007-05-16 15:46:22 +00:00
{
AgentInventory inventory = null ;
if ( sessionInfo . LoginInfo . InventoryFolder ! = null )
{
inventory = this . CreateInventory ( sessionInfo . LoginInfo . InventoryFolder ) ;
if ( sessionInfo . LoginInfo . BaseFolder ! = null )
{
if ( ! inventory . HasFolder ( sessionInfo . LoginInfo . BaseFolder ) )
2007-03-22 10:11:15 +00:00
{
2007-05-16 15:46:22 +00:00
m_inventoryCache . CreateNewInventoryFolder ( this , sessionInfo . LoginInfo . BaseFolder ) ;
}
this . newAssetFolder = sessionInfo . LoginInfo . BaseFolder ;
AssetBase [ ] inventorySet = m_assetCache . CreateNewInventorySet ( this . AgentID ) ;
if ( inventorySet ! = null )
{
for ( int i = 0 ; i < inventorySet . Length ; i + + )
2007-03-22 10:11:15 +00:00
{
2007-05-16 15:46:22 +00:00
if ( inventorySet [ i ] ! = null )
2007-03-22 10:11:15 +00:00
{
2007-05-16 15:46:22 +00:00
m_inventoryCache . AddNewInventoryItem ( this , sessionInfo . LoginInfo . BaseFolder , inventorySet [ i ] ) ;
2007-03-22 10:11:15 +00:00
}
}
}
}
}
}
2007-03-28 18:10:52 +00:00
private AgentInventory CreateInventory ( LLUUID baseFolder )
2007-03-22 10:11:15 +00:00
{
2007-03-28 18:10:52 +00:00
AgentInventory inventory = null ;
if ( this . m_userServer ! = null )
{
// a user server is set so request the inventory from it
2007-03-29 17:04:24 +00:00
Console . WriteLine ( "getting inventory from user server" ) ;
2007-03-28 18:10:52 +00:00
inventory = m_inventoryCache . FetchAgentsInventory ( this . AgentID , m_userServer ) ;
}
else
{
inventory = new AgentInventory ( ) ;
inventory . AgentID = this . AgentID ;
inventory . CreateRootFolder ( this . AgentID , false ) ;
m_inventoryCache . AddNewAgentsInventory ( inventory ) ;
m_inventoryCache . CreateNewInventoryFolder ( this , baseFolder ) ;
}
return inventory ;
2007-03-22 10:11:15 +00:00
}
2007-03-30 11:09:51 +00:00
private void CreateInventoryItem ( CreateInventoryItemPacket packet )
{
2007-05-11 21:03:11 +00:00
if ( ! ( packet . InventoryBlock . Type = = 3 | | packet . InventoryBlock . Type = = 7 ) )
{
System . Console . WriteLine ( "Attempted to create " + Util . FieldToString ( packet . InventoryBlock . Name ) + " in inventory. Unsupported type" ) ;
return ;
}
//lets try this out with creating a notecard
AssetBase asset = new AssetBase ( ) ;
asset . Name = Util . FieldToString ( packet . InventoryBlock . Name ) ;
asset . Description = Util . FieldToString ( packet . InventoryBlock . Description ) ;
asset . InvType = packet . InventoryBlock . InvType ;
asset . Type = packet . InventoryBlock . Type ;
asset . FullID = LLUUID . Random ( ) ;
switch ( packet . InventoryBlock . Type )
2007-03-30 11:09:51 +00:00
{
2007-05-11 21:03:11 +00:00
case 7 : // Notecard
asset . Data = new byte [ 0 ] ;
break ;
case 3 : // Landmark
String content ;
2007-05-13 12:25:08 +00:00
content = "Landmark version 2\n" ;
2007-05-11 21:03:11 +00:00
content + = "region_id " + m_regionData . SimUUID + "\n" ;
String strPos = String . Format ( "%.2f %.2f %.2f>" ,
this . ClientAvatar . Pos . X ,
this . ClientAvatar . Pos . Y ,
this . ClientAvatar . Pos . Z ) ;
content + = "local_pos " + strPos + "\n" ;
asset . Data = ( new System . Text . ASCIIEncoding ( ) ) . GetBytes ( content ) ;
break ;
default :
break ;
2007-03-30 11:09:51 +00:00
}
2007-05-11 21:03:11 +00:00
m_assetCache . AddAsset ( asset ) ;
m_inventoryCache . AddNewInventoryItem ( this , packet . InventoryBlock . FolderID , asset ) ;
2007-03-30 11:09:51 +00:00
}
2007-05-16 15:46:22 +00:00
# endregion
2007-05-15 21:33:03 +00:00
2007-05-16 16:01:01 +00:00
#region Nested Classes
2007-05-15 21:33:03 +00:00
public class QueItem
{
public QueItem ( )
{
}
public Packet Packet ;
public bool Incoming ;
}
2007-05-16 16:01:01 +00:00
# endregion
2007-03-22 10:11:15 +00:00
}
}