diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index ef00c19b04..246c669f4a 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -1,34 +1,36 @@
The following people have contributed to OpenSim (Thank you
for your effort!)
-Add your name in here if you have committed to OpenSim
-
= Current OpenSim Developers (in very rough order of appearance) =
These folks represent the current core team for OpenSim, and are the
people that make the day to day of OpenSim happen.
+* justincc
+* chi11ken (Genkii)
+* dahlia
+* Melanie Thielker
+* Diva (Crista Lopes, University of California, Irvine)
+* Dan Lake (Intel)
+* Marck
+* Mic Bowman (Intel)
+* BlueWall (James Hughes)
+
+= Core Developers Following the White Rabbit =
+Core developers who have temporarily (we hope) gone chasing the white rabbit.
+They are in all similar to the active core developers, except that they haven't
+been that active lately, so their voting rights are awaiting their come back.
+
* MW (Tribal Media AB)
* Adam Frisby (DeepThink Pty Ltd)
-* MingChen (DeepThink Pty Ltd)
* lbsa71 (Tribal Media AB)
-* Sean Dague / sdague (IBM)
-* Tedd
-* justincc
* Teravus (w3z)
-* Johan Berntsson (3Di)
* Ckrinke (Charles Krinke)
-* chi11ken (Genkii)
-* adjohn (Genkii)
* Dr Scofield aka Dirk Husemann (IBM Research - Zurich)
-* dahlia
* mikem (3Di)
-* Melanie Thielker
* Homer_Horwitz
-* idb (Ian Brown)
-* Diva (Crista Lopes, University of California, Irvine)
* nlin (3Di)
* Arthur Rodrigo S Valadares (IBM)
-* BlueWall (James Hughes)
+* John Hurliman
= Past Open Sim Developers =
These folks are alumns of the OpenSim core group, but are now
@@ -44,6 +46,12 @@ where we are today.
* Dalien
* Darok
* Alondria
+* Sean Dague / sdague (IBM)
+* Tedd
+* MingChen (DeepThink Pty Ltd)
+* adjohn (Genkii)
+* idb (Ian Brown)
+* Johan Berntsson (3Di)
= Additional OpenSim Contributors =
@@ -102,6 +110,7 @@ what it is today.
* Misterblue (Intel)
* Mircea Kitsune
* mpallari
+* MrMonkE
* nornalbion
* Omar Vera Ustariz (IBM)
* openlifegrid.com
diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs
index 6a5d6eb58a..f5492b3050 100644
--- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs
+++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs
@@ -56,15 +56,15 @@ namespace OpenSim.Data.MSSQL
string realm, string storeName)
{
m_Realm = realm;
+
+ m_ConnectionString = connectionString;
if (storeName != String.Empty)
{
- Assembly assem = GetType().Assembly;
- m_ConnectionString = connectionString;
using (SqlConnection conn = new SqlConnection(m_ConnectionString))
{
conn.Open();
- Migration m = new Migration(conn, assem, storeName);
+ Migration m = new Migration(conn, GetType().Assembly, storeName);
m.Update();
}
diff --git a/OpenSim/Data/MSSQL/MSSQLMigration.cs b/OpenSim/Data/MSSQL/MSSQLMigration.cs
index aea31c9eaa..cd395b84d1 100644
--- a/OpenSim/Data/MSSQL/MSSQLMigration.cs
+++ b/OpenSim/Data/MSSQL/MSSQLMigration.cs
@@ -61,7 +61,8 @@ namespace OpenSim.Data.MSSQL
}
catch
{
- // Something went wrong, so we're version 0
+ // Return -1 to indicate table does not exist
+ return -1;
}
}
return version;
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
index 80ec65e246..5155e567e6 100644
--- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
@@ -492,12 +492,11 @@ ELSE
using (SqlConnection conn = new SqlConnection(m_connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
+ conn.Open();
foreach (TaskInventoryItem taskItem in items)
{
cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem));
- conn.Open();
cmd.ExecuteNonQuery();
-
cmd.Parameters.Clear();
}
}
@@ -1154,9 +1153,9 @@ VALUES
PrimitiveBaseShape baseShape = new PrimitiveBaseShape();
baseShape.Scale = new Vector3(
- Convert.ToSingle(shapeRow["ScaleX"]),
- Convert.ToSingle(shapeRow["ScaleY"]),
- Convert.ToSingle(shapeRow["ScaleZ"]));
+ (float)Convert.ToDouble(shapeRow["ScaleX"]),
+ (float)Convert.ToDouble(shapeRow["ScaleY"]),
+ (float)Convert.ToDouble(shapeRow["ScaleZ"]));
// paths
baseShape.PCode = Convert.ToByte(shapeRow["PCode"]);
@@ -1193,8 +1192,11 @@ VALUES
{
}
- if (!(shapeRow["Media"] is System.DBNull))
+ if (!(shapeRow["Media"] is System.DBNull) )
+ {
baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]);
+ }
+
return baseShape;
}
@@ -1573,7 +1575,16 @@ VALUES
parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry));
parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams));
parameters.Add(_Database.CreateParameter("State", s.State));
- parameters.Add(_Database.CreateParameter("Media", null == s.Media ? null : s.Media.ToXml()));
+
+ if(null == s.Media )
+ {
+ parameters.Add(_Database.CreateParameter("Media", DBNull.Value));
+ }
+ else
+ {
+ parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml()));
+ }
+
return parameters.ToArray();
}
diff --git a/OpenSim/Data/MSSQL/Resources/AuthStore.migrations b/OpenSim/Data/MSSQL/Resources/AuthStore.migrations
index 5b90ca3d36..eb9129645f 100644
--- a/OpenSim/Data/MSSQL/Resources/AuthStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/AuthStore.migrations
@@ -22,7 +22,11 @@ COMMIT
BEGIN TRANSACTION
-INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users;
+IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[users]') AND type in (N'U'))
+ INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users;
+
+COMMIT
+
+
-COMMIT
\ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/Avatar.migrations b/OpenSim/Data/MSSQL/Resources/Avatar.migrations
index 759e939caf..5364153363 100644
--- a/OpenSim/Data/MSSQL/Resources/Avatar.migrations
+++ b/OpenSim/Data/MSSQL/Resources/Avatar.migrations
@@ -13,5 +13,28 @@ PRIMARY KEY CLUSTERED
) ON [PRIMARY]
+COMMIT
+
+:VERSION 2
+
+BEGIN TRANSACTION
+
+CREATE TABLE dbo.Tmp_Avatars
+ (
+ PrincipalID uniqueidentifier NOT NULL,
+ [Name] varchar(32) NOT NULL,
+ Value text NOT NULL DEFAULT '',
+ ) ON [PRIMARY]
+ TEXTIMAGE_ON [PRIMARY]
+
+IF EXISTS(SELECT * FROM dbo.Avatars)
+ EXEC('INSERT INTO dbo.Tmp_Avatars (PrincipalID, Name, Value)
+ SELECT PrincipalID, CONVERT(text, Name), Value FROM dbo.Avatars WITH (HOLDLOCK TABLOCKX)')
+
+DROP TABLE dbo.Avatars
+
+EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT'
+
+COMMIT
+
-COMMIT
\ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations b/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations
index f981a91999..4d8ab0f622 100644
--- a/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations
@@ -15,6 +15,8 @@ COMMIT
BEGIN TRANSACTION
-INSERT INTO Friends (PrincipalID, Friend, Flags, Offered) SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends;
+IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[userfriends]') AND type in (N'U'))
+INSERT INTO Friends (PrincipalID, Friend, Flags, Offered)
+SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends;
COMMIT
\ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/GridStore.migrations b/OpenSim/Data/MSSQL/Resources/GridStore.migrations
index d2ca27a071..c6342fcdfd 100644
--- a/OpenSim/Data/MSSQL/Resources/GridStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/GridStore.migrations
@@ -222,4 +222,17 @@ ALTER TABLE [regions] ADD [Token] varchar(255) NOT NULL DEFAULT 0;
COMMIT
+:VERSION 8
+BEGIN TRANSACTION
+ALTER TABLE regions ALTER COLUMN regionName VarChar(128)
+
+DROP INDEX IX_regions_name ON dbo.regions
+ALTER TABLE regions ALTER COLUMN regionName VarChar(128) null
+
+CREATE NONCLUSTERED INDEX IX_regions_name ON dbo.regions
+ (
+ regionName
+ ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+
+COMMIT
\ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations b/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations
index e2a8d5709b..4a3cb27312 100644
--- a/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations
@@ -238,7 +238,10 @@ alter table inventoryitems
COMMIT
-
-
-
+:VERSION 8
+ALTER TABLE inventoryitems
+ADD CONSTRAINT DF_inventoryitems_creatorID
+DEFAULT '00000000-0000-0000-0000-000000000000' FOR creatorID
+
+:GO
\ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/Presence.migrations b/OpenSim/Data/MSSQL/Resources/Presence.migrations
index 35f78e1f52..bcb6328434 100644
--- a/OpenSim/Data/MSSQL/Resources/Presence.migrations
+++ b/OpenSim/Data/MSSQL/Resources/Presence.migrations
@@ -7,14 +7,7 @@ CREATE TABLE [Presence] (
[RegionID] uniqueidentifier NOT NULL,
[SessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
[SecureSessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
-[Online] char(5) NOT NULL DEFAULT 'false',
-[Login] char(16) NOT NULL DEFAULT '0',
-[Logout] char(16) NOT NULL DEFAULT '0',
-[Position] char(64) NOT NULL DEFAULT '<0,0,0>',
-[LookAt] char(64) NOT NULL DEFAULT '<0,0,0>',
-[HomeRegionID] uniqueidentifier NOT NULL,
-[HomePosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>',
-[HomeLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>',
+
)
ON [PRIMARY]
@@ -27,4 +20,12 @@ BEGIN TRANSACTION
CREATE UNIQUE INDEX SessionID ON Presence(SessionID);
CREATE INDEX UserID ON Presence(UserID);
+COMMIT
+
+:VERSION 2
+
+BEGIN TRANSACTION
+
+ALTER TABLE Presence ADD LastSeen DateTime
+
COMMIT
\ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
index e2e8cbb117..340b63dec3 100644
--- a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
@@ -1,4 +1,3 @@
-
:VERSION 1
CREATE TABLE [dbo].[prims](
@@ -926,11 +925,121 @@ ALTER TABLE regionsettings ADD loaded_creation_datetime int NOT NULL default 0
COMMIT
:VERSION 24
--- Added post 0.7
BEGIN TRANSACTION
-ALTER TABLE prims ADD COLUMN MediaURL varchar(255)
-ALTER TABLE primshapes ADD COLUMN Media TEXT
+ALTER TABLE prims ADD MediaURL varchar(255)
+ALTER TABLE primshapes ADD Media TEXT NULL
-COMMIT
\ No newline at end of file
+COMMIT
+
+:VERSION 25
+
+BEGIN TRANSACTION
+CREATE TABLE "regionwindlight" (
+ "region_id" varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000',
+ "water_color_r" [float] NOT NULL DEFAULT '4.000000',
+ "water_color_g" [float] NOT NULL DEFAULT '38.000000',
+ "water_color_b" [float] NOT NULL DEFAULT '64.000000',
+ "water_fog_density_exponent" [float] NOT NULL DEFAULT '4.0',
+ "underwater_fog_modifier" [float] NOT NULL DEFAULT '0.25',
+ "reflection_wavelet_scale_1" [float] NOT NULL DEFAULT '2.0',
+ "reflection_wavelet_scale_2" [float] NOT NULL DEFAULT '2.0',
+ "reflection_wavelet_scale_3" [float] NOT NULL DEFAULT '2.0',
+ "fresnel_scale" [float] NOT NULL DEFAULT '0.40',
+ "fresnel_offset" [float] NOT NULL DEFAULT '0.50',
+ "refract_scale_above" [float] NOT NULL DEFAULT '0.03',
+ "refract_scale_below" [float] NOT NULL DEFAULT '0.20',
+ "blur_multiplier" [float] NOT NULL DEFAULT '0.040',
+ "big_wave_direction_x" [float] NOT NULL DEFAULT '1.05',
+ "big_wave_direction_y" [float] NOT NULL DEFAULT '-0.42',
+ "little_wave_direction_x" [float] NOT NULL DEFAULT '1.11',
+ "little_wave_direction_y" [float] NOT NULL DEFAULT '-1.16',
+ "normal_map_texture" varchar(36) NOT NULL DEFAULT '822ded49-9a6c-f61c-cb89-6df54f42cdf4',
+ "horizon_r" [float] NOT NULL DEFAULT '0.25',
+ "horizon_g" [float] NOT NULL DEFAULT '0.25',
+ "horizon_b" [float] NOT NULL DEFAULT '0.32',
+ "horizon_i" [float] NOT NULL DEFAULT '0.32',
+ "haze_horizon" [float] NOT NULL DEFAULT '0.19',
+ "blue_density_r" [float] NOT NULL DEFAULT '0.12',
+ "blue_density_g" [float] NOT NULL DEFAULT '0.22',
+ "blue_density_b" [float] NOT NULL DEFAULT '0.38',
+ "blue_density_i" [float] NOT NULL DEFAULT '0.38',
+ "haze_density" [float] NOT NULL DEFAULT '0.70',
+ "density_multiplier" [float] NOT NULL DEFAULT '0.18',
+ "distance_multiplier" [float] NOT NULL DEFAULT '0.8',
+ "max_altitude" int NOT NULL DEFAULT '1605',
+ "sun_moon_color_r" [float] NOT NULL DEFAULT '0.24',
+ "sun_moon_color_g" [float] NOT NULL DEFAULT '0.26',
+ "sun_moon_color_b" [float] NOT NULL DEFAULT '0.30',
+ "sun_moon_color_i" [float] NOT NULL DEFAULT '0.30',
+ "sun_moon_position" [float] NOT NULL DEFAULT '0.317',
+ "ambient_r" [float] NOT NULL DEFAULT '0.35',
+ "ambient_g" [float] NOT NULL DEFAULT '0.35',
+ "ambient_b" [float] NOT NULL DEFAULT '0.35',
+ "ambient_i" [float] NOT NULL DEFAULT '0.35',
+ "east_angle" [float] NOT NULL DEFAULT '0.00',
+ "sun_glow_focus" [float] NOT NULL DEFAULT '0.10',
+ "sun_glow_size" [float] NOT NULL DEFAULT '1.75',
+ "scene_gamma" [float] NOT NULL DEFAULT '1.00',
+ "star_brightness" [float] NOT NULL DEFAULT '0.00',
+ "cloud_color_r" [float] NOT NULL DEFAULT '0.41',
+ "cloud_color_g" [float] NOT NULL DEFAULT '0.41',
+ "cloud_color_b" [float] NOT NULL DEFAULT '0.41',
+ "cloud_color_i" [float] NOT NULL DEFAULT '0.41',
+ "cloud_x" [float] NOT NULL DEFAULT '1.00',
+ "cloud_y" [float] NOT NULL DEFAULT '0.53',
+ "cloud_density" [float] NOT NULL DEFAULT '1.00',
+ "cloud_coverage" [float] NOT NULL DEFAULT '0.27',
+ "cloud_scale" [float] NOT NULL DEFAULT '0.42',
+ "cloud_detail_x" [float] NOT NULL DEFAULT '1.00',
+ "cloud_detail_y" [float] NOT NULL DEFAULT '0.53',
+ "cloud_detail_density" [float] NOT NULL DEFAULT '0.12',
+ "cloud_scroll_x" [float] NOT NULL DEFAULT '0.20',
+ "cloud_scroll_x_lock" tinyint NOT NULL DEFAULT '0',
+ "cloud_scroll_y" [float] NOT NULL DEFAULT '0.01',
+ "cloud_scroll_y_lock" tinyint NOT NULL DEFAULT '0',
+ "draw_classic_clouds" tinyint NOT NULL DEFAULT '1',
+ PRIMARY KEY ("region_id")
+)
+
+COMMIT TRANSACTION
+
+:VERSION 26
+
+BEGIN TRANSACTION
+
+ALTER TABLE regionsettings ADD map_tile_ID CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'
+
+COMMIT
+
+:VERSION 27 #---------------------
+
+BEGIN TRANSACTION
+ALTER TABLE land ADD MediaType VARCHAR(32) NOT NULL DEFAULT 'none/none'
+ALTER TABLE land ADD MediaDescription VARCHAR(255) NOT NULL DEFAULT ''
+ALTER TABLE land ADD MediaSize VARCHAR(16) NOT NULL DEFAULT '0,0'
+ALTER TABLE land ADD MediaLoop bit NOT NULL DEFAULT 0
+ALTER TABLE land ADD ObscureMusic bit NOT NULL DEFAULT 0
+ALTER TABLE land ADD ObscureMedia bit NOT NULL DEFAULT 0
+COMMIT
+
+:VERSION 28 #---------------------
+
+BEGIN TRANSACTION
+
+ALTER TABLE prims
+ADD CONSTRAINT DF_prims_CreatorID
+DEFAULT '00000000-0000-0000-0000-000000000000'
+FOR CreatorID
+
+ALTER TABLE prims ALTER COLUMN CreatorID uniqueidentifier NOT NULL
+
+ALTER TABLE primitems
+ADD CONSTRAINT DF_primitems_CreatorID
+DEFAULT '00000000-0000-0000-0000-000000000000'
+FOR CreatorID
+
+ALTER TABLE primitems ALTER COLUMN CreatorID uniqueidentifier NOT NULL
+
+COMMIT
diff --git a/OpenSim/Data/MSSQL/Resources/UserAccount.migrations b/OpenSim/Data/MSSQL/Resources/UserAccount.migrations
index 8534e235c9..a81704dcd6 100644
--- a/OpenSim/Data/MSSQL/Resources/UserAccount.migrations
+++ b/OpenSim/Data/MSSQL/Resources/UserAccount.migrations
@@ -19,7 +19,7 @@ CREATE TABLE [UserAccounts] (
:VERSION 2
BEGIN TRANSACTION
-
+IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[users]') AND type in (N'U'))
INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT [UUID] AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID,
username AS FirstName,
lastname AS LastName,
diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs
index 3dbc215d46..dbd47d392a 100644
--- a/OpenSim/Framework/AgentCircuitData.cs
+++ b/OpenSim/Framework/AgentCircuitData.cs
@@ -151,27 +151,6 @@ namespace OpenSim.Framework
{
}
- ///
- /// Create AgentCircuitData from a Serializable AgentCircuitData
- ///
- ///
- public AgentCircuitData(sAgentCircuitData cAgent)
- {
- AgentID = new UUID(cAgent.AgentID);
- SessionID = new UUID(cAgent.SessionID);
- SecureSessionID = new UUID(cAgent.SecureSessionID);
- startpos = new Vector3(cAgent.startposx, cAgent.startposy, cAgent.startposz);
- firstname = cAgent.firstname;
- lastname = cAgent.lastname;
- circuitcode = cAgent.circuitcode;
- child = cAgent.child;
- InventoryFolder = new UUID(cAgent.InventoryFolder);
- BaseFolder = new UUID(cAgent.BaseFolder);
- CapsPath = cAgent.CapsPath;
- ChildrenCapSeeds = cAgent.ChildrenCapSeeds;
- Viewer = cAgent.Viewer;
- }
-
///
/// Pack AgentCircuitData into an OSDMap for transmission over LLSD XML or LLSD json
///
@@ -369,52 +348,4 @@ namespace OpenSim.Framework
}
- ///
- /// Serializable Agent Circuit Data
- ///
- [Serializable]
- public class sAgentCircuitData
- {
- public Guid AgentID;
- public Guid BaseFolder;
- public string CapsPath = String.Empty;
- public Dictionary ChildrenCapSeeds;
- public bool child;
- public uint circuitcode;
- public string firstname;
- public Guid InventoryFolder;
- public string lastname;
- public Guid SecureSessionID;
- public Guid SessionID;
- public float startposx;
- public float startposy;
- public float startposz;
- public string Viewer;
- public string Channel;
- public string Mac;
- public string Id0;
-
- public sAgentCircuitData()
- {
- }
-
- public sAgentCircuitData(AgentCircuitData cAgent)
- {
- AgentID = cAgent.AgentID.Guid;
- SessionID = cAgent.SessionID.Guid;
- SecureSessionID = cAgent.SecureSessionID.Guid;
- startposx = cAgent.startpos.X;
- startposy = cAgent.startpos.Y;
- startposz = cAgent.startpos.Z;
- firstname = cAgent.firstname;
- lastname = cAgent.lastname;
- circuitcode = cAgent.circuitcode;
- child = cAgent.child;
- InventoryFolder = cAgent.InventoryFolder.Guid;
- BaseFolder = cAgent.BaseFolder.Guid;
- CapsPath = cAgent.CapsPath;
- ChildrenCapSeeds = cAgent.ChildrenCapSeeds;
- Viewer = cAgent.Viewer;
- }
- }
}
diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs
index ce0b2fb784..28fe3ba889 100644
--- a/OpenSim/Framework/ChildAgentDataUpdate.cs
+++ b/OpenSim/Framework/ChildAgentDataUpdate.cs
@@ -62,7 +62,7 @@ namespace OpenSim.Framework
UUID AgentID { get; set; }
OSDMap Pack();
- void Unpack(OSDMap map);
+ void Unpack(OSDMap map, IScene scene);
}
///
@@ -122,7 +122,7 @@ namespace OpenSim.Framework
return args;
}
- public void Unpack(OSDMap args)
+ public void Unpack(OSDMap args, IScene scene)
{
if (args.ContainsKey("region_handle"))
UInt64.TryParse(args["region_handle"].AsString(), out RegionHandle);
@@ -329,6 +329,10 @@ namespace OpenSim.Framework
public string CallbackURI;
+ // These two must have the same Count
+ public List AttachmentObjects;
+ public List AttachmentObjectStates;
+
public virtual OSDMap Pack()
{
m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data");
@@ -441,7 +445,30 @@ namespace OpenSim.Framework
if ((CallbackURI != null) && (!CallbackURI.Equals("")))
args["callback_uri"] = OSD.FromString(CallbackURI);
+ // Attachment objects for fatpack messages
+ if (AttachmentObjects != null)
+ {
+ int i = 0;
+ OSDArray attObjs = new OSDArray(AttachmentObjects.Count);
+ foreach (ISceneObject so in AttachmentObjects)
+ {
+ OSDMap info = new OSDMap(4);
+ info["sog"] = OSD.FromString(so.ToXml2());
+ info["extra"] = OSD.FromString(so.ExtraToXmlString());
+ info["modified"] = OSD.FromBoolean(so.HasGroupChanged);
+ try
+ {
+ info["state"] = OSD.FromString(AttachmentObjectStates[i++]);
+ }
+ catch (IndexOutOfRangeException e)
+ {
+ m_log.WarnFormat("[CHILD AGENT DATA]: scripts list is shorter than object list.");
+ }
+ attObjs.Add(info);
+ }
+ args["attach_objects"] = attObjs;
+ }
return args;
}
@@ -450,7 +477,7 @@ namespace OpenSim.Framework
/// Avoiding reflection makes it painful to write, but that's the price!
///
///
- public virtual void Unpack(OSDMap args)
+ public virtual void Unpack(OSDMap args, IScene scene)
{
m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data");
@@ -628,6 +655,26 @@ namespace OpenSim.Framework
if (args["callback_uri"] != null)
CallbackURI = args["callback_uri"].AsString();
+
+ // Attachment objects
+ if (args["attach_objects"] != null && args["attach_objects"].Type == OSDType.Array)
+ {
+ OSDArray attObjs = (OSDArray)(args["attach_objects"]);
+ AttachmentObjects = new List();
+ AttachmentObjectStates = new List();
+ foreach (OSD o in attObjs)
+ {
+ if (o.Type == OSDType.Map)
+ {
+ OSDMap info = (OSDMap)o;
+ ISceneObject so = scene.DeserializeObject(info["sog"].AsString());
+ so.ExtraFromXmlString(info["extra"].AsString());
+ so.HasGroupChanged = info["modified"].AsBoolean();
+ AttachmentObjects.Add(so);
+ AttachmentObjectStates.Add(info["state"].AsString());
+ }
+ }
+ }
}
public AgentData()
@@ -655,9 +702,9 @@ namespace OpenSim.Framework
return base.Pack();
}
- public override void Unpack(OSDMap map)
+ public override void Unpack(OSDMap map, IScene scene)
{
- base.Unpack(map);
+ base.Unpack(map, scene);
}
}
}
diff --git a/OpenSim/Framework/ClientInfo.cs b/OpenSim/Framework/ClientInfo.cs
index fbd18b5636..62acb70566 100644
--- a/OpenSim/Framework/ClientInfo.cs
+++ b/OpenSim/Framework/ClientInfo.cs
@@ -31,10 +31,9 @@ using System.Net;
namespace OpenSim.Framework
{
- [Serializable]
public class ClientInfo
{
- public sAgentCircuitData agentcircuit;
+ public AgentCircuitData agentcircuit;
public Dictionary needAck;
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index f573c32d07..069987bd71 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -572,34 +572,69 @@ namespace OpenSim.Framework
public class IEntityUpdate
{
- public ISceneEntity Entity;
- public uint Flags;
+ private ISceneEntity m_entity;
+ private uint m_flags;
+ private int m_updateTime;
+
+ public ISceneEntity Entity
+ {
+ get { return m_entity; }
+ }
+
+ public uint Flags
+ {
+ get { return m_flags; }
+ }
+
+ public int UpdateTime
+ {
+ get { return m_updateTime; }
+ }
public virtual void Update(IEntityUpdate update)
{
- this.Flags |= update.Flags;
+ m_flags |= update.Flags;
+
+ // Use the older of the updates as the updateTime
+ if (Util.EnvironmentTickCountCompare(UpdateTime, update.UpdateTime) > 0)
+ m_updateTime = update.UpdateTime;
}
public IEntityUpdate(ISceneEntity entity, uint flags)
{
- Entity = entity;
- Flags = flags;
+ m_entity = entity;
+ m_flags = flags;
+ m_updateTime = Util.EnvironmentTickCount();
+ }
+
+ public IEntityUpdate(ISceneEntity entity, uint flags, Int32 updateTime)
+ {
+ m_entity = entity;
+ m_flags = flags;
+ m_updateTime = updateTime;
}
}
-
public class EntityUpdate : IEntityUpdate
{
- // public ISceneEntity Entity;
- // public PrimUpdateFlags Flags;
- public float TimeDilation;
+ private float m_timeDilation;
+
+ public float TimeDilation
+ {
+ get { return m_timeDilation; }
+ }
public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation)
- : base(entity,(uint)flags)
+ : base(entity, (uint)flags)
{
- //Entity = entity;
// Flags = flags;
- TimeDilation = timedilation;
+ m_timeDilation = timedilation;
+ }
+
+ public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation, Int32 updateTime)
+ : base(entity,(uint)flags,updateTime)
+ {
+ m_timeDilation = timedilation;
}
}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs
similarity index 61%
rename from OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
rename to OpenSim/Framework/PriorityQueue.cs
index b62ec07ed9..3e6fdaa7f9 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
+++ b/OpenSim/Framework/PriorityQueue.cs
@@ -34,50 +34,81 @@ using OpenSim.Framework;
using OpenSim.Framework.Client;
using log4net;
-namespace OpenSim.Region.ClientStack.LindenUDP
+namespace OpenSim.Framework
{
public class PriorityQueue
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
+ public delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
- // Heap[0] for self updates
- // Heap[1..12] for entity updates
+ ///
+ /// Total number of queues (priorities) available
+ ///
+ public const uint NumberOfQueues = 12;
- internal const uint m_numberOfQueues = 12;
+ ///
+ /// Number of queuest (priorities) that are processed immediately
+ /// [] m_heaps = new MinHeap[m_numberOfQueues];
+ private MinHeap[] m_heaps = new MinHeap[NumberOfQueues];
private Dictionary m_lookupTable;
+
+ // internal state used to ensure the deqeues are spread across the priority
+ // queues "fairly". queuecounts is the amount to pull from each queue in
+ // each pass. weighted towards the higher priority queues
private uint m_nextQueue = 0;
+ private uint m_countFromQueue = 0;
+ private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 };
+
+ // next request is a counter of the number of updates queued, it provides
+ // a total ordering on the updates coming through the queue and is more
+ // lightweight (and more discriminating) than tick count
private UInt64 m_nextRequest = 0;
+ ///
+ /// Lock for enqueue and dequeue operations on the priority queue
+ ///
private object m_syncRoot = new object();
public object SyncRoot {
get { return this.m_syncRoot; }
}
- internal PriorityQueue() : this(MinHeap.DEFAULT_CAPACITY) { }
+#region constructor
+ public PriorityQueue() : this(MinHeap.DEFAULT_CAPACITY) { }
- internal PriorityQueue(int capacity)
+ public PriorityQueue(int capacity)
{
m_lookupTable = new Dictionary(capacity);
for (int i = 0; i < m_heaps.Length; ++i)
m_heaps[i] = new MinHeap(capacity);
- }
- internal int Count
+ m_nextQueue = NumberOfImmediateQueues;
+ m_countFromQueue = m_queueCounts[m_nextQueue];
+ }
+#endregion Constructor
+
+#region PublicMethods
+ ///
+ /// Return the number of items in the queues
+ ///
+ public int Count
{
get
{
int count = 0;
for (int i = 0; i < m_heaps.Length; ++i)
count += m_heaps[i].Count;
+
return count;
}
}
+ ///
+ /// Enqueue an item into the specified priority queue
+ ///
public bool Enqueue(uint pqueue, IEntityUpdate value)
{
LookupItem lookup;
@@ -91,7 +122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
lookup.Heap.Remove(lookup.Handle);
}
- pqueue = Util.Clamp(pqueue, 0, m_numberOfQueues - 1);
+ pqueue = Util.Clamp(pqueue, 0, NumberOfQueues - 1);
lookup.Heap = m_heaps[pqueue];
lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
m_lookupTable[localid] = lookup;
@@ -99,20 +130,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return true;
}
- internal bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
+ ///
+ /// Remove an item from one of the queues. Specifically, it removes the
+ /// oldest item from the next queue in order to provide fair access to
+ /// all of the queues
+ ///
+ public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
{
- for (int i = 0; i < m_numberOfQueues; ++i)
+ // If there is anything in priority queue 0, return it first no
+ // matter what else. Breaks fairness. But very useful.
+ for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
{
- // To get the fair queing, we cycle through each of the
- // queues when finding an element to dequeue, this code
- // assumes that the distribution of updates in the queues
- // is polynomial, probably quadractic (eg distance of PI * R^2)
- uint h = (uint)((m_nextQueue + i) % m_numberOfQueues);
- if (m_heaps[h].Count > 0)
+ if (m_heaps[iq].Count > 0)
{
- m_nextQueue = (uint)((h + 1) % m_numberOfQueues);
+ MinHeapItem item = m_heaps[iq].RemoveMin();
+ m_lookupTable.Remove(item.Value.Entity.LocalId);
+ timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
+ value = item.Value;
- MinHeapItem item = m_heaps[h].RemoveMin();
+ return true;
+ }
+ }
+
+ // To get the fair queing, we cycle through each of the
+ // queues when finding an element to dequeue.
+ // We pull (NumberOfQueues - QueueIndex) items from each queue in order
+ // to give lower numbered queues a higher priority and higher percentage
+ // of the bandwidth.
+
+ // Check for more items to be pulled from the current queue
+ if (m_heaps[m_nextQueue].Count > 0 && m_countFromQueue > 0)
+ {
+ m_countFromQueue--;
+
+ MinHeapItem item = m_heaps[m_nextQueue].RemoveMin();
+ m_lookupTable.Remove(item.Value.Entity.LocalId);
+ timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
+ value = item.Value;
+
+ return true;
+ }
+
+ // Find the next non-immediate queue with updates in it
+ for (int i = 0; i < NumberOfQueues; ++i)
+ {
+ m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues);
+ m_countFromQueue = m_queueCounts[m_nextQueue];
+
+ // if this is one of the immediate queues, just skip it
+ if (m_nextQueue < NumberOfImmediateQueues)
+ continue;
+
+ if (m_heaps[m_nextQueue].Count > 0)
+ {
+ m_countFromQueue--;
+
+ MinHeapItem item = m_heaps[m_nextQueue].RemoveMin();
m_lookupTable.Remove(item.Value.Entity.LocalId);
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
value = item.Value;
@@ -126,7 +199,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return false;
}
- internal void Reprioritize(UpdatePriorityHandler handler)
+ ///
+ /// Reapply the prioritization function to each of the updates currently
+ /// stored in the priority queues.
+ /// (this.m_lookupTable.Values))
@@ -140,7 +217,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
// unless the priority queue has changed, there is no need to modify
// the entry
- pqueue = Util.Clamp(pqueue, 0, m_numberOfQueues - 1);
+ pqueue = Util.Clamp(pqueue, 0, NumberOfQueues - 1);
if (pqueue != item.PriorityQueue)
{
lookup.Heap.Remove(lookup.Handle);
@@ -161,17 +238,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
+ ///
+ ///
public override string ToString()
{
string s = "";
- for (int i = 0; i < m_numberOfQueues; i++)
- {
- if (s != "") s += ",";
- s += m_heaps[i].Count.ToString();
- }
+ for (int i = 0; i < NumberOfQueues; i++)
+ s += String.Format("{0,7} ",m_heaps[i].Count);
return s;
}
+#endregion PublicMethods
+
#region MinHeapItem
private struct MinHeapItem : IComparable
{
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
index e7f8bfc1f0..76de6be267 100644
--- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
+++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
@@ -115,7 +115,7 @@ namespace OpenSim.Framework.Tests
position2 = new AgentPosition();
Assert.IsFalse(position2.AgentID == position1.AgentID, "Test Error, position2 should be a blank uninitialized AgentPosition");
- position2.Unpack(position1.Pack());
+ position2.Unpack(position1.Pack(), null);
Assert.IsTrue(position2.AgentID == position1.AgentID, "Agent ID didn't unpack the same way it packed");
Assert.IsTrue(position2.Position == position1.Position, "Position didn't unpack the same way it packed");
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 5a5046e547..aaa2724532 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -1537,6 +1537,23 @@ namespace OpenSim.Framework
return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
}
+ // Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount
+ // Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount().
+ // A positive return value indicates A occured later than B
+ public static Int32 EnvironmentTickCountCompare(Int32 tcA, Int32 tcB)
+ {
+ // A, B and TC are all between 0 and 0x3fffffff
+ int tc = EnvironmentTickCount();
+
+ if (tc - tcA >= 0)
+ tcA += EnvironmentTickCountMask + 1;
+
+ if (tc - tcB >= 0)
+ tcB += EnvironmentTickCountMask + 1;
+
+ return tcA - tcB;
+ }
+
///
/// Prints the call stack at any given point. Useful for debugging.
///
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index 9d70f63189..ac0828b90e 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -142,17 +142,17 @@ namespace OpenSim.Framework
///
public static OSDMap PutToService(string url, OSDMap data)
{
- return ServiceOSDRequest(url,data,"PUT",10000);
+ return ServiceOSDRequest(url,data,"PUT",30000);
}
public static OSDMap PostToService(string url, OSDMap data)
{
- return ServiceOSDRequest(url,data,"POST",10000);
+ return ServiceOSDRequest(url,data,"POST",30000);
}
public static OSDMap GetFromService(string url)
{
- return ServiceOSDRequest(url,null,"GET",10000);
+ return ServiceOSDRequest(url,null,"GET",30000);
}
public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout)
@@ -171,15 +171,15 @@ namespace OpenSim.Framework
request.Timeout = timeout;
request.KeepAlive = false;
request.MaximumAutomaticRedirections = 10;
- request.ReadWriteTimeout = timeout / 4;
+ request.ReadWriteTimeout = timeout * 8;
request.Headers[OSHeaderRequestID] = reqnum.ToString();
// If there is some input, write it into the request
if (data != null)
{
- string strBuffer = OSDParser.SerializeJsonString(data);
+ string strBuffer = OSDParser.SerializeJsonString(data);
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
-
+
request.ContentType = "application/json";
request.ContentLength = buffer.Length; //Count bytes to send
using (Stream requestStream = request.GetRequestStream())
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 0f7f666c60..43903ce1bd 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -384,6 +384,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
+ ///
+ /// Entity update queues
+ ///
+ public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } }
+
///
/// First name of the agent/avatar represented by the client
///
@@ -3561,6 +3566,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
}
+ ///
+ /// Requeue an EntityUpdate when it was not acknowledged by the client.
+ /// We will update the priority and put it in the correct queue, merging update flags
+ /// with any other updates that may be queued for the same entity.
+ /// The original update time is used for the merged update.
+ ///
+ private void ResendPrimUpdate(EntityUpdate update)
+ {
+ // If the update exists in priority queue, it will be updated.
+ // If it does not exist then it will be added with the current (rather than its original) priority
+ uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity);
+
+ lock (m_entityUpdates.SyncRoot)
+ m_entityUpdates.Enqueue(priority, update);
+ }
+
+ ///
+ /// Requeue a list of EntityUpdates when they were not acknowledged by the client.
+ /// We will update the priority and put it in the correct queue, merging update flags
+ /// with any other updates that may be queued for the same entity.
+ /// The original update time is used for the merged update.
+ ///
+ private void ResendPrimUpdates(List updates, OutgoingPacket oPacket)
+ {
+ // m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime);
+
+ // Remove the update packet from the list of packets waiting for acknowledgement
+ // because we are requeuing the list of updates. They will be resent in new packets
+ // with the most recent state and priority.
+ m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
+
+ // Count this as a resent packet since we are going to requeue all of the updates contained in it
+ Interlocked.Increment(ref m_udpClient.PacketsResent);
+
+ foreach (EntityUpdate update in updates)
+ ResendPrimUpdate(update);
+ }
+
private void ProcessEntityUpdates(int maxUpdates)
{
OpenSim.Framework.Lazy> objectUpdateBlocks = new OpenSim.Framework.Lazy>();
@@ -3568,6 +3611,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OpenSim.Framework.Lazy> terseUpdateBlocks = new OpenSim.Framework.Lazy>();
OpenSim.Framework.Lazy> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy>();
+ OpenSim.Framework.Lazy> objectUpdates = new OpenSim.Framework.Lazy>();
+ OpenSim.Framework.Lazy> compressedUpdates = new OpenSim.Framework.Lazy>();
+ OpenSim.Framework.Lazy> terseUpdates = new OpenSim.Framework.Lazy>();
+ OpenSim.Framework.Lazy> terseAgentUpdates = new OpenSim.Framework.Lazy>();
+
// Check to see if this is a flush
if (maxUpdates <= 0)
{
@@ -3583,7 +3631,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
float avgTimeDilation = 1.0f;
IEntityUpdate iupdate;
Int32 timeinqueue; // this is just debugging code & can be dropped later
-
+
while (updatesThisCall < maxUpdates)
{
lock (m_entityUpdates.SyncRoot)
@@ -3688,24 +3736,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (update.Entity is ScenePresence)
{
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
+ objectUpdates.Value.Add(update);
}
else
{
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
+ objectUpdates.Value.Add(update);
}
}
else if (!canUseImproved)
{
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
+ compressedUpdates.Value.Add(update);
}
else
{
if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
+ {
// Self updates go into a special list
terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
+ terseAgentUpdates.Value.Add(update);
+ }
else
+ {
// Everything else goes here
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
+ terseUpdates.Value.Add(update);
+ }
}
#endregion Block Construction
@@ -3713,28 +3770,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Packet Sending
-
- //const float TIME_DILATION = 1.0f;
-
-
ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
-
+
if (terseAgentUpdateBlocks.IsValueCreated)
{
List blocks = terseAgentUpdateBlocks.Value;
-
+
ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
packet.RegionData.TimeDilation = timeDilation;
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
-
+
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
-
-
- OutPacket(packet, ThrottleOutPacketType.Unknown, true);
+ // If any of the packets created from this call go unacknowledged, all of the updates will be resent
+ OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); });
}
-
+
if (objectUpdateBlocks.IsValueCreated)
{
List blocks = objectUpdateBlocks.Value;
@@ -3746,8 +3798,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
-
- OutPacket(packet, ThrottleOutPacketType.Task, true);
+ // If any of the packets created from this call go unacknowledged, all of the updates will be resent
+ OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
}
if (compressedUpdateBlocks.IsValueCreated)
@@ -3761,10 +3813,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
-
- OutPacket(packet, ThrottleOutPacketType.Task, true);
+ // If any of the packets created from this call go unacknowledged, all of the updates will be resent
+ OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
}
-
+
if (terseUpdateBlocks.IsValueCreated)
{
List blocks = terseUpdateBlocks.Value;
@@ -3776,8 +3828,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
-
- OutPacket(packet, ThrottleOutPacketType.Task, true);
+ // If any of the packets created from this call go unacknowledged, all of the updates will be resent
+ OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
}
}
@@ -3969,7 +4021,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
SendFamilyProps = SendFamilyProps || update.SendFamilyProps;
SendObjectProps = SendObjectProps || update.SendObjectProps;
- Flags |= update.Flags;
+ // other properties may need to be updated by base class
+ base.Update(update);
}
}
@@ -3980,6 +4033,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false));
}
+ private void ResendPropertyUpdate(ObjectPropertyUpdate update)
+ {
+ uint priority = 0;
+ lock (m_entityProps.SyncRoot)
+ m_entityProps.Enqueue(priority, update);
+ }
+
+ private void ResendPropertyUpdates(List updates, OutgoingPacket oPacket)
+ {
+ // m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime);
+
+ // Remove the update packet from the list of packets waiting for acknowledgement
+ // because we are requeuing the list of updates. They will be resent in new packets
+ // with the most recent state.
+ m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
+
+ // Count this as a resent packet since we are going to requeue all of the updates contained in it
+ Interlocked.Increment(ref m_udpClient.PacketsResent);
+
+ foreach (ObjectPropertyUpdate update in updates)
+ ResendPropertyUpdate(update);
+ }
+
public void SendObjectPropertiesReply(ISceneEntity entity)
{
uint priority = 0; // time based ordering only
@@ -3995,6 +4071,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OpenSim.Framework.Lazy> objectPropertiesBlocks =
new OpenSim.Framework.Lazy>();
+ OpenSim.Framework.Lazy> familyUpdates =
+ new OpenSim.Framework.Lazy>();
+
+ OpenSim.Framework.Lazy> propertyUpdates =
+ new OpenSim.Framework.Lazy>();
+
IEntityUpdate iupdate;
Int32 timeinqueue; // this is just debugging code & can be dropped later
@@ -4013,6 +4095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SceneObjectPart sop = (SceneObjectPart)update.Entity;
ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
objectFamilyBlocks.Value.Add(objPropDB);
+ familyUpdates.Value.Add(update);
}
}
@@ -4023,6 +4106,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SceneObjectPart sop = (SceneObjectPart)update.Entity;
ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
objectPropertiesBlocks.Value.Add(objPropDB);
+ propertyUpdates.Value.Add(update);
}
}
@@ -4030,12 +4114,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
- Int32 ppcnt = 0;
- Int32 pbcnt = 0;
+ // Int32 ppcnt = 0;
+ // Int32 pbcnt = 0;
if (objectPropertiesBlocks.IsValueCreated)
{
List blocks = objectPropertiesBlocks.Value;
+ List updates = propertyUpdates.Value;
ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
@@ -4043,28 +4128,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
packet.ObjectData[i] = blocks[i];
packet.Header.Zerocoded = true;
- OutPacket(packet, ThrottleOutPacketType.Task, true);
- pbcnt += blocks.Count;
- ppcnt++;
+ // Pass in the delegate so that if this packet needs to be resent, we send the current properties
+ // of the object rather than the properties when the packet was created
+ OutPacket(packet, ThrottleOutPacketType.Task, true,
+ delegate(OutgoingPacket oPacket)
+ {
+ ResendPropertyUpdates(updates, oPacket);
+ });
+
+ // pbcnt += blocks.Count;
+ // ppcnt++;
}
- Int32 fpcnt = 0;
- Int32 fbcnt = 0;
+ // Int32 fpcnt = 0;
+ // Int32 fbcnt = 0;
if (objectFamilyBlocks.IsValueCreated)
{
List blocks = objectFamilyBlocks.Value;
-
- // ObjectPropertiesFamilyPacket objPropFamilyPack =
- // (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
- //
- // objPropFamilyPack.ObjectData = new ObjectPropertiesFamilyPacket.ObjectDataBlock[blocks.Count];
- // for (int i = 0; i < blocks.Count; i++)
- // objPropFamilyPack.ObjectData[i] = blocks[i];
- //
- // OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task, true);
-
+
// one packet per object block... uggh...
for (int i = 0; i < blocks.Count; i++)
{
@@ -4073,10 +4156,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
packet.ObjectData = blocks[i];
packet.Header.Zerocoded = true;
- OutPacket(packet, ThrottleOutPacketType.Task);
- fpcnt++;
- fbcnt++;
+ // Pass in the delegate so that if this packet needs to be resent, we send the current properties
+ // of the object rather than the properties when the packet was created
+ List updates = new List();
+ updates.Add(familyUpdates.Value[i]);
+ OutPacket(packet, ThrottleOutPacketType.Task, true,
+ delegate(OutgoingPacket oPacket)
+ {
+ ResendPropertyUpdates(updates, oPacket);
+ });
+
+ // fpcnt++;
+ // fbcnt++;
}
}
@@ -4113,7 +4205,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return block;
}
-
+
private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop)
{
//ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
@@ -11336,7 +11428,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
public byte[] GetThrottlesPacked(float multiplier)
{
- return m_udpClient.GetThrottlesPacked();
+ return m_udpClient.GetThrottlesPacked(multiplier);
}
///
@@ -11370,6 +11462,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// packets (the default), or false to disable splitting if the calling code
/// handles splitting manually
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
+ {
+ OutPacket(packet, throttlePacketType, doAutomaticSplitting, null);
+ }
+
+ ///
+ /// This is the starting point for sending a simulator packet out to the client
+ ///
+ /// Packet to send
+ /// Throttling category for the packet
+ /// True to automatically split oversized
+ /// packets (the default), or false to disable splitting if the calling code
+ /// handles splitting manually
+ /// The method to be called in the event this packet is reliable
+ /// and unacknowledged. The server will provide normal resend capability if you do not
+ /// provide your own method.
+ protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
{
if (m_debugPacketLevel > 0)
{
@@ -11396,7 +11504,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
}
- m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting);
+ m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method);
}
public bool AddMoney(int debit)
@@ -11527,7 +11635,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
info.userEP = m_userEndPoint;
info.proxyEP = null;
- info.agentcircuit = new sAgentCircuitData(RequestClientInfo());
+ info.agentcircuit = RequestClientInfo();
return info;
}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 7be8a0ae59..ca5501d875 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -135,7 +135,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_nextOnQueueEmpty = 1;
/// Throttle bucket for this agent's connection
- private readonly TokenBucket m_throttleClient;
+ private readonly AdaptiveTokenBucket m_throttleClient;
+ public AdaptiveTokenBucket FlowThrottle
+ {
+ get { return m_throttleClient; }
+ }
+
/// Throttle bucket for this agent's connection
private readonly TokenBucket m_throttleCategory;
/// Throttle buckets for each packet category
@@ -176,9 +181,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_maxRTO = maxRTO;
// Create a token bucket throttle for this client that has the scene token bucket as a parent
- m_throttleClient = new TokenBucket(parentThrottle, rates.TotalLimit);
+ m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled);
// Create a token bucket throttle for the total categary with the client bucket as a throttle
- m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit);
+ m_throttleCategory = new TokenBucket(m_throttleClient, 0);
// Create an array of token buckets for this clients different throttle categories
m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
@@ -189,7 +194,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Initialize the packet outboxes, where packets sit while they are waiting for tokens
m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue();
// Initialize the token buckets that control the throttling for each category
- m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetLimit(type));
+ m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
}
// Default the retransmission timeout to three seconds
@@ -223,26 +228,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Information about the client connection
public ClientInfo GetClientInfo()
{
-///
- TokenBucket tb;
-
- tb = m_throttleClient.Parent;
- m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"ROOT");
-
- tb = m_throttleClient;
- m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CLIENT");
-
- tb = m_throttleCategory;
- m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CATEGORY");
-
- for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
- {
- tb = m_throttleCategories[i];
- m_log.WarnFormat("[TOKENS] {4} <{0}:{1}>: Actual={2},Requested={3}",AgentID,i,tb.DripRate,tb.RequestedDripRate," BUCKET");
- }
-
-///
-
// TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
// of pending and needed ACKs for every client every time some method wants information about
// this connection is a recipe for poor performance
@@ -254,12 +239,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
- // info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
- info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
- info.taskThrottle + info.assetThrottle + info.textureThrottle;
+ info.totalThrottle = (int)m_throttleCategory.DripRate;
return info;
}
@@ -346,8 +329,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
// State is a subcategory of task that we allocate a percentage to
int state = 0;
- // int state = (int)((float)task * STATE_TASK_PERCENTAGE);
- // task -= state;
// Make sure none of the throttles are set below our packet MTU,
// otherwise a throttle could become permanently clogged
@@ -358,19 +339,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
task = Math.Max(task, LLUDPServer.MTU);
texture = Math.Max(texture, LLUDPServer.MTU);
asset = Math.Max(asset, LLUDPServer.MTU);
- state = Math.Max(state, LLUDPServer.MTU);
- int total = resend + land + wind + cloud + task + texture + asset + state;
-
- //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}",
- // AgentID, resend, land, wind, cloud, task, texture, asset, state, total);
+ //int total = resend + land + wind + cloud + task + texture + asset;
+ //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
+ // AgentID, resend, land, wind, cloud, task, texture, asset, total);
// Update the token buckets with new throttle values
TokenBucket bucket;
- bucket = m_throttleCategory;
- bucket.RequestedDripRate = total;
-
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
bucket.RequestedDripRate = resend;
@@ -399,22 +375,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_packedThrottles = null;
}
- public byte[] GetThrottlesPacked()
+ public byte[] GetThrottlesPacked(float multiplier)
{
byte[] data = m_packedThrottles;
if (data == null)
{
+ float rate;
+
data = new byte[7 * 4];
int i = 0;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4;
+ // multiply by 8 to convert bytes back to bits
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
m_packedThrottles = data;
}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index d08b25f79d..aff90c5259 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -297,7 +297,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
delegate(IClientAPI client)
{
if (client is LLClientView)
- SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
+ SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
}
);
}
@@ -309,7 +309,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
delegate(IClientAPI client)
{
if (client is LLClientView)
- SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
+ SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
}
);
}
@@ -322,7 +322,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
///
///
- public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
+ public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
{
// CoarseLocationUpdate packets cannot be split in an automated way
if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
@@ -339,13 +339,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
for (int i = 0; i < packetCount; i++)
{
byte[] data = datas[i];
- SendPacketData(udpClient, data, packet.Type, category);
+ SendPacketData(udpClient, data, packet.Type, category, method);
}
}
else
{
byte[] data = packet.ToBytes();
- SendPacketData(udpClient, data, packet.Type, category);
+ SendPacketData(udpClient, data, packet.Type, category, method);
}
}
@@ -356,7 +356,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
///
///
- public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category)
+ public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
{
int dataLength = data.Length;
bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
@@ -411,7 +411,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Queue or Send
- OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
+ OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
+ // If we were not provided a method for handling unacked, use the UDPServer default method
+ outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
// If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
// continue to display the deleted object until relog. Therefore, we need to always queue a kill object
@@ -445,7 +447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
packet.Header.Reliable = false;
packet.Packets = blocks.ToArray();
- SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true);
+ SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true, null);
}
}
@@ -458,17 +460,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
pc.PingID.OldestUnacked = 0;
- SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false);
+ SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null);
}
public void CompletePing(LLUDPClient udpClient, byte pingID)
{
CompletePingCheckPacket completePing = new CompletePingCheckPacket();
completePing.PingID.PingID = pingID;
- SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false);
+ SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null);
}
- public void ResendUnacked(LLUDPClient udpClient)
+ public void HandleUnacked(LLUDPClient udpClient)
{
if (!udpClient.IsConnected)
return;
@@ -488,33 +490,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (expiredPackets != null)
{
- //m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);
-
+ //m_log.Debug("[LLUDPSERVER]: Handling " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);
// Exponential backoff of the retransmission timeout
udpClient.BackoffRTO();
-
- // Resend packets
- for (int i = 0; i < expiredPackets.Count; i++)
- {
- OutgoingPacket outgoingPacket = expiredPackets[i];
-
- //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
- // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);
-
- // Set the resent flag
- outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
- outgoingPacket.Category = ThrottleOutPacketType.Resend;
-
- // Bump up the resend count on this packet
- Interlocked.Increment(ref outgoingPacket.ResendCount);
-
- // Requeue or resend the packet
- if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
- SendPacketFinal(outgoingPacket);
- }
+ for (int i = 0; i < expiredPackets.Count; ++i)
+ expiredPackets[i].UnackedMethod(expiredPackets[i]);
}
}
+ public void ResendUnacked(OutgoingPacket outgoingPacket)
+ {
+ //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
+ // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);
+
+ // Set the resent flag
+ outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
+ outgoingPacket.Category = ThrottleOutPacketType.Resend;
+
+ // Bump up the resend count on this packet
+ Interlocked.Increment(ref outgoingPacket.ResendCount);
+
+ // Requeue or resend the packet
+ if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
+ SendPacketFinal(outgoingPacket);
+ }
+
public void Flush(LLUDPClient udpClient)
{
// FIXME: Implement?
@@ -672,7 +672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
{
for (int i = 0; i < packet.Header.AckList.Length; i++)
- udpClient.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent);
+ udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
}
// Handle PacketAck packets
@@ -681,7 +681,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
PacketAckPacket ackPacket = (PacketAckPacket)packet;
for (int i = 0; i < ackPacket.Packets.Length; i++)
- udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent);
+ udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
// We don't need to do anything else with PacketAck packets
return;
@@ -1096,7 +1096,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (udpClient.IsConnected)
{
if (m_resendUnacked)
- ResendUnacked(udpClient);
+ HandleUnacked(udpClient);
if (m_sendAcks)
SendAcks(udpClient);
@@ -1152,7 +1152,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
nticksUnack++;
watch2.Start();
- ResendUnacked(udpClient);
+ HandleUnacked(udpClient);
watch2.Stop();
avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
index 1a1a1cb4e3..76c6c145c8 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
@@ -31,6 +31,8 @@ using OpenMetaverse;
namespace OpenSim.Region.ClientStack.LindenUDP
{
+
+ public delegate void UnackedPacketMethod(OutgoingPacket oPacket);
///
/// Holds a reference to the this packet is
/// destined for, along with the serialized packet data, sequence number
@@ -52,6 +54,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public int TickCount;
/// Category this packet belongs to
public ThrottleOutPacketType Category;
+ /// The delegate to be called if this packet is determined to be unacknowledged
+ public UnackedPacketMethod UnackedMethod;
///
/// Default constructor
@@ -60,11 +64,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Serialized packet data. If the flags or sequence number
/// need to be updated, they will be injected directly into this binary buffer
/// Throttling category for this packet
- public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category)
+ public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method)
{
Client = client;
Buffer = buffer;
Category = category;
+ UnackedMethod = method;
}
}
}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
index aaf6e26d58..c9aac0ba09 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
@@ -52,30 +52,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public int Texture;
/// Drip rate for asset packets
public int Asset;
- /// Drip rate for state packets
- public int State;
+
/// Drip rate for the parent token bucket
public int Total;
- /// Maximum burst rate for resent packets
- public int ResendLimit;
- /// Maximum burst rate for land packets
- public int LandLimit;
- /// Maximum burst rate for wind packets
- public int WindLimit;
- /// Maximum burst rate for cloud packets
- public int CloudLimit;
- /// Maximum burst rate for task (state and transaction) packets
- public int TaskLimit;
- /// Maximum burst rate for texture packets
- public int TextureLimit;
- /// Maximum burst rate for asset packets
- public int AssetLimit;
- /// Maximum burst rate for state packets
- public int StateLimit;
- /// Burst rate for the parent token bucket
- public int TotalLimit;
-
+ /// Flag used to enable adaptive throttles
+ public bool AdaptiveThrottlesEnabled;
+
///
/// Default constructor
///
@@ -86,26 +69,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
- Resend = throttleConfig.GetInt("resend_default", 12500);
- Land = throttleConfig.GetInt("land_default", 1000);
- Wind = throttleConfig.GetInt("wind_default", 1000);
- Cloud = throttleConfig.GetInt("cloud_default", 1000);
- Task = throttleConfig.GetInt("task_default", 1000);
- Texture = throttleConfig.GetInt("texture_default", 1000);
- Asset = throttleConfig.GetInt("asset_default", 1000);
- State = throttleConfig.GetInt("state_default", 1000);
-
- ResendLimit = throttleConfig.GetInt("resend_limit", 18750);
- LandLimit = throttleConfig.GetInt("land_limit", 29750);
- WindLimit = throttleConfig.GetInt("wind_limit", 18750);
- CloudLimit = throttleConfig.GetInt("cloud_limit", 18750);
- TaskLimit = throttleConfig.GetInt("task_limit", 18750);
- TextureLimit = throttleConfig.GetInt("texture_limit", 55750);
- AssetLimit = throttleConfig.GetInt("asset_limit", 27500);
- StateLimit = throttleConfig.GetInt("state_limit", 37000);
+ Resend = throttleConfig.GetInt("resend_default", 6625);
+ Land = throttleConfig.GetInt("land_default", 9125);
+ Wind = throttleConfig.GetInt("wind_default", 1750);
+ Cloud = throttleConfig.GetInt("cloud_default", 1750);
+ Task = throttleConfig.GetInt("task_default", 18500);
+ Texture = throttleConfig.GetInt("texture_default", 18500);
+ Asset = throttleConfig.GetInt("asset_default", 10500);
Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
- TotalLimit = Total;
+
+ AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
}
catch (Exception) { }
}
@@ -128,34 +102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return Texture;
case ThrottleOutPacketType.Asset:
return Asset;
- case ThrottleOutPacketType.State:
- return State;
- case ThrottleOutPacketType.Unknown:
- default:
- return 0;
- }
- }
-
- public int GetLimit(ThrottleOutPacketType type)
- {
- switch (type)
- {
- case ThrottleOutPacketType.Resend:
- return ResendLimit;
- case ThrottleOutPacketType.Land:
- return LandLimit;
- case ThrottleOutPacketType.Wind:
- return WindLimit;
- case ThrottleOutPacketType.Cloud:
- return CloudLimit;
- case ThrottleOutPacketType.Task:
- return TaskLimit;
- case ThrottleOutPacketType.Texture:
- return TextureLimit;
- case ThrottleOutPacketType.Asset:
- return AssetLimit;
- case ThrottleOutPacketType.State:
- return StateLimit;
case ThrottleOutPacketType.Unknown:
default:
return 0;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index 07b0a1df7a..29fd1a409a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -29,6 +29,8 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
+using OpenSim.Framework;
+
using log4net;
namespace OpenSim.Region.ClientStack.LindenUDP
@@ -48,31 +50,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Number of ticks (ms) per quantum, drip rate and max burst
/// are defined over this interval.
///
- private const Int32 m_ticksPerQuantum = 1000;
+ protected const Int32 m_ticksPerQuantum = 1000;
///
/// This is the number of quantums worth of packets that can
/// be accommodated during a burst
///
- private const Double m_quantumsPerBurst = 1.5;
+ protected const Double m_quantumsPerBurst = 1.5;
///
///
- private const Int32 m_minimumDripRate = 1400;
+ protected const Int32 m_minimumDripRate = 1400;
/// Time of the last drip, in system ticks
- private Int32 m_lastDrip;
+ protected Int32 m_lastDrip;
///
/// The number of bytes that can be sent at this moment. This is the
/// current number of tokens in the bucket
///
- private Int64 m_tokenCount;
+ protected Int64 m_tokenCount;
///
/// Map of children buckets and their requested maximum burst rate
///
- private Dictionary m_children = new Dictionary();
+ protected Dictionary m_children = new Dictionary();
#region Properties
@@ -81,7 +83,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// parent. The parent bucket will limit the aggregate bandwidth of all
/// of its children buckets
///
- private TokenBucket m_parent;
+ protected TokenBucket m_parent;
public TokenBucket Parent
{
get { return m_parent; }
@@ -93,7 +95,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// of tokens that can accumulate in the bucket at any one time. This
/// also sets the total request for leaf nodes
///
- private Int64 m_burstRate;
+ protected Int64 m_burstRate;
public Int64 RequestedBurstRate
{
get { return m_burstRate; }
@@ -118,8 +120,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Tokens are added to the bucket any time
/// is called, at the granularity of
/// the system tick interval (typically around 15-22ms)
- private Int64 m_dripRate;
- public Int64 RequestedDripRate
+ protected Int64 m_dripRate;
+ public virtual Int64 RequestedDripRate
{
get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
set {
@@ -131,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
- public Int64 DripRate
+ public virtual Int64 DripRate
{
get {
if (m_parent == null)
@@ -149,7 +151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// The current total of the requested maximum burst rates of
/// this bucket's children buckets.
///
- private Int64 m_totalDripRequest;
+ protected Int64 m_totalDripRequest;
public Int64 TotalDripRequest
{
get { return m_totalDripRequest; }
@@ -177,7 +179,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
RequestedDripRate = dripRate;
// TotalDripRequest = dripRate; // this will be overwritten when a child node registers
// MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
- m_lastDrip = Environment.TickCount & Int32.MaxValue;
+ m_lastDrip = Util.EnvironmentTickCount();
}
#endregion Constructor
@@ -189,7 +191,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// hierarchy. However, if any of the parents is over-booked, then
/// the modifier will be less than 1.
///
- private double DripRateModifier()
+ protected double DripRateModifier()
{
Int64 driprate = DripRate;
return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
@@ -197,7 +199,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
///
- private double BurstRateModifier()
+ protected double BurstRateModifier()
{
// for now... burst rate is always m_quantumsPerBurst (constant)
// larger than drip rate so the ratio of burst requests is the
@@ -211,12 +213,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
public void RegisterRequest(TokenBucket child, Int64 request)
{
- m_children[child] = request;
- // m_totalDripRequest = m_children.Values.Sum();
+ lock (m_children)
+ {
+ m_children[child] = request;
+ // m_totalDripRequest = m_children.Values.Sum();
- m_totalDripRequest = 0;
- foreach (KeyValuePair cref in m_children)
- m_totalDripRequest += cref.Value;
+ m_totalDripRequest = 0;
+ foreach (KeyValuePair cref in m_children)
+ m_totalDripRequest += cref.Value;
+ }
// Pass the new values up to the parent
if (m_parent != null)
@@ -229,12 +234,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
public void UnregisterRequest(TokenBucket child)
{
- m_children.Remove(child);
- // m_totalDripRequest = m_children.Values.Sum();
+ lock (m_children)
+ {
+ m_children.Remove(child);
+ // m_totalDripRequest = m_children.Values.Sum();
- m_totalDripRequest = 0;
- foreach (KeyValuePair cref in m_children)
- m_totalDripRequest += cref.Value;
+ m_totalDripRequest = 0;
+ foreach (KeyValuePair cref in m_children)
+ m_totalDripRequest += cref.Value;
+ }
+
// Pass the new values up to the parent
if (m_parent != null)
@@ -268,7 +277,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Deposit tokens into the bucket from a child bucket that did
/// not use all of its available tokens
///
- private void Deposit(Int64 count)
+ protected void Deposit(Int64 count)
{
m_tokenCount += count;
@@ -285,7 +294,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// call to Drip
///
/// True if tokens were added to the bucket, otherwise false
- private void Drip()
+ protected void Drip()
{
// This should never happen... means we are a leaf node and were created
// with no drip rate...
@@ -297,10 +306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Determine the interval over which we are adding tokens, never add
// more than a single quantum of tokens
- Int32 now = Environment.TickCount & Int32.MaxValue;
- Int32 deltaMS = Math.Min(now - m_lastDrip, m_ticksPerQuantum);
-
- m_lastDrip = now;
+ Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum);
+ m_lastDrip = Util.EnvironmentTickCount();
// This can be 0 in the very unusual case that the timer wrapped
// It can be 0 if we try add tokens at a sub-tick rate
@@ -310,4 +317,77 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Deposit(deltaMS * DripRate / m_ticksPerQuantum);
}
}
+
+ public class AdaptiveTokenBucket : TokenBucket
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ ///
+ /// The minimum rate for flow control. Minimum drip rate is one
+ /// packet per second. Open the throttle to 15 packets per second
+ /// or about 160kbps.
+ ///
+ protected const Int64 m_minimumFlow = m_minimumDripRate * 15;
+
+ //
+ // The maximum rate for flow control. Drip rate can never be
+ // greater than this.
+ //
+ protected Int64 m_maxDripRate = 0;
+ protected Int64 MaxDripRate
+ {
+ get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
+ set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); }
+ }
+
+ private bool m_enabled = false;
+
+ //
+ //
+ //
+ public virtual Int64 AdjustedDripRate
+ {
+ get { return m_dripRate; }
+ set {
+ m_dripRate = OpenSim.Framework.Util.Clamp(value,m_minimumFlow,MaxDripRate);
+ m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
+ if (m_parent != null)
+ m_parent.RegisterRequest(this,m_dripRate);
+ }
+ }
+
+ //
+ //
+ //
+ public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate)
+ {
+ m_enabled = enabled;
+
+ if (m_enabled)
+ {
+ // m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled");
+ MaxDripRate = maxDripRate;
+ AdjustedDripRate = m_minimumFlow;
+ }
+ }
+
+ //
+ //
+ //
+ public void ExpirePackets(Int32 count)
+ {
+ // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
+ if (m_enabled)
+ AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count));
+ }
+
+ //
+ //
+ //
+ public void AcknowledgePackets(Int32 count)
+ {
+ if (m_enabled)
+ AdjustedDripRate = AdjustedDripRate + count;
+ }
+ }
}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
index d195110a23..793aefe6e5 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
@@ -65,7 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Holds packets that need to be added to the unacknowledged list
private LocklessQueue m_pendingAdds = new LocklessQueue();
/// Holds information about pending acknowledgements
- private LocklessQueue m_pendingRemoves = new LocklessQueue();
+ private LocklessQueue m_pendingAcknowledgements = new LocklessQueue();
+ /// Holds information about pending removals
+ private LocklessQueue m_pendingRemoves = new LocklessQueue();
///
/// Add an unacked packet to the collection
@@ -83,15 +85,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
/// Marks a packet as acknowledged
+ /// This method is used when an acknowledgement is received from the network for a previously
+ /// sent packet. Effects of removal this way are to update unacked byte count, adjust RTT
+ /// and increase throttle to the coresponding client.
///
/// Sequence number of the packet to
/// acknowledge
/// Current value of Environment.TickCount
/// This does not immediately acknowledge the packet, it only
/// queues the ack so it can be handled in a thread-safe way later
- public void Remove(uint sequenceNumber, int currentTime, bool fromResend)
+ public void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend)
{
- m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
+ m_pendingAcknowledgements.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
+ }
+
+ ///
+ /// Marks a packet as no longer needing acknowledgement without a received acknowledgement.
+ /// This method is called when a packet expires and we no longer need an acknowledgement.
+ /// When some reliable packet types expire, they are handled in a way other than simply
+ /// resending them. The only effect of removal this way is to update unacked byte count.
+ ///
+ /// Sequence number of the packet to
+ /// acknowledge
+ /// The does not immediately remove the packet, it only queues the removal
+ /// so it can be handled in a thread safe way later
+ public void Remove(uint sequenceNumber)
+ {
+ m_pendingRemoves.Enqueue(sequenceNumber);
}
///
@@ -130,6 +150,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// is actually sent out again
packet.TickCount = 0;
+ // As with other network applications, assume that an expired packet is
+ // an indication of some network problem, slow transmission
+ packet.Client.FlowThrottle.ExpirePackets(1);
+
expiredPackets.Add(packet);
}
}
@@ -147,29 +171,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_packets[pendingAdd.SequenceNumber] = pendingAdd;
// Process all the pending removes, including updating statistics and round-trip times
- PendingAck pendingRemove;
- OutgoingPacket ackedPacket;
- while (m_pendingRemoves.TryDequeue(out pendingRemove))
+ PendingAck pendingAcknowledgement;
+ while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
{
- if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket))
+ OutgoingPacket ackedPacket;
+ if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
{
if (ackedPacket != null)
{
- m_packets.Remove(pendingRemove.SequenceNumber);
+ m_packets.Remove(pendingAcknowledgement.SequenceNumber);
+
+ // As with other network applications, assume that an acknowledged packet is an
+ // indication that the network can handle a little more load, speed up the transmission
+ ackedPacket.Client.FlowThrottle.AcknowledgePackets(ackedPacket.Buffer.DataLength);
// Update stats
Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
- if (!pendingRemove.FromResend)
+ if (!pendingAcknowledgement.FromResend)
{
// Calculate the round-trip time for this packet and its ACK
- int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount;
+ int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount;
if (rtt > 0)
ackedPacket.Client.UpdateRoundTrip(rtt);
}
}
}
}
+
+ uint pendingRemove;
+ while(m_pendingRemoves.TryDequeue(out pendingRemove))
+ {
+ OutgoingPacket removedPacket;
+ if (m_packets.TryGetValue(pendingRemove, out removedPacket))
+ {
+ if (removedPacket != null)
+ {
+ m_packets.Remove(pendingRemove);
+
+ // Update stats
+ Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
+ }
+ }
+ }
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index 771038e1af..9d8082bd33 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -41,8 +41,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
///
public class AgentAssetTransactions
{
-// private static readonly ILog m_log = LogManager.GetLogger(
-// MethodBase.GetCurrentMethod().DeclaringType);
+// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// Fields
private bool m_dumpAssetsToFile;
@@ -149,6 +148,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
if (asset != null)
{
+// m_log.DebugFormat(
+// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}",
+// item.Name, part.Name, transactionID);
+
asset.FullID = UUID.Random();
asset.Name = item.Name;
asset.Description = item.Description;
@@ -156,8 +159,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
item.AssetID = asset.FullID;
m_Scene.AssetService.Store(asset);
-
- part.Inventory.UpdateInventoryItem(item);
}
}
}
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index ff262648e5..520d794e74 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -562,14 +562,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
///
///
///
- ///
+ ///
///
- protected void AttachToAgent(ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 AttachOffset, bool silent)
+ protected void AttachToAgent(ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
{
- // don't attach attachments to child agents
- if (avatar.IsChildAgent) return;
-// m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
+ m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", Name, avatar.Name,
+ attachmentpoint, attachOffset, so.RootPart.AttachedPos);
so.DetachFromBackup();
@@ -590,8 +589,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
so.RootPart.PhysActor = null;
}
- so.AbsolutePosition = AttachOffset;
- so.RootPart.AttachedPos = AttachOffset;
+ so.AbsolutePosition = attachOffset;
+ so.RootPart.AttachedPos = attachOffset;
so.RootPart.IsAttachment = true;
so.RootPart.SetParentLocalId(avatar.LocalId);
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index c88be7ddb0..b985fbb371 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -285,11 +285,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
string reason;
- if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out reason))
+ string version;
+ if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
{
sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason);
return;
}
+ m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
sp.ControllingClient.SendTeleportStart(teleportFlags);
@@ -371,20 +373,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
}
- // Expect avatar crossing is a heavy-duty function at the destination.
- // That is where MakeRoot is called, which fetches appearance and inventory.
- // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
- //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
- // position, false);
-
- //{
- // avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
- // // We should close that agent we just created over at destination...
- // List lst = new List();
- // lst.Add(reg.RegionHandle);
- // SendCloseChildAgentAsync(avatar.UUID, lst);
- // return;
- //}
SetInTransit(sp.UUID);
@@ -426,7 +414,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
// trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
- // that the client contacted the destination before we send the attachments and close things here.
+ // that the client contacted the destination before we close things here.
if (!WaitForCallback(sp.UUID))
{
m_log.WarnFormat(
@@ -437,14 +425,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return;
}
- // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
- CrossAttachmentsIntoNewRegion(finalDestination, sp, true);
+ // For backwards compatibility
+ if (version == "Unknown" || version == string.Empty)
+ {
+ // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
+ m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old simulator, sending attachments one by one...");
+ CrossAttachmentsIntoNewRegion(finalDestination, sp, true);
+ }
+
+ // May need to logout or other cleanup
+ AgentHasMovedAway(sp, logout);
// Well, this is it. The agent is over there.
KillEntity(sp.Scene, sp.LocalId);
- // May need to logout or other cleanup
- AgentHasMovedAway(sp.ControllingClient.SessionId, logout);
// Now let's make it officially a child agent
sp.MakeChildAgent();
@@ -485,7 +479,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// Fail. Reset it back
sp.IsChildAgent = false;
-
+ ReInstantiateScripts(sp);
ResetFromTransit(sp.UUID);
EnableChildAgents(sp);
@@ -513,8 +507,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
- protected virtual void AgentHasMovedAway(UUID sessionID, bool logout)
+ protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
{
+ foreach (SceneObjectGroup sop in sp.Attachments)
+ {
+ sop.Scene.DeleteSceneObject(sop, true);
+ }
+ sp.Attachments.Clear();
}
protected void KillEntity(Scene scene, uint localID)
@@ -784,7 +783,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
string reason;
- if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos, out reason))
+ string version;
+ if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos, out version, out reason))
{
agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel");
if (r == null)
@@ -804,7 +804,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agent.InTransit();
CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync;
- d.BeginInvoke(agent, newpos, neighbourx, neighboury, neighbourRegion, isFlying, CrossAgentToNewRegionCompleted, d);
+ d.BeginInvoke(agent, newpos, neighbourx, neighboury, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d);
return true;
}
@@ -861,17 +861,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
icon.EndInvoke(iar);
}
- public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying);
+ public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version);
///
/// This Closes child agents on neighbouring regions
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
///
- protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying)
+ protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version)
{
ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
- m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3}", agent.Firstname, agent.Lastname, neighbourx, neighboury);
+ m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}", agent.Firstname, agent.Lastname, neighbourx, neighboury, version);
Scene m_scene = agent.Scene;
@@ -930,6 +930,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (!WaitForCallback(agent.UUID))
{
m_log.Debug("[ENTITY TRANSFER MODULE]: Callback never came in crossing agent");
+ ReInstantiateScripts(agent);
ResetFromTransit(agent.UUID);
// Yikes! We should just have a ref to scene here.
@@ -945,7 +946,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agent.SendOtherAgentsAvatarDataToMe();
agent.SendOtherAgentsAppearanceToMe();
- CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
+ // Backwards compatibility
+ if (version == "Unknown" || version == string.Empty)
+ {
+ m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old neighbor, passing attachments one by one...");
+ CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
+ }
+
+ AgentHasMovedAway(agent, false);
// the user may change their profile information in other region,
// so the userinfo in UserProfileCache is not reliable any more, delete it
@@ -1749,7 +1757,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return false;
}
-
+ protected void ReInstantiateScripts(ScenePresence sp)
+ {
+ sp.Attachments.ForEach(delegate(SceneObjectGroup sog)
+ {
+ sog.CreateScriptInstances(0, false, sp.Scene.DefaultScriptEngine, 0);
+ sog.ResumeScripts();
+ });
+ }
#endregion
}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 79e76b4cbf..5c53f787bf 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -142,11 +142,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return false;
}
- protected override void AgentHasMovedAway(UUID sessionID, bool logout)
+ protected override void AgentHasMovedAway(ScenePresence sp, bool logout)
{
+ base.AgentHasMovedAway(sp, logout);
if (logout)
// Log them out of this grid
- m_aScene.PresenceService.LogoutAgent(sessionID);
+ m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
}
protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index a298b65820..2cf02b5544 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -41,6 +41,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ // Version of this service
+ private const string m_Version = "SIMULATION/0.1";
+
private List m_sceneList = new List();
private IEntityTransferModule m_AgentTransferModule;
@@ -257,9 +260,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
}
- public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason)
+ public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
{
reason = "Communications failure";
+ version = m_Version;
if (destination == null)
return false;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index 67f4d6030c..f8cea71b43 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -179,7 +179,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return true;
// else do the remote thing
- if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
+ if (!m_localBackend.IsLocalRegion(destination.RegionID))
{
return m_remoteConnector.CreateAgent(destination, aCircuit, teleportFlags, out reason);
}
@@ -229,19 +229,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
}
- public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason)
+ public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
{
reason = "Communications failure";
+ version = "Unknown";
if (destination == null)
return false;
// Try local first
- if (m_localBackend.QueryAccess(destination, id, position, out reason))
+ if (m_localBackend.QueryAccess(destination, id, position, out version, out reason))
return true;
// else do the remote thing
- if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
- return m_remoteConnector.QueryAccess(destination, id, position, out reason);
+ if (!m_localBackend.IsLocalRegion(destination.RegionID))
+ return m_remoteConnector.QueryAccess(destination, id, position, out version, out reason);
return false;
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index e3ed905c2f..4595a29c66 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -119,16 +119,40 @@ namespace OpenSim.Region.Framework.Scenes
private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity)
{
- return 1;
+ // And anything attached to this avatar gets top priority as well
+ if (entity is SceneObjectPart)
+ {
+ SceneObjectPart sop = (SceneObjectPart)entity;
+ if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
+ return 1;
+ }
+
+ return PriorityQueue.NumberOfImmediateQueues; // first queue past the immediate queues
}
private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
{
+ // And anything attached to this avatar gets top priority as well
+ if (entity is SceneObjectPart)
+ {
+ SceneObjectPart sop = (SceneObjectPart)entity;
+ if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
+ return 1;
+ }
+
return ComputeDistancePriority(client,entity,false);
}
private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
{
+ // And anything attached to this avatar gets top priority as well
+ if (entity is SceneObjectPart)
+ {
+ SceneObjectPart sop = (SceneObjectPart)entity;
+ if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
+ return 1;
+ }
+
return ComputeDistancePriority(client,entity,true);
}
@@ -141,18 +165,20 @@ namespace OpenSim.Region.Framework.Scenes
{
if (!presence.IsChildAgent)
{
+ // All avatars other than our own go into pqueue 1
+ if (entity is ScenePresence)
+ return 1;
+
if (entity is SceneObjectPart)
{
+ // Attachments are high priority,
+ if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
+ return 1;
+
// Non physical prims are lower priority than physical prims
PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
if (physActor == null || !physActor.IsPhysical)
pqueue++;
-
- // Attachments are high priority,
- // MIC: shouldn't these already be in the highest priority queue already
- // since their root position is same as the avatars?
- if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
- pqueue = 1;
}
}
}
@@ -172,7 +198,7 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId);
// throw new InvalidOperationException("Prioritization agent not defined");
- return Int32.MaxValue;
+ return PriorityQueue.NumberOfQueues - 1;
}
// Use group position for child prims, since we are putting child prims in
@@ -197,8 +223,10 @@ namespace OpenSim.Region.Framework.Scenes
// And convert the distance to a priority queue, this computation gives queues
// at 10, 20, 40, 80, 160, 320, 640, and 1280m
- uint pqueue = 1;
- for (int i = 0; i < 8; i++)
+ uint pqueue = PriorityQueue.NumberOfImmediateQueues;
+ uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
+
+ for (int i = 0; i < queues - 1; i++)
{
if (distance < 10 * Math.Pow(2.0,i))
break;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 0f85925c78..b0f0de62bb 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -1430,6 +1430,10 @@ namespace OpenSim.Region.Framework.Scenes
}
else // Updating existing item with new perms etc
{
+// m_log.DebugFormat(
+// "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()",
+// currentItem.Name, part.Name);
+
IAgentAssetTransactions agentTransactions = this.RequestModuleInterface();
if (agentTransactions != null)
{
@@ -2039,6 +2043,12 @@ namespace OpenSim.Region.Framework.Scenes
if (rot != null)
group.UpdateGroupRotationR((Quaternion)rot);
+ // TODO: This needs to be refactored with the similar code in
+ // SceneGraph.AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel)
+ // possibly by allowing this method to take a null rotation.
+ if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero)
+ group.RootPart.ApplyImpulse((vel * group.GetMass()), false);
+
// We can only call this after adding the scene object, since the scene object references the scene
// to find out if scripts should be activated at all.
group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 01de82451f..7c5e24652c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1229,7 +1229,6 @@ namespace OpenSim.Region.Framework.Scenes
// Increment the frame counter
++Frame;
-
try
{
// Check if any objects have reached their targets
@@ -2316,7 +2315,9 @@ namespace OpenSim.Region.Framework.Scenes
///
public bool IncomingCreateObject(ISceneObject sog)
{
- //m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted);
+ //m_log.DebugFormat(" >>> IncomingCreateObject(sog) <<< {0} deleted? {1} isAttach? {2}", ((SceneObjectGroup)sog).AbsolutePosition,
+ // ((SceneObjectGroup)sog).IsDeleted, ((SceneObjectGroup)sog).RootPart.IsAttachment);
+
SceneObjectGroup newObject;
try
{
@@ -2334,9 +2335,29 @@ namespace OpenSim.Region.Framework.Scenes
return false;
}
- newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
-
- newObject.ResumeScripts();
+ // For attachments, we need to wait until the agent is root
+ // before we restart the scripts, or else some functions won't work.
+ if (!newObject.IsAttachment)
+ {
+ newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
+ newObject.ResumeScripts();
+ }
+ else
+ {
+ ScenePresence sp;
+ if (TryGetScenePresence(newObject.OwnerID, out sp))
+ {
+ // If the scene presence is here and already a root
+ // agent, we came from a ;egacy region. Start the scripts
+ // here as they used to start.
+ // TODO: Remove in 0.7.3
+ if (!sp.IsChildAgent)
+ {
+ newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
+ newObject.ResumeScripts();
+ }
+ }
+ }
// Do this as late as possible so that listeners have full access to the incoming object
EventManager.TriggerOnIncomingSceneObject(newObject);
@@ -2453,17 +2474,8 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence sp = GetScenePresence(sog.OwnerID);
if (sp != null)
- {
- AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(sp.UUID);
+ return sp.GetStateSource();
- if (aCircuit != null && (aCircuit.teleportFlags != (uint)TeleportFlags.Default))
- {
- // This will get your attention
- //m_log.Error("[XXX] Triggering CHANGED_TELEPORT");
-
- return 5; // StateSource.Teleporting
- }
- }
return 2; // StateSource.PrimCrossing
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3281eabd33..3b60f8c6da 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -693,8 +693,9 @@ namespace OpenSim.Region.Framework.Scenes
{
TaskInventoryItem it = GetInventoryItem(item.ItemID);
if (it != null)
-
{
+// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
+
item.ParentID = m_part.UUID;
item.ParentPartID = m_part.UUID;
@@ -711,14 +712,16 @@ namespace OpenSim.Region.Framework.Scenes
m_items[item.ItemID] = item;
m_inventorySerial++;
}
-
+
if (fireScriptEvents)
m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
+
if (considerChanged)
{
HasInventoryChanged = true;
m_part.ParentGroup.HasGroupChanged = true;
}
+
return true;
}
else
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 00a1487ab6..5b86735ef3 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -840,6 +840,9 @@ namespace OpenSim.Region.Framework.Scenes
//m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
+ bool wasChild = m_isChildAgent;
+ m_isChildAgent = false;
+
IGroupsModule gm = m_scene.RequestModuleInterface();
if (gm != null)
m_grouptitle = gm.GetGroupTitle(m_uuid);
@@ -929,14 +932,21 @@ namespace OpenSim.Region.Framework.Scenes
// Animator.SendAnimPack();
m_scene.SwapRootAgentCount(false);
-
- //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid);
- //if (userInfo != null)
- // userInfo.FetchInventory();
- //else
- // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid);
-
- m_isChildAgent = false;
+
+ // The initial login scene presence is already root when it gets here
+ // and it has already rezzed the attachments and started their scripts.
+ // We do the following only for non-login agents, because their scripts
+ // haven't started yet.
+ if (wasChild && Attachments != null && Attachments.Count > 0)
+ {
+ m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
+ // Resume scripts
+ Attachments.ForEach(delegate(SceneObjectGroup sog)
+ {
+ sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
+ sog.ResumeScripts();
+ });
+ }
// send the animations of the other presences to me
m_scene.ForEachScenePresence(delegate(ScenePresence presence)
@@ -948,6 +958,20 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.EventManager.TriggerOnMakeRootAgent(this);
}
+ public int GetStateSource()
+ {
+ AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID);
+
+ if (aCircuit != null && (aCircuit.teleportFlags != (uint)TeleportFlags.Default))
+ {
+ // This will get your attention
+ //m_log.Error("[XXX] Triggering CHANGED_TELEPORT");
+
+ return 5; // StateSource.Teleporting
+ }
+ return 2; // StateSource.PrimCrossing
+ }
+
///
/// This turns a root agent into a child agent
/// when an agent departs this region for a neighbor, this gets called.
@@ -1139,7 +1163,6 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = pos;
}
- m_isChildAgent = false;
bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
MakeRootAgent(AbsolutePosition, m_flying);
@@ -2340,12 +2363,14 @@ namespace OpenSim.Region.Framework.Scenes
#region Update Client(s)
+
///
/// Sends a location update to the client connected to this scenePresence
///
///
public void SendTerseUpdateToClient(IClientAPI remoteClient)
{
+
// If the client is inactive, it's getting its updates from another
// server.
if (remoteClient.IsActive)
@@ -2358,8 +2383,8 @@ namespace OpenSim.Region.Framework.Scenes
//m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
remoteClient.SendPrimUpdate(
- this,
- PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
+ this,
+ PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
| PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
@@ -2367,16 +2392,31 @@ namespace OpenSim.Region.Framework.Scenes
}
}
+
+ // vars to support reduced update frequency when velocity is unchanged
+ private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
+ private int lastTerseUpdateToAllClientsTick = Util.EnvironmentTickCount();
+
///
/// Send a location/velocity/accelleration update to all agents in scene
///
public void SendTerseUpdateToAllClients()
{
- m_perfMonMS = Util.EnvironmentTickCount();
-
- m_scene.ForEachClient(SendTerseUpdateToClient);
+ int currentTick = Util.EnvironmentTickCount();
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ // decrease update frequency when avatar is moving but velocity is not changing
+ if (m_velocity.Length() < 0.01f
+ || Vector3.Distance(lastVelocitySentToAllClients, m_velocity) > 0.01f
+ || currentTick - lastTerseUpdateToAllClientsTick > 1500)
+ {
+ m_perfMonMS = currentTick;
+ lastVelocitySentToAllClients = m_velocity;
+ lastTerseUpdateToAllClientsTick = currentTick;
+
+ m_scene.ForEachClient(SendTerseUpdateToClient);
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
}
public void SendCoarseLocations(List coarseLocations, List avatarUUIDs)
@@ -2632,18 +2672,17 @@ namespace OpenSim.Region.Framework.Scenes
cadu.GroupAccess = 0;
cadu.Position = AbsolutePosition;
cadu.regionHandle = m_rootRegionHandle;
- float multiplier = 1;
- int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
- if (innacurateNeighbors != 0)
- {
- multiplier = 1f / (float)innacurateNeighbors;
- }
- if (multiplier <= 0f)
- {
- multiplier = 0.25f;
- }
- //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
+ // Throttles
+ float multiplier = 1;
+ int childRegions = m_knownChildRegions.Count;
+ if (childRegions != 0)
+ multiplier = 1f / childRegions;
+
+ // Minimum throttle for a child region is 1/4 of the root region throttle
+ if (multiplier <= 0.25f)
+ multiplier = 0.25f;
+
cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
cadu.Velocity = Velocity;
@@ -3039,16 +3078,14 @@ namespace OpenSim.Region.Framework.Scenes
// Throttles
float multiplier = 1;
- int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
- if (innacurateNeighbors != 0)
- {
- multiplier = 1f / innacurateNeighbors;
- }
- if (multiplier <= 0f)
- {
+ int childRegions = m_knownChildRegions.Count;
+ if (childRegions != 0)
+ multiplier = 1f / childRegions;
+
+ // Minimum throttle for a child region is 1/4 of the root region throttle
+ if (multiplier <= 0.25f)
multiplier = 0.25f;
- }
- //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
+
cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
cAgent.HeadRotation = m_headrotation;
@@ -3064,54 +3101,6 @@ namespace OpenSim.Region.Framework.Scenes
cAgent.Appearance = new AvatarAppearance(m_appearance);
-/*
- try
- {
- // We might not pass the Wearables in all cases...
- // They're only needed so that persistent changes to the appearance
- // are preserved in the new region where the user is moving to.
- // But in Hypergrid we might not let this happen.
- int i = 0;
- UUID[] wears = new UUID[m_appearance.Wearables.Length * 2];
- foreach (AvatarWearable aw in m_appearance.Wearables)
- {
- if (aw != null)
- {
- wears[i++] = aw.ItemID;
- wears[i++] = aw.AssetID;
- }
- else
- {
- wears[i++] = UUID.Zero;
- wears[i++] = UUID.Zero;
- }
- }
- cAgent.Wearables = wears;
-
- cAgent.VisualParams = m_appearance.VisualParams;
-
- if (m_appearance.Texture != null)
- cAgent.AgentTextures = m_appearance.Texture.GetBytes();
- }
- catch (Exception e)
- {
- m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message);
- }
-
- //Attachments
- List attPoints = m_appearance.GetAttachedPoints();
- if (attPoints != null)
- {
- //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count);
- int i = 0;
- AvatarAttachment[] attachs = new AvatarAttachment[attPoints.Count];
- foreach (int point in attPoints)
- {
- attachs[i++] = new AvatarAttachment(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point));
- }
- cAgent.Attachments = attachs;
- }
-*/
lock (scriptedcontrols)
{
ControllerData[] controls = new ControllerData[scriptedcontrols.Count];
@@ -3131,9 +3120,26 @@ namespace OpenSim.Region.Framework.Scenes
}
catch { }
- // cAgent.GroupID = ??
- // Groups???
-
+ // Attachment objects
+ if (m_attachments != null && m_attachments.Count > 0)
+ {
+ cAgent.AttachmentObjects = new List();
+ cAgent.AttachmentObjectStates = new List();
+ IScriptModule se = m_scene.RequestModuleInterface();
+ foreach (SceneObjectGroup sog in m_attachments)
+ {
+ // We need to make a copy and pass that copy
+ // because of transfers withn the same sim
+ ISceneObject clone = sog.CloneForNewScene();
+ // Attachment module assumes that GroupPosition holds the offsets...!
+ ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
+ ((SceneObjectGroup)clone).RootPart.IsAttachment = false;
+ cAgent.AttachmentObjects.Add(clone);
+ cAgent.AttachmentObjectStates.Add(sog.GetStateSnapshot());
+ // Let's remove the scripts of the original object here
+ sog.RemoveScriptInstances(true);
+ }
+ }
}
public void CopyFrom(AgentData cAgent)
@@ -3174,50 +3180,6 @@ namespace OpenSim.Region.Framework.Scenes
AddToPhysicalScene(isFlying);
}
-/*
- uint i = 0;
- try
- {
- if (cAgent.Wearables == null)
- cAgent.Wearables = new UUID[0];
- AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2];
- for (uint n = 0; n < cAgent.Wearables.Length; n += 2)
- {
- UUID itemId = cAgent.Wearables[n];
- UUID assetId = cAgent.Wearables[n + 1];
- wears[i++] = new AvatarWearable(itemId, assetId);
- }
- // m_appearance.Wearables = wears;
- Primitive.TextureEntry textures = null;
- if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1)
- textures = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length);
-
- byte[] visuals = null;
-
- if ((cAgent.VisualParams != null) && (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT))
- visuals = (byte[])cAgent.VisualParams.Clone();
-
- m_appearance = new AvatarAppearance(cAgent.AgentID,wears,textures,visuals);
- }
- catch (Exception e)
- {
- m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message);
- }
-
- // Attachments
- try
- {
- if (cAgent.Attachments != null)
- {
- m_appearance.ClearAttachments();
- foreach (AvatarAttachment att in cAgent.Attachments)
- {
- m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID);
- }
- }
- }
- catch { }
-*/
try
{
lock (scriptedcontrols)
@@ -3247,8 +3209,18 @@ namespace OpenSim.Region.Framework.Scenes
}
catch { }
- //cAgent.GroupID = ??
- //Groups???
+ if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0)
+ {
+ m_attachments = new List();
+ int i = 0;
+ foreach (ISceneObject so in cAgent.AttachmentObjects)
+ {
+ ((SceneObjectGroup)so).LocalId = 0;
+ ((SceneObjectGroup)so).RootPart.UpdateFlag = 0;
+ so.SetState(cAgent.AttachmentObjectStates[i++], m_scene);
+ m_scene.IncomingCreateObject(so);
+ }
+ }
}
public bool CopyAgent(out IAgentData agent)
@@ -3271,10 +3243,7 @@ namespace OpenSim.Region.Framework.Scenes
m_updateflag = true;
- // The magic constant 0.95f seems to make walking feel less jerky,
- // probably because it hackishly accounts for the overall latency of
- // these Velocity updates -- Diva
- Velocity = force * .95F;
+ Velocity = force;
m_forceToApply = null;
}
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
index 6a24cc1092..db17d8faf7 100644
--- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -81,6 +81,14 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
lock (m_scenes)
m_scenes[scene.RegionInfo.RegionID] = scene;
+ scene.AddCommand(
+ this, "show pqueues",
+ "show pqueues [full]",
+ "Show priority queue data for each client",
+ "Without the 'full' option, only root agents are shown."
+ + " With the 'full' option child agents are also shown.",
+ ShowPQueuesReport);
+
scene.AddCommand(
this, "show queues",
"show queues [full]",
@@ -119,6 +127,11 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
}
+ protected void ShowPQueuesReport(string module, string[] cmd)
+ {
+ MainConsole.Instance.Output(GetPQueuesReport(cmd));
+ }
+
protected void ShowQueuesReport(string module, string[] cmd)
{
MainConsole.Instance.Output(GetQueuesReport(cmd));
@@ -155,6 +168,80 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
"");
}
+
+ ///
+ /// Generate UDP Queue data report for each client
+ ///
+ ///
+ ///
+ protected string GetPQueuesReport(string[] showParams)
+ {
+ bool showChildren = false;
+ string pname = "";
+
+ if (showParams.Length > 2 && showParams[2] == "full")
+ showChildren = true;
+ else if (showParams.Length > 3)
+ pname = showParams[2] + " " + showParams[3];
+
+ StringBuilder report = new StringBuilder();
+
+ int columnPadding = 2;
+ int maxNameLength = 18;
+ int maxRegionNameLength = 14;
+ int maxTypeLength = 4;
+ int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding;
+
+ report.Append(GetColumnEntry("User", maxNameLength, columnPadding));
+ report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding));
+ report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
+
+ report.AppendFormat(
+ "{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7} {10,7} {11,7}\n",
+ "Pri 0",
+ "Pri 1",
+ "Pri 2",
+ "Pri 3",
+ "Pri 4",
+ "Pri 5",
+ "Pri 6",
+ "Pri 7",
+ "Pri 8",
+ "Pri 9",
+ "Pri 10",
+ "Pri 11");
+
+ lock (m_scenes)
+ {
+ foreach (Scene scene in m_scenes.Values)
+ {
+ scene.ForEachClient(
+ delegate(IClientAPI client)
+ {
+ if (client is LLClientView)
+ {
+ bool isChild = scene.PresenceChildStatus(client.AgentId);
+ if (isChild && !showChildren)
+ return;
+
+ string name = client.Name;
+ if (pname != "" && name != pname)
+ return;
+
+ string regionName = scene.RegionInfo.RegionName;
+
+ report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
+ report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
+ report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
+ report.AppendLine(((LLClientView)client).EntityUpdateQueue.ToString());
+ }
+ });
+ }
+ }
+
+ return report.ToString();
+ }
+
///
/// Generate UDP Queue data report for each client
///
@@ -163,10 +250,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
protected string GetQueuesReport(string[] showParams)
{
bool showChildren = false;
+ string pname = "";
if (showParams.Length > 2 && showParams[2] == "full")
showChildren = true;
-
+ else if (showParams.Length > 3)
+ pname = showParams[2] + " " + showParams[3];
+
StringBuilder report = new StringBuilder();
int columnPadding = 2;
@@ -224,6 +314,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
return;
string name = client.Name;
+ if (pname != "" && name != pname)
+ return;
+
string regionName = scene.RegionInfo.RegionName;
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
@@ -249,10 +342,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
protected string GetThrottlesReport(string[] showParams)
{
bool showChildren = false;
+ string pname = "";
if (showParams.Length > 2 && showParams[2] == "full")
showChildren = true;
-
+ else if (showParams.Length > 3)
+ pname = showParams[2] + " " + showParams[3];
+
StringBuilder report = new StringBuilder();
int columnPadding = 2;
@@ -302,7 +398,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
if (client is LLClientView)
{
LLClientView llClient = client as LLClientView;
-
+
if (firstClient)
{
report.AppendLine(GetServerThrottlesReport(llClient.UDPServer));
@@ -314,6 +410,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
return;
string name = client.Name;
+ if (pname != "" && name != pname)
+ return;
+
string regionName = scene.RegionInfo.RegionName;
LLUDPClient llUdpClient = llClient.UDPClient;
@@ -352,7 +451,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
int maxRegionNameLength = 14;
int maxTypeLength = 4;
- string name = "SERVER AGENT LIMITS";
+ string name = "SERVER AGENT RATES";
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding));
@@ -362,13 +461,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
report.AppendFormat(
"{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}",
(throttleRates.Total * 8) / 1000,
- (throttleRates.ResendLimit * 8) / 1000,
- (throttleRates.LandLimit * 8) / 1000,
- (throttleRates.WindLimit * 8) / 1000,
- (throttleRates.CloudLimit * 8) / 1000,
- (throttleRates.TaskLimit * 8) / 1000,
- (throttleRates.TextureLimit * 8) / 1000,
- (throttleRates.AssetLimit * 8) / 1000);
+ (throttleRates.Resend * 8) / 1000,
+ (throttleRates.Land * 8) / 1000,
+ (throttleRates.Wind * 8) / 1000,
+ (throttleRates.Cloud * 8) / 1000,
+ (throttleRates.Task * 8) / 1000,
+ (throttleRates.Texture * 8) / 1000,
+ (throttleRates.Asset * 8) / 1000);
return report.ToString();
}
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 64774d8ee5..f89b824614 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -88,7 +88,8 @@ namespace OpenSim.Region.Physics.Meshing
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
- useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
+ if(mesh_config != null)
+ useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
try
{
diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
index 372a59c038..8b6fb4f5c1 100644
--- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
@@ -50,6 +50,7 @@ namespace OpenSim.Server.Handlers.Simulation
public class AgentHandler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
private ISimulationService m_SimulationService;
protected bool m_Proxy = false;
@@ -275,7 +276,7 @@ namespace OpenSim.Server.Handlers.Simulation
AgentData agent = new AgentData();
try
{
- agent.Unpack(args);
+ agent.Unpack(args, m_SimulationService.GetScene(destination.RegionHandle));
}
catch (Exception ex)
{
@@ -295,7 +296,7 @@ namespace OpenSim.Server.Handlers.Simulation
AgentPosition agent = new AgentPosition();
try
{
- agent.Unpack(args);
+ agent.Unpack(args, m_SimulationService.GetScene(destination.RegionHandle));
}
catch (Exception ex)
{
@@ -342,7 +343,8 @@ namespace OpenSim.Server.Handlers.Simulation
destination.RegionID = regionID;
string reason;
- bool result = m_SimulationService.QueryAccess(destination, id, position, out reason);
+ string version;
+ bool result = m_SimulationService.QueryAccess(destination, id, position, out version, out reason);
responsedata["int_response_code"] = HttpStatusCode.OK;
@@ -350,6 +352,7 @@ namespace OpenSim.Server.Handlers.Simulation
resp["success"] = OSD.FromBoolean(result);
resp["reason"] = OSD.FromString(reason);
+ resp["version"] = OSD.FromString(version);
responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
}
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index 93b3ae62a9..5cb82699d6 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -241,7 +241,7 @@ namespace OpenSim.Services.Connectors.Simulation
if (args != null)
{
agent = new CompleteAgentData();
- agent.Unpack(args);
+ agent.Unpack(args, null);
return true;
}
}
@@ -256,9 +256,10 @@ namespace OpenSim.Services.Connectors.Simulation
///
///
- public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason)
+ public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
{
reason = "Failed to contact destination";
+ version = "Unknown";
// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position);
@@ -275,9 +276,16 @@ namespace OpenSim.Services.Connectors.Simulation
{
OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000);
bool success = result["success"].AsBoolean();
- reason = result["reason"].AsString();
+ if (result.ContainsKey("_Result"))
+ {
+ OSDMap data = (OSDMap)result["_Result"];
- //m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1}", uri, success);
+ reason = data["reason"].AsString();
+ if (data["version"] != null && data["version"].AsString() != string.Empty)
+ version = data["version"].AsString();
+
+ m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1} version {2} ({3})", uri, success, version, data["version"].AsString());
+ }
if (!success)
{
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs
index b66bfed42f..9385b8df74 100644
--- a/OpenSim/Services/HypergridService/GatekeeperService.cs
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -29,6 +29,7 @@ using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
+using System.Text.RegularExpressions;
using OpenSim.Framework;
using OpenSim.Services.Interfaces;
@@ -57,6 +58,9 @@ namespace OpenSim.Services.HypergridService
private static IUserAgentService m_UserAgentService;
private static ISimulationService m_SimulationService;
+ protected string m_AllowedClients = string.Empty;
+ protected string m_DeniedClients = string.Empty;
+
private static UUID m_ScopeID;
private static bool m_AllowTeleportsToAnyRegion;
private static string m_ExternalName;
@@ -104,6 +108,9 @@ namespace OpenSim.Services.HypergridService
else if (simulationService != string.Empty)
m_SimulationService = ServerUtils.LoadPlugin(simulationService, args);
+ m_AllowedClients = serverConfig.GetString("AllowedClients", string.Empty);
+ m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty);
+
if (m_GridService == null || m_PresenceService == null || m_SimulationService == null)
throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function.");
@@ -181,8 +188,36 @@ namespace OpenSim.Services.HypergridService
string authURL = string.Empty;
if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
authURL = aCircuit.ServiceURLs["HomeURI"].ToString();
- m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to login foreign agent {0} {1} @ {2} ({3}) at destination {4}",
- aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName);
+ m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9}",
+ aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName,
+ aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0);
+
+ //
+ // Check client
+ //
+ if (m_AllowedClients != string.Empty)
+ {
+ Regex arx = new Regex(m_AllowedClients);
+ Match am = arx.Match(aCircuit.Viewer);
+
+ if (!am.Success)
+ {
+ m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", aCircuit.Viewer);
+ return false;
+ }
+ }
+
+ if (m_DeniedClients != string.Empty)
+ {
+ Regex drx = new Regex(m_DeniedClients);
+ Match dm = drx.Match(aCircuit.Viewer);
+
+ if (dm.Success)
+ {
+ m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", aCircuit.Viewer);
+ return false;
+ }
+ }
//
// Authenticate the user
diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs
index 55c9cc5717..5f9ce6d8b8 100644
--- a/OpenSim/Services/Interfaces/ISimulationService.cs
+++ b/OpenSim/Services/Interfaces/ISimulationService.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Services.Interfaces
bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent);
- bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason);
+ bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason);
///
/// Message from receiving region to departing region, telling it got contacted by the client.
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index d364aa4b9f..9bcc3dd225 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -77,7 +77,11 @@ namespace OpenSim.Services.LLLoginService
protected string m_MapTileURL;
protected string m_SearchURL;
+ protected string m_AllowedClients;
+ protected string m_DeniedClients;
+
IConfig m_LoginServerConfig;
+ IConfig m_ClientsConfig;
public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService)
{
@@ -105,7 +109,10 @@ namespace OpenSim.Services.LLLoginService
m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty);
m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty);
m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty);
-
+
+ m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty);
+ m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty);
+
// These are required; the others aren't
if (accountService == string.Empty || authService == string.Empty)
throw new Exception("LoginService is missing service specifications");
@@ -215,10 +222,37 @@ namespace OpenSim.Services.LLLoginService
bool success = false;
UUID session = UUID.Random();
- m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} from {2} with user agent {3} starting in {4}",
- firstName, lastName, clientIP.Address.ToString(), clientVersion, startLocation);
+ m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} at {2} using viewer {3}, channel {4}, IP {5}, Mac {6}, Id0 {7}",
+ firstName, lastName, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0);
try
{
+ //
+ // Check client
+ //
+ if (m_AllowedClients != string.Empty)
+ {
+ Regex arx = new Regex(m_AllowedClients);
+ Match am = arx.Match(clientVersion);
+
+ if (!am.Success)
+ {
+ m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is not allowed", clientVersion);
+ return LLFailedLoginResponse.LoginBlockedProblem;
+ }
+ }
+
+ if (m_DeniedClients != string.Empty)
+ {
+ Regex drx = new Regex(m_DeniedClients);
+ Match dm = drx.Match(clientVersion);
+
+ if (dm.Success)
+ {
+ m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is denied", clientVersion);
+ return LLFailedLoginResponse.LoginBlockedProblem;
+ }
+ }
+
//
// Get the account and check that it exists
//
diff --git a/README.txt b/README.txt
index 391a6599d1..72702a231d 100644
--- a/README.txt
+++ b/README.txt
@@ -37,7 +37,7 @@ Now see the "Configuring OpenSim" section
=== Running OpenSim on Linux ===
================================
-You will need Mono >= 2.4.2 to run OpenSim. On some Linux distributions you
+You will need Mono >= 2.4.3 to run OpenSim. On some Linux distributions you
may need to install additional packages. See http://opensimulator.org/wiki/Dependencies
for more information.
diff --git a/bin/Axiom.MathLib.dll b/bin/Axiom.MathLib.dll
old mode 100644
new mode 100755
diff --git a/bin/BulletDotNET.dll b/bin/BulletDotNET.dll
old mode 100644
new mode 100755
diff --git a/bin/C5.dll b/bin/C5.dll
old mode 100644
new mode 100755
diff --git a/bin/CSJ2K.dll b/bin/CSJ2K.dll
old mode 100644
new mode 100755
diff --git a/bin/Community.CsharpSqlite.Sqlite.dll b/bin/Community.CsharpSqlite.Sqlite.dll
old mode 100644
new mode 100755
diff --git a/bin/Community.CsharpSqlite.dll b/bin/Community.CsharpSqlite.dll
old mode 100644
new mode 100755
diff --git a/bin/CookComputing.XmlRpcV2.dll b/bin/CookComputing.XmlRpcV2.dll
old mode 100644
new mode 100755
diff --git a/bin/DotNetOpenId.dll b/bin/DotNetOpenId.dll
old mode 100644
new mode 100755
diff --git a/bin/DotNetOpenMail.dll b/bin/DotNetOpenMail.dll
old mode 100644
new mode 100755
diff --git a/bin/Fadd.Globalization.Yaml.dll b/bin/Fadd.Globalization.Yaml.dll
old mode 100644
new mode 100755
diff --git a/bin/Fadd.dll b/bin/Fadd.dll
old mode 100644
new mode 100755
diff --git a/bin/GlynnTucker.Cache.dll b/bin/GlynnTucker.Cache.dll
old mode 100644
new mode 100755
diff --git a/bin/Google.ProtocolBuffers.dll b/bin/Google.ProtocolBuffers.dll
old mode 100644
new mode 100755
diff --git a/bin/HttpServer.dll b/bin/HttpServer.dll
old mode 100644
new mode 100755
diff --git a/bin/HttpServer_OpenSim.dll b/bin/HttpServer_OpenSim.dll
old mode 100644
new mode 100755
diff --git a/bin/Iesi.Collections.dll b/bin/Iesi.Collections.dll
old mode 100644
new mode 100755
diff --git a/bin/Kds.Serialization.dll b/bin/Kds.Serialization.dll
old mode 100644
new mode 100755
diff --git a/bin/Modified.XnaDevRu.BulletX.dll b/bin/Modified.XnaDevRu.BulletX.dll
old mode 100644
new mode 100755
diff --git a/bin/Mono.Addins.CecilReflector.dll b/bin/Mono.Addins.CecilReflector.dll
old mode 100644
new mode 100755
diff --git a/bin/Mono.Addins.Setup.dll b/bin/Mono.Addins.Setup.dll
old mode 100644
new mode 100755
diff --git a/bin/Mono.Addins.dll b/bin/Mono.Addins.dll
old mode 100644
new mode 100755
diff --git a/bin/Mono.Data.Sqlite.dll b/bin/Mono.Data.Sqlite.dll
old mode 100644
new mode 100755
diff --git a/bin/Mono.Data.SqliteClient.dll b/bin/Mono.Data.SqliteClient.dll
old mode 100644
new mode 100755
diff --git a/bin/MonoXnaCompactMaths.dll b/bin/MonoXnaCompactMaths.dll
old mode 100644
new mode 100755
diff --git a/bin/MySql.Data.dll b/bin/MySql.Data.dll
old mode 100644
new mode 100755
diff --git a/bin/NDesk.Options.dll b/bin/NDesk.Options.dll
old mode 100644
new mode 100755
diff --git a/bin/Newtonsoft.Json.Net20.dll b/bin/Newtonsoft.Json.Net20.dll
old mode 100644
new mode 100755
diff --git a/bin/Nini.dll b/bin/Nini.dll
old mode 100644
new mode 100755
diff --git a/bin/Npgsql.dll b/bin/Npgsql.dll
old mode 100644
new mode 100755
diff --git a/bin/Ode.NET.dll b/bin/Ode.NET.dll
old mode 100644
new mode 100755
diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll
old mode 100644
new mode 100755
diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll
old mode 100644
new mode 100755
diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll
old mode 100644
new mode 100755
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index fbaa590aed..5389b4455a 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -626,7 +626,7 @@
; LocalServiceModule = OpenSim.Services.Connectors.dll:RemoteFreeswitchConnector
;; If using a remote connector, specify the server URL
- ; FreeswitchServiceURL = http://my.grid.server:8003/fsapi
+ ; FreeswitchServiceURL = http://my.grid.server:8004/fsapi
[FreeswitchService]
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 02fa7c5c97..8807444272 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -362,30 +362,24 @@
;
;client_throttle_max_bps = 196608
- ; Per-client bytes per second rates for the various throttle categories.
- ; These are default values that will be overriden by clients
+ ; Adaptive throttling attempts to limit network overload when multiple
+ ; clients login by starting each connection more slowly. Disabled by
+ ; default
;
- ;resend_default = 12500
- ;land_default = 1000
- ;wind_default = 1000
- ;cloud_default = 1000
- ;task_default = 1000
- ;texture_default = 1000
- ;asset_default = 1000
- ;state_default = 1000
+ ;enable_adaptive_throttles = true
- ; Per-client maximum burst rates in bytes per second for the various
- ; throttle categories. These are default values that will be overriden by
- ; clients
- ;
- ;resend_limit = 18750
- ;land_limit = 29750
- ;wind_limit = 18750
- ;cloud_limit = 18750
- ;task_limit = 18750
- ;texture_limit = 55750
- ;asset_limit = 27500
- ;state_limit = 37000
+ ; Per-client bytes per second rates for the various throttle categories.
+ ; These are default values that will be overriden by clients. These
+ ; defaults are approximately equivalent to the throttles set by the Imprudence
+ ; viewer when maximum bandwidth is set to 350kbps
+
+ ;resend_default = 6625
+ ;land_default = 9125
+ ;wind_default = 1750
+ ;cloud_default = 1750
+ ;task_default = 18500
+ ;texture_default = 18500
+ ;asset_default = 10500
; Configures how ObjectUpdates are aggregated. These numbers
; do not literally mean how many updates will be put in each
diff --git a/bin/PhysX-wrapper.dll b/bin/PhysX-wrapper.dll
old mode 100644
new mode 100755
diff --git a/bin/PhysX_Wrapper_Dotnet.dll b/bin/PhysX_Wrapper_Dotnet.dll
old mode 100644
new mode 100755
diff --git a/bin/PrimMesher.dll b/bin/PrimMesher.dll
old mode 100644
new mode 100755
diff --git a/bin/PumaCode.SvnDotNet.dll b/bin/PumaCode.SvnDotNet.dll
old mode 100644
new mode 100755
diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example
index e2e9624831..572497c0b3 100644
--- a/bin/Robust.HG.ini.example
+++ b/bin/Robust.HG.ini.example
@@ -21,7 +21,7 @@
; * [[@]/][:]
; *
[Startup]
-ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8002/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector"
+ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector"
; * This is common for all services, it's the network setup for the entire
; * server instance, if none is specified above
@@ -197,6 +197,23 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
SRV_AssetServerURI = "http://127.0.0.1:8002"
SRV_ProfileServerURI = "http://127.0.0.1:8002/user"
+ ;; Regular expressions for controlling which client versions are accepted/denied.
+ ;; An empty string means nothing is checked.
+ ;;
+ ;; Example 1: allow only these 3 types of clients (any version of them)
+ ;; AllowedClients = "Imprudence|Hippo|Second Life"
+ ;;
+ ;; Example 2: allow all clients except these
+ ;; DeniedClients = "Twisted|Crawler|Cryolife|FuckLife|StreetLife|GreenLife|AntiLife|KORE-Phaze|Synlyfe|Purple Second Life|SecondLi |Emerald"
+ ;;
+ ;; Note that these are regular expressions, so every character counts.
+ ;; Also note that this is very weak security and should not be trusted as a reliable means
+ ;; for keeping bad clients out; modified clients can fake their identifiers.
+ ;;
+ ;;
+ ;AllowedClients = ""
+ ;DeniedClients = ""
+
[GridInfoService]
; These settings are used to return information on a get_grid_info call.
; Client launcher scripts and third-party clients make use of this to
@@ -256,6 +273,22 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
; If you run this gatekeeper server behind a proxy, set this to true
; HasProxy = false
+ ;; Regular expressions for controlling which client versions are accepted/denied.
+ ;; An empty string means nothing is checked.
+ ;;
+ ;; Example 1: allow only these 3 types of clients (any version of them)
+ ;; AllowedClients = "Imprudence|Hippo|Second Life"
+ ;;
+ ;; Example 2: allow all clients except these
+ ;; DeniedClients = "Twisted|Crawler|Cryolife|FuckLife|StreetLife|GreenLife|AntiLife|KORE-Phaze|Synlyfe|Purple Second Life|SecondLi |Emerald"
+ ;;
+ ;; Note that these are regular expressions, so every character counts.
+ ;; Also note that this is very weak security and should not be trusted as a reliable means
+ ;; for keeping bad clients out; modified clients can fake their identifiers.
+ ;;
+ ;;
+ ;AllowedClients = ""
+ ;DeniedClients = ""
[UserAgentService]
LocalServiceModule = "OpenSim.Services.HypergridService.dll:UserAgentService"
diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example
index 4d16236044..047e9eeed6 100644
--- a/bin/Robust.ini.example
+++ b/bin/Robust.ini.example
@@ -13,7 +13,7 @@
; * [[@]/][:]
; *
[Startup]
-ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8002/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
+ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
; * This is common for all services, it's the network setup for the entire
; * server instance, if none is specified above
@@ -176,6 +176,23 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
; If you run this login server behind a proxy, set this to true
; HasProxy = false
+ ;; Regular expressions for controlling which client versions are accepted/denied.
+ ;; An empty string means nothing is checked.
+ ;;
+ ;; Example 1: allow only these 3 types of clients (any version of them)
+ ;; AllowedClients = "Imprudence|Hippo|Second Life"
+ ;;
+ ;; Example 2: allow all clients except these
+ ;; DeniedClients = "Twisted|Crawler|Cryolife|FuckLife|StreetLife|GreenLife|AntiLife|KORE-Phaze|Synlyfe|Purple Second Life|SecondLi |Emerald"
+ ;;
+ ;; Note that these are regular expressions, so every character counts.
+ ;; Also note that this is very weak security and should not be trusted as a reliable means
+ ;; for keeping bad clients out; modified clients can fake their identifiers.
+ ;;
+ ;;
+ ;AllowedClients = ""
+ ;DeniedClients = ""
+
[GridInfoService]
; These settings are used to return information on a get_grid_info call.
; Client launcher scripts and third-party clients make use of this to
diff --git a/bin/Tools.dll b/bin/Tools.dll
old mode 100644
new mode 100755
diff --git a/bin/Warp3D.dll b/bin/Warp3D.dll
old mode 100644
new mode 100755
diff --git a/bin/XMLRPC.dll b/bin/XMLRPC.dll
old mode 100644
new mode 100755
diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example
index dcebd63184..67efa11564 100644
--- a/bin/config-include/StandaloneCommon.ini.example
+++ b/bin/config-include/StandaloneCommon.ini.example
@@ -83,6 +83,23 @@
SRV_AssetServerURI = "http://127.0.0.1:9000"
SRV_ProfileServerURI = "http://127.0.0.1:9000"
+ ;; Regular expressions for controlling which client versions are accepted/denied.
+ ;; An empty string means nothing is checked.
+ ;;
+ ;; Example 1: allow only these 3 types of clients (any version of them)
+ ;; AllowedClients = "Imprudence|Hippo|Second Life"
+ ;;
+ ;; Example 2: allow all clients except these
+ ;; DeniedClients = "Twisted|Crawler|Cryolife|FuckLife|StreetLife|GreenLife|AntiLife|KORE-Phaze|Synlyfe|Purple Second Life|SecondLi |Emerald"
+ ;;
+ ;; Note that these are regular expressions, so every character counts.
+ ;; Also note that this is very weak security and should not be trusted as a reliable means
+ ;; for keeping bad clients out; modified clients can fake their identifiers.
+ ;;
+ ;;
+ ;AllowedClients = ""
+ ;DeniedClients = ""
+
[GatekeeperService]
ExternalName = "http://127.0.0.1:9000"
@@ -90,6 +107,23 @@
; If false, HG TPs happen only to the Default regions specified in [GridService] section
AllowTeleportsToAnyRegion = true
+ ;; Regular expressions for controlling which client versions are accepted/denied.
+ ;; An empty string means nothing is checked.
+ ;;
+ ;; Example 1: allow only these 3 types of clients (any version of them)
+ ;; AllowedClients = "Imprudence|Hippo|Second Life"
+ ;;
+ ;; Example 2: allow all clients except these
+ ;; DeniedClients = "Twisted|Crawler|Cryolife|FuckLife|StreetLife|GreenLife|AntiLife|KORE-Phaze|Synlyfe|Purple Second Life|SecondLi |Emerald"
+ ;;
+ ;; Note that these are regular expressions, so every character counts.
+ ;; Also note that this is very weak security and should not be trusted as a reliable means
+ ;; for keeping bad clients out; modified clients can fake their identifiers.
+ ;;
+ ;;
+ ;AllowedClients = ""
+ ;DeniedClients = ""
+
[GridInfoService]
; These settings are used to return information on a get_grid_info call.
; Client launcher scripts and third-party clients make use of this to
diff --git a/bin/libbulletnet.dll b/bin/libbulletnet.dll
old mode 100644
new mode 100755
diff --git a/bin/libdb_dotNET43.dll b/bin/libdb_dotNET43.dll
old mode 100644
new mode 100755
diff --git a/bin/log4net.dll b/bin/log4net.dll
old mode 100644
new mode 100755
diff --git a/bin/nunit.framework.dll b/bin/nunit.framework.dll
old mode 100644
new mode 100755
diff --git a/bin/ode.dll b/bin/ode.dll
old mode 100644
new mode 100755
diff --git a/bin/openjpeg-dotnet-x86_64.dll b/bin/openjpeg-dotnet-x86_64.dll
old mode 100644
new mode 100755
diff --git a/bin/openjpeg-dotnet.dll b/bin/openjpeg-dotnet.dll
old mode 100644
new mode 100755
diff --git a/bin/xunit.dll b/bin/xunit.dll
old mode 100644
new mode 100755
diff --git a/bin/zlib.net.dll b/bin/zlib.net.dll
old mode 100644
new mode 100755