started using BerkeleyDB as local database

standalone
MW 2007-02-16 16:06:40 +00:00
parent b8822e4340
commit 4be3f7c49b
24 changed files with 1549 additions and 248 deletions

View File

@ -26,24 +26,173 @@
*/ */
using System; using System;
using System.Collections.Generic;
using libsecondlife; using libsecondlife;
using libsecondlife.Packets;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Manages Agent details. /// Manages Agent details.
/// </summary> /// </summary>
public class AgentManager public class AgentManager
{ {
public AgentManager() public Dictionary<libsecondlife.LLUUID,AgentProfile> AgentList;
private uint _localNumber=0;
private Server _server;
public AgentManager(Server server)
{ {
_server=server;
this.AgentList = new Dictionary<LLUUID, AgentProfile>();
} }
public AgentName GetAgentName(LLUUID AgentID) public AgentName GetAgentName(LLUUID AgentID)
{ {
AgentName name = new AgentName();
AgentName name;
if(AgentList.ContainsKey(AgentID))
{
name=AgentList[AgentID].Name;
}
else
{
name = new AgentName();
}
return(name); return(name);
} }
public AgentProfile GetAgent(LLUUID id)
{
if(!this.AgentList.ContainsKey(id))
{
return null;
}
else
{
AgentProfile avatar = this.AgentList[id];
return avatar;
}
}
/// <summary>
///
/// </summary>
/// <param name="agent"></param>
public void AddAgent(AgentProfile agent)
{
this.AgentList.Add(agent.Avatar.FullID, agent);
}
/// <summary>
///
/// </summary>
/// <param name="userInfo"></param>
/// <param name="first"></param>
/// <param name="last"></param>
/// <param name="baseFolder"></param>
/// <param name="inventoryFolder"></param>
/// <returns></returns>
public bool NewAgent(NetworkInfo userInfo, string first, string last, LLUUID baseFolder, LLUUID inventoryFolder)
{
Console.WriteLine("new agent called");
AgentProfile agent = new AgentProfile();
agent.Avatar.FullID = userInfo.User.AgentID;
agent.Avatar.NetInfo = userInfo;
agent.Avatar.NetInfo.User.FirstName =first;
agent.Avatar.NetInfo.User.LastName = last;
agent.Avatar.Position = new LLVector3(100, 100, 22);
agent.Avatar.BaseFolder = baseFolder;
agent.Avatar.InventoryFolder = inventoryFolder;
agent.Avatar.LocalID = 8880000 + this._localNumber;
this._localNumber++;
this.AgentList.Add(agent.Avatar.FullID, agent);
//Create new Wearable Assets and place in Inventory
//this.assetManager.CreateNewInventorySet(ref agent, userInfo);
return(true);
}
/// <summary>
///
/// </summary>
/// <param name="UserInfo"></param>
public void RemoveAgent(NetworkInfo userInfo)
{
this.AgentList.Remove(userInfo.User.AgentID);
//tell other clients to delete this avatar
}
/// <summary>
///
/// </summary>
/// <param name="userInfo"></param>
public void AgentJoin(NetworkInfo userInfo)
{
//inform client of join comlete
libsecondlife.Packets.AgentMovementCompletePacket mov = new AgentMovementCompletePacket();
mov.AgentData.SessionID = userInfo.User.SessionID;
mov.AgentData.AgentID = userInfo.User.AgentID;
mov.Data.RegionHandle = Globals.Instance.RegionHandle;
mov.Data.Timestamp = 1169838966;
mov.Data.Position = new LLVector3(100f, 100f, 22f);
mov.Data.LookAt = new LLVector3(0.99f, 0.042f, 0);
_server.SendPacket(mov, true, userInfo);
}
public void RequestWearables(NetworkInfo userInfo)
{
AgentProfile Agent = this.AgentList[userInfo.User.AgentID];
AgentWearablesUpdatePacket aw = new AgentWearablesUpdatePacket();
aw.AgentData.AgentID = userInfo.User.AgentID;
aw.AgentData.SerialNum = 0;
aw.AgentData.SessionID = userInfo.User.SessionID;
aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13];
AgentWearablesUpdatePacket.WearableDataBlock awb = null;
awb = new AgentWearablesUpdatePacket.WearableDataBlock();
awb.WearableType = (byte)0;
awb.AssetID = Agent.Avatar.Wearables[0].AssetID;
awb.ItemID = Agent.Avatar.Wearables[0].ItemID;
aw.WearableData[0] = awb;
awb = new AgentWearablesUpdatePacket.WearableDataBlock();
awb.WearableType =(byte)1;
awb.AssetID = Agent.Avatar.Wearables[1].AssetID;
awb.ItemID = Agent.Avatar.Wearables[1].ItemID;
aw.WearableData[1] = awb;
for(int i=2; i<13; i++)
{
awb = new AgentWearablesUpdatePacket.WearableDataBlock();
awb.WearableType = (byte)i;
awb.AssetID = new LLUUID("00000000-0000-0000-0000-000000000000");
awb.ItemID = new LLUUID("00000000-0000-0000-0000-000000000000");
aw.WearableData[i] = awb;
}
_server.SendPacket(aw, true, userInfo);
}
public void SendPacketToAllExcept(Packet packet, LLUUID exceptAgent)
{
foreach (KeyValuePair<libsecondlife.LLUUID, AgentProfile> kp in this.AgentList)
{
if(kp.Value.Avatar.NetInfo.User.AgentID != exceptAgent)
{
_server.SendPacket(packet, true, kp.Value.Avatar.NetInfo);
}
}
}
public void SendPacketToALL(Packet packet)
{
foreach (KeyValuePair<libsecondlife.LLUUID, AgentProfile> kp in this.AgentList)
{
_server.SendPacket(packet, true, kp.Value.Avatar.NetInfo);
}
}
} }
public struct AgentName public struct AgentName
@ -54,9 +203,74 @@ namespace OpenSimLite
public class AgentProfile public class AgentProfile
{ {
public AgentName Name;
public AvatarData Avatar;
//public AgentInventory Inventory;
public AgentProfile() public AgentProfile()
{
Name = new AgentName();
Avatar = new AvatarData();
}
}
public class AvatarData : Node
{
public NetworkInfo NetInfo;
public LLUUID FullID;
public uint LocalID;
//public LLQuaternion Rotation;
public bool Walk = false;
public bool Started = false;
//public TextureEntry TextureEntry;
public AvatarWearable[] Wearables;
public LLUUID InventoryFolder;
public LLUUID BaseFolder;
public AvatarParams VisParams;
public List<libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock> ObjectUpdateList;
public List<libsecondlife.Packets.ImprovedTerseObjectUpdatePacket.ObjectDataBlock> TerseUpdateList;
public AvatarData()
{
Wearables=new AvatarWearable[2]; //should be 13
for(int i = 0; i < 2; i++)
{
Wearables[i] = new AvatarWearable();
}
this.SceneType = 1; //Avatar type
this.ObjectUpdateList = new List<libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock>();
this.TerseUpdateList = new List<libsecondlife.Packets.ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
VisParams = new AvatarParams();
}
}
public class AvatarWearable
{
public LLUUID AssetID;
public LLUUID ItemID;
public AvatarWearable()
{ {
} }
} }
public class AvatarParams
{
public byte[] Params;
public AvatarParams()
{
Params = new byte [ 218];
for(int i = 0; i < 218; i++)
{
Params[i] = 100;
}
}
}
} }

View File

@ -8,11 +8,11 @@ using System.Runtime.InteropServices;
// change them to the information which is associated with the assembly // change them to the information which is associated with the assembly
// you compile. // you compile.
[assembly: AssemblyTitle("OpenSimLite")] [assembly: AssemblyTitle("OpenSim")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("OpenSim project")] [assembly: AssemblyCompany("OpenSim project")]
[assembly: AssemblyProduct("OpenSimLite")] [assembly: AssemblyProduct("OpenSim")]
[assembly: AssemblyCopyright("(c) OpenSim project")] [assembly: AssemblyCopyright("(c) OpenSim project")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]

View File

@ -30,23 +30,33 @@ using System.Collections.Generic;
using libsecondlife; using libsecondlife;
using libsecondlife.Packets; using libsecondlife.Packets;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Manages local cache of assets and their sending to viewers. /// Manages local cache of assets and their sending to viewers.
/// </summary> /// </summary>
public class AssetManager public class AssetManager : IAssetReceived
{ {
public Dictionary<libsecondlife.LLUUID, AssetInfo> Assets; public Dictionary<libsecondlife.LLUUID, AssetInfo> Assets;
public Dictionary<libsecondlife.LLUUID, TextureImage> Textures; public Dictionary<libsecondlife.LLUUID, TextureImage> Textures;
public List<AssetRequest> AssetRequests = new List<AssetRequest>(); //assets ready to be sent to viewers
public List<TextureRequest> TextureRequests = new List<TextureRequest>(); //textures ready to be sent
public List<AssetRequest> RequestedAssets = new List<AssetRequest>(); //Assets requested from the asset server
public List<TextureRequest> RequestedTextures = new List<TextureRequest>(); //Textures requested from the asset server
private AssetServer _assetServer; private AssetServer _assetServer;
private Server _server;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public AssetManager(AssetServer assetServer) public AssetManager(Server server, AssetServer assetServer)
{ {
_assetServer=assetServer; _server = server;
_assetServer = assetServer;
_assetServer.SetReceiver(this);
} }
/// <summary> /// <summary>
@ -54,15 +64,8 @@ namespace OpenSimLite
/// </summary> /// </summary>
private void RunAssetManager() private void RunAssetManager()
{ {
this.ProcessAssetQueue();
} this.ProcessTextureQueue();
/// <summary>
///
/// </summary>
private void ProcessAssetQueue()
{
} }
/// <summary> /// <summary>
@ -70,9 +73,97 @@ namespace OpenSimLite
/// </summary> /// </summary>
private void ProcessTextureQueue() private void ProcessTextureQueue()
{ {
if(this.TextureRequests.Count == 0)
{
//no requests waiting
return;
}
int num;
//should be running in its own thread but for now is called by timer
if(this.TextureRequests.Count < 5)
{
//lower than 5 so do all of them
num = this.TextureRequests.Count;
}
else
{
num=5;
}
TextureRequest req;
for(int i = 0; i < num; i++)
{
req=(TextureRequest)this.TextureRequests[i];
if(req.PacketCounter == 0)
{
//first time for this request so send imagedata packet
if(req.NumPackets == 1)
{
//only one packet so send whole file
ImageDataPacket im = new ImageDataPacket();
im.ImageID.Packets = 1;
im.ImageID.ID = req.ImageInfo.FullID;
im.ImageID.Size = (uint)req.ImageInfo.Data.Length;
im.ImageData.Data = req.ImageInfo.Data;
im.ImageID.Codec = 2;
_server.SendPacket(im, true, req.RequestUser);
req.PacketCounter++;
//req.ImageInfo.l= time;
//System.Console.WriteLine("sent texture: "+req.image_info.FullID);
}
else
{
//more than one packet so split file up
ImageDataPacket im = new ImageDataPacket();
im.ImageID.Packets = (ushort)req.NumPackets;
im.ImageID.ID = req.ImageInfo.FullID;
im.ImageID.Size = (uint)req.ImageInfo.Data.Length;
im.ImageData.Data = new byte[600];
Array.Copy(req.ImageInfo.Data, 0, im.ImageData.Data, 0, 600);
im.ImageID.Codec = 2;
_server.SendPacket(im, true, req.RequestUser);
req.PacketCounter++;
//req.ImageInfo.last_used = time;
//System.Console.WriteLine("sent first packet of texture:
}
}
else
{
//send imagepacket
//more than one packet so split file up
ImagePacketPacket im = new ImagePacketPacket();
im.ImageID.Packet = (ushort)req.PacketCounter;
im.ImageID.ID = req.ImageInfo.FullID;
int size = req.ImageInfo.Data.Length - 600 - 1000*(req.PacketCounter - 1);
if(size > 1000) size = 1000;
im.ImageData.Data = new byte[size];
Array.Copy(req.ImageInfo.Data, 600 + 1000*(req.PacketCounter - 1), im.ImageData.Data, 0, size);
_server.SendPacket(im, true, req.RequestUser);
req.PacketCounter++;
//req.ImageInfo.last_used = time;
//System.Console.WriteLine("sent a packet of texture: "+req.image_info.FullID);
}
}
//remove requests that have been completed
for(int i = 0; i < num; i++)
{
req=(TextureRequest)this.TextureRequests[i];
if(req.PacketCounter == req.NumPackets)
{
this.TextureRequests.Remove(req);
}
}
} }
public void AssetReceived(AssetBase asset)
{
//check if it is a texture or not
//then add to the correct cache list
//then check for waiting requests for this asset/texture (in the Requested lists)
//and move those requests into the Requests list.
}
#region Assets #region Assets
/// <summary> /// <summary>
/// ///
@ -81,8 +172,32 @@ namespace OpenSimLite
/// <param name="transferRequest"></param> /// <param name="transferRequest"></param>
public void AddAssetRequest(NetworkInfo userInfo, TransferRequestPacket transferRequest) public void AddAssetRequest(NetworkInfo userInfo, TransferRequestPacket transferRequest)
{ {
LLUUID RequestID = new LLUUID(transferRequest.TransferInfo.Params, 0); LLUUID requestID = new LLUUID(transferRequest.TransferInfo.Params, 0);
//check to see if asset is in local cache, if not we need to request it from asset server. //check to see if asset is in local cache, if not we need to request it from asset server.
if(!this.Assets.ContainsKey(requestID))
{
//not found asset
// so request from asset server
AssetRequest request = new AssetRequest();
request.RequestUser = userInfo;
request.RequestImage = requestID;
this.AssetRequests.Add(request);
this._assetServer.RequestAsset(requestID);
return;
}
//it is in our cache
AssetInfo info = this.Assets[requestID];
//work out how many packets it should be sent in
// and add to the AssetRequests list
}
/// <summary>
///
/// </summary>
private void ProcessAssetQueue()
{
} }
#endregion #endregion
@ -96,39 +211,72 @@ namespace OpenSimLite
public void AddTextureRequest(NetworkInfo userInfo, LLUUID imageID) public void AddTextureRequest(NetworkInfo userInfo, LLUUID imageID)
{ {
//check to see if texture is in local cache, if not request from asset server //check to see if texture is in local cache, if not request from asset server
if(!this.Textures.ContainsKey(imageID))
{
/*not found image so send back image not in data base message
ImageNotInDatabasePacket im_not = new ImageNotInDatabasePacket();
im_not.ImageID.ID=imageID;
_server.SendPacket(im_not, true, userInfo);*/
//not is cache so request from asset server
TextureRequest request = new TextureRequest();
request.RequestUser = userInfo;
request.RequestImage = imageID;
this.TextureRequests.Add(request);
this._assetServer.RequestAsset(imageID);
return;
}
TextureImage imag = this.Textures[imageID];
TextureRequest req = new TextureRequest();
req.RequestUser = userInfo;
req.RequestImage = imageID;
req.ImageInfo = imag;
if(imag.Data.LongLength>600)
{
//over 600 bytes so split up file
req.NumPackets = 1 + (int)(imag.Data.Length-600+999)/1000;
}
else
{
req.NumPackets = 1;
}
this.TextureRequests.Add(req);
} }
#endregion #endregion
} }
public class AssetBase public class AssetRequest
{ {
public byte[] Data; public NetworkInfo RequestUser;
public LLUUID FullID; public LLUUID RequestImage;
public sbyte Type; public AssetInfo asset_inf;
public sbyte InvType; public long data_pointer = 0;
public string Name; public int num_packets = 0;
public string Description; public int packet_counter = 0;
public string Filename; //public bool AssetInCache;
//public int TimeRequested;
public AssetBase() public AssetRequest()
{ {
} }
} }
//needed? public class TextureRequest
public class TextureImage
{ {
public TextureImage() public NetworkInfo RequestUser;
{ public LLUUID RequestImage;
public TextureImage ImageInfo;
} public long DataPointer = 0;
} public int NumPackets = 0;
public int PacketCounter = 0;
public class AssetInfo //public bool TextureInCache;
{ //public int TimeRequested;
public AssetInfo()
public TextureRequest()
{ {
} }

View File

@ -26,14 +26,20 @@
*/ */
using System; using System;
using libsecondlife;
using BerkeleyDb;
using Kds.Serialization;
using Kds.Serialization.Buffer;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Handles connection to Asset Server. /// Handles connection to Asset Server.
/// </summary> /// </summary>
public class AssetServer public class AssetServer : IAssetServer
{ {
private IAssetReceived _receiver;
public AssetServer() public AssetServer()
{ {
} }
@ -46,5 +52,71 @@ namespace OpenSimLite
} }
} }
public void SetReceiver(IAssetReceived receiver)
{
this._receiver = receiver;
}
public void RequestAsset(LLUUID assetID)
{
AssetBase asset = null;
byte[] dataBuffer = new byte[4096];
byte[] keyBuffer = new byte[256];
int index;
DbEntry keyEntry;
DbEntry dataEntry;
dataEntry = DbEntry.InOut(dataBuffer, 0, 4096);
index = 0;
BerkeleyDatabases.Instance.dbs.Formatter.Serialize<string>(assetID.ToStringHyphenated(), keyBuffer, ref index);
byte[] co= new byte[44];
Array.Copy(keyBuffer,co,44);
keyEntry = DbEntry.InOut(co, 0, 44);
ReadStatus status = BerkeleyDatabases.Instance.dbs.AssetDb.Get(null, ref keyEntry, ref dataEntry, DbFile.ReadFlags.None);
if (status != ReadStatus.Success)
{
throw new ApplicationException("Read failed");
}
index = 0;
BerkeleyDatabases.Instance.dbs.Formatter.Deserialize<AssetBase>(ref asset, dataEntry.Buffer, ref index);
this._receiver.AssetReceived( asset);
}
public void UpdateAsset(AssetBase asset)
{
//can we use UploadNewAsset to update as well?
this.UploadNewAsset(asset);
}
public void UploadNewAsset(AssetBase asset)
{
byte[] dataBuffer = new byte[4096];
byte[] keyBuffer = new byte[256];
int index;
DbEntry keyEntry;
DbEntry dataEntry;
index = 0;
BerkeleyDatabases.Instance.dbs.Formatter.Serialize<string>(asset.FullID.ToStringHyphenated(), keyBuffer, ref index);
byte[] co= new byte[44];
Array.Copy(keyBuffer,co,44);
keyEntry = DbEntry.InOut(co, 0, 44);
index = 0;
BerkeleyDatabases.Instance.dbs.Formatter.Serialize<AssetBase>(asset, dataBuffer, ref index);
dataEntry = DbEntry.InOut(dataBuffer, 0, index);
WriteStatus status = BerkeleyDatabases.Instance.dbs.AssetDb.Put(null, ref keyEntry, ref dataEntry, DbFile.WriteFlags.None);
if (status != WriteStatus.Success)
throw new ApplicationException("Put failed");
}
}
public interface IAssetServer
{
void SetReceiver(IAssetReceived receiver);
void RequestAsset(LLUUID assetID);
void UpdateAsset(AssetBase asset);
void UploadNewAsset(AssetBase asset);
}
// could change to delegate
public interface IAssetReceived
{
void AssetReceived(AssetBase asset);
} }
} }

105
Assets.cs Normal file
View File

@ -0,0 +1,105 @@
/*
* Copyright (c) OpenSim project, http://sim.opensecondlife.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 libsecondlife;
namespace OpenSim
{
/// <summary>
/// Description of Assets.
/// </summary>
public class AssetBase
{
public byte[] Data;
public LLUUID FullID;
public sbyte Type;
public sbyte InvType;
public string Name;
public string Description;
public string Filename;
public AssetBase()
{
}
}
public class PrimAsset: AssetBase
{
public PrimData PrimData;
public PrimAsset()
{
this.PrimData = new PrimData();
}
}
public class PrimData
{
public LLUUID OwnerID;
public byte PCode;
public byte PathBegin;
public byte PathEnd;
public byte PathScaleX;
public byte PathScaleY;
public byte PathShearX;
public byte PathShearY;
public sbyte PathSkew;
public byte ProfileBegin;
public byte ProfileEnd;
public LLVector3 Scale;
public byte PathCurve;
public byte ProfileCurve;
public uint ParentID=0;
public byte ProfileHollow;
//public bool DataBaseStorage=false;
public PrimData()
{
}
}
//a hangover from the old code, so is it needed for future use?
public class TextureImage: AssetBase
{
public TextureImage()
{
}
}
//a hangover from the old code, so is it needed for future use?
public class AssetInfo :AssetBase
{
public AssetInfo()
{
}
}
}

205
BerkeleyDatabase.cs Normal file
View File

@ -0,0 +1,205 @@
/*
* Copyright (c) OpenSim project, http://sim.opensecondlife.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 libsecondlife;
using BerkeleyDb;
using System.IO;
using Kds.Serialization;
using Kds.Serialization.Buffer;
namespace OpenSim
{
/// <summary>
/// Description of BerkeleyDatabase.
/// </summary>
public class BerkeleyDatabases
{
public const string primDbName = "prim.db";
public const string assetDbName = "asset.db";
// will be initialized on first access to static field in a thread-safe way
private static readonly BerkeleyDatabases instance = new BerkeleyDatabases();
private FileStream errStream;
private string dbDir;
private DbBTree primDb;
private DbBTree assetDb;
// used for key gnerator call-backs, not thread-safe
private BEFormatter formatter;
private byte[] keyBuffer = new byte[2048];
private BerkeleyDatabases() {
formatter = new BEFormatter();
formatter.RegisterField<PrimAsset>(new PrimAssetField(formatter));
formatter.RegisterField<AssetBase>(new AssetBaseField(formatter));
}
~BerkeleyDatabases()
{
this.Close();
}
public BerkeleyDatabases dbs;
// singleton
public static BerkeleyDatabases Instance {
get { return instance; }
}
public void Open(string dbDir, string appName, Stream errStream) {
this.dbDir = dbDir;
//Remove();
// open local prim database
Db db = new Db(DbCreateFlags.None);
db.ErrorPrefix = appName;
db.ErrorStream = errStream;
primDb = (DbBTree)db.Open(null, PrimDbName, null, DbType.BTree, Db.OpenFlags.Create, 0);
//open asset server database
db = new Db(DbCreateFlags.None);
db.ErrorPrefix = appName;
db.ErrorStream = errStream;
assetDb = (DbBTree)db.Open(null, AssetDbName, null, DbType.BTree, Db.OpenFlags.Create, 0);
}
public void Remove() {
try {
Db db = new Db(DbCreateFlags.None);
db.Remove(PrimDbName, null);
}
catch { }
try {
Db db = new Db(DbCreateFlags.None);
db.Remove(AssetDbName, null);
}
catch { }
}
public void Close() {
if (primDb != null) {
primDb.GetDb().Close();
primDb = null;
}
if (assetDb != null) {
assetDb.GetDb().Close();
assetDb = null;
}
}
public BEFormatter Formatter {
get { return formatter; }
}
public string PrimDbName {
get { return Path.Combine(dbDir, primDbName); }
}
public DbBTree PrimDb {
get { return primDb; }
}
public string AssetDbName {
get { return Path.Combine(dbDir, assetDbName); }
}
public DbBTree AssetDb {
get { return assetDb; }
}
public void Startup()
{
dbs = BerkeleyDatabases.Instance;
string dbPath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Db");
string appName = Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
errStream = File.Open(Path.Combine(dbPath, "errors.txt"), FileMode.OpenOrCreate, FileAccess.Write);
dbs.Open(dbPath, appName, errStream);
}
}
public class PrimAssetField: ReferenceField<PrimAsset>
{
public PrimAssetField(Formatter formatter) : base(formatter) { }
protected override void SerializeValue(PrimAsset value) {
Formatter.Serialize<string>(value.Name);
Formatter.Serialize<string>(value.Description);
}
protected override void DeserializeInstance(ref PrimAsset instance) {
if (instance == null)
instance = new PrimAsset();
}
protected override void DeserializeMembers(PrimAsset instance) {
Formatter.Deserialize<string>(ref instance.Name);
Formatter.Deserialize<string>(ref instance.Description);
}
protected override void SkipValue() {
if (Formatter.Skip<string>())
Formatter.Skip<string>();
}
}
public class AssetBaseField: ReferenceField<AssetBase>
{
public AssetBaseField(Formatter formatter) : base(formatter) { }
protected override void SerializeValue(AssetBase value) {
Formatter.Serialize<string>(value.Name);
Formatter.Serialize<string>(value.Description);
}
protected override void DeserializeInstance(ref AssetBase instance) {
if (instance == null)
instance = new AssetBase();
}
protected override void DeserializeMembers(AssetBase instance) {
Formatter.Deserialize<string>(ref instance.Name);
Formatter.Deserialize<string>(ref instance.Description);
}
protected override void SkipValue() {
if (Formatter.Skip<string>())
Formatter.Skip<string>();
}
}
}

View File

@ -31,7 +31,7 @@ using System.Threading;
using libsecondlife; using libsecondlife;
using libsecondlife.Packets; using libsecondlife.Packets;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Hanldes a single clients connection. Runs in own thread. /// Hanldes a single clients connection. Runs in own thread.
@ -40,6 +40,9 @@ namespace OpenSimLite
{ {
public static GridManager Grid; public static GridManager Grid;
public static SceneGraph Scene; public static SceneGraph Scene;
public static AgentManager AgentManager;
public static PrimManager PrimManager;
public byte ConnectionType=1;
private Thread _mthread; private Thread _mthread;
@ -50,6 +53,7 @@ namespace OpenSimLite
public override void Start() public override void Start()
{ {
_mthread = new Thread(new ThreadStart(RunClientRead)); _mthread = new Thread(new ThreadStart(RunClientRead));
_mthread.IsBackground = true;
_mthread.Start(); _mthread.Start();
} }
@ -64,16 +68,45 @@ namespace OpenSimLite
switch(packet.Type) switch(packet.Type)
{ {
case PacketType.UseCircuitCode: case PacketType.UseCircuitCode:
//should be a new user joining Console.WriteLine("new circuit");
Console.WriteLine("new agent"); //should be a new user/circuit joining
// add agents profile to agentmanager
string first = "",last ="";
LLUUID baseFolder = null, inventoryFolder =null;
//rather than use IncomingLogins list, the logon object could be passed to this connection on creation
lock(Globals.Instance.IncomingLogins)
{
for(int i = 0; i < Globals.Instance.IncomingLogins.Count; i++)
{
if(Globals.Instance.IncomingLogins[i].Agent == this.NetInfo.User.AgentID)
{
first = Globals.Instance.IncomingLogins[i].First;
last = Globals.Instance.IncomingLogins[i].Last;
baseFolder = Globals.Instance.IncomingLogins[i].BaseFolder;
inventoryFolder = Globals.Instance.IncomingLogins[i].InventoryFolder;
Globals.Instance.IncomingLogins.RemoveAt(i);
break;
}
}
}
if(first != "")
{
AgentManager.NewAgent(this.NetInfo, first, last, baseFolder, inventoryFolder);
}
break; break;
case PacketType.CompleteAgentMovement: case PacketType.CompleteAgentMovement:
//Agent completing movement to region //Agent completing movement to region
// so send region handshake
Grid.SendRegionData(this.NetInfo); Grid.SendRegionData(this.NetInfo);
// send movmentcomplete reply
Scene.AgentCompletingMove(this.NetInfo);
break; break;
case PacketType.RegionHandshakeReply: case PacketType.RegionHandshakeReply:
Console.WriteLine("RegionHandshake reply"); Console.WriteLine("RegionHandshake reply");
Scene.SendTerrainData(this.NetInfo); Scene.SendTerrainData(this.NetInfo);
Scene.AddNewAvatar(AgentManager.GetAgent(this.NetInfo.User.AgentID).Avatar);
// send current avatars and prims data
break; break;
default: default:
break; break;
@ -82,7 +115,7 @@ namespace OpenSimLite
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e.Message); Console.WriteLine(e.Message + ", So die!");
} }
} }
} }
@ -101,67 +134,5 @@ namespace OpenSimLite
{ {
} }
} }
public class BlockingQueue< T >
{
private Queue< T > _queue = new Queue< T >();
private object _queueSync = new object();
public void Enqueue(T value)
{
lock(_queueSync)
{
_queue.Enqueue(value);
Monitor.Pulse(_queueSync);
}
}
public T Dequeue()
{
lock(_queueSync)
{
if( _queue.Count < 1)
Monitor.Wait(_queueSync);
return _queue.Dequeue();
}
}
}
public class NonBlockingQueue< T >
{
private Queue< T > _queue = new Queue< T >();
private object _queueSync = new object();
public void Enqueue(T value)
{
lock(_queueSync)
{
_queue.Enqueue(value);
}
}
public T Dequeue()
{
T rValue = default(T);
lock(_queueSync)
{
if( _queue.Count > 0)
{
rValue = _queue.Dequeue();
}
}
return rValue;
}
public int Count
{
get
{
return(_queue.Count);
}
}
}
} }

View File

@ -31,7 +31,7 @@ using System.Collections.Generic;
using libsecondlife; using libsecondlife;
using libsecondlife.Packets; using libsecondlife.Packets;
namespace OpenSimLite namespace OpenSim
{ {
class Controller class Controller
{ {
@ -40,29 +40,47 @@ namespace OpenSimLite
private LoginServer _loginServer; private LoginServer _loginServer;
private GridManager _gridManager; private GridManager _gridManager;
private AgentManager _agentManager; private AgentManager _agentManager;
private AssetManager _assetManager;
private SceneGraph _scene; private SceneGraph _scene;
private PrimManager _primManager;
public static void Main(string[] args) public static void Main(string[] args)
{ {
Controller c = new Controller(); Controller c = new Controller();
while( true ) bool Run=true;
System.Threading.Thread.Sleep( 1000 ); while( Run )
{
string input = Console.ReadLine();
if(input == "Exit")
{
Run = false;
}
}
BerkeleyDatabases.Instance.Close();
} }
public Controller() public Controller()
{ {
_viewerServer = new Server();
_backboneServers = new BackboneServers(); _backboneServers = new BackboneServers();
_agentManager = new AgentManager(); _viewerServer = new Server(_backboneServers.UserServer);
_agentManager = new AgentManager(_viewerServer);
_gridManager = new GridManager(_viewerServer, _agentManager); _gridManager = new GridManager(_viewerServer, _agentManager);
_scene = new SceneGraph(_viewerServer); _scene = new SceneGraph(_viewerServer, _agentManager);
_assetManager = new AssetManager(_viewerServer, _backboneServers.AssetServer);
ClientConnection.Grid = _gridManager; ClientConnection.Grid = _gridManager;
ClientConnection.Scene = _scene; ClientConnection.Scene = _scene;
ClientConnection.AgentManager = _agentManager;
_viewerServer.Startup(); _viewerServer.Startup();
BerkeleyDatabases.Instance.Startup();
_primManager = new PrimManager();
if(Globals.Instance.StartLoginServer) if(Globals.Instance.StartLoginServer)
{ {
_loginServer = new LoginServer(); _loginServer = new LoginServer(_backboneServers.UserServer);
_loginServer.Startup(); _loginServer.Startup();
} }

View File

@ -29,7 +29,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using libsecondlife; using libsecondlife;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Description of Globals. /// Description of Globals.

View File

@ -32,7 +32,7 @@ using libsecondlife;
using libsecondlife.Packets; using libsecondlife.Packets;
using System.Collections.Generic; using System.Collections.Generic;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
@ -213,7 +213,7 @@ namespace OpenSimLite
} }
/// <summary> /// <summary>
/// /// most of this should be moved into the grid server class
/// </summary> /// </summary>
private void LoadGrid() private void LoadGrid()
{ {

View File

@ -26,17 +26,33 @@
*/ */
using System; using System;
using libsecondlife;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Handles connection to Grid Servers. /// Handles connection to Grid Servers.
/// also Sim to Sim connections? /// also Sim to Sim connections?
/// </summary> /// </summary>
public class GridServer public class GridServer //:IGridServer
{ {
public GridServer() public GridServer()
{ {
} }
} }
public interface IGridServer
{
bool RequestConnection(RegionInfo myRegion);
UUIDBlock RequestUUIDBlock();
RegionInfo[] RequestNeighbours();
}
public struct UUIDBlock
{
public LLUUID BlockStart;
public LLUUID BlockEnd;
}
} }

View File

@ -27,7 +27,7 @@
using System; using System;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Description of InstantMessaging. /// Description of InstantMessaging.

View File

@ -29,7 +29,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using libsecondlife; using libsecondlife;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Local cache of Inventories /// Local cache of Inventories

46
LocalAssetCache.cs Normal file
View File

@ -0,0 +1,46 @@
/*
* Copyright (c) OpenSim project, http://sim.opensecondlife.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;
namespace OpenSim
{
/// <summary>
/// Description of LocalAssetCache.
/// </summary>
public class LocalAssetCache
{
public LocalAssetCache()
{
}
}
public interface ILocalCacheStorage
{
void SaveAsset(AssetBase asset);
}
}

132
LocalStorageBase.cs Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (c) OpenSim project, http://sim.opensecondlife.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 BerkeleyDb;
using Kds.Serialization;
using Kds.Serialization.Buffer;
using libsecondlife;
namespace OpenSim
{
/// <summary>
/// Description of LocalPrimDB.
/// </summary>
///
public class LocalPrimDb :ILocalPrimStorage
{
public LocalPrimDb()
{
}
public void LoadScene(IPrimReceiver receiver)
{
}
public void CreateNewPrimStorage(PrimAsset prim)
{
byte[] dataBuffer = new byte[4096];
byte[] keyBuffer = new byte[256];
int index;
DbEntry keyEntry;
DbEntry dataEntry;
index = 0;
BerkeleyDatabases.Instance.dbs.Formatter.Serialize<string>(prim.FullID.ToStringHyphenated(), keyBuffer, ref index);
byte[] co= new byte[44];
Array.Copy(keyBuffer,co,44);
keyEntry = DbEntry.InOut(co, 0, 44);
index = 0;
BerkeleyDatabases.Instance.dbs.Formatter.Serialize<PrimAsset>(prim, dataBuffer, ref index);
dataEntry = DbEntry.InOut(dataBuffer, 0, index);
WriteStatus status = BerkeleyDatabases.Instance.dbs.PrimDb.Put(null, ref keyEntry, ref dataEntry, DbFile.WriteFlags.None);
if (status != WriteStatus.Success)
throw new ApplicationException("Put failed");
}
public void UpdatePrimStorage(PrimAsset prim)
{
//can we just use CreateNewPrimStorage to update a prim?
this.CreateNewPrimStorage(prim);
}
public void RemovePrimStorage()
{
}
public PrimAsset GetPrimFromStroage(LLUUID primID)
{
PrimAsset prim = null;
byte[] dataBuffer = new byte[4096];
byte[] keyBuffer = new byte[256];
int index;
DbEntry keyEntry;
DbEntry dataEntry;
dataEntry = DbEntry.InOut(dataBuffer, 0, 4096);
index = 0;
BerkeleyDatabases.Instance.dbs.Formatter.Serialize<string>(primID.ToStringHyphenated(), keyBuffer, ref index);
byte[] co= new byte[44];
Array.Copy(keyBuffer,co,44);
keyEntry = DbEntry.InOut(co, 0, 44);
ReadStatus status = BerkeleyDatabases.Instance.dbs.PrimDb.Get(null, ref keyEntry, ref dataEntry, DbFile.ReadFlags.None);
if (status != ReadStatus.Success)
{
throw new ApplicationException("Read failed");
}
index = 0;
BerkeleyDatabases.Instance.dbs.Formatter.Deserialize<PrimAsset>(ref prim, dataEntry.Buffer, ref index);
return prim;
}
/// <summary>
/// test function
/// </summary>
public void ReadWholedatabase()
{
foreach (KeyDataPair entry in BerkeleyDatabases.Instance.dbs.PrimDb.OpenCursor(null, DbFileCursor.CreateFlags.None)) {
PrimAsset vendor = null;
int index = entry.Data.Start;
BerkeleyDatabases.Instance.dbs.Formatter.Deserialize<PrimAsset>(ref vendor, entry.Data.Buffer, ref index);
Console.WriteLine("prim found: "+vendor.Name + " "+ vendor.Description);
}
}
}
public interface ILocalPrimStorage
{
void LoadScene(IPrimReceiver receiver);
void CreateNewPrimStorage(PrimAsset prim);
void UpdatePrimStorage(PrimAsset prim);
void RemovePrimStorage();
PrimAsset GetPrimFromStroage(LLUUID primID);
}
//change to delegate?
public interface IPrimReceiver
{
void ReceivePrim(PrimAsset prim);
}
}

View File

@ -37,18 +37,19 @@ using System.Collections;
using System.Xml; using System.Xml;
using libsecondlife; using libsecondlife;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// When running in local (default) mode , handles client logins. /// When running in local (default) mode , handles client logins.
/// </summary> /// </summary>
public class LoginServer public class LoginServer
{ {
public LoginServer() public LoginServer(UserServer userServer)
{ {
_userServer = userServer;
} }
private Logon _login; private Logon _login;
private UserServer _userServer;
private ushort _loginPort = Globals.Instance.LoginServerPort; private ushort _loginPort = Globals.Instance.LoginServerPort;
public IPAddress clientAddress = IPAddress.Loopback; public IPAddress clientAddress = IPAddress.Loopback;
public IPAddress remoteAddress = IPAddress.Any; public IPAddress remoteAddress = IPAddress.Any;
@ -58,7 +59,7 @@ namespace OpenSimLite
private string _defaultResponse; private string _defaultResponse;
private string _mpasswd; private string _mpasswd;
private bool _needPassswd=false; private bool _needPasswd=false;
// InitializeLoginProxy: initialize the login proxy // InitializeLoginProxy: initialize the login proxy
private void InitializeLoginProxy() { private void InitializeLoginProxy() {
@ -66,7 +67,7 @@ namespace OpenSimLite
loginServer.Bind(new IPEndPoint(remoteAddress, _loginPort)); loginServer.Bind(new IPEndPoint(remoteAddress, _loginPort));
loginServer.Listen(1); loginServer.Listen(1);
this._needPassswd=Globals.Instance.NeedPasswd; this._needPasswd=Globals.Instance.NeedPasswd;
//read in default response string //read in default response string
StreamReader SR; StreamReader SR;
string lines; string lines;
@ -94,7 +95,7 @@ namespace OpenSimLite
private void RunLoginProxy() private void RunLoginProxy()
{ {
Console.WriteLine("Starting Login Sever"); Console.WriteLine("Starting Login Server");
try try
{ {
for (;;) for (;;)
@ -145,7 +146,7 @@ namespace OpenSimLite
{ {
// read one line of the header // read one line of the header
line = reader.ReadLine(); line = reader.ReadLine();
// check for premature EOF // check for premature EOF
if (line == null) if (line == null)
throw new Exception("EOF in client HTTP header"); throw new Exception("EOF in client HTTP header");
@ -157,7 +158,6 @@ namespace OpenSimLite
} while (line != ""); } while (line != "");
// read the HTTP body into a buffer // read the HTTP body into a buffer
this._login = new Logon();
char[] content = new char[contentLength]; char[] content = new char[contentLength];
reader.Read(content, 0, contentLength); reader.Read(content, 0, contentLength);
@ -180,6 +180,7 @@ namespace OpenSimLite
{ {
first = "test"; first = "test";
} }
if(requestData.Contains("last")) if(requestData.Contains("last"))
{ {
last = (string)requestData["last"]; last = (string)requestData["last"];
@ -188,6 +189,7 @@ namespace OpenSimLite
{ {
last = "User"+NumClients.ToString(); last = "User"+NumClients.ToString();
} }
if(requestData.Contains("passwd")) if(requestData.Contains("passwd"))
{ {
passwd = (string)requestData["passwd"]; passwd = (string)requestData["passwd"];
@ -235,6 +237,7 @@ namespace OpenSimLite
CustomiseLoginResponse( responseData, first, last ); CustomiseLoginResponse( responseData, first, last );
this._login = new Logon();
//copy data to login object //copy data to login object
_login.First = first; _login.First = first;
_login.Last = last; _login.Last = last;
@ -243,9 +246,10 @@ namespace OpenSimLite
_login.BaseFolder = BaseFolderID; _login.BaseFolder = BaseFolderID;
_login.InventoryFolder = InventoryFolderID; _login.InventoryFolder = InventoryFolderID;
lock(Globals.Instance.IncomingLogins) //working on local computer so lets add to the userserver's list of sessions
lock(this._userServer.Sessions)
{ {
Globals.Instance.IncomingLogins.Add(_login); this._userServer.Sessions.Add(_login);
} }
// forward the XML-RPC response to the client // forward the XML-RPC response to the client
@ -279,11 +283,11 @@ namespace OpenSimLite
protected virtual bool Authenticate(string first, string last, string passwd) protected virtual bool Authenticate(string first, string last, string passwd)
{ {
if(this._needPassswd) if(this._needPasswd)
{ {
//every user needs the password to login //every user needs the password to login
string encodedpass = passwd.Remove(0,3); //remove $1$ string encodedPass = passwd.Remove(0,3); //remove $1$
if(encodedpass == this._mpasswd) if(encodedPass == this._mpasswd)
{ {
return true; return true;
} }
@ -294,7 +298,7 @@ namespace OpenSimLite
} }
else else
{ {
//not need password to login //do not need password to login
return true; return true;
} }
} }

View File

@ -1,8 +1,8 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RootNamespace>OpenSimLite</RootNamespace> <RootNamespace>OpenSim</RootNamespace>
<AssemblyName>OpenSimLite</AssemblyName> <AssemblyName>OpenSim</AssemblyName>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{782CCAFD-7313-4638-ADAC-53703DF24DF0}</ProjectGuid> <ProjectGuid>{782CCAFD-7313-4638-ADAC-53703DF24DF0}</ProjectGuid>
@ -31,6 +31,14 @@
<HintPath>bin\Debug\libsecondlife.dll</HintPath> <HintPath>bin\Debug\libsecondlife.dll</HintPath>
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
</Reference> </Reference>
<Reference Include="libdb_dotNET43">
<HintPath>bin\Debug\libdb_dotNET43.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Kds.Serialization">
<HintPath>bin\Debug\Kds.Serialization.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Controller.cs" /> <Compile Include="Controller.cs" />
@ -52,6 +60,10 @@
<Compile Include="InstantMessaging.cs" /> <Compile Include="InstantMessaging.cs" />
<Compile Include="Globals.cs" /> <Compile Include="Globals.cs" />
<Compile Include="Utility.cs" /> <Compile Include="Utility.cs" />
<Compile Include="LocalStorageBase.cs" />
<Compile Include="Assets.cs" />
<Compile Include="LocalAssetCache.cs" />
<Compile Include="BerkeleyDatabase.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project> </Project>

View File

@ -27,7 +27,7 @@
using System; using System;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Description of PhysicsManager. /// Description of PhysicsManager.

View File

@ -26,16 +26,34 @@
*/ */
using System; using System;
using libsecondlife;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Manages and provides local cache of Prims. /// Manages and provides local cache of Prims.
/// </summary> /// </summary>
public class PrimManager public class PrimManager
{ {
private LocalPrimDb _localPrimDB;
public PrimManager() public PrimManager()
{ {
this._localPrimDB = new LocalPrimDb();
//database test
/*PrimAsset prim = new PrimAsset();
prim.Name="happy now";
prim.Description= "test";
prim.FullID = new LLUUID("00000000-0000-0000-0000-000000000008");
this._localPrimDB.CreateNewPrimStorage(prim);
PrimAsset prim1 = this._localPrimDB.GetPrimFromStroage( new LLUUID("00000000-0000-0000-0000-000000000008"));
Console.WriteLine("prim recieved : "+prim1.Name + " "+ prim1.Description);
*/
//this._localPrimDB.ReadWholedatabase();
} }
} }
} }

View File

@ -32,7 +32,7 @@ using System.Threading;
using libsecondlife; using libsecondlife;
using libsecondlife.Packets; using libsecondlife.Packets;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Manages prim and avatar sim positions and movements and updating clients /// Manages prim and avatar sim positions and movements and updating clients
@ -45,7 +45,10 @@ namespace OpenSimLite
private Server _server; private Server _server;
private System.Text.Encoding _enc = System.Text.Encoding.ASCII; private System.Text.Encoding _enc = System.Text.Encoding.ASCII;
private libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock _avatarTemplate; private libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock _avatarTemplate;
private int _objectCount=0;
private UpdateSender _updateSender;
private AgentManager _agentManager;
public NonBlockingQueue<UpdateCommand> Commands; public NonBlockingQueue<UpdateCommand> Commands;
@ -54,21 +57,112 @@ namespace OpenSimLite
private object _sendTerrainSync = new object(); private object _sendTerrainSync = new object();
#endregion #endregion
public SceneGraph(Server server) public SceneGraph(Server server, AgentManager agentManager)
{ {
_server = server; _server = server;
RootNode = new Node(); RootNode = new Node();
_physics = new PhysicsManager(this); _physics = new PhysicsManager(this);
Commands = new NonBlockingQueue<UpdateCommand>(); Commands = new NonBlockingQueue<UpdateCommand>();
Terrain = new Terrain(); Terrain = new Terrain();
_updateSender = new UpdateSender(_server, agentManager);
_agentManager = agentManager;
//testing //testing
this.SetupTemplate("objectupate168.dat"); this.SetupTemplate("objectupate168.dat");
_updateSender.Startup();
} }
public void Update() public void Update()
{ {
// run physics engine to update positions etc since last frame
// process command list
lock(this.Commands) //do we want to stop new commands being added while we process?
{
while(this.Commands.Count > 0)
{
UpdateCommand command = this.Commands.Dequeue();
switch(command.CommandType)
{
case 1:
break;
default:
break;
}
}
}
// check to see if any new avatars have joined since last frame
//if so send data to clients.
lock(this.RootNode)
{
for (int i = 0; i < this.RootNode.ChildrenCount; i++)
{
//for now we will limit avatars to being a child of the rootnode
if(this.RootNode.GetChild(i).SceneType == 1) //check it is a avatar node
{
AvatarData avatar =(AvatarData) this.RootNode.GetChild(i);
int updatemask = avatar.UpdateFlag & (128);
if(updatemask == 128) //is a new avatar?
{
this.SendAvatarDataToAll(avatar);
//should send a avatar appearance to other clients except the avatar's owner
//and send complete scene update to the new avatar's owner
this.SendCompleteSceneTo(avatar);
//reset new avatar flag
//avatar.UpdateFlag -= 128;
}
}
}
}
//send updates to clients
//might be better to do these updates reverse to how is done here
// ie.. loop through the avatars and find objects /other avatars in their range/vision
//instead of looping through all objects/avatars and then finding avatars in range
//but that would mean looping through all objects/avatar for each avatar,
//rather than looping through just the avatars for each object/avatar
lock(this.RootNode)
{
for (int i = 0; i < this.RootNode.ChildrenCount; i++)
{
if(this.RootNode.GetChild(i).SceneType == 1) //check it is a avatar node
{
AvatarData avatar =(AvatarData) this.RootNode.GetChild(i);
int updatemask = avatar.UpdateFlag & (1);
if(updatemask == 1)
{
//avatar has changed velocity
//check what avatars are in range and add to their update lists
//but for now we will say all avatars are in range
for (int n = 0; n < this.RootNode.ChildrenCount; n++)
{
if(this.RootNode.GetChild(n).SceneType == 1) //check it is a avatar node
{
AvatarData avatar2 =(AvatarData) this.RootNode.GetChild(i);
int newmask = avatar2.UpdateFlag & (128);
if(newmask != 128) //is a new avatar?
{
//no its not so let add to its updatelist
avatar2.TerseUpdateList.Add(this.CreateTerseBlock(avatar));
}
}
}
}
}
}
}
//now reset all update flags
lock(this.RootNode)
{
for (int i = 0; i < this.RootNode.ChildrenCount; i++)
{
this.RootNode.GetChild(i).UpdateFlag = 0;
}
}
} }
#region send terrain data #region send terrain data
@ -80,13 +174,15 @@ namespace OpenSimLite
{ {
lock(this._sendTerrainSync) lock(this._sendTerrainSync)
{ {
string data_path = System.AppDomain.CurrentDomain.BaseDirectory + @"\layer_data\"; string data_path = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory ,"layer_data" );
//send layerdata //send layerdata
LayerDataPacket layerpack = new LayerDataPacket(); LayerDataPacket layerpack = new LayerDataPacket();
layerpack.LayerID.Type = 76; layerpack.LayerID.Type = 76;
this.SendLayerData(userInfo, layerpack, data_path+@"layerdata0.dat"); this.SendLayerData(userInfo, layerpack, Path.Combine(data_path,"layerdata0.dat"));
Console.WriteLine("Sent terrain data"); Console.WriteLine("Sent terrain data");
//test
this.SendAvatarData(userInfo); this.SendAvatarData(userInfo);
} }
} }
@ -112,6 +208,32 @@ namespace OpenSimLite
} }
#endregion #endregion
public void AgentCompletingMove(NetworkInfo userInfo)
{
libsecondlife.Packets.AgentMovementCompletePacket mov = new AgentMovementCompletePacket();
mov.AgentData.SessionID = userInfo.User.SessionID;
mov.AgentData.AgentID = userInfo.User.AgentID;
mov.Data.RegionHandle = Globals.Instance.RegionHandle;
mov.Data.Timestamp = 1169838966;
mov.Data.Position = new LLVector3(100f, 100f, 22f);
mov.Data.LookAt = new LLVector3(0.99f, 0.042f, 0);
_server.SendPacket(mov, true, userInfo);
}
public void AddNewAvatar(AvatarData avatar)
{
lock(this.RootNode)
{
avatar.SceneName = "Avatar" + this._objectCount.ToString("00000");
this._objectCount++;
this.RootNode.AddChild(avatar);
}
avatar.UpdateFlag = 128;
//add to new clients list?
}
#region testing #region testing
//test only //test only
private void SendAvatarData(NetworkInfo userInfo) private void SendAvatarData(NetworkInfo userInfo)
@ -132,7 +254,7 @@ namespace OpenSimLite
//userInfo.User.FullName = "FirstName STRING RW SV " + userInfo.first_name + "\nLastName STRING RW SV " + userInfo.last_name + " \0"; //userInfo.User.FullName = "FirstName STRING RW SV " + userInfo.first_name + "\nLastName STRING RW SV " + userInfo.last_name + " \0";
libsecondlife.LLVector3 pos2 = new LLVector3(100f, 100.0f, 22.0f); libsecondlife.LLVector3 pos2 = new LLVector3(100f, 100.0f, 22.0f);
byte[] pb = pos2.GetBytes(); byte[] pb = pos2.GetBytes();
Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length);
//this._localNumber++; //this._localNumber++;
@ -142,7 +264,7 @@ namespace OpenSimLite
//test only //test only
private void SetupTemplate(string name) private void SetupTemplate(string name)
{ {
//should be replaced with completely code generated packets
int i = 0; int i = 0;
FileInfo fInfo = new FileInfo(name); FileInfo fInfo = new FileInfo(name);
long numBytes = fInfo.Length; long numBytes = fInfo.Length;
@ -168,7 +290,44 @@ namespace OpenSimLite
} }
#endregion #endregion
private void SendAvatarDataToAll(AvatarData avatar)
{
ObjectUpdatePacket objupdate = new ObjectUpdatePacket();
objupdate.RegionData.RegionHandle = Globals.Instance.RegionHandle;
objupdate.RegionData.TimeDilation = 0;
objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1];
objupdate.ObjectData[0] = _avatarTemplate;
objupdate.ObjectData[0].ID = avatar.LocalID;
objupdate.ObjectData[0].FullID = avatar.NetInfo.User.AgentID;
objupdate.ObjectData[0].NameValue = _enc.GetBytes("FirstName STRING RW SV " + avatar.NetInfo.User.FirstName + "\nLastName STRING RW SV " + avatar.NetInfo.User.LastName + " \0");
libsecondlife.LLVector3 pos2 = new LLVector3(100f, 100.0f, 22.0f);
byte[] pb = pos2.GetBytes();
Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length);
SendInfo send = new SendInfo();
send.Incr = true;
send.NetInfo = avatar.NetInfo;
send.Packet = objupdate;
send.SentTo = 1; //to all clients
this._updateSender.SendList.Enqueue(send);
}
public void SendCompleteSceneTo(AvatarData avatar)
{
}
public ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateTerseBlock(AvatarData avatar)
{
return(null);
}
public void SendAvatarAppearanceToAllExcept(AvatarData avatar)
{
}
} }
//any need for separate nodes and sceneobjects? //any need for separate nodes and sceneobjects?
@ -176,7 +335,12 @@ namespace OpenSimLite
public class Node public class Node
{ {
private List<Node> _children; private List<Node> _children;
private List<SceneObject> _attached; //private List<SceneObject> _attached;
public byte SceneType;
public string SceneName;
public LLVector3 Position;
public LLVector3 Velocity = new LLVector3(0,0,0);
public byte UpdateFlag;
public List<Node> ChildNodes public List<Node> ChildNodes
{ {
@ -186,6 +350,14 @@ namespace OpenSimLite
} }
} }
public int ChildrenCount
{
get
{
return(_children.Count);
}
}
/*
public List<SceneObject> AttachedObjexts public List<SceneObject> AttachedObjexts
{ {
get get
@ -193,13 +365,13 @@ namespace OpenSimLite
return(_attached); return(_attached);
} }
} }
*/
public Node() public Node()
{ {
_children = new List<Node>(); _children = new List<Node>();
_attached = new List<SceneObject>(); //_attached = new List<SceneObject>();
} }
/*
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@ -252,6 +424,7 @@ namespace OpenSimLite
} }
return(rValue); return(rValue);
} }
*/
/// <summary> /// <summary>
/// ///
@ -289,15 +462,18 @@ namespace OpenSimLite
} }
} }
/*
public class SceneObject public class SceneObject
{ {
public byte SceneType; public byte SceneType;
public string SceneName;
public SceneObject() public SceneObject()
{ {
} }
} }*/
public class Terrain public class Terrain
{ {
@ -326,7 +502,7 @@ namespace OpenSimLite
public class UpdateCommand public class UpdateCommand
{ {
public byte CommandType; public byte CommandType;
public SceneObject SObject; public Node SObject;
public LLVector3 Position; public LLVector3 Position;
public LLVector3 Velocity; public LLVector3 Velocity;
public LLQuaternion Rotation; public LLQuaternion Rotation;
@ -341,29 +517,63 @@ namespace OpenSimLite
{ {
public BlockingQueue<SendInfo> SendList; public BlockingQueue<SendInfo> SendList;
private Thread mthread; private Thread mthread;
private Server _server;
private AgentManager _agentManager;
public UpdateSender() public UpdateSender(Server server, AgentManager agentManager)
{ {
SendList = new BlockingQueue<SendInfo>(); SendList = new BlockingQueue<SendInfo>();
_server = server;
_agentManager = agentManager;
} }
public void Startup() public void Startup()
{ {
mthread = new Thread(new System.Threading.ThreadStart(RunSender)); mthread = new Thread(new System.Threading.ThreadStart(RunSender));
mthread.IsBackground = true;
mthread.Start(); mthread.Start();
} }
private void RunSender() private void RunSender()
{ {
//process SendList and send packets to clients
try
{
for(;;)
{
SendInfo sendInfo;
sendInfo = this.SendList.Dequeue();
switch(sendInfo.SentTo)
{
case 0:
this._server.SendPacket(sendInfo.Packet, sendInfo.Incr, sendInfo.NetInfo);
break;
case 1:
this._agentManager.SendPacketToALL(sendInfo.Packet);
break;
case 2:
this._agentManager.SendPacketToAllExcept(sendInfo.Packet, sendInfo.NetInfo.User.AgentID);
break;
default:
break;
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
} }
} }
public class SendInfo public class SendInfo
{ {
public Packet Packet; public Packet Packet;
public bool Incr; public bool Incr = true;
public NetworkInfo NetInfo; public NetworkInfo NetInfo;
public byte SentTo = 0; // 0 just this client, 1 to all clients, 2 to all except this client.
public SendInfo() public SendInfo()
{ {

View File

@ -27,7 +27,7 @@
using System; using System;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Description of ScriptManager. /// Description of ScriptManager.
@ -39,10 +39,10 @@ namespace OpenSimLite
} }
} }
public interface ScriptPlugin public interface IScriptPlugin
{ {
ScriptObject ICompileScript(string script); ScriptObject CompileScript(string script);
bool IStart(); bool Start();
} }
public interface ScriptObject public interface ScriptObject

View File

@ -26,17 +26,21 @@
*/ */
using System; using System;
using libsecondlife;
using System.Collections.Generic;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Handles connection to User Servers /// Handles connection to User Servers
/// ///
/// </summary> /// </summary>
public class UserServer public class UserServer :IUserServer
{ {
public List<Logon> Sessions = new List<Logon>(); //should change to something other than logon classes?
public UserServer() public UserServer()
{ {
Sessions = new List<Logon>();
} }
private void Initialise() private void Initialise()
@ -47,5 +51,46 @@ namespace OpenSimLite
} }
} }
public AuthenticateResponse AuthenticateSession(LLUUID sessionID, LLUUID agentID, uint circuitCode)
{
//For Grid use:
//should check to see if it is a teleportation, if so then we should be expecting this session, agent. (?)
//if not check with User server/ login server that it is authorised.
//but for now we are running local
AuthenticateResponse user = new AuthenticateResponse();
lock(this.Sessions)
{
for(int i = 0; i < Sessions.Count; i++)
{
if((Sessions[i].Agent == agentID) && (Sessions[i].Session == sessionID))
{
user.Authorised = true;
user.LogonInfo = Sessions[i];
}
}
}
return(user);
}
}
public interface IUserServer
{
AuthenticateResponse AuthenticateSession(LLUUID sessionID, LLUUID agentID, uint circuitCode);
}
public class AuthenticateResponse
{
public bool Authorised;
public Logon LogonInfo;
public AuthenticateResponse()
{
}
} }
} }

View File

@ -27,10 +27,12 @@
using System; using System;
using System.Text; using System.Text;
using System.Collections.Generic;
using System.Threading;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Security.Cryptography; using System.Security.Cryptography;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Description of Utility. /// Description of Utility.
@ -54,4 +56,65 @@ namespace OpenSimLite
return Regex.Replace(BitConverter.ToString(encodedBytes), "-", "").ToLower(); return Regex.Replace(BitConverter.ToString(encodedBytes), "-", "").ToLower();
} }
} }
public class BlockingQueue< T >
{
private Queue< T > _queue = new Queue< T >();
private object _queueSync = new object();
public void Enqueue(T value)
{
lock(_queueSync)
{
_queue.Enqueue(value);
Monitor.Pulse(_queueSync);
}
}
public T Dequeue()
{
lock(_queueSync)
{
if( _queue.Count < 1)
Monitor.Wait(_queueSync);
return _queue.Dequeue();
}
}
}
public class NonBlockingQueue< T >
{
private Queue< T > _queue = new Queue< T >();
private object _queueSync = new object();
public void Enqueue(T value)
{
lock(_queueSync)
{
_queue.Enqueue(value);
}
}
public T Dequeue()
{
T rValue = default(T);
lock(_queueSync)
{
if( _queue.Count > 0)
{
rValue = _queue.Dequeue();
}
}
return rValue;
}
public int Count
{
get
{
return(_queue.Count);
}
}
}
} }

View File

@ -35,7 +35,7 @@ using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Timers; using System.Timers;
namespace OpenSimLite namespace OpenSim
{ {
/// <summary> /// <summary>
/// Manages Viewer connections /// Manages Viewer connections
@ -55,7 +55,7 @@ namespace OpenSimLite
} }
}*/ }*/
//for now though, we will use a slightly adapted version of the server //for now though, we will use a adapted version of the server
// class from version 0.1 // class from version 0.1
public class Server public class Server
{ {
@ -66,6 +66,7 @@ namespace OpenSimLite
/// <summary>The Region class that this Simulator wraps</summary> /// <summary>The Region class that this Simulator wraps</summary>
// public Region Region; // public Region Region;
private object _sendPacketSync = new object();
/// <summary> /// <summary>
/// Used internally to track sim disconnections, do not modify this /// Used internally to track sim disconnections, do not modify this
/// variable /// variable
@ -116,13 +117,14 @@ namespace OpenSimLite
private System.Timers.Timer AckTimer; private System.Timers.Timer AckTimer;
private Server_Settings Settings=new Server_Settings(); private Server_Settings Settings=new Server_Settings();
public ArrayList User_agents=new ArrayList(); public ArrayList User_agents=new ArrayList();
private IUserServer _userServer;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public Server() public Server(IUserServer userServer)
{ {
this._userServer = userServer;
} }
/// <summary> /// <summary>
@ -207,110 +209,113 @@ namespace OpenSimLite
/// <param name="incrementSequence">Increment sequence number?</param> /// <param name="incrementSequence">Increment sequence number?</param>
public void SendPacket(Packet packet, bool incrementSequence, NetworkInfo User_info) public void SendPacket(Packet packet, bool incrementSequence, NetworkInfo User_info)
{ {
byte[] buffer; lock(this._sendPacketSync)
int bytes;
if (!connected && packet.Type != PacketType.UseCircuitCode)
{ {
// Client.Log("Trying to send a " + packet.Type.ToString() + " packet when the socket is closed", byte[] buffer;
// Helpers.LogLevel.Info); int bytes;
return; if (!connected && packet.Type != PacketType.UseCircuitCode)
}
if (packet.Header.AckList.Length > 0)
{
// Scrub any appended ACKs since all of the ACK handling is done here
packet.Header.AckList = new uint[0];
}
packet.Header.AppendedAcks = false;
// Keep track of when this packet was sent out
packet.TickCount = Environment.TickCount;
if (incrementSequence)
{
// Set the sequence number
lock (SequenceLock)
{ {
if (Sequence > Settings.MAX_SEQUENCE) // Client.Log("Trying to send a " + packet.Type.ToString() + " packet when the socket is closed",
Sequence = 1; // Helpers.LogLevel.Info);
else
Sequence++; return;
packet.Header.Sequence = Sequence;
} }
if (packet.Header.Reliable) if (packet.Header.AckList.Length > 0)
{ {
lock (User_info.NeedAck) // Scrub any appended ACKs since all of the ACK handling is done here
packet.Header.AckList = new uint[0];
}
packet.Header.AppendedAcks = false;
// Keep track of when this packet was sent out
packet.TickCount = Environment.TickCount;
if (incrementSequence)
{
// Set the sequence number
lock (SequenceLock)
{ {
if (!User_info.NeedAck.ContainsKey(packet.Header.Sequence)) if (Sequence > Settings.MAX_SEQUENCE)
{ Sequence = 1;
User_info.NeedAck.Add(packet.Header.Sequence, packet);
}
else else
{ Sequence++;
// Client.Log("Attempted to add a duplicate sequence number (" + packet.Header.Sequence = Sequence;
// 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 if (packet.Header.Reliable)
// delivery to fail
if (!packet.Header.Resent)
{ {
// Append any ACKs that need to be sent out to this packet lock (User_info.NeedAck)
lock (User_info.PendingAcks)
{ {
if (User_info.PendingAcks.Count > 0 && User_info.PendingAcks.Count < Settings.MAX_APPENDED_ACKS && if (!User_info.NeedAck.ContainsKey(packet.Header.Sequence))
packet.Type != PacketType.PacketAck &&
packet.Type != PacketType.LogoutRequest)
{ {
packet.Header.AckList = new uint[User_info.PendingAcks.Count]; User_info.NeedAck.Add(packet.Header.Sequence, packet);
int i = 0; }
else
foreach (uint ack in User_info.PendingAcks.Values) {
{ // Client.Log("Attempted to add a duplicate sequence number (" +
packet.Header.AckList[i] = ack; // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
i++; // packet.Type.ToString(), Helpers.LogLevel.Warning);
} }
}
User_info.PendingAcks.Clear(); // Don't append ACKs to resent packets, in case that's what was causing the
packet.Header.AppendedAcks = true; // delivery to fail
if (!packet.Header.Resent)
{
// Append any ACKs that need to be sent out to this packet
lock (User_info.PendingAcks)
{
if (User_info.PendingAcks.Count > 0 && User_info.PendingAcks.Count < Settings.MAX_APPENDED_ACKS &&
packet.Type != PacketType.PacketAck &&
packet.Type != PacketType.LogoutRequest)
{
packet.Header.AckList = new uint[User_info.PendingAcks.Count];
int i = 0;
foreach (uint ack in User_info.PendingAcks.Values)
{
packet.Header.AckList[i] = ack;
i++;
}
User_info.PendingAcks.Clear();
packet.Header.AppendedAcks = true;
}
} }
} }
} }
} }
}
// Serialize the packet // Serialize the packet
buffer = packet.ToBytes(); buffer = packet.ToBytes();
bytes = buffer.Length; bytes = buffer.Length;
try try
{
// Zerocode if needed
if (packet.Header.Zerocoded)
{ {
lock (ZeroOutBuffer) // Zerocode if needed
if (packet.Header.Zerocoded)
{ {
bytes = Helpers.ZeroEncode(buffer, bytes, ZeroOutBuffer); lock (ZeroOutBuffer)
Connection.SendTo(ZeroOutBuffer, bytes, SocketFlags.None,User_info.endpoint); {
bytes = Helpers.ZeroEncode(buffer, bytes, ZeroOutBuffer);
Connection.SendTo(ZeroOutBuffer, bytes, SocketFlags.None,User_info.endpoint);
}
}
else
{
Connection.SendTo(buffer, bytes, SocketFlags.None,User_info.endpoint);
} }
} }
else catch (SocketException)
{ {
//Client.Log("Tried to send a " + packet.Type.ToString() + " on a closed socket",
Connection.SendTo(buffer, bytes, SocketFlags.None,User_info.endpoint); // Helpers.LogLevel.Warning);
}
}
catch (SocketException)
{
//Client.Log("Tried to send a " + packet.Type.ToString() + " on a closed socket",
// Helpers.LogLevel.Warning);
Disconnect(); Disconnect();
}
} }
} }
@ -425,6 +430,23 @@ namespace OpenSimLite
{ {
//new connection //new connection
UseCircuitCodePacket cir_pack=(UseCircuitCodePacket)packet; UseCircuitCodePacket cir_pack=(UseCircuitCodePacket)packet;
//should check that this session/circuit is authorised
AuthenticateResponse sessionInfo = this._userServer.AuthenticateSession(cir_pack.CircuitCode.SessionID, cir_pack.CircuitCode.ID, cir_pack.CircuitCode.Code);
if(!sessionInfo.Authorised)
{
//session/circuit not authorised
//so do something about it
}
else
{
//is authorised so add the logon object to the incominglogin list
//should be a better way of doing this now the login server connects to the user server
// like passing the logon object straight to the ClientConnection
lock(Globals.Instance.IncomingLogins)
{
Globals.Instance.IncomingLogins.Add(sessionInfo.LogonInfo);
}
}
NetworkInfo new_user=new NetworkInfo(); NetworkInfo new_user=new NetworkInfo();
new_user.CircuitCode=cir_pack.CircuitCode.Code; new_user.CircuitCode=cir_pack.CircuitCode.Code;
new_user.User.AgentID=cir_pack.CircuitCode.ID; new_user.User.AgentID=cir_pack.CircuitCode.ID;