From d51ce47b2d7635b17f3dd429158e8f59b78b83aa Mon Sep 17 00:00:00 2001
From: Jeff Ames
Date: Thu, 1 May 2008 14:31:30 +0000
Subject: Update svn properties. Minor formatting cleanup.
---
OpenSim/Data/MySQL/Resources/CreateLandTable.sql | 76 +-
.../MySQL/Resources/UpgradeLandTableToVersion2.sql | 4 +-
OpenSim/Framework/Location.cs | 128 +-
OpenSim/Region/Application/OpenSimMain.cs | 1 -
.../Agent/AssetDownload/AssetDownloadModule.cs | 454 +--
.../AssetTransaction/AgentAssetsTransactions.cs | 822 +++---
.../AssetTransaction/AssetTransactionModule.cs | 580 ++--
.../Agent/TextureDownload/TextureDownloadModule.cs | 436 +--
.../Agent/TextureDownload/TextureNotFoundSender.cs | 194 +-
.../TextureDownload/UserTextureDownloadService.cs | 496 ++--
.../Modules/Agent/TextureSender/TextureSender.cs | 444 +--
.../Environment/Modules/Agent/Xfer/XferModule.cs | 468 ++--
.../Avatar/AvatarFactory/AvatarFactoryModule.cs | 676 ++---
.../Environment/Modules/Avatar/Chat/ChatModule.cs | 1734 ++++++------
.../Currency/SampleMoney/SampleMoneyModule.cs | 2938 ++++++++++----------
.../Modules/Avatar/Friends/FriendsModule.cs | 1000 +++----
.../Modules/Avatar/Groups/GroupsModule.cs | 544 ++--
.../Avatar/InstantMessage/InstantMessageModule.cs | 314 +--
.../Modules/Avatar/Inventory/InventoryModule.cs | 438 +--
.../Avatar/Profiles/AvatarProfilesModule.cs | 264 +-
.../Voice/AsterixVoice/AsteriskVoiceModule.cs | 578 ++--
.../Avatar/Voice/SIPVoice/SIPVoiceModule.cs | 398 +--
.../Environment/Modules/Framework/Commander.cs | 614 ++--
.../Modules/Framework/CommanderTestModule.cs | 174 +-
.../Modules/Grid/Interregion/IInterregionModule.cs | 30 +-
.../Modules/Grid/Interregion/InterregionModule.cs | 358 +--
.../Modules/Grid/Interregion/RemotingObject.cs | 98 +-
.../DynamicTexture/DynamicTextureModule.cs | 564 ++--
.../Scripting/HttpRequest/ScriptsHttpRequests.cs | 726 ++---
.../Scripting/LoadImageURL/LoadImageURLModule.cs | 380 +--
.../Scripting/VectorRender/VectorRenderModule.cs | 736 ++---
.../Modules/Scripting/WorldComm/WorldCommModule.cs | 1168 ++++----
.../Modules/Scripting/XMLRPC/XMLRPCModule.cs | 1342 ++++-----
.../Environment/Modules/World/Land/LandChannel.cs | 1998 ++++++-------
.../Modules/World/Land/LandManagementModule.cs | 156 +-
.../Environment/Modules/World/Land/LandObject.cs | 1854 ++++++------
.../Modules/World/Serialiser/IFileSerialiser.cs | 70 +-
.../Modules/World/Serialiser/IRegionSerialiser.cs | 72 +-
.../Modules/World/Serialiser/SerialiseObjects.cs | 248 +-
.../Modules/World/Serialiser/SerialiseTerrain.cs | 104 +-
.../Modules/World/Serialiser/SerialiserModule.cs | 336 +--
.../Environment/Modules/World/Sun/SunModule.cs | 396 +--
.../Modules/World/Terrain/Effects/CookieCutter.cs | 246 +-
.../Terrain/Effects/DefaultTerrainGenerator.cs | 108 +-
.../Modules/World/Terrain/FileLoaders/BMP.cs | 122 +-
.../Modules/World/Terrain/FileLoaders/GIF.cs | 92 +-
.../Terrain/FileLoaders/GenericSystemDrawing.cs | 342 +--
.../Modules/World/Terrain/FileLoaders/JPEG.cs | 186 +-
.../Modules/World/Terrain/FileLoaders/LLRAW.cs | 294 +-
.../Modules/World/Terrain/FileLoaders/PNG.cs | 92 +-
.../Modules/World/Terrain/FileLoaders/RAW32.cs | 304 +-
.../Modules/World/Terrain/FileLoaders/TIFF.cs | 92 +-
.../Modules/World/Terrain/FileLoaders/Terragen.cs | 252 +-
.../World/Terrain/FloodBrushes/FlattenArea.cs | 140 +-
.../World/Terrain/FloodBrushes/LowerArea.cs | 106 +-
.../World/Terrain/FloodBrushes/NoiseArea.cs | 110 +-
.../World/Terrain/FloodBrushes/RaiseArea.cs | 104 +-
.../World/Terrain/FloodBrushes/RevertArea.cs | 118 +-
.../World/Terrain/FloodBrushes/SmoothArea.cs | 226 +-
.../Modules/World/Terrain/ITerrainEffect.cs | 70 +-
.../Modules/World/Terrain/ITerrainFloodEffect.cs | 72 +-
.../Modules/World/Terrain/ITerrainLoader.cs | 76 +-
.../Modules/World/Terrain/ITerrainModule.cs | 14 +-
.../World/Terrain/ITerrainPaintableEffect.cs | 70 +-
.../Modules/World/Terrain/MapImageModule.cs | 334 +--
.../World/Terrain/PaintBrushes/ErodeSphere.cs | 622 ++---
.../World/Terrain/PaintBrushes/FlattenSphere.cs | 186 +-
.../World/Terrain/PaintBrushes/LowerSphere.cs | 132 +-
.../World/Terrain/PaintBrushes/NoiseSphere.cs | 138 +-
.../World/Terrain/PaintBrushes/OlsenSphere.cs | 448 +--
.../World/Terrain/PaintBrushes/RaiseSphere.cs | 132 +-
.../World/Terrain/PaintBrushes/RevertSphere.cs | 162 +-
.../World/Terrain/PaintBrushes/SmoothSphere.cs | 184 +-
.../World/Terrain/PaintBrushes/WeatherSphere.cs | 412 +--
.../Modules/World/Terrain/TerrainChannel.cs | 312 +--
.../Modules/World/Terrain/TerrainException.cs | 90 +-
.../Modules/World/Terrain/TerrainModule.cs | 1470 +++++-----
.../Modules/World/Terrain/TerrainUtil.cs | 264 +-
.../Modules/World/Terrain/Tests/TerrainTest.cs | 116 +-
.../World/TreePopulator/TreePopulatorModule.cs | 500 ++--
OpenSim/Region/Environment/Scenes/Scene.cs | 3 -
OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 30 +-
82 files changed, 16583 insertions(+), 16599 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Data/MySQL/Resources/CreateLandTable.sql b/OpenSim/Data/MySQL/Resources/CreateLandTable.sql
index 8a1b626..6c7254a 100644
--- a/OpenSim/Data/MySQL/Resources/CreateLandTable.sql
+++ b/OpenSim/Data/MySQL/Resources/CreateLandTable.sql
@@ -1,39 +1,39 @@
-CREATE TABLE `land`
- (
- `UUID` varchar (255) NOT NULL,
- `RegionUUID` varchar (255) DEFAULT NULL ,
- `LocalLandID` int (11) DEFAULT NULL ,
- `Bitmap` longblob,
- `Name` varchar (255) DEFAULT NULL ,
- `Description` varchar (255) DEFAULT NULL ,
- `OwnerUUID` varchar (255) DEFAULT NULL ,
- `IsGroupOwned` int (11) DEFAULT NULL ,
- `Area` int (11) DEFAULT NULL ,
- `AuctionID` int (11) DEFAULT NULL ,
- `Category` int (11) DEFAULT NULL ,
- `ClaimDate` int (11) DEFAULT NULL ,
- `ClaimPrice` int (11) DEFAULT NULL ,
- `GroupUUID` varchar (255) DEFAULT NULL ,
- `SalePrice` int (11) DEFAULT NULL ,
- `LandStatus` int (11) DEFAULT NULL ,
- `LandFlags` int (11) DEFAULT NULL ,
- `LandingType` int (11) DEFAULT NULL ,
- `MediaAutoScale` int (11) DEFAULT NULL ,
- `MediaTextureUUID` varchar (255) DEFAULT NULL ,
- `MediaURL` varchar (255) DEFAULT NULL ,
- `MusicURL` varchar (255) DEFAULT NULL ,
- `PassHours` float DEFAULT NULL ,
- `PassPrice` int (11) DEFAULT NULL ,
- `SnapshotUUID` varchar (255) DEFAULT NULL ,
- `UserLocationX` float DEFAULT NULL ,
- `UserLocationY` float DEFAULT NULL ,
- `UserLocationZ` float DEFAULT NULL ,
- `UserLookAtX` float DEFAULT NULL ,
- `UserLookAtY` float DEFAULT NULL ,
- `UserLookAtZ` float DEFAULT NULL ,
- `AuthbuyerID` varchar(36) default '00000000-0000-0000-0000-000000000000' not null,
-
- PRIMARY KEY (`UUID`)
- )
- ENGINE=INNODB
+CREATE TABLE `land`
+ (
+ `UUID` varchar (255) NOT NULL,
+ `RegionUUID` varchar (255) DEFAULT NULL ,
+ `LocalLandID` int (11) DEFAULT NULL ,
+ `Bitmap` longblob,
+ `Name` varchar (255) DEFAULT NULL ,
+ `Description` varchar (255) DEFAULT NULL ,
+ `OwnerUUID` varchar (255) DEFAULT NULL ,
+ `IsGroupOwned` int (11) DEFAULT NULL ,
+ `Area` int (11) DEFAULT NULL ,
+ `AuctionID` int (11) DEFAULT NULL ,
+ `Category` int (11) DEFAULT NULL ,
+ `ClaimDate` int (11) DEFAULT NULL ,
+ `ClaimPrice` int (11) DEFAULT NULL ,
+ `GroupUUID` varchar (255) DEFAULT NULL ,
+ `SalePrice` int (11) DEFAULT NULL ,
+ `LandStatus` int (11) DEFAULT NULL ,
+ `LandFlags` int (11) DEFAULT NULL ,
+ `LandingType` int (11) DEFAULT NULL ,
+ `MediaAutoScale` int (11) DEFAULT NULL ,
+ `MediaTextureUUID` varchar (255) DEFAULT NULL ,
+ `MediaURL` varchar (255) DEFAULT NULL ,
+ `MusicURL` varchar (255) DEFAULT NULL ,
+ `PassHours` float DEFAULT NULL ,
+ `PassPrice` int (11) DEFAULT NULL ,
+ `SnapshotUUID` varchar (255) DEFAULT NULL ,
+ `UserLocationX` float DEFAULT NULL ,
+ `UserLocationY` float DEFAULT NULL ,
+ `UserLocationZ` float DEFAULT NULL ,
+ `UserLookAtX` float DEFAULT NULL ,
+ `UserLookAtY` float DEFAULT NULL ,
+ `UserLookAtZ` float DEFAULT NULL ,
+ `AuthbuyerID` varchar(36) default '00000000-0000-0000-0000-000000000000' not null,
+
+ PRIMARY KEY (`UUID`)
+ )
+ ENGINE=INNODB
DEFAULT CHARSET=utf8 COMMENT='Rev. 2';
\ No newline at end of file
diff --git a/OpenSim/Data/MySQL/Resources/UpgradeLandTableToVersion2.sql b/OpenSim/Data/MySQL/Resources/UpgradeLandTableToVersion2.sql
index eb024be..c5c55f1 100644
--- a/OpenSim/Data/MySQL/Resources/UpgradeLandTableToVersion2.sql
+++ b/OpenSim/Data/MySQL/Resources/UpgradeLandTableToVersion2.sql
@@ -1,3 +1,3 @@
-ALTER TABLE `land`
- ADD COLUMN `AuthbuyerID` varchar(36) default '00000000-0000-0000-0000-000000000000' not null,
+ALTER TABLE `land`
+ ADD COLUMN `AuthbuyerID` varchar(36) default '00000000-0000-0000-0000-000000000000' not null,
COMMENT='Rev. 2';
\ No newline at end of file
diff --git a/OpenSim/Framework/Location.cs b/OpenSim/Framework/Location.cs
index 24430c6..4019a79 100644
--- a/OpenSim/Framework/Location.cs
+++ b/OpenSim/Framework/Location.cs
@@ -1,65 +1,65 @@
-using System;
-
-namespace OpenSim.Framework
-{
- [Serializable]
- public class Location : ICloneable
- {
- private readonly int m_x;
- private readonly int m_y;
-
- public Location(int x, int y)
- {
- m_x = x;
- m_y = y;
- }
-
- public int X
- {
- get { return m_x; }
- }
-
- public int Y
- {
- get { return m_y; }
- }
-
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(obj, this))
- return true;
-
- if (obj is Location)
- {
- return Equals((Location) obj);
- }
-
- return base.Equals(obj);
- }
-
- public bool Equals(Location loc)
- {
- return loc.X == X && loc.Y == Y;
- }
-
- public bool Equals(int x, int y)
- {
- return X == x && y == Y;
- }
-
- public UInt64 RegionHandle
- {
- get { return UInt64.MinValue; }
- }
-
- public override int GetHashCode()
- {
- return X.GetHashCode() * 29 + Y.GetHashCode();
- }
-
- public object Clone()
- {
- return new Location(X, Y);
- }
- }
+using System;
+
+namespace OpenSim.Framework
+{
+ [Serializable]
+ public class Location : ICloneable
+ {
+ private readonly int m_x;
+ private readonly int m_y;
+
+ public Location(int x, int y)
+ {
+ m_x = x;
+ m_y = y;
+ }
+
+ public int X
+ {
+ get { return m_x; }
+ }
+
+ public int Y
+ {
+ get { return m_y; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(obj, this))
+ return true;
+
+ if (obj is Location)
+ {
+ return Equals((Location) obj);
+ }
+
+ return base.Equals(obj);
+ }
+
+ public bool Equals(Location loc)
+ {
+ return loc.X == X && loc.Y == Y;
+ }
+
+ public bool Equals(int x, int y)
+ {
+ return X == x && y == Y;
+ }
+
+ public UInt64 RegionHandle
+ {
+ get { return UInt64.MinValue; }
+ }
+
+ public override int GetHashCode()
+ {
+ return X.GetHashCode() * 29 + Y.GetHashCode();
+ }
+
+ public object Clone()
+ {
+ return new Location(X, Y);
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs
index d05a632..cad0380 100644
--- a/OpenSim/Region/Application/OpenSimMain.cs
+++ b/OpenSim/Region/Application/OpenSimMain.cs
@@ -588,7 +588,6 @@ namespace OpenSim
m_moduleLoader, m_dumpAssetsToFile, m_physicalPrim, m_see_into_region_from_neighbor);
}
-
public void handleRestartRegion(RegionInfo whichRegion)
{
m_log.Error("[OPENSIM MAIN]: Got restart signal from SceneManager");
diff --git a/OpenSim/Region/Environment/Modules/Agent/AssetDownload/AssetDownloadModule.cs b/OpenSim/Region/Environment/Modules/Agent/AssetDownload/AssetDownloadModule.cs
index c0b7380..48db51b 100644
--- a/OpenSim/Region/Environment/Modules/Agent/AssetDownload/AssetDownloadModule.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/AssetDownload/AssetDownloadModule.cs
@@ -1,228 +1,228 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System.Collections.Generic;
-using libsecondlife;
-using libsecondlife.Packets;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Agent.AssetDownload
-{
- public class AssetDownloadModule : IRegionModule
- {
- ///
- /// Asset requests with data which are ready to be sent back to requesters. This includes textures.
- ///
- private List AssetRequests;
-
- private Scene m_scene;
- private Dictionary RegisteredScenes = new Dictionary();
-
- ///
- /// Assets requests (for each user) which are waiting for asset server data. This includes texture requests
- ///
- private Dictionary> RequestedAssets;
-
- public AssetDownloadModule()
- {
- RequestedAssets = new Dictionary>();
- AssetRequests = new List();
- }
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
- {
- RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
- // scene.EventManager.OnNewClient += NewClient;
- }
-
- if (m_scene == null)
- {
- m_scene = scene;
- // m_thread = new Thread(new ThreadStart(RunAssetQueue));
- // m_thread.Name = "AssetDownloadQueueThread";
- // m_thread.IsBackground = true;
- // m_thread.Start();
- // OpenSim.Framework.ThreadTracker.Add(m_thread);
- }
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "AssetDownloadModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return true; }
- }
-
- #endregion
-
- public void NewClient(IClientAPI client)
- {
- // client.OnRequestAsset += AddAssetRequest;
- }
-
- ///
- /// Make an asset request the result of which will be packeted up and sent directly back to the client.
- ///
- ///
- ///
- public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest)
- {
- LLUUID requestID = null;
- byte source = 2;
- if (transferRequest.TransferInfo.SourceType == 2)
- {
- //direct asset request
- requestID = new LLUUID(transferRequest.TransferInfo.Params, 0);
- }
- else if (transferRequest.TransferInfo.SourceType == 3)
- {
- //inventory asset request
- requestID = new LLUUID(transferRequest.TransferInfo.Params, 80);
- source = 3;
- //Console.WriteLine("asset request " + requestID);
- }
-
- //not found asset
- // so request from asset server
- Dictionary userRequests = null;
- if (RequestedAssets.TryGetValue(userInfo.AgentId, out userRequests))
- {
- if (!userRequests.ContainsKey(requestID))
- {
- AssetRequest request = new AssetRequest();
- request.RequestUser = userInfo;
- request.RequestAssetID = requestID;
- request.TransferRequestID = transferRequest.TransferInfo.TransferID;
- request.AssetRequestSource = source;
- request.Params = transferRequest.TransferInfo.Params;
- userRequests[requestID] = request;
- m_scene.AssetCache.GetAsset(requestID, AssetCallback, false);
- }
- }
- else
- {
- userRequests = new Dictionary();
- AssetRequest request = new AssetRequest();
- request.RequestUser = userInfo;
- request.RequestAssetID = requestID;
- request.TransferRequestID = transferRequest.TransferInfo.TransferID;
- request.AssetRequestSource = source;
- request.Params = transferRequest.TransferInfo.Params;
- userRequests.Add(requestID, request);
- RequestedAssets[userInfo.AgentId] = userRequests;
- m_scene.AssetCache.GetAsset(requestID, AssetCallback, false);
- }
- }
-
- public void AssetCallback(LLUUID assetID, AssetBase asset)
- {
- if (asset != null)
- {
- foreach (Dictionary userRequests in RequestedAssets.Values)
- {
- if (userRequests.ContainsKey(assetID))
- {
- AssetRequest req = userRequests[assetID];
- if (req != null)
- {
- req.AssetInf = asset;
- req.NumPackets = CalculateNumPackets(asset.Data);
-
- userRequests.Remove(assetID);
- AssetRequests.Add(req);
- }
- }
- }
- }
- }
-
- ///
- /// Calculate the number of packets required to send the asset to the client.
- ///
- ///
- ///
- private int CalculateNumPackets(byte[] data)
- {
- const uint m_maxPacketSize = 600;
- int numPackets = 1;
-
- if (data.LongLength > m_maxPacketSize)
- {
- // over max number of bytes so split up file
- long restData = data.LongLength - m_maxPacketSize;
- int restPackets = (int) ((restData + m_maxPacketSize - 1) / m_maxPacketSize);
- numPackets += restPackets;
- }
-
- return numPackets;
- }
-
- #region Nested type: AssetRequest
-
- public class AssetRequest
- {
- public AssetBase AssetInf;
- public byte AssetRequestSource = 2;
- public long DataPointer = 0;
- public int DiscardLevel = -1;
- public AssetBase ImageInfo;
- public bool IsTextureRequest;
- public int NumPackets = 0;
- public int PacketCounter = 0;
- public byte[] Params = null;
- public LLUUID RequestAssetID;
- public IClientAPI RequestUser;
- public LLUUID TransferRequestID;
- //public bool AssetInCache;
- //public int TimeRequested;
-
- public AssetRequest()
- {
- }
- }
-
- #endregion
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.Collections.Generic;
+using libsecondlife;
+using libsecondlife.Packets;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Agent.AssetDownload
+{
+ public class AssetDownloadModule : IRegionModule
+ {
+ ///
+ /// Asset requests with data which are ready to be sent back to requesters. This includes textures.
+ ///
+ private List AssetRequests;
+
+ private Scene m_scene;
+ private Dictionary RegisteredScenes = new Dictionary();
+
+ ///
+ /// Assets requests (for each user) which are waiting for asset server data. This includes texture requests
+ ///
+ private Dictionary> RequestedAssets;
+
+ public AssetDownloadModule()
+ {
+ RequestedAssets = new Dictionary>();
+ AssetRequests = new List();
+ }
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
+ {
+ RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
+ // scene.EventManager.OnNewClient += NewClient;
+ }
+
+ if (m_scene == null)
+ {
+ m_scene = scene;
+ // m_thread = new Thread(new ThreadStart(RunAssetQueue));
+ // m_thread.Name = "AssetDownloadQueueThread";
+ // m_thread.IsBackground = true;
+ // m_thread.Start();
+ // OpenSim.Framework.ThreadTracker.Add(m_thread);
+ }
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "AssetDownloadModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return true; }
+ }
+
+ #endregion
+
+ public void NewClient(IClientAPI client)
+ {
+ // client.OnRequestAsset += AddAssetRequest;
+ }
+
+ ///
+ /// Make an asset request the result of which will be packeted up and sent directly back to the client.
+ ///
+ ///
+ ///
+ public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest)
+ {
+ LLUUID requestID = null;
+ byte source = 2;
+ if (transferRequest.TransferInfo.SourceType == 2)
+ {
+ //direct asset request
+ requestID = new LLUUID(transferRequest.TransferInfo.Params, 0);
+ }
+ else if (transferRequest.TransferInfo.SourceType == 3)
+ {
+ //inventory asset request
+ requestID = new LLUUID(transferRequest.TransferInfo.Params, 80);
+ source = 3;
+ //Console.WriteLine("asset request " + requestID);
+ }
+
+ //not found asset
+ // so request from asset server
+ Dictionary userRequests = null;
+ if (RequestedAssets.TryGetValue(userInfo.AgentId, out userRequests))
+ {
+ if (!userRequests.ContainsKey(requestID))
+ {
+ AssetRequest request = new AssetRequest();
+ request.RequestUser = userInfo;
+ request.RequestAssetID = requestID;
+ request.TransferRequestID = transferRequest.TransferInfo.TransferID;
+ request.AssetRequestSource = source;
+ request.Params = transferRequest.TransferInfo.Params;
+ userRequests[requestID] = request;
+ m_scene.AssetCache.GetAsset(requestID, AssetCallback, false);
+ }
+ }
+ else
+ {
+ userRequests = new Dictionary();
+ AssetRequest request = new AssetRequest();
+ request.RequestUser = userInfo;
+ request.RequestAssetID = requestID;
+ request.TransferRequestID = transferRequest.TransferInfo.TransferID;
+ request.AssetRequestSource = source;
+ request.Params = transferRequest.TransferInfo.Params;
+ userRequests.Add(requestID, request);
+ RequestedAssets[userInfo.AgentId] = userRequests;
+ m_scene.AssetCache.GetAsset(requestID, AssetCallback, false);
+ }
+ }
+
+ public void AssetCallback(LLUUID assetID, AssetBase asset)
+ {
+ if (asset != null)
+ {
+ foreach (Dictionary userRequests in RequestedAssets.Values)
+ {
+ if (userRequests.ContainsKey(assetID))
+ {
+ AssetRequest req = userRequests[assetID];
+ if (req != null)
+ {
+ req.AssetInf = asset;
+ req.NumPackets = CalculateNumPackets(asset.Data);
+
+ userRequests.Remove(assetID);
+ AssetRequests.Add(req);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Calculate the number of packets required to send the asset to the client.
+ ///
+ ///
+ ///
+ private int CalculateNumPackets(byte[] data)
+ {
+ const uint m_maxPacketSize = 600;
+ int numPackets = 1;
+
+ if (data.LongLength > m_maxPacketSize)
+ {
+ // over max number of bytes so split up file
+ long restData = data.LongLength - m_maxPacketSize;
+ int restPackets = (int) ((restData + m_maxPacketSize - 1) / m_maxPacketSize);
+ numPackets += restPackets;
+ }
+
+ return numPackets;
+ }
+
+ #region Nested type: AssetRequest
+
+ public class AssetRequest
+ {
+ public AssetBase AssetInf;
+ public byte AssetRequestSource = 2;
+ public long DataPointer = 0;
+ public int DiscardLevel = -1;
+ public AssetBase ImageInfo;
+ public bool IsTextureRequest;
+ public int NumPackets = 0;
+ public int PacketCounter = 0;
+ public byte[] Params = null;
+ public LLUUID RequestAssetID;
+ public IClientAPI RequestUser;
+ public LLUUID TransferRequestID;
+ //public bool AssetInCache;
+ //public int TimeRequested;
+
+ public AssetRequest()
+ {
+ }
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index 8192be4..555d5f4 100644
--- a/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -1,412 +1,412 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using libsecondlife;
-using libsecondlife.Packets;
-using OpenSim.Framework;
-using OpenSim.Framework.Communications.Cache;
-
-namespace OpenSim.Region.Environment.Modules.Agent.AssetTransaction
-{
- ///
- /// Manage asset transactions for a single agent.
- ///
- public class AgentAssetTransactions
- {
- //private static readonly log4net.ILog m_log
- // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
-
- // Fields
- private bool m_dumpAssetsToFile;
- public AgentAssetTransactionsManager Manager;
- public LLUUID UserID;
- public Dictionary XferUploaders = new Dictionary();
-
- // Methods
- public AgentAssetTransactions(LLUUID agentID, AgentAssetTransactionsManager manager, bool dumpAssetsToFile)
- {
- UserID = agentID;
- Manager = manager;
- m_dumpAssetsToFile = dumpAssetsToFile;
- }
-
- public AssetXferUploader RequestXferUploader(LLUUID transactionID)
- {
- if (!XferUploaders.ContainsKey(transactionID))
- {
- AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile);
-
- lock (XferUploaders)
- {
- XferUploaders.Add(transactionID, uploader);
- }
-
- return uploader;
- }
- return null;
- }
-
- public void HandleXfer(ulong xferID, uint packetID, byte[] data)
- {
- // AssetXferUploader uploaderFound = null;
-
- lock (XferUploaders)
- {
- foreach (AssetXferUploader uploader in XferUploaders.Values)
- {
- if (uploader.XferID == xferID)
- {
- uploader.HandleXferPacket(xferID, packetID, data);
- break;
- }
- }
- }
- }
-
- public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
- uint callbackID, string description, string name, sbyte invType,
- sbyte type, byte wearableType, uint nextOwnerMask)
- {
- if (XferUploaders.ContainsKey(transactionID))
- {
- XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID,
- callbackID, description, name, invType, type,
- wearableType, nextOwnerMask);
- }
- }
-
- public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID,
- InventoryItemBase item)
- {
- if (XferUploaders.ContainsKey(transactionID))
- {
- XferUploaders[transactionID].RequestUpdateInventoryItem(remoteClient, transactionID, item);
- }
- }
-
- ///
- /// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed.
- ///
- ///
- /// The asset if the upload has completed, null if it has not.
- public AssetBase GetTransactionAsset(LLUUID transactionID)
- {
- if (XferUploaders.ContainsKey(transactionID))
- {
- AssetXferUploader uploader = XferUploaders[transactionID];
- AssetBase asset = uploader.GetAssetData();
-
- lock (XferUploaders)
- {
- XferUploaders.Remove(transactionID);
- }
-
- return asset;
- }
-
- return null;
- }
-
- // Nested Types
-
- #region Nested type: AssetXferUploader
-
- public class AssetXferUploader
- {
- // Fields
- public bool AddToInventory;
- public AssetBase Asset;
- public LLUUID InventFolder = LLUUID.Zero;
- private sbyte invType = 0;
- private bool m_createItem = false;
- private string m_description = String.Empty;
- private bool m_dumpAssetToFile;
- private bool m_finished = false;
- private string m_name = String.Empty;
- private bool m_storeLocal;
- private AgentAssetTransactions m_userTransactions;
- private uint nextPerm = 0;
- private IClientAPI ourClient;
- public LLUUID TransactionID = LLUUID.Zero;
- private sbyte type = 0;
- public bool UploadComplete;
- private byte wearableType = 0;
- public ulong XferID;
-
- public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile)
- {
- m_userTransactions = transactions;
- m_dumpAssetToFile = dumpAssetToFile;
- }
-
- ///
- /// Process transfer data received from the client.
- ///
- ///
- ///
- ///
- /// True if the transfer is complete, false otherwise or if the xferID was not valid
- public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data)
- {
- if (XferID == xferID)
- {
- if (Asset.Data.Length > 1)
- {
- byte[] destinationArray = new byte[Asset.Data.Length + data.Length];
- Array.Copy(Asset.Data, 0, destinationArray, 0, Asset.Data.Length);
- Array.Copy(data, 0, destinationArray, Asset.Data.Length, data.Length);
- Asset.Data = destinationArray;
- }
- else
- {
- byte[] buffer2 = new byte[data.Length - 4];
- Array.Copy(data, 4, buffer2, 0, data.Length - 4);
- Asset.Data = buffer2;
- }
- ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket();
- newPack.XferID.ID = xferID;
- newPack.XferID.Packet = packetID;
- ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
- if ((packetID & 0x80000000) != 0)
- {
- SendCompleteMessage();
- return true;
- }
- }
-
- return false;
- }
-
- ///
- /// Initialise asset transfer from the client
- ///
- ///
- ///
- ///
- /// True if the transfer is complete, false otherwise
- public bool Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data,
- bool storeLocal, bool tempFile)
- {
- ourClient = remoteClient;
- Asset = new AssetBase();
- Asset.FullID = assetID;
- Asset.InvType = type;
- Asset.Type = type;
- Asset.Data = data;
- Asset.Name = "blank";
- Asset.Description = "empty";
- Asset.Local = storeLocal;
- Asset.Temporary = tempFile;
-
- TransactionID = transaction;
- m_storeLocal = storeLocal;
- if (Asset.Data.Length > 2)
- {
- SendCompleteMessage();
- return true;
- }
- else
- {
- RequestStartXfer();
- }
-
- return false;
- }
-
- protected void RequestStartXfer()
- {
- UploadComplete = false;
- XferID = Util.GetNextXferID();
- RequestXferPacket newPack = new RequestXferPacket();
- newPack.XferID.ID = XferID;
- newPack.XferID.VFileType = Asset.Type;
- newPack.XferID.VFileID = Asset.FullID;
- newPack.XferID.FilePath = 0;
- newPack.XferID.Filename = new byte[0];
- ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
- }
-
- protected void SendCompleteMessage()
- {
- UploadComplete = true;
- AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
- newPack.AssetBlock.Type = Asset.Type;
- newPack.AssetBlock.Success = true;
- newPack.AssetBlock.UUID = Asset.FullID;
- ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
- m_finished = true;
- if (m_createItem)
- {
- DoCreateItem();
- }
- else if (m_storeLocal)
- {
- m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
- }
-
- // Console.WriteLine("upload complete "+ this.TransactionID);
-
- if (m_dumpAssetToFile)
- {
- DateTime now = DateTime.Now;
- string filename =
- String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", now.Year, now.Month, now.Day,
- now.Hour, now.Minute, now.Second, Asset.Name, Asset.Type);
- SaveAssetToFile(filename, Asset.Data);
- }
- }
-
- ///Left this in and commented in case there are unforseen issues
- //private void SaveAssetToFile(string filename, byte[] data)
- //{
- // FileStream fs = File.Create(filename);
- // BinaryWriter bw = new BinaryWriter(fs);
- // bw.Write(data);
- // bw.Close();
- // fs.Close();
- //}
- private void SaveAssetToFile(string filename, byte[] data)
- {
- string assetPath = "UserAssets";
- if (!Directory.Exists(assetPath))
- {
- Directory.CreateDirectory(assetPath);
- }
- FileStream fs = File.Create(Path.Combine(assetPath, filename));
- BinaryWriter bw = new BinaryWriter(fs);
- bw.Write(data);
- bw.Close();
- fs.Close();
- }
-
- public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
- uint callbackID, string description, string name, sbyte invType,
- sbyte type, byte wearableType, uint nextOwnerMask)
- {
- if (TransactionID == transactionID)
- {
- InventFolder = folderID;
- m_name = name;
- m_description = description;
- this.type = type;
- this.invType = invType;
- this.wearableType = wearableType;
- nextPerm = nextOwnerMask;
- Asset.Name = name;
- Asset.Description = description;
- Asset.Type = type;
- Asset.InvType = invType;
- m_createItem = true;
- if (m_finished)
- {
- DoCreateItem();
- }
- }
- }
-
- public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID,
- InventoryItemBase item)
- {
- if (TransactionID == transactionID)
- {
- CachedUserInfo userInfo =
- m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(
- remoteClient.AgentId);
-
- if (userInfo != null)
- {
- LLUUID assetID = LLUUID.Combine(transactionID, remoteClient.SecureSessionId);
-
- AssetBase asset
- = m_userTransactions.Manager.MyScene.CommsManager.AssetCache.GetAsset(
- assetID, (item.AssetType == (int) AssetType.Texture ? true : false));
-
- if (asset == null)
- {
- asset = m_userTransactions.GetTransactionAsset(transactionID);
- }
-
- if (asset != null && asset.FullID == assetID)
- {
- asset.Name = item.Name;
- asset.Description = item.Description;
- asset.InvType = (sbyte) item.InvType;
- asset.Type = (sbyte) item.AssetType;
- item.AssetID = asset.FullID;
-
- m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
- }
-
- userInfo.UpdateItem(remoteClient.AgentId, item);
- }
- }
- }
-
- private void DoCreateItem()
- {
- //really need to fix this call, if lbsa71 saw this he would die.
- m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
- CachedUserInfo userInfo =
- m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(ourClient.AgentId);
- if (userInfo != null)
- {
- InventoryItemBase item = new InventoryItemBase();
- item.Owner = ourClient.AgentId;
- item.Creator = ourClient.AgentId;
- item.ID = LLUUID.Random();
- item.AssetID = Asset.FullID;
- item.Description = m_description;
- item.Name = m_name;
- item.AssetType = type;
- item.InvType = invType;
- item.Folder = InventFolder;
- item.BasePermissions = 2147483647;
- item.CurrentPermissions = 2147483647;
- item.NextPermissions = nextPerm;
- item.Flags = (uint) wearableType;
-
- userInfo.AddItem(ourClient.AgentId, item);
- ourClient.SendInventoryItemCreateUpdate(item);
- }
- }
-
- public AssetBase GetAssetData()
- {
- if (m_finished)
- {
- return Asset;
- }
- return null;
- }
- }
-
- #endregion
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using libsecondlife;
+using libsecondlife.Packets;
+using OpenSim.Framework;
+using OpenSim.Framework.Communications.Cache;
+
+namespace OpenSim.Region.Environment.Modules.Agent.AssetTransaction
+{
+ ///
+ /// Manage asset transactions for a single agent.
+ ///
+ public class AgentAssetTransactions
+ {
+ //private static readonly log4net.ILog m_log
+ // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+
+ // Fields
+ private bool m_dumpAssetsToFile;
+ public AgentAssetTransactionsManager Manager;
+ public LLUUID UserID;
+ public Dictionary XferUploaders = new Dictionary();
+
+ // Methods
+ public AgentAssetTransactions(LLUUID agentID, AgentAssetTransactionsManager manager, bool dumpAssetsToFile)
+ {
+ UserID = agentID;
+ Manager = manager;
+ m_dumpAssetsToFile = dumpAssetsToFile;
+ }
+
+ public AssetXferUploader RequestXferUploader(LLUUID transactionID)
+ {
+ if (!XferUploaders.ContainsKey(transactionID))
+ {
+ AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile);
+
+ lock (XferUploaders)
+ {
+ XferUploaders.Add(transactionID, uploader);
+ }
+
+ return uploader;
+ }
+ return null;
+ }
+
+ public void HandleXfer(ulong xferID, uint packetID, byte[] data)
+ {
+ // AssetXferUploader uploaderFound = null;
+
+ lock (XferUploaders)
+ {
+ foreach (AssetXferUploader uploader in XferUploaders.Values)
+ {
+ if (uploader.XferID == xferID)
+ {
+ uploader.HandleXferPacket(xferID, packetID, data);
+ break;
+ }
+ }
+ }
+ }
+
+ public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
+ uint callbackID, string description, string name, sbyte invType,
+ sbyte type, byte wearableType, uint nextOwnerMask)
+ {
+ if (XferUploaders.ContainsKey(transactionID))
+ {
+ XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID,
+ callbackID, description, name, invType, type,
+ wearableType, nextOwnerMask);
+ }
+ }
+
+ public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID,
+ InventoryItemBase item)
+ {
+ if (XferUploaders.ContainsKey(transactionID))
+ {
+ XferUploaders[transactionID].RequestUpdateInventoryItem(remoteClient, transactionID, item);
+ }
+ }
+
+ ///
+ /// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed.
+ ///
+ ///
+ /// The asset if the upload has completed, null if it has not.
+ public AssetBase GetTransactionAsset(LLUUID transactionID)
+ {
+ if (XferUploaders.ContainsKey(transactionID))
+ {
+ AssetXferUploader uploader = XferUploaders[transactionID];
+ AssetBase asset = uploader.GetAssetData();
+
+ lock (XferUploaders)
+ {
+ XferUploaders.Remove(transactionID);
+ }
+
+ return asset;
+ }
+
+ return null;
+ }
+
+ // Nested Types
+
+ #region Nested type: AssetXferUploader
+
+ public class AssetXferUploader
+ {
+ // Fields
+ public bool AddToInventory;
+ public AssetBase Asset;
+ public LLUUID InventFolder = LLUUID.Zero;
+ private sbyte invType = 0;
+ private bool m_createItem = false;
+ private string m_description = String.Empty;
+ private bool m_dumpAssetToFile;
+ private bool m_finished = false;
+ private string m_name = String.Empty;
+ private bool m_storeLocal;
+ private AgentAssetTransactions m_userTransactions;
+ private uint nextPerm = 0;
+ private IClientAPI ourClient;
+ public LLUUID TransactionID = LLUUID.Zero;
+ private sbyte type = 0;
+ public bool UploadComplete;
+ private byte wearableType = 0;
+ public ulong XferID;
+
+ public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile)
+ {
+ m_userTransactions = transactions;
+ m_dumpAssetToFile = dumpAssetToFile;
+ }
+
+ ///
+ /// Process transfer data received from the client.
+ ///
+ ///
+ ///
+ ///
+ /// True if the transfer is complete, false otherwise or if the xferID was not valid
+ public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data)
+ {
+ if (XferID == xferID)
+ {
+ if (Asset.Data.Length > 1)
+ {
+ byte[] destinationArray = new byte[Asset.Data.Length + data.Length];
+ Array.Copy(Asset.Data, 0, destinationArray, 0, Asset.Data.Length);
+ Array.Copy(data, 0, destinationArray, Asset.Data.Length, data.Length);
+ Asset.Data = destinationArray;
+ }
+ else
+ {
+ byte[] buffer2 = new byte[data.Length - 4];
+ Array.Copy(data, 4, buffer2, 0, data.Length - 4);
+ Asset.Data = buffer2;
+ }
+ ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket();
+ newPack.XferID.ID = xferID;
+ newPack.XferID.Packet = packetID;
+ ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
+ if ((packetID & 0x80000000) != 0)
+ {
+ SendCompleteMessage();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// Initialise asset transfer from the client
+ ///
+ ///
+ ///
+ ///
+ /// True if the transfer is complete, false otherwise
+ public bool Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data,
+ bool storeLocal, bool tempFile)
+ {
+ ourClient = remoteClient;
+ Asset = new AssetBase();
+ Asset.FullID = assetID;
+ Asset.InvType = type;
+ Asset.Type = type;
+ Asset.Data = data;
+ Asset.Name = "blank";
+ Asset.Description = "empty";
+ Asset.Local = storeLocal;
+ Asset.Temporary = tempFile;
+
+ TransactionID = transaction;
+ m_storeLocal = storeLocal;
+ if (Asset.Data.Length > 2)
+ {
+ SendCompleteMessage();
+ return true;
+ }
+ else
+ {
+ RequestStartXfer();
+ }
+
+ return false;
+ }
+
+ protected void RequestStartXfer()
+ {
+ UploadComplete = false;
+ XferID = Util.GetNextXferID();
+ RequestXferPacket newPack = new RequestXferPacket();
+ newPack.XferID.ID = XferID;
+ newPack.XferID.VFileType = Asset.Type;
+ newPack.XferID.VFileID = Asset.FullID;
+ newPack.XferID.FilePath = 0;
+ newPack.XferID.Filename = new byte[0];
+ ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
+ }
+
+ protected void SendCompleteMessage()
+ {
+ UploadComplete = true;
+ AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
+ newPack.AssetBlock.Type = Asset.Type;
+ newPack.AssetBlock.Success = true;
+ newPack.AssetBlock.UUID = Asset.FullID;
+ ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
+ m_finished = true;
+ if (m_createItem)
+ {
+ DoCreateItem();
+ }
+ else if (m_storeLocal)
+ {
+ m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
+ }
+
+ // Console.WriteLine("upload complete "+ this.TransactionID);
+
+ if (m_dumpAssetToFile)
+ {
+ DateTime now = DateTime.Now;
+ string filename =
+ String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", now.Year, now.Month, now.Day,
+ now.Hour, now.Minute, now.Second, Asset.Name, Asset.Type);
+ SaveAssetToFile(filename, Asset.Data);
+ }
+ }
+
+ ///Left this in and commented in case there are unforseen issues
+ //private void SaveAssetToFile(string filename, byte[] data)
+ //{
+ // FileStream fs = File.Create(filename);
+ // BinaryWriter bw = new BinaryWriter(fs);
+ // bw.Write(data);
+ // bw.Close();
+ // fs.Close();
+ //}
+ private void SaveAssetToFile(string filename, byte[] data)
+ {
+ string assetPath = "UserAssets";
+ if (!Directory.Exists(assetPath))
+ {
+ Directory.CreateDirectory(assetPath);
+ }
+ FileStream fs = File.Create(Path.Combine(assetPath, filename));
+ BinaryWriter bw = new BinaryWriter(fs);
+ bw.Write(data);
+ bw.Close();
+ fs.Close();
+ }
+
+ public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
+ uint callbackID, string description, string name, sbyte invType,
+ sbyte type, byte wearableType, uint nextOwnerMask)
+ {
+ if (TransactionID == transactionID)
+ {
+ InventFolder = folderID;
+ m_name = name;
+ m_description = description;
+ this.type = type;
+ this.invType = invType;
+ this.wearableType = wearableType;
+ nextPerm = nextOwnerMask;
+ Asset.Name = name;
+ Asset.Description = description;
+ Asset.Type = type;
+ Asset.InvType = invType;
+ m_createItem = true;
+ if (m_finished)
+ {
+ DoCreateItem();
+ }
+ }
+ }
+
+ public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID,
+ InventoryItemBase item)
+ {
+ if (TransactionID == transactionID)
+ {
+ CachedUserInfo userInfo =
+ m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(
+ remoteClient.AgentId);
+
+ if (userInfo != null)
+ {
+ LLUUID assetID = LLUUID.Combine(transactionID, remoteClient.SecureSessionId);
+
+ AssetBase asset
+ = m_userTransactions.Manager.MyScene.CommsManager.AssetCache.GetAsset(
+ assetID, (item.AssetType == (int) AssetType.Texture ? true : false));
+
+ if (asset == null)
+ {
+ asset = m_userTransactions.GetTransactionAsset(transactionID);
+ }
+
+ if (asset != null && asset.FullID == assetID)
+ {
+ asset.Name = item.Name;
+ asset.Description = item.Description;
+ asset.InvType = (sbyte) item.InvType;
+ asset.Type = (sbyte) item.AssetType;
+ item.AssetID = asset.FullID;
+
+ m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
+ }
+
+ userInfo.UpdateItem(remoteClient.AgentId, item);
+ }
+ }
+ }
+
+ private void DoCreateItem()
+ {
+ //really need to fix this call, if lbsa71 saw this he would die.
+ m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
+ CachedUserInfo userInfo =
+ m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(ourClient.AgentId);
+ if (userInfo != null)
+ {
+ InventoryItemBase item = new InventoryItemBase();
+ item.Owner = ourClient.AgentId;
+ item.Creator = ourClient.AgentId;
+ item.ID = LLUUID.Random();
+ item.AssetID = Asset.FullID;
+ item.Description = m_description;
+ item.Name = m_name;
+ item.AssetType = type;
+ item.InvType = invType;
+ item.Folder = InventFolder;
+ item.BasePermissions = 2147483647;
+ item.CurrentPermissions = 2147483647;
+ item.NextPermissions = nextPerm;
+ item.Flags = (uint) wearableType;
+
+ userInfo.AddItem(ourClient.AgentId, item);
+ ourClient.SendInventoryItemCreateUpdate(item);
+ }
+ }
+
+ public AssetBase GetAssetData()
+ {
+ if (m_finished)
+ {
+ return Asset;
+ }
+ return null;
+ }
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetTransactionModule.cs
index b264c8a..fcd0e0c 100644
--- a/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -1,291 +1,291 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using libsecondlife;
-using log4net;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Agent.AssetTransaction
-{
- public class AssetTransactionModule : IRegionModule, IAgentAssetTransactions
- {
- private readonly Dictionary RegisteredScenes = new Dictionary();
- private bool m_dumpAssetsToFile = false;
- private Scene m_scene = null;
-
- private AgentAssetTransactionsManager m_transactionManager;
-
- public AssetTransactionModule()
- {
- // System.Console.WriteLine("creating AgentAssetTransactionModule");
- }
-
- #region IAgentAssetTransactions Members
-
- public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
- uint callbackID, string description, string name, sbyte invType,
- sbyte type, byte wearableType, uint nextOwnerMask)
- {
- m_transactionManager.HandleItemCreationFromTransaction(remoteClient, transactionID, folderID, callbackID, description, name, invType, type,
- wearableType, nextOwnerMask);
- }
-
- public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID,
- InventoryItemBase item)
- {
- m_transactionManager.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
- }
-
- public void RemoveAgentAssetTransactions(LLUUID userID)
- {
- m_transactionManager.RemoveAgentAssetTransactions(userID);
- }
-
- #endregion
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
- {
- // System.Console.WriteLine("initialising AgentAssetTransactionModule");
- RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
- scene.RegisterModuleInterface(this);
-
- scene.EventManager.OnNewClient += NewClient;
- }
-
- if (m_scene == null)
- {
- m_scene = scene;
- if (config.Configs["StandAlone"] != null)
- {
- try
- {
- m_dumpAssetsToFile = config.Configs["StandAlone"].GetBoolean("dump_assets_to_file", false);
- m_transactionManager = new AgentAssetTransactionsManager(m_scene, m_dumpAssetsToFile);
- }
- catch (Exception)
- {
- m_transactionManager = new AgentAssetTransactionsManager(m_scene, false);
- }
- }
- else
- {
- m_transactionManager = new AgentAssetTransactionsManager(m_scene, false);
- }
- }
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "AgentTransactionModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return true; }
- }
-
- #endregion
-
- public void NewClient(IClientAPI client)
- {
- client.OnAssetUploadRequest += m_transactionManager.HandleUDPUploadRequest;
- client.OnXferReceive += m_transactionManager.HandleXfer;
- }
- }
-
- public class AgentAssetTransactionsManager
- {
- private static readonly ILog m_log
- = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- // Fields
-
- ///
- /// Each agent has its own singleton collection of transactions
- ///
- private Dictionary AgentTransactions =
- new Dictionary();
-
- ///
- /// Should we dump uploaded assets to the filesystem?
- ///
- private bool m_dumpAssetsToFile;
-
- public Scene MyScene;
-
- public AgentAssetTransactionsManager(Scene scene, bool dumpAssetsToFile)
- {
- MyScene = scene;
- m_dumpAssetsToFile = dumpAssetsToFile;
- }
-
- ///
- /// Get the collection of asset transactions for the given user. If one does not already exist, it
- /// is created.
- ///
- ///
- ///
- private AgentAssetTransactions GetUserTransactions(LLUUID userID)
- {
- lock (AgentTransactions)
- {
- if (!AgentTransactions.ContainsKey(userID))
- {
- AgentAssetTransactions transactions
- = new AgentAssetTransactions(userID, this, m_dumpAssetsToFile);
- AgentTransactions.Add(userID, transactions);
- }
-
- return AgentTransactions[userID];
- }
- }
-
- ///
- /// Remove the given agent asset transactions. This should be called when a client is departing
- /// from a scene (and hence won't be making any more transactions here).
- ///
- ///
- public void RemoveAgentAssetTransactions(LLUUID userID)
- {
- // m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID);
-
- lock (AgentTransactions)
- {
- AgentTransactions.Remove(userID);
- }
- }
-
- ///
- /// Create an inventory item from data that has been received through a transaction.
- ///
- /// This is called when new clothing or body parts are created. It may also be called in other
- /// situations.
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
- uint callbackID, string description, string name, sbyte invType,
- sbyte type, byte wearableType, uint nextOwnerMask)
- {
- m_log.DebugFormat(
- "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name);
-
- AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
-
- transactions.RequestCreateInventoryItem(
- remoteClient, transactionID, folderID, callbackID, description,
- name, invType, type, wearableType, nextOwnerMask);
- }
-
- ///
- /// Update an inventory item with data that has been received through a transaction.
- ///
- /// This is called when clothing or body parts are updated (for instance, with new textures or
- /// colours). It may also be called in other situations.
- ///
- ///
- ///
- ///
- public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID,
- InventoryItemBase item)
- {
- m_log.DebugFormat(
- "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}",
- item.Name);
-
- AgentAssetTransactions transactions
- = GetUserTransactions(remoteClient.AgentId);
-
- transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item);
- }
-
- ///
- /// Request that a client (agent) begin an asset transfer.
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type,
- byte[] data, bool storeLocal, bool tempFile)
- {
- // Console.WriteLine("asset upload of " + assetID);
- AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
-
- AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
- if (uploader != null)
- {
- if (uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile))
- {
- }
- }
- }
-
- ///
- /// Handle asset transfer data packets received in response to the asset upload request in
- /// HandleUDPUploadRequest()
- ///
- ///
- ///
- ///
- ///
- public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
- {
- AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
-
- transactions.HandleXfer(xferID, packetID, data);
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using libsecondlife;
+using log4net;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Agent.AssetTransaction
+{
+ public class AssetTransactionModule : IRegionModule, IAgentAssetTransactions
+ {
+ private readonly Dictionary RegisteredScenes = new Dictionary();
+ private bool m_dumpAssetsToFile = false;
+ private Scene m_scene = null;
+
+ private AgentAssetTransactionsManager m_transactionManager;
+
+ public AssetTransactionModule()
+ {
+ // System.Console.WriteLine("creating AgentAssetTransactionModule");
+ }
+
+ #region IAgentAssetTransactions Members
+
+ public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
+ uint callbackID, string description, string name, sbyte invType,
+ sbyte type, byte wearableType, uint nextOwnerMask)
+ {
+ m_transactionManager.HandleItemCreationFromTransaction(remoteClient, transactionID, folderID, callbackID, description, name, invType, type,
+ wearableType, nextOwnerMask);
+ }
+
+ public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID,
+ InventoryItemBase item)
+ {
+ m_transactionManager.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
+ }
+
+ public void RemoveAgentAssetTransactions(LLUUID userID)
+ {
+ m_transactionManager.RemoveAgentAssetTransactions(userID);
+ }
+
+ #endregion
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
+ {
+ // System.Console.WriteLine("initialising AgentAssetTransactionModule");
+ RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
+ scene.RegisterModuleInterface(this);
+
+ scene.EventManager.OnNewClient += NewClient;
+ }
+
+ if (m_scene == null)
+ {
+ m_scene = scene;
+ if (config.Configs["StandAlone"] != null)
+ {
+ try
+ {
+ m_dumpAssetsToFile = config.Configs["StandAlone"].GetBoolean("dump_assets_to_file", false);
+ m_transactionManager = new AgentAssetTransactionsManager(m_scene, m_dumpAssetsToFile);
+ }
+ catch (Exception)
+ {
+ m_transactionManager = new AgentAssetTransactionsManager(m_scene, false);
+ }
+ }
+ else
+ {
+ m_transactionManager = new AgentAssetTransactionsManager(m_scene, false);
+ }
+ }
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "AgentTransactionModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return true; }
+ }
+
+ #endregion
+
+ public void NewClient(IClientAPI client)
+ {
+ client.OnAssetUploadRequest += m_transactionManager.HandleUDPUploadRequest;
+ client.OnXferReceive += m_transactionManager.HandleXfer;
+ }
+ }
+
+ public class AgentAssetTransactionsManager
+ {
+ private static readonly ILog m_log
+ = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ // Fields
+
+ ///
+ /// Each agent has its own singleton collection of transactions
+ ///
+ private Dictionary AgentTransactions =
+ new Dictionary();
+
+ ///
+ /// Should we dump uploaded assets to the filesystem?
+ ///
+ private bool m_dumpAssetsToFile;
+
+ public Scene MyScene;
+
+ public AgentAssetTransactionsManager(Scene scene, bool dumpAssetsToFile)
+ {
+ MyScene = scene;
+ m_dumpAssetsToFile = dumpAssetsToFile;
+ }
+
+ ///
+ /// Get the collection of asset transactions for the given user. If one does not already exist, it
+ /// is created.
+ ///
+ ///
+ ///
+ private AgentAssetTransactions GetUserTransactions(LLUUID userID)
+ {
+ lock (AgentTransactions)
+ {
+ if (!AgentTransactions.ContainsKey(userID))
+ {
+ AgentAssetTransactions transactions
+ = new AgentAssetTransactions(userID, this, m_dumpAssetsToFile);
+ AgentTransactions.Add(userID, transactions);
+ }
+
+ return AgentTransactions[userID];
+ }
+ }
+
+ ///
+ /// Remove the given agent asset transactions. This should be called when a client is departing
+ /// from a scene (and hence won't be making any more transactions here).
+ ///
+ ///
+ public void RemoveAgentAssetTransactions(LLUUID userID)
+ {
+ // m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID);
+
+ lock (AgentTransactions)
+ {
+ AgentTransactions.Remove(userID);
+ }
+ }
+
+ ///
+ /// Create an inventory item from data that has been received through a transaction.
+ ///
+ /// This is called when new clothing or body parts are created. It may also be called in other
+ /// situations.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
+ uint callbackID, string description, string name, sbyte invType,
+ sbyte type, byte wearableType, uint nextOwnerMask)
+ {
+ m_log.DebugFormat(
+ "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name);
+
+ AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
+
+ transactions.RequestCreateInventoryItem(
+ remoteClient, transactionID, folderID, callbackID, description,
+ name, invType, type, wearableType, nextOwnerMask);
+ }
+
+ ///
+ /// Update an inventory item with data that has been received through a transaction.
+ ///
+ /// This is called when clothing or body parts are updated (for instance, with new textures or
+ /// colours). It may also be called in other situations.
+ ///
+ ///
+ ///
+ ///
+ public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID,
+ InventoryItemBase item)
+ {
+ m_log.DebugFormat(
+ "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}",
+ item.Name);
+
+ AgentAssetTransactions transactions
+ = GetUserTransactions(remoteClient.AgentId);
+
+ transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item);
+ }
+
+ ///
+ /// Request that a client (agent) begin an asset transfer.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type,
+ byte[] data, bool storeLocal, bool tempFile)
+ {
+ // Console.WriteLine("asset upload of " + assetID);
+ AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
+
+ AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
+ if (uploader != null)
+ {
+ if (uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile))
+ {
+ }
+ }
+ }
+
+ ///
+ /// Handle asset transfer data packets received in response to the asset upload request in
+ /// HandleUDPUploadRequest()
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
+ {
+ AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
+
+ transactions.HandleXfer(xferID, packetID, data);
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs
index ae2df69..474ac75 100644
--- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs
@@ -1,219 +1,219 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using libsecondlife;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
-{
- public class TextureDownloadModule : IRegionModule
- {
- //private static readonly log4net.ILog m_log
- // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
-
- ///
- /// There is one queue for all textures waiting to be sent, regardless of the requesting user.
- ///
- private readonly BlockingQueue m_queueSenders
- = new BlockingQueue();
-
- ///
- /// Each user has their own texture download service.
- ///
- private readonly Dictionary m_userTextureServices =
- new Dictionary();
-
- private Scene m_scene;
- private List m_scenes = new List();
-
- private Thread m_thread;
-
- public TextureDownloadModule()
- {
- }
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- if (m_scene == null)
- {
- //Console.WriteLine("Creating Texture download module");
- m_thread = new Thread(new ThreadStart(ProcessTextureSenders));
- m_thread.Name = "ProcessTextureSenderThread";
- m_thread.IsBackground = true;
- m_thread.Start();
- ThreadTracker.Add(m_thread);
- }
-
- if (!m_scenes.Contains(scene))
- {
- m_scenes.Add(scene);
- m_scene = scene;
- m_scene.EventManager.OnNewClient += NewClient;
- m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence;
- }
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "TextureDownloadModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return false; }
- }
-
- #endregion
-
- ///
- /// Cleanup the texture service related objects for the removed presence.
- ///
- ///
- private void EventManager_OnRemovePresence(LLUUID agentId)
- {
- UserTextureDownloadService textureService;
-
- lock (m_userTextureServices)
- {
- if (m_userTextureServices.TryGetValue(agentId, out textureService))
- {
- textureService.Close();
-
- m_userTextureServices.Remove(agentId);
- }
- }
- }
-
- public void NewClient(IClientAPI client)
- {
- client.OnRequestTexture += TextureRequest;
- }
-
- ///
- /// Does this user have a registered texture download service?
- ///
- ///
- ///
- /// Always returns true, since a service is created if one does not already exist
- private bool TryGetUserTextureService(
- IClientAPI client, out UserTextureDownloadService textureService)
- {
- lock (m_userTextureServices)
- {
- if (m_userTextureServices.TryGetValue(client.AgentId, out textureService))
- {
- return true;
- }
-
- textureService = new UserTextureDownloadService(client, m_scene, m_queueSenders);
- m_userTextureServices.Add(client.AgentId, textureService);
-
- return true;
- }
- }
-
- ///
- /// Start the process of requesting a given texture.
- ///
- ///
- ///
- public void TextureRequest(Object sender, TextureRequestArgs e)
- {
- IClientAPI client = (IClientAPI) sender;
- UserTextureDownloadService textureService;
-
- if (TryGetUserTextureService(client, out textureService))
- {
- textureService.HandleTextureRequest(e);
- }
- }
-
- ///
- /// Entry point for the thread dedicated to processing the texture queue.
- ///
- public void ProcessTextureSenders()
- {
- ITextureSender sender = null;
-
- while (true)
- {
- sender = m_queueSenders.Dequeue();
-
- if (sender.Cancel)
- {
- TextureSent(sender);
-
- sender.Cancel = false;
- }
- else
- {
- bool finished = sender.SendTexturePacket();
- if (finished)
- {
- TextureSent(sender);
- }
- else
- {
- m_queueSenders.Enqueue(sender);
- }
- }
-
- // Make sure that any sender we currently have can get garbage collected
- sender = null;
-
- //m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count());
- }
- }
-
- ///
- /// Called when the texture has finished sending.
- ///
- ///
- private void TextureSent(ITextureSender sender)
- {
- sender.Sending = false;
- //m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID);
- m_scene.AddPendingDownloads(-1);
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using libsecondlife;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
+{
+ public class TextureDownloadModule : IRegionModule
+ {
+ //private static readonly log4net.ILog m_log
+ // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+
+ ///
+ /// There is one queue for all textures waiting to be sent, regardless of the requesting user.
+ ///
+ private readonly BlockingQueue m_queueSenders
+ = new BlockingQueue();
+
+ ///
+ /// Each user has their own texture download service.
+ ///
+ private readonly Dictionary m_userTextureServices =
+ new Dictionary();
+
+ private Scene m_scene;
+ private List m_scenes = new List();
+
+ private Thread m_thread;
+
+ public TextureDownloadModule()
+ {
+ }
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ if (m_scene == null)
+ {
+ //Console.WriteLine("Creating Texture download module");
+ m_thread = new Thread(new ThreadStart(ProcessTextureSenders));
+ m_thread.Name = "ProcessTextureSenderThread";
+ m_thread.IsBackground = true;
+ m_thread.Start();
+ ThreadTracker.Add(m_thread);
+ }
+
+ if (!m_scenes.Contains(scene))
+ {
+ m_scenes.Add(scene);
+ m_scene = scene;
+ m_scene.EventManager.OnNewClient += NewClient;
+ m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence;
+ }
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "TextureDownloadModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return false; }
+ }
+
+ #endregion
+
+ ///
+ /// Cleanup the texture service related objects for the removed presence.
+ ///
+ ///
+ private void EventManager_OnRemovePresence(LLUUID agentId)
+ {
+ UserTextureDownloadService textureService;
+
+ lock (m_userTextureServices)
+ {
+ if (m_userTextureServices.TryGetValue(agentId, out textureService))
+ {
+ textureService.Close();
+
+ m_userTextureServices.Remove(agentId);
+ }
+ }
+ }
+
+ public void NewClient(IClientAPI client)
+ {
+ client.OnRequestTexture += TextureRequest;
+ }
+
+ ///
+ /// Does this user have a registered texture download service?
+ ///
+ ///
+ ///
+ /// Always returns true, since a service is created if one does not already exist
+ private bool TryGetUserTextureService(
+ IClientAPI client, out UserTextureDownloadService textureService)
+ {
+ lock (m_userTextureServices)
+ {
+ if (m_userTextureServices.TryGetValue(client.AgentId, out textureService))
+ {
+ return true;
+ }
+
+ textureService = new UserTextureDownloadService(client, m_scene, m_queueSenders);
+ m_userTextureServices.Add(client.AgentId, textureService);
+
+ return true;
+ }
+ }
+
+ ///
+ /// Start the process of requesting a given texture.
+ ///
+ ///
+ ///
+ public void TextureRequest(Object sender, TextureRequestArgs e)
+ {
+ IClientAPI client = (IClientAPI) sender;
+ UserTextureDownloadService textureService;
+
+ if (TryGetUserTextureService(client, out textureService))
+ {
+ textureService.HandleTextureRequest(e);
+ }
+ }
+
+ ///
+ /// Entry point for the thread dedicated to processing the texture queue.
+ ///
+ public void ProcessTextureSenders()
+ {
+ ITextureSender sender = null;
+
+ while (true)
+ {
+ sender = m_queueSenders.Dequeue();
+
+ if (sender.Cancel)
+ {
+ TextureSent(sender);
+
+ sender.Cancel = false;
+ }
+ else
+ {
+ bool finished = sender.SendTexturePacket();
+ if (finished)
+ {
+ TextureSent(sender);
+ }
+ else
+ {
+ m_queueSenders.Enqueue(sender);
+ }
+ }
+
+ // Make sure that any sender we currently have can get garbage collected
+ sender = null;
+
+ //m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count());
+ }
+ }
+
+ ///
+ /// Called when the texture has finished sending.
+ ///
+ ///
+ private void TextureSent(ITextureSender sender)
+ {
+ sender.Sending = false;
+ //m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID);
+ m_scene.AddPendingDownloads(-1);
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs
index b181d20..70e44d4 100644
--- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs
@@ -1,98 +1,98 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using libsecondlife;
-using libsecondlife.Packets;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-
-namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
-{
- ///
- /// Sends a 'texture not found' packet back to the client
- ///
- public class TextureNotFoundSender : ITextureSender
- {
- //private static readonly log4net.ILog m_log
- // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
-
- private bool m_cancel = false;
- private IClientAPI m_client;
-
- // See ITextureSender
-
- private bool m_sending = false;
- private LLUUID m_textureId;
-
- // See ITextureSender
-
- public TextureNotFoundSender(IClientAPI client, LLUUID textureID)
- {
- m_client = client;
- m_textureId = textureID;
- }
-
- #region ITextureSender Members
-
- public bool Sending
- {
- get { return false; }
- set { m_sending = value; }
- }
-
- public bool Cancel
- {
- get { return false; }
- set { m_cancel = value; }
- }
-
- // See ITextureSender
- public void UpdateRequest(int discardLevel, uint packetNumber)
- {
- // Not need to implement since priority changes don't affect this operation
- }
-
- // See ITextureSender
- public bool SendTexturePacket()
- {
- //m_log.InfoFormat(
- // "[TEXTURE NOT FOUND SENDER]: Informing the client that texture {0} cannot be found",
- // m_textureId);
-
- ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket();
- notFound.ImageID.ID = m_textureId;
-
- // XXX Temporarily disabling as this appears to be causing client crashes on at least
- // 1.19.0(5) of the Linden Second Life client.
- // m_client.OutPacket(notFound, ThrottleOutPacketType.Texture);
-
- return true;
- }
-
- #endregion
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using libsecondlife;
+using libsecondlife.Packets;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+
+namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
+{
+ ///
+ /// Sends a 'texture not found' packet back to the client
+ ///
+ public class TextureNotFoundSender : ITextureSender
+ {
+ //private static readonly log4net.ILog m_log
+ // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+
+ private bool m_cancel = false;
+ private IClientAPI m_client;
+
+ // See ITextureSender
+
+ private bool m_sending = false;
+ private LLUUID m_textureId;
+
+ // See ITextureSender
+
+ public TextureNotFoundSender(IClientAPI client, LLUUID textureID)
+ {
+ m_client = client;
+ m_textureId = textureID;
+ }
+
+ #region ITextureSender Members
+
+ public bool Sending
+ {
+ get { return false; }
+ set { m_sending = value; }
+ }
+
+ public bool Cancel
+ {
+ get { return false; }
+ set { m_cancel = value; }
+ }
+
+ // See ITextureSender
+ public void UpdateRequest(int discardLevel, uint packetNumber)
+ {
+ // Not need to implement since priority changes don't affect this operation
+ }
+
+ // See ITextureSender
+ public bool SendTexturePacket()
+ {
+ //m_log.InfoFormat(
+ // "[TEXTURE NOT FOUND SENDER]: Informing the client that texture {0} cannot be found",
+ // m_textureId);
+
+ ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket();
+ notFound.ImageID.ID = m_textureId;
+
+ // XXX Temporarily disabling as this appears to be causing client crashes on at least
+ // 1.19.0(5) of the Linden Second Life client.
+ // m_client.OutPacket(notFound, ThrottleOutPacketType.Texture);
+
+ return true;
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs
index 4f63fd0..a450cdc 100644
--- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs
@@ -1,249 +1,249 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System.Collections.Generic;
-using System.Reflection;
-using libsecondlife;
-using log4net;
-using OpenSim.Framework;
-using OpenSim.Framework.Communications.Limit;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
-{
- ///
- /// This module sets up texture senders in response to client texture requests, and places them on a
- /// processing queue once those senders have the appropriate data (i.e. a texture retrieved from the
- /// asset cache).
- ///
- public class UserTextureDownloadService
- {
- private static readonly ILog m_log
- = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- ///
- /// We will allow the client to request the same texture n times before dropping further requests
- ///
- /// This number includes repeated requests for the same texture at different resolutions (which we don't
- /// currently handle properly as far as I know). However, this situation should be handled in a more
- /// sophisticated way.
- ///
- private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 5;
-
- ///
- /// XXX Also going to limit requests for found textures.
- ///
- private readonly IRequestLimitStrategy foundTextureLimitStrategy
- = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS);
-
- private readonly IClientAPI m_client;
- private readonly Scene m_scene;
-
- ///
- /// Texture Senders are placed in this queue once they have received their texture from the asset
- /// cache. Another module actually invokes the send.
- ///
- private readonly BlockingQueue m_sharedSendersQueue;
-
- ///
- /// Holds texture senders before they have received the appropriate texture from the asset cache.
- ///
- private readonly Dictionary m_textureSenders = new Dictionary();
-
- ///
- /// We're going to limit requests for the same missing texture.
- /// XXX This is really a temporary solution to deal with the situation where a client continually requests
- /// the same missing textures
- ///
- private readonly IRequestLimitStrategy missingTextureLimitStrategy
- = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS);
-
- public UserTextureDownloadService(
- IClientAPI client, Scene scene, BlockingQueue sharedQueue)
- {
- m_client = client;
- m_scene = scene;
- m_sharedSendersQueue = sharedQueue;
- }
-
- ///
- /// Handle a texture request. This involves creating a texture sender and placing it on the
- /// previously passed in shared queue.
- ///
- ///
- public void HandleTextureRequest(TextureRequestArgs e)
- {
- TextureSender.TextureSender textureSender;
-
- //TODO: should be working out the data size/ number of packets to be sent for each discard level
- if ((e.DiscardLevel >= 0) || (e.Priority != 0))
- {
- lock (m_textureSenders)
- {
- if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
- {
- // If we've received new non UUID information for this request and it hasn't dispatched
- // yet, then update the request accordingly.
- textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber);
- }
- else
- {
- if (!foundTextureLimitStrategy.AllowRequest(e.RequestedAssetID))
- {
-// m_log.DebugFormat(
-// "[USER TEXTURE DOWNLOAD SERVICE]: Refusing request for {0} from client {1}",
-// e.RequestedAssetID, m_client.AgentId);
-
- return;
- }
- else if (!missingTextureLimitStrategy.AllowRequest(e.RequestedAssetID))
- {
- if (missingTextureLimitStrategy.IsFirstRefusal(e.RequestedAssetID))
- {
- // Commenting out this message for now as it causes too much noise with other
- // debug messages.
- // TODO: possibly record this as a statistic in the future
- //
-// m_log.DebugFormat(
-// "[USER TEXTURE DOWNLOAD SERVICE]: Dropping requests for notified missing texture {0} for client {1} since we have received more than {2} requests",
-// e.RequestedAssetID, m_client.AgentId, MAX_ALLOWED_TEXTURE_REQUESTS);
- }
-
- return;
- }
-
- m_scene.AddPendingDownloads(1);
-
- TextureSender.TextureSender requestHandler = new TextureSender.TextureSender(m_client, e.DiscardLevel, e.PacketNumber);
- m_textureSenders.Add(e.RequestedAssetID, requestHandler);
-
- m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true);
- }
- }
- }
- else
- {
- lock (m_textureSenders)
- {
- if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
- {
- textureSender.Cancel = true;
- }
- }
- }
- }
-
- ///
- /// The callback for the asset cache when a texture has been retrieved. This method queues the
- /// texture sender for processing.
- ///
- ///
- ///
- public void TextureCallback(LLUUID textureID, AssetBase texture)
- {
- //m_log.DebugFormat("[USER TEXTURE DOWNLOAD SERVICE]: Calling TextureCallback with {0}, texture == null is {1}", textureID, (texture == null ? true : false));
-
- lock (m_textureSenders)
- {
- TextureSender.TextureSender textureSender;
-
- if (m_textureSenders.TryGetValue(textureID, out textureSender))
- {
- // XXX It may be perfectly valid for a texture to have no data... but if we pass
- // this on to the TextureSender it will blow up, so just discard for now.
- // Needs investigation.
- if (texture == null || texture.Data == null)
- {
- if (!missingTextureLimitStrategy.IsMonitoringRequests(textureID))
- {
- missingTextureLimitStrategy.MonitorRequests(textureID);
-
- m_log.DebugFormat(
- "[USER TEXTURE DOWNLOAD SERVICE]: Queueing first TextureNotFoundSender for {0}, client {1}",
- textureID, m_client.AgentId);
- }
-
- ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID);
- EnqueueTextureSender(textureNotFoundSender);
- }
- else
- {
- if (!textureSender.ImageLoaded)
- {
- textureSender.TextureReceived(texture);
- EnqueueTextureSender(textureSender);
-
- foundTextureLimitStrategy.MonitorRequests(textureID);
- }
- }
-
- //m_log.InfoFormat("[TEXTURE SENDER] Removing texture sender with uuid {0}", textureID);
- m_textureSenders.Remove(textureID);
- //m_log.InfoFormat("[TEXTURE SENDER] Current texture senders in dictionary: {0}", m_textureSenders.Count);
- }
- else
- {
- m_log.WarnFormat(
- "Got a texture uuid {0} with no sender object to handle it, this shouldn't happen",
- textureID);
- }
- }
- }
-
- ///
- /// Place a ready texture sender on the processing queue.
- ///
- ///
- private void EnqueueTextureSender(ITextureSender textureSender)
- {
- textureSender.Cancel = false;
- textureSender.Sending = true;
-
- if (!m_sharedSendersQueue.Contains(textureSender))
- {
- m_sharedSendersQueue.Enqueue(textureSender);
- }
- }
-
- ///
- /// Close this module.
- ///
- internal void Close()
- {
- lock (m_textureSenders)
- {
- foreach (TextureSender.TextureSender textureSender in m_textureSenders.Values)
- {
- textureSender.Cancel = true;
- }
-
- m_textureSenders.Clear();
- }
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.Collections.Generic;
+using System.Reflection;
+using libsecondlife;
+using log4net;
+using OpenSim.Framework;
+using OpenSim.Framework.Communications.Limit;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
+{
+ ///
+ /// This module sets up texture senders in response to client texture requests, and places them on a
+ /// processing queue once those senders have the appropriate data (i.e. a texture retrieved from the
+ /// asset cache).
+ ///
+ public class UserTextureDownloadService
+ {
+ private static readonly ILog m_log
+ = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ ///
+ /// We will allow the client to request the same texture n times before dropping further requests
+ ///
+ /// This number includes repeated requests for the same texture at different resolutions (which we don't
+ /// currently handle properly as far as I know). However, this situation should be handled in a more
+ /// sophisticated way.
+ ///
+ private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 5;
+
+ ///
+ /// XXX Also going to limit requests for found textures.
+ ///
+ private readonly IRequestLimitStrategy foundTextureLimitStrategy
+ = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS);
+
+ private readonly IClientAPI m_client;
+ private readonly Scene m_scene;
+
+ ///
+ /// Texture Senders are placed in this queue once they have received their texture from the asset
+ /// cache. Another module actually invokes the send.
+ ///
+ private readonly BlockingQueue m_sharedSendersQueue;
+
+ ///
+ /// Holds texture senders before they have received the appropriate texture from the asset cache.
+ ///
+ private readonly Dictionary m_textureSenders = new Dictionary();
+
+ ///
+ /// We're going to limit requests for the same missing texture.
+ /// XXX This is really a temporary solution to deal with the situation where a client continually requests
+ /// the same missing textures
+ ///
+ private readonly IRequestLimitStrategy missingTextureLimitStrategy
+ = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS);
+
+ public UserTextureDownloadService(
+ IClientAPI client, Scene scene, BlockingQueue sharedQueue)
+ {
+ m_client = client;
+ m_scene = scene;
+ m_sharedSendersQueue = sharedQueue;
+ }
+
+ ///
+ /// Handle a texture request. This involves creating a texture sender and placing it on the
+ /// previously passed in shared queue.
+ ///
+ ///
+ public void HandleTextureRequest(TextureRequestArgs e)
+ {
+ TextureSender.TextureSender textureSender;
+
+ //TODO: should be working out the data size/ number of packets to be sent for each discard level
+ if ((e.DiscardLevel >= 0) || (e.Priority != 0))
+ {
+ lock (m_textureSenders)
+ {
+ if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
+ {
+ // If we've received new non UUID information for this request and it hasn't dispatched
+ // yet, then update the request accordingly.
+ textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber);
+ }
+ else
+ {
+ if (!foundTextureLimitStrategy.AllowRequest(e.RequestedAssetID))
+ {
+// m_log.DebugFormat(
+// "[USER TEXTURE DOWNLOAD SERVICE]: Refusing request for {0} from client {1}",
+// e.RequestedAssetID, m_client.AgentId);
+
+ return;
+ }
+ else if (!missingTextureLimitStrategy.AllowRequest(e.RequestedAssetID))
+ {
+ if (missingTextureLimitStrategy.IsFirstRefusal(e.RequestedAssetID))
+ {
+ // Commenting out this message for now as it causes too much noise with other
+ // debug messages.
+ // TODO: possibly record this as a statistic in the future
+ //
+// m_log.DebugFormat(
+// "[USER TEXTURE DOWNLOAD SERVICE]: Dropping requests for notified missing texture {0} for client {1} since we have received more than {2} requests",
+// e.RequestedAssetID, m_client.AgentId, MAX_ALLOWED_TEXTURE_REQUESTS);
+ }
+
+ return;
+ }
+
+ m_scene.AddPendingDownloads(1);
+
+ TextureSender.TextureSender requestHandler = new TextureSender.TextureSender(m_client, e.DiscardLevel, e.PacketNumber);
+ m_textureSenders.Add(e.RequestedAssetID, requestHandler);
+
+ m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true);
+ }
+ }
+ }
+ else
+ {
+ lock (m_textureSenders)
+ {
+ if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
+ {
+ textureSender.Cancel = true;
+ }
+ }
+ }
+ }
+
+ ///
+ /// The callback for the asset cache when a texture has been retrieved. This method queues the
+ /// texture sender for processing.
+ ///
+ ///
+ ///
+ public void TextureCallback(LLUUID textureID, AssetBase texture)
+ {
+ //m_log.DebugFormat("[USER TEXTURE DOWNLOAD SERVICE]: Calling TextureCallback with {0}, texture == null is {1}", textureID, (texture == null ? true : false));
+
+ lock (m_textureSenders)
+ {
+ TextureSender.TextureSender textureSender;
+
+ if (m_textureSenders.TryGetValue(textureID, out textureSender))
+ {
+ // XXX It may be perfectly valid for a texture to have no data... but if we pass
+ // this on to the TextureSender it will blow up, so just discard for now.
+ // Needs investigation.
+ if (texture == null || texture.Data == null)
+ {
+ if (!missingTextureLimitStrategy.IsMonitoringRequests(textureID))
+ {
+ missingTextureLimitStrategy.MonitorRequests(textureID);
+
+ m_log.DebugFormat(
+ "[USER TEXTURE DOWNLOAD SERVICE]: Queueing first TextureNotFoundSender for {0}, client {1}",
+ textureID, m_client.AgentId);
+ }
+
+ ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID);
+ EnqueueTextureSender(textureNotFoundSender);
+ }
+ else
+ {
+ if (!textureSender.ImageLoaded)
+ {
+ textureSender.TextureReceived(texture);
+ EnqueueTextureSender(textureSender);
+
+ foundTextureLimitStrategy.MonitorRequests(textureID);
+ }
+ }
+
+ //m_log.InfoFormat("[TEXTURE SENDER] Removing texture sender with uuid {0}", textureID);
+ m_textureSenders.Remove(textureID);
+ //m_log.InfoFormat("[TEXTURE SENDER] Current texture senders in dictionary: {0}", m_textureSenders.Count);
+ }
+ else
+ {
+ m_log.WarnFormat(
+ "Got a texture uuid {0} with no sender object to handle it, this shouldn't happen",
+ textureID);
+ }
+ }
+ }
+
+ ///
+ /// Place a ready texture sender on the processing queue.
+ ///
+ ///
+ private void EnqueueTextureSender(ITextureSender textureSender)
+ {
+ textureSender.Cancel = false;
+ textureSender.Sending = true;
+
+ if (!m_sharedSendersQueue.Contains(textureSender))
+ {
+ m_sharedSendersQueue.Enqueue(textureSender);
+ }
+ }
+
+ ///
+ /// Close this module.
+ ///
+ internal void Close()
+ {
+ lock (m_textureSenders)
+ {
+ foreach (TextureSender.TextureSender textureSender in m_textureSenders.Values)
+ {
+ textureSender.Cancel = true;
+ }
+
+ m_textureSenders.Clear();
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs
index b6f7095..02c541b 100644
--- a/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs
@@ -1,223 +1,223 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Reflection;
-using libsecondlife.Packets;
-using log4net;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-
-namespace OpenSim.Region.Environment.Modules.Agent.TextureSender
-{
- ///
- /// A TextureSender handles the process of receiving a texture requested by the client from the
- /// AssetCache, and then sending that texture back to the client.
- ///
- public class TextureSender : ITextureSender
- {
- private static readonly ILog m_log
- = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- ///
- /// Records the number of times texture send has been called.
- ///
- public int counter = 0;
-
- public bool ImageLoaded = false;
-
- ///
- /// Holds the texture asset to send.
- ///
- private AssetBase m_asset;
-
- //public LLUUID assetID { get { return m_asset.FullID; } }
-
- private bool m_cancel = false;
-
- // See ITextureSender
-
- private bool m_sending = false;
-
- ///
- /// This is actually the number of extra packets required to send the texture data! We always assume
- /// at least one is required.
- ///
- private int NumPackets = 0;
-
- ///
- /// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts
- /// at the 600th byte (0th indexed).
- ///
- private int PacketCounter = 0;
-
- private int RequestedDiscardLevel = -1;
- private IClientAPI RequestUser;
- private uint StartPacketNumber = 0;
-
- public TextureSender(IClientAPI client, int discardLevel, uint packetNumber)
- {
- RequestUser = client;
- RequestedDiscardLevel = discardLevel;
- StartPacketNumber = packetNumber;
- }
-
- #region ITextureSender Members
-
- public bool Cancel
- {
- get { return false; }
- set { m_cancel = value; }
- }
-
- public bool Sending
- {
- get { return false; }
- set { m_sending = value; }
- }
-
- // See ITextureSender
- public void UpdateRequest(int discardLevel, uint packetNumber)
- {
- RequestedDiscardLevel = discardLevel;
- StartPacketNumber = packetNumber;
- PacketCounter = (int) StartPacketNumber;
- }
-
- // See ITextureSender
- public bool SendTexturePacket()
- {
- //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID);
-
- SendPacket();
- counter++;
- if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) ||
- ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets / (RequestedDiscardLevel + 1)))))
- {
- return true;
- }
- return false;
- }
-
- #endregion
-
- ///
- /// Load up the texture data to send.
- ///
- ///
- /// A
- ///
- public void TextureReceived(AssetBase asset)
- {
- m_asset = asset;
- NumPackets = CalculateNumPackets(asset.Data.Length);
- PacketCounter = (int) StartPacketNumber;
- ImageLoaded = true;
- }
-
- ///
- /// Sends a texture packet to the client.
- ///
- private void SendPacket()
- {
- if (PacketCounter <= NumPackets)
- {
- if (PacketCounter == 0)
- {
- if (NumPackets == 0)
- {
- ImageDataPacket im = new ImageDataPacket();
- im.Header.Reliable = false;
- im.ImageID.Packets = 1;
- im.ImageID.ID = m_asset.FullID;
- im.ImageID.Size = (uint) m_asset.Data.Length;
- im.ImageData.Data = m_asset.Data;
- im.ImageID.Codec = 2;
- RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
- PacketCounter++;
- }
- else
- {
- ImageDataPacket im = new ImageDataPacket();
- im.Header.Reliable = false;
- im.ImageID.Packets = (ushort) (NumPackets);
- im.ImageID.ID = m_asset.FullID;
- im.ImageID.Size = (uint) m_asset.Data.Length;
- im.ImageData.Data = new byte[600];
- Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600);
- im.ImageID.Codec = 2;
- RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
- PacketCounter++;
- }
- }
- else
- {
- ImagePacketPacket im = new ImagePacketPacket();
- im.Header.Reliable = false;
- im.ImageID.Packet = (ushort) (PacketCounter);
- im.ImageID.ID = m_asset.FullID;
- int size = m_asset.Data.Length - 600 - (1000 * (PacketCounter - 1));
- if (size > 1000) size = 1000;
- im.ImageData.Data = new byte[size];
- try
- {
- Array.Copy(m_asset.Data, 600 + (1000 * (PacketCounter - 1)), im.ImageData.Data, 0, size);
- }
- catch (ArgumentOutOfRangeException)
- {
- m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" +
- m_asset.FullID.ToString());
- return;
- }
- RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
- PacketCounter++;
- }
- }
- }
-
- ///
- /// Calculate the number of packets that will be required to send the texture loaded into this sender
- /// This is actually the number of 1000 byte packets not including an initial 600 byte packet...
- ///
- ///
- ///
- private int CalculateNumPackets(int length)
- {
- int numPackets = 0;
-
- if (length > 600)
- {
- //over 600 bytes so split up file
- int restData = (length - 600);
- int restPackets = ((restData + 999) / 1000);
- numPackets = restPackets;
- }
-
- return numPackets;
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Reflection;
+using libsecondlife.Packets;
+using log4net;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+
+namespace OpenSim.Region.Environment.Modules.Agent.TextureSender
+{
+ ///
+ /// A TextureSender handles the process of receiving a texture requested by the client from the
+ /// AssetCache, and then sending that texture back to the client.
+ ///
+ public class TextureSender : ITextureSender
+ {
+ private static readonly ILog m_log
+ = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ ///
+ /// Records the number of times texture send has been called.
+ ///
+ public int counter = 0;
+
+ public bool ImageLoaded = false;
+
+ ///
+ /// Holds the texture asset to send.
+ ///
+ private AssetBase m_asset;
+
+ //public LLUUID assetID { get { return m_asset.FullID; } }
+
+ private bool m_cancel = false;
+
+ // See ITextureSender
+
+ private bool m_sending = false;
+
+ ///
+ /// This is actually the number of extra packets required to send the texture data! We always assume
+ /// at least one is required.
+ ///
+ private int NumPackets = 0;
+
+ ///
+ /// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts
+ /// at the 600th byte (0th indexed).
+ ///
+ private int PacketCounter = 0;
+
+ private int RequestedDiscardLevel = -1;
+ private IClientAPI RequestUser;
+ private uint StartPacketNumber = 0;
+
+ public TextureSender(IClientAPI client, int discardLevel, uint packetNumber)
+ {
+ RequestUser = client;
+ RequestedDiscardLevel = discardLevel;
+ StartPacketNumber = packetNumber;
+ }
+
+ #region ITextureSender Members
+
+ public bool Cancel
+ {
+ get { return false; }
+ set { m_cancel = value; }
+ }
+
+ public bool Sending
+ {
+ get { return false; }
+ set { m_sending = value; }
+ }
+
+ // See ITextureSender
+ public void UpdateRequest(int discardLevel, uint packetNumber)
+ {
+ RequestedDiscardLevel = discardLevel;
+ StartPacketNumber = packetNumber;
+ PacketCounter = (int) StartPacketNumber;
+ }
+
+ // See ITextureSender
+ public bool SendTexturePacket()
+ {
+ //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID);
+
+ SendPacket();
+ counter++;
+ if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) ||
+ ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets / (RequestedDiscardLevel + 1)))))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ #endregion
+
+ ///
+ /// Load up the texture data to send.
+ ///
+ ///
+ /// A
+ ///
+ public void TextureReceived(AssetBase asset)
+ {
+ m_asset = asset;
+ NumPackets = CalculateNumPackets(asset.Data.Length);
+ PacketCounter = (int) StartPacketNumber;
+ ImageLoaded = true;
+ }
+
+ ///
+ /// Sends a texture packet to the client.
+ ///
+ private void SendPacket()
+ {
+ if (PacketCounter <= NumPackets)
+ {
+ if (PacketCounter == 0)
+ {
+ if (NumPackets == 0)
+ {
+ ImageDataPacket im = new ImageDataPacket();
+ im.Header.Reliable = false;
+ im.ImageID.Packets = 1;
+ im.ImageID.ID = m_asset.FullID;
+ im.ImageID.Size = (uint) m_asset.Data.Length;
+ im.ImageData.Data = m_asset.Data;
+ im.ImageID.Codec = 2;
+ RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
+ PacketCounter++;
+ }
+ else
+ {
+ ImageDataPacket im = new ImageDataPacket();
+ im.Header.Reliable = false;
+ im.ImageID.Packets = (ushort) (NumPackets);
+ im.ImageID.ID = m_asset.FullID;
+ im.ImageID.Size = (uint) m_asset.Data.Length;
+ im.ImageData.Data = new byte[600];
+ Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600);
+ im.ImageID.Codec = 2;
+ RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
+ PacketCounter++;
+ }
+ }
+ else
+ {
+ ImagePacketPacket im = new ImagePacketPacket();
+ im.Header.Reliable = false;
+ im.ImageID.Packet = (ushort) (PacketCounter);
+ im.ImageID.ID = m_asset.FullID;
+ int size = m_asset.Data.Length - 600 - (1000 * (PacketCounter - 1));
+ if (size > 1000) size = 1000;
+ im.ImageData.Data = new byte[size];
+ try
+ {
+ Array.Copy(m_asset.Data, 600 + (1000 * (PacketCounter - 1)), im.ImageData.Data, 0, size);
+ }
+ catch (ArgumentOutOfRangeException)
+ {
+ m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" +
+ m_asset.FullID.ToString());
+ return;
+ }
+ RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
+ PacketCounter++;
+ }
+ }
+ }
+
+ ///
+ /// Calculate the number of packets that will be required to send the texture loaded into this sender
+ /// This is actually the number of 1000 byte packets not including an initial 600 byte packet...
+ ///
+ ///
+ ///
+ private int CalculateNumPackets(int length)
+ {
+ int numPackets = 0;
+
+ if (length > 600)
+ {
+ //over 600 bytes so split up file
+ int restData = (length - 600);
+ int restPackets = ((restData + 999) / 1000);
+ numPackets = restPackets;
+ }
+
+ return numPackets;
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Agent/Xfer/XferModule.cs b/OpenSim/Region/Environment/Modules/Agent/Xfer/XferModule.cs
index e35b6f5..8e90d17 100644
--- a/OpenSim/Region/Environment/Modules/Agent/Xfer/XferModule.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/Xfer/XferModule.cs
@@ -1,235 +1,235 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections.Generic;
-using libsecondlife;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Agent.Xfer
-{
- public class XferModule : IRegionModule, IXfer
- {
- private Scene m_scene;
- public Dictionary NewFiles = new Dictionary();
- public Dictionary Transfers = new Dictionary();
-
- public XferModule()
- {
- }
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- m_scene = scene;
- m_scene.EventManager.OnNewClient += NewClient;
-
- m_scene.RegisterModuleInterface(this);
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "XferModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return false; }
- }
-
- #endregion
-
- #region IXfer Members
-
- public bool AddNewFile(string fileName, byte[] data)
- {
- lock (NewFiles)
- {
- if (NewFiles.ContainsKey(fileName))
- {
- NewFiles[fileName] = data;
- }
- else
- {
- NewFiles.Add(fileName, data);
- }
- }
- return true;
- }
-
- #endregion
-
- public void NewClient(IClientAPI client)
- {
- client.OnRequestXfer += RequestXfer;
- client.OnConfirmXfer += AckPacket;
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public void RequestXfer(IClientAPI remoteClient, ulong xferID, string fileName)
- {
- lock (NewFiles)
- {
- if (NewFiles.ContainsKey(fileName))
- {
- if (!Transfers.ContainsKey(xferID))
- {
- byte[] fileData = NewFiles[fileName];
- XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient);
- Transfers.Add(xferID, transaction);
- NewFiles.Remove(fileName);
-
- if (transaction.StartSend())
- {
- Transfers.Remove(xferID);
- }
- }
- }
- }
- }
-
- public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet)
- {
- if (Transfers.ContainsKey(xferID))
- {
- if (Transfers[xferID].AckPacket(packet))
- {
- {
- Transfers.Remove(xferID);
- }
- }
- }
- }
-
- #region Nested type: XferDownLoad
-
- public class XferDownLoad
- {
- public IClientAPI Client;
- private bool complete;
- public byte[] Data = new byte[0];
- public int DataPointer = 0;
- public string FileName = String.Empty;
- public uint Packet = 0;
- public uint Serial = 1;
- public ulong XferID = 0;
-
- public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client)
- {
- FileName = fileName;
- Data = data;
- XferID = xferID;
- Client = client;
- }
-
- public XferDownLoad()
- {
- }
-
- ///
- /// Start a transfer
- ///
- /// True if the transfer is complete, false if not
- public bool StartSend()
- {
- if (Data.Length < 1000)
- {
- // for now (testing ) we only support files under 1000 bytes
- byte[] transferData = new byte[Data.Length + 4];
- Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4);
- Array.Copy(Data, 0, transferData, 4, Data.Length);
- Client.SendXferPacket(XferID, 0 + 0x80000000, transferData);
-
- complete = true;
- }
- else
- {
- byte[] transferData = new byte[1000 + 4];
- Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4);
- Array.Copy(Data, 0, transferData, 4, 1000);
- Client.SendXferPacket(XferID, 0, transferData);
- Packet++;
- DataPointer = 1000;
- }
-
- return complete;
- }
-
- ///
- /// Respond to an ack packet from the client
- ///
- ///
- /// True if the transfer is complete, false otherwise
- public bool AckPacket(uint packet)
- {
- if (!complete)
- {
- if ((Data.Length - DataPointer) > 1000)
- {
- byte[] transferData = new byte[1000];
- Array.Copy(Data, DataPointer, transferData, 0, 1000);
- Client.SendXferPacket(XferID, Packet, transferData);
- Packet++;
- DataPointer += 1000;
- }
- else
- {
- byte[] transferData = new byte[Data.Length - DataPointer];
- Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer);
- uint endPacket = Packet |= (uint) 0x80000000;
- Client.SendXferPacket(XferID, endPacket, transferData);
- Packet++;
- DataPointer += (Data.Length - DataPointer);
-
- complete = true;
- }
- }
-
- return complete;
- }
- }
-
- #endregion
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using libsecondlife;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Agent.Xfer
+{
+ public class XferModule : IRegionModule, IXfer
+ {
+ private Scene m_scene;
+ public Dictionary NewFiles = new Dictionary();
+ public Dictionary Transfers = new Dictionary();
+
+ public XferModule()
+ {
+ }
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ m_scene = scene;
+ m_scene.EventManager.OnNewClient += NewClient;
+
+ m_scene.RegisterModuleInterface(this);
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "XferModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return false; }
+ }
+
+ #endregion
+
+ #region IXfer Members
+
+ public bool AddNewFile(string fileName, byte[] data)
+ {
+ lock (NewFiles)
+ {
+ if (NewFiles.ContainsKey(fileName))
+ {
+ NewFiles[fileName] = data;
+ }
+ else
+ {
+ NewFiles.Add(fileName, data);
+ }
+ }
+ return true;
+ }
+
+ #endregion
+
+ public void NewClient(IClientAPI client)
+ {
+ client.OnRequestXfer += RequestXfer;
+ client.OnConfirmXfer += AckPacket;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void RequestXfer(IClientAPI remoteClient, ulong xferID, string fileName)
+ {
+ lock (NewFiles)
+ {
+ if (NewFiles.ContainsKey(fileName))
+ {
+ if (!Transfers.ContainsKey(xferID))
+ {
+ byte[] fileData = NewFiles[fileName];
+ XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient);
+ Transfers.Add(xferID, transaction);
+ NewFiles.Remove(fileName);
+
+ if (transaction.StartSend())
+ {
+ Transfers.Remove(xferID);
+ }
+ }
+ }
+ }
+ }
+
+ public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet)
+ {
+ if (Transfers.ContainsKey(xferID))
+ {
+ if (Transfers[xferID].AckPacket(packet))
+ {
+ {
+ Transfers.Remove(xferID);
+ }
+ }
+ }
+ }
+
+ #region Nested type: XferDownLoad
+
+ public class XferDownLoad
+ {
+ public IClientAPI Client;
+ private bool complete;
+ public byte[] Data = new byte[0];
+ public int DataPointer = 0;
+ public string FileName = String.Empty;
+ public uint Packet = 0;
+ public uint Serial = 1;
+ public ulong XferID = 0;
+
+ public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client)
+ {
+ FileName = fileName;
+ Data = data;
+ XferID = xferID;
+ Client = client;
+ }
+
+ public XferDownLoad()
+ {
+ }
+
+ ///
+ /// Start a transfer
+ ///
+ /// True if the transfer is complete, false if not
+ public bool StartSend()
+ {
+ if (Data.Length < 1000)
+ {
+ // for now (testing ) we only support files under 1000 bytes
+ byte[] transferData = new byte[Data.Length + 4];
+ Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4);
+ Array.Copy(Data, 0, transferData, 4, Data.Length);
+ Client.SendXferPacket(XferID, 0 + 0x80000000, transferData);
+
+ complete = true;
+ }
+ else
+ {
+ byte[] transferData = new byte[1000 + 4];
+ Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4);
+ Array.Copy(Data, 0, transferData, 4, 1000);
+ Client.SendXferPacket(XferID, 0, transferData);
+ Packet++;
+ DataPointer = 1000;
+ }
+
+ return complete;
+ }
+
+ ///
+ /// Respond to an ack packet from the client
+ ///
+ ///
+ /// True if the transfer is complete, false otherwise
+ public bool AckPacket(uint packet)
+ {
+ if (!complete)
+ {
+ if ((Data.Length - DataPointer) > 1000)
+ {
+ byte[] transferData = new byte[1000];
+ Array.Copy(Data, DataPointer, transferData, 0, 1000);
+ Client.SendXferPacket(XferID, Packet, transferData);
+ Packet++;
+ DataPointer += 1000;
+ }
+ else
+ {
+ byte[] transferData = new byte[Data.Length - DataPointer];
+ Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer);
+ uint endPacket = Packet |= (uint) 0x80000000;
+ Client.SendXferPacket(XferID, endPacket, transferData);
+ Packet++;
+ DataPointer += (Data.Length - DataPointer);
+
+ complete = true;
+ }
+ }
+
+ return complete;
+ }
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 3614686..cb94021 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -1,338 +1,338 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using libsecondlife;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Framework.Communications.Cache;
-using OpenSim.Data.MySQLMapper;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-using OpenSim.Data.Base;
-
-namespace OpenSim.Region.Environment.Modules
-{
- public class AvatarFactoryModule : IAvatarFactory
- {
- private Scene m_scene = null;
- private readonly Dictionary m_avatarsAppearance = new Dictionary();
-
- private bool m_enablePersist = false;
- private string m_connectionString;
- private bool m_configured = false;
- private BaseDatabaseConnector m_databaseMapper;
- private AppearanceTableMapper m_appearanceMapper;
-
- private Dictionary m_fetchesInProgress = new Dictionary();
- private object m_syncLock = new object();
-
- public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance)
- {
-
- //should only let one thread at a time do this part
- EventWaitHandle waitHandle = null;
- bool fetchInProgress = false;
- lock (m_syncLock)
- {
- appearance = CheckCache(avatarId);
- if (appearance != null)
- {
- return true;
- }
-
- //not in cache so check to see if another thread is already fetching it
- if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle))
- {
- fetchInProgress = true;
- }
- else
- {
- fetchInProgress = false;
-
- //no thread already fetching this appearance, so add a wait handle to list
- //for any following threads that want the same appearance
- waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
- m_fetchesInProgress.Add(avatarId, waitHandle);
- }
- }
-
- if (fetchInProgress)
- {
- waitHandle.WaitOne();
- appearance = CheckCache(avatarId);
- if (appearance != null)
- {
- waitHandle = null;
- return true;
- }
- else
- {
- waitHandle = null;
- return false;
- }
- }
- else
- {
- Thread.Sleep(5000);
-
- //this is the first thread to request this appearance
- //so let it check the db and if not found then create a default appearance
- //and add that to the cache
- appearance = CheckDatabase(avatarId);
- if (appearance != null)
- {
- //appearance has now been added to cache so lets pulse any waiting threads
- lock (m_syncLock)
- {
- m_fetchesInProgress.Remove(avatarId);
- waitHandle.Set();
- }
- // waitHandle.Close();
- waitHandle = null;
- return true;
- }
-
- //not found a appearance for the user, so create a new default one
- appearance = CreateDefault(avatarId);
- if (appearance != null)
- {
- //update database
- if (m_enablePersist)
- {
- m_appearanceMapper.Add(avatarId.UUID, appearance);
- }
-
- //add appearance to dictionary cache
- lock (m_avatarsAppearance)
- {
- m_avatarsAppearance[avatarId] = appearance;
- }
-
- //appearance has now been added to cache so lets pulse any waiting threads
- lock (m_syncLock)
- {
- m_fetchesInProgress.Remove(avatarId);
- waitHandle.Set();
- }
- // waitHandle.Close();
- waitHandle = null;
- return true;
- }
- else
- {
- //something went wrong, so release the wait handle and remove it
- //all waiting threads will fail to find cached appearance
- //but its better for them to fail than wait for ever
- lock (m_syncLock)
- {
- m_fetchesInProgress.Remove(avatarId);
- waitHandle.Set();
- }
- //waitHandle.Close();
- waitHandle = null;
- return false;
- }
- }
- }
-
- private AvatarAppearance CreateDefault(LLUUID avatarId)
- {
- AvatarAppearance appearance = null;
- AvatarWearable[] wearables;
- byte[] visualParams;
- GetDefaultAvatarAppearance(out wearables, out visualParams);
- appearance = new AvatarAppearance(avatarId, wearables, visualParams);
-
- return appearance;
- }
-
- private AvatarAppearance CheckDatabase(LLUUID avatarId)
- {
- AvatarAppearance appearance = null;
- if (m_enablePersist)
- {
- if (m_appearanceMapper.TryGetValue(avatarId.UUID, out appearance))
- {
- appearance.VisualParams = GetDefaultVisualParams();
- appearance.TextureEntry = AvatarAppearance.GetDefaultTextureEntry();
- lock (m_avatarsAppearance)
- {
- m_avatarsAppearance[avatarId] = appearance;
- }
- }
- }
- return appearance;
- }
-
- private AvatarAppearance CheckCache(LLUUID avatarId)
- {
- AvatarAppearance appearance = null;
- lock (m_avatarsAppearance)
- {
- if (m_avatarsAppearance.ContainsKey(avatarId))
- {
- appearance = m_avatarsAppearance[avatarId];
- }
- }
- return appearance;
- }
-
- public void Initialise(Scene scene, IConfigSource source)
- {
- scene.RegisterModuleInterface(this);
- scene.EventManager.OnNewClient += NewClient;
-
- if (m_scene == null)
- {
- m_scene = scene;
- }
-
- if (!m_configured)
- {
- m_configured = true;
- try
- {
- m_enablePersist = source.Configs["Startup"].GetBoolean("appearance_persist", false);
- m_connectionString = source.Configs["Startup"].GetString("appearance_connection_string", "");
- }
- catch (Exception)
- {
- }
- if (m_enablePersist)
- {
- m_databaseMapper = new MySQLDatabaseMapper(m_connectionString);
- m_appearanceMapper = new AppearanceTableMapper(m_databaseMapper, "AvatarAppearance");
- }
- }
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "Default Avatar Factory"; }
- }
-
- public bool IsSharedModule
- {
- get { return true; }
- }
-
- public void NewClient(IClientAPI client)
- {
- client.OnAvatarNowWearing += AvatarIsWearing;
- }
-
- public void RemoveClient(IClientAPI client)
- {
- // client.OnAvatarNowWearing -= AvatarIsWearing;
- }
-
- public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
- {
- IClientAPI clientView = (IClientAPI)sender;
- CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId);
- if (profile != null)
- {
- if (profile.RootFolder != null)
- {
- if (m_avatarsAppearance.ContainsKey(clientView.AgentId))
- {
- AvatarAppearance avatAppearance = null;
- lock (m_avatarsAppearance)
- {
- avatAppearance = m_avatarsAppearance[clientView.AgentId];
- }
-
- foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
- {
- if (wear.Type < 13)
- {
- if (wear.ItemID == LLUUID.Zero)
- {
- avatAppearance.Wearables[wear.Type].ItemID = LLUUID.Zero;
- avatAppearance.Wearables[wear.Type].AssetID = LLUUID.Zero;
-
- UpdateDatabase(clientView.AgentId, avatAppearance);
- }
- else
- {
- LLUUID assetId;
-
- InventoryItemBase baseItem = profile.RootFolder.HasItem(wear.ItemID);
- if (baseItem != null)
- {
- assetId = baseItem.assetID;
- avatAppearance.Wearables[wear.Type].AssetID = assetId;
- avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID;
-
- UpdateDatabase(clientView.AgentId, avatAppearance);
- }
- }
- }
- }
- }
- }
- }
- }
-
- public void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance)
- {
- if (m_enablePersist)
- {
- m_appearanceMapper.Update(userID.UUID, avatAppearance);
- }
- }
-
- public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams)
- {
- visualParams = GetDefaultVisualParams();
- wearables = AvatarWearable.DefaultWearables;
- }
-
- private static byte[] GetDefaultVisualParams()
- {
- byte[] visualParams;
- visualParams = new byte[218];
- for (int i = 0; i < 218; i++)
- {
- visualParams[i] = 100;
- }
- return visualParams;
- }
- }
-}*/
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using libsecondlife;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Framework.Communications.Cache;
+using OpenSim.Data.MySQLMapper;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+using OpenSim.Data.Base;
+
+namespace OpenSim.Region.Environment.Modules
+{
+ public class AvatarFactoryModule : IAvatarFactory
+ {
+ private Scene m_scene = null;
+ private readonly Dictionary m_avatarsAppearance = new Dictionary();
+
+ private bool m_enablePersist = false;
+ private string m_connectionString;
+ private bool m_configured = false;
+ private BaseDatabaseConnector m_databaseMapper;
+ private AppearanceTableMapper m_appearanceMapper;
+
+ private Dictionary m_fetchesInProgress = new Dictionary();
+ private object m_syncLock = new object();
+
+ public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance)
+ {
+
+ //should only let one thread at a time do this part
+ EventWaitHandle waitHandle = null;
+ bool fetchInProgress = false;
+ lock (m_syncLock)
+ {
+ appearance = CheckCache(avatarId);
+ if (appearance != null)
+ {
+ return true;
+ }
+
+ //not in cache so check to see if another thread is already fetching it
+ if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle))
+ {
+ fetchInProgress = true;
+ }
+ else
+ {
+ fetchInProgress = false;
+
+ //no thread already fetching this appearance, so add a wait handle to list
+ //for any following threads that want the same appearance
+ waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
+ m_fetchesInProgress.Add(avatarId, waitHandle);
+ }
+ }
+
+ if (fetchInProgress)
+ {
+ waitHandle.WaitOne();
+ appearance = CheckCache(avatarId);
+ if (appearance != null)
+ {
+ waitHandle = null;
+ return true;
+ }
+ else
+ {
+ waitHandle = null;
+ return false;
+ }
+ }
+ else
+ {
+ Thread.Sleep(5000);
+
+ //this is the first thread to request this appearance
+ //so let it check the db and if not found then create a default appearance
+ //and add that to the cache
+ appearance = CheckDatabase(avatarId);
+ if (appearance != null)
+ {
+ //appearance has now been added to cache so lets pulse any waiting threads
+ lock (m_syncLock)
+ {
+ m_fetchesInProgress.Remove(avatarId);
+ waitHandle.Set();
+ }
+ // waitHandle.Close();
+ waitHandle = null;
+ return true;
+ }
+
+ //not found a appearance for the user, so create a new default one
+ appearance = CreateDefault(avatarId);
+ if (appearance != null)
+ {
+ //update database
+ if (m_enablePersist)
+ {
+ m_appearanceMapper.Add(avatarId.UUID, appearance);
+ }
+
+ //add appearance to dictionary cache
+ lock (m_avatarsAppearance)
+ {
+ m_avatarsAppearance[avatarId] = appearance;
+ }
+
+ //appearance has now been added to cache so lets pulse any waiting threads
+ lock (m_syncLock)
+ {
+ m_fetchesInProgress.Remove(avatarId);
+ waitHandle.Set();
+ }
+ // waitHandle.Close();
+ waitHandle = null;
+ return true;
+ }
+ else
+ {
+ //something went wrong, so release the wait handle and remove it
+ //all waiting threads will fail to find cached appearance
+ //but its better for them to fail than wait for ever
+ lock (m_syncLock)
+ {
+ m_fetchesInProgress.Remove(avatarId);
+ waitHandle.Set();
+ }
+ //waitHandle.Close();
+ waitHandle = null;
+ return false;
+ }
+ }
+ }
+
+ private AvatarAppearance CreateDefault(LLUUID avatarId)
+ {
+ AvatarAppearance appearance = null;
+ AvatarWearable[] wearables;
+ byte[] visualParams;
+ GetDefaultAvatarAppearance(out wearables, out visualParams);
+ appearance = new AvatarAppearance(avatarId, wearables, visualParams);
+
+ return appearance;
+ }
+
+ private AvatarAppearance CheckDatabase(LLUUID avatarId)
+ {
+ AvatarAppearance appearance = null;
+ if (m_enablePersist)
+ {
+ if (m_appearanceMapper.TryGetValue(avatarId.UUID, out appearance))
+ {
+ appearance.VisualParams = GetDefaultVisualParams();
+ appearance.TextureEntry = AvatarAppearance.GetDefaultTextureEntry();
+ lock (m_avatarsAppearance)
+ {
+ m_avatarsAppearance[avatarId] = appearance;
+ }
+ }
+ }
+ return appearance;
+ }
+
+ private AvatarAppearance CheckCache(LLUUID avatarId)
+ {
+ AvatarAppearance appearance = null;
+ lock (m_avatarsAppearance)
+ {
+ if (m_avatarsAppearance.ContainsKey(avatarId))
+ {
+ appearance = m_avatarsAppearance[avatarId];
+ }
+ }
+ return appearance;
+ }
+
+ public void Initialise(Scene scene, IConfigSource source)
+ {
+ scene.RegisterModuleInterface(this);
+ scene.EventManager.OnNewClient += NewClient;
+
+ if (m_scene == null)
+ {
+ m_scene = scene;
+ }
+
+ if (!m_configured)
+ {
+ m_configured = true;
+ try
+ {
+ m_enablePersist = source.Configs["Startup"].GetBoolean("appearance_persist", false);
+ m_connectionString = source.Configs["Startup"].GetString("appearance_connection_string", "");
+ }
+ catch (Exception)
+ {
+ }
+ if (m_enablePersist)
+ {
+ m_databaseMapper = new MySQLDatabaseMapper(m_connectionString);
+ m_appearanceMapper = new AppearanceTableMapper(m_databaseMapper, "AvatarAppearance");
+ }
+ }
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "Default Avatar Factory"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return true; }
+ }
+
+ public void NewClient(IClientAPI client)
+ {
+ client.OnAvatarNowWearing += AvatarIsWearing;
+ }
+
+ public void RemoveClient(IClientAPI client)
+ {
+ // client.OnAvatarNowWearing -= AvatarIsWearing;
+ }
+
+ public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
+ {
+ IClientAPI clientView = (IClientAPI)sender;
+ CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId);
+ if (profile != null)
+ {
+ if (profile.RootFolder != null)
+ {
+ if (m_avatarsAppearance.ContainsKey(clientView.AgentId))
+ {
+ AvatarAppearance avatAppearance = null;
+ lock (m_avatarsAppearance)
+ {
+ avatAppearance = m_avatarsAppearance[clientView.AgentId];
+ }
+
+ foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
+ {
+ if (wear.Type < 13)
+ {
+ if (wear.ItemID == LLUUID.Zero)
+ {
+ avatAppearance.Wearables[wear.Type].ItemID = LLUUID.Zero;
+ avatAppearance.Wearables[wear.Type].AssetID = LLUUID.Zero;
+
+ UpdateDatabase(clientView.AgentId, avatAppearance);
+ }
+ else
+ {
+ LLUUID assetId;
+
+ InventoryItemBase baseItem = profile.RootFolder.HasItem(wear.ItemID);
+ if (baseItem != null)
+ {
+ assetId = baseItem.assetID;
+ avatAppearance.Wearables[wear.Type].AssetID = assetId;
+ avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID;
+
+ UpdateDatabase(clientView.AgentId, avatAppearance);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance)
+ {
+ if (m_enablePersist)
+ {
+ m_appearanceMapper.Update(userID.UUID, avatAppearance);
+ }
+ }
+
+ public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams)
+ {
+ visualParams = GetDefaultVisualParams();
+ wearables = AvatarWearable.DefaultWearables;
+ }
+
+ private static byte[] GetDefaultVisualParams()
+ {
+ byte[] visualParams;
+ visualParams = new byte[218];
+ for (int i = 0; i < 218; i++)
+ {
+ visualParams[i] = 100;
+ }
+ return visualParams;
+ }
+ }
+}*/
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs
index 966f5f3..15720fc 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs
@@ -1,868 +1,868 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Net.Sockets;
-using System.Reflection;
-using System.Text.RegularExpressions;
-using System.Threading;
-using libsecondlife;
-using log4net;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Avatar.Chat
-{
- public class ChatModule : IRegionModule, ISimChat
- {
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private string m_defaultzone = null;
-
- private IRCChatModule m_irc = null;
- private Thread m_irc_connector = null;
-
- private string m_last_leaving_user = null;
- private string m_last_new_user = null;
- private int m_saydistance = 30;
- private List m_scenes = new List();
- private int m_shoutdistance = 100;
- internal object m_syncInit = new object();
- internal object m_syncLogout = new object();
- private int m_whisperdistance = 10;
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- lock (m_syncInit)
- {
- if (!m_scenes.Contains(scene))
- {
- m_scenes.Add(scene);
- scene.EventManager.OnNewClient += NewClient;
- scene.RegisterModuleInterface(this);
- }
-
- // wrap this in a try block so that defaults will work if
- // the config file doesn't specify otherwise.
- try
- {
- m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
- m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
- m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
- }
- catch (Exception)
- {
- }
-
- try
- {
- m_defaultzone = config.Configs["IRC"].GetString("nick", "Sim");
- }
- catch (Exception)
- {
- }
-
- // setup IRC Relay
- if (m_irc == null)
- {
- m_irc = new IRCChatModule(config);
- }
- if (m_irc_connector == null)
- {
- m_irc_connector = new Thread(IRCConnectRun);
- m_irc_connector.Name = "IRCConnectorThread";
- m_irc_connector.IsBackground = true;
- }
- }
- }
-
- public void PostInitialise()
- {
- if (m_irc.Enabled)
- {
- try
- {
- //m_irc.Connect(m_scenes);
- if (m_irc_connector == null)
- {
- m_irc_connector = new Thread(IRCConnectRun);
- m_irc_connector.Name = "IRCConnectorThread";
- m_irc_connector.IsBackground = true;
- }
- if (!m_irc_connector.IsAlive)
- {
- m_irc_connector.Start();
- ThreadTracker.Add(m_irc_connector);
- }
- }
- catch (Exception)
- {
- }
- }
- }
-
- public void Close()
- {
- m_irc.Close();
- }
-
- public string Name
- {
- get { return "ChatModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return true; }
- }
-
- #endregion
-
- #region ISimChat Members
-
- public void SimChat(Object sender, ChatFromViewerArgs e)
- {
- // FROM: Sim TO: IRC
-
- ScenePresence avatar = null;
-
- //TODO: Move ForEachScenePresence and others into IScene.
- Scene scene = (Scene) e.Scene;
-
- //TODO: Remove the need for this check
- if (scene == null)
- scene = m_scenes[0];
-
- // Filled in since it's easier than rewriting right now.
- LLVector3 fromPos = e.Position;
- LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
-
- string fromName = e.From;
- string message = e.Message;
- LLUUID fromAgentID = LLUUID.Zero;
-
- if (e.Sender != null)
- {
- avatar = scene.GetScenePresence(e.Sender.AgentId);
- }
-
- if (avatar != null)
- {
- fromPos = avatar.AbsolutePosition;
- regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
- fromName = avatar.Firstname + " " + avatar.Lastname;
- fromAgentID = e.Sender.AgentId;
- }
-
- // Try to reconnect to server if not connected
- if (m_irc.Enabled && !m_irc.Connected)
- {
- // In a non-blocking way. Eventually the connector will get it started
- try
- {
- if (m_irc_connector == null)
- {
- m_irc_connector = new Thread(IRCConnectRun);
- m_irc_connector.Name = "IRCConnectorThread";
- m_irc_connector.IsBackground = true;
- }
- if (!m_irc_connector.IsAlive)
- {
- m_irc_connector.Start();
- ThreadTracker.Add(m_irc_connector);
- }
- }
- catch (Exception)
- {
- }
- }
-
-
- // We only want to relay stuff on channel 0
- if (e.Channel == 0)
- {
- // IRC stuff
- if (e.Message.Length > 0)
- {
- if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC
- {
- m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message);
- }
- }
-
- foreach (Scene s in m_scenes)
- {
- s.ForEachScenePresence(delegate(ScenePresence presence)
- {
- TrySendChatMessage(presence, fromPos, regionPos,
- fromAgentID, fromName, e.Type, message);
- });
- }
- }
- }
-
- #endregion
-
- public void NewClient(IClientAPI client)
- {
- try
- {
- client.OnChatFromViewer += SimChat;
-
- if ((m_irc.Enabled) && (m_irc.Connected))
- {
- string clientName = client.FirstName + " " + client.LastName;
- // handles simple case. May not work for hundred connecting in per second.
- // and the NewClients calles getting interleved
- // but filters out multiple reports
- if (clientName != m_last_new_user)
- {
- m_last_new_user = clientName;
- string clientRegion = FindClientRegion(client.FirstName, client.LastName);
- m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " in " + clientRegion);
- }
- }
- client.OnLogout += ClientLoggedOut;
- client.OnConnectionClosed += ClientLoggedOut;
- client.OnLogout += ClientLoggedOut;
- }
- catch (Exception ex)
- {
- m_log.Error("[IRC]: NewClient exception trap:" + ex.ToString());
- }
- }
-
- public void ClientLoggedOut(IClientAPI client)
- {
- lock (m_syncLogout)
- {
- try
- {
- if ((m_irc.Enabled) && (m_irc.Connected))
- {
- string clientName = client.FirstName + " " + client.LastName;
- string clientRegion = FindClientRegion(client.FirstName, client.LastName);
- // handles simple case. May not work for hundred connecting in per second.
- // and the NewClients calles getting interleved
- // but filters out multiple reports
- if (clientName != m_last_leaving_user)
- {
- m_last_leaving_user = clientName;
- m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " left " + clientRegion);
- m_log.Info("[IRC]: IRC watcher notices " + clientName + " left " + clientRegion);
- }
- }
- }
- catch (Exception ex)
- {
- m_log.Error("[IRC]: ClientLoggedOut exception trap:" + ex.ToString());
- }
- }
- }
-
- private void TrySendChatMessage(ScenePresence presence, LLVector3 fromPos, LLVector3 regionPos,
- LLUUID fromAgentID, string fromName, ChatTypeEnum type, string message)
- {
- if (!presence.IsChildAgent)
- {
- LLVector3 fromRegionPos = fromPos + regionPos;
- LLVector3 toRegionPos = presence.AbsolutePosition + regionPos;
- int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos));
-
- if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
- type == ChatTypeEnum.Say && dis > m_saydistance ||
- type == ChatTypeEnum.Shout && dis > m_shoutdistance)
- {
- return;
- }
-
- // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
- presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, fromAgentID);
- }
- }
-
- // if IRC is enabled then just keep trying using a monitor thread
- public void IRCConnectRun()
- {
- while (true)
- {
- if ((m_irc.Enabled) && (!m_irc.Connected))
- {
- m_irc.Connect(m_scenes);
- }
- Thread.Sleep(15000);
- }
- }
-
- public string FindClientRegion(string client_FirstName, string client_LastName)
- {
- string sourceRegion = null;
- foreach (Scene s in m_scenes)
- {
- s.ForEachScenePresence(delegate(ScenePresence presence)
- {
- if ((presence.IsChildAgent == false)
- && (presence.Firstname == client_FirstName)
- && (presence.Lastname == client_LastName))
- {
- sourceRegion = presence.Scene.RegionInfo.RegionName;
- //sourceRegion= s.RegionInfo.RegionName;
- }
- });
- if (sourceRegion != null) return sourceRegion;
- }
- if (m_defaultzone == null)
- {
- m_defaultzone = "Sim";
- }
- return m_defaultzone;
- }
- }
-
- internal class IRCChatModule
- {
- #region ErrorReplies enum
-
- public enum ErrorReplies
- {
- NotRegistered = 451, // ":You have not registered"
- NicknameInUse = 433 // " :Nickname is already in use"
- }
-
- #endregion
-
- #region Replies enum
-
- public enum Replies
- {
- MotdStart = 375, // ":- Message of the day - "
- Motd = 372, // ":- "
- EndOfMotd = 376 // ":End of /MOTD command"
- }
-
- #endregion
-
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private Thread listener;
-
- private string m_basenick = null;
- private string m_channel = null;
- private bool m_connected = false;
- private bool m_enabled = false;
- private List m_last_scenes = null;
- private string m_nick = null;
- private uint m_port = 6668;
- private string m_privmsgformat = "PRIVMSG {0} :<{1} in {2}>: {3}";
- private StreamReader m_reader;
- private List m_scenes = null;
- private string m_server = null;
-
- private NetworkStream m_stream;
- internal object m_syncConnect = new object();
- private TcpClient m_tcp;
- private string m_user = "USER OpenSimBot 8 * :I'm a OpenSim to irc bot";
- private StreamWriter m_writer;
-
- private Thread pingSender;
-
- public IRCChatModule(IConfigSource config)
- {
- m_nick = "OSimBot" + Util.RandomClass.Next(1, 99);
- m_tcp = null;
- m_writer = null;
- m_reader = null;
-
- // configuration in OpenSim.ini
- // [IRC]
- // server = chat.freenode.net
- // nick = OSimBot_mysim
- // ;username = USER OpenSimBot 8 * :I'm a OpenSim to irc bot
- // ; username is the IRC command line sent
- // ; USER * :
- // channel = #opensim-regions
- // port = 6667
- // ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message
- // ;for : :
- // ;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}"
- // ;for : - :
- // ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}"
- // ;for : - from :
- // ;msgformat = "PRIVMSG {0} : {3} - from {1}"
- // Traps I/O disconnects so it does not crash the sim
- // Trys to reconnect if disconnected and someone says something
- // Tells IRC server "QUIT" when doing a close (just to be nice)
- // Default port back to 6667
-
- try
- {
- m_server = config.Configs["IRC"].GetString("server");
- m_nick = config.Configs["IRC"].GetString("nick");
- m_basenick = m_nick;
- m_channel = config.Configs["IRC"].GetString("channel");
- m_port = (uint) config.Configs["IRC"].GetInt("port", (int) m_port);
- m_user = config.Configs["IRC"].GetString("username", m_user);
- m_privmsgformat = config.Configs["IRC"].GetString("msgformat", m_privmsgformat);
- if (m_server != null && m_nick != null && m_channel != null)
- {
- m_nick = m_nick + Util.RandomClass.Next(1, 99);
- m_enabled = true;
- }
- }
- catch (Exception)
- {
- m_log.Info("[CHAT]: No IRC config information, skipping IRC bridge configuration");
- }
- }
-
- public bool Enabled
- {
- get { return m_enabled; }
- }
-
- public bool Connected
- {
- get { return m_connected; }
- }
-
- public string Nick
- {
- get { return m_nick; }
- }
-
- public bool Connect(List scenes)
- {
- lock (m_syncConnect)
- {
- try
- {
- if (m_connected) return true;
- m_scenes = scenes;
- if (m_last_scenes == null)
- {
- m_last_scenes = scenes;
- }
-
- m_tcp = new TcpClient(m_server, (int) m_port);
- m_log.Info("[IRC]: Connecting...");
- m_stream = m_tcp.GetStream();
- m_log.Info("[IRC]: Connected to " + m_server);
- m_reader = new StreamReader(m_stream);
- m_writer = new StreamWriter(m_stream);
-
- pingSender = new Thread(new ThreadStart(PingRun));
- pingSender.Name = "PingSenderThread";
- pingSender.IsBackground = true;
- pingSender.Start();
- ThreadTracker.Add(pingSender);
-
- listener = new Thread(new ThreadStart(ListenerRun));
- listener.Name = "IRCChatModuleListenerThread";
- listener.IsBackground = true;
- listener.Start();
- ThreadTracker.Add(listener);
-
- m_writer.WriteLine(m_user);
- m_writer.Flush();
- m_writer.WriteLine("NICK " + m_nick);
- m_writer.Flush();
- m_writer.WriteLine("JOIN " + m_channel);
- m_writer.Flush();
- m_log.Info("[IRC]: Connection fully established");
- m_connected = true;
- }
- catch (Exception e)
- {
- Console.WriteLine(e.ToString());
- }
- return m_connected;
- }
- }
-
- public void Reconnect()
- {
- m_connected = false;
- listener.Abort();
- pingSender.Abort();
- m_writer.Close();
- m_reader.Close();
- m_tcp.Close();
- if (m_enabled)
- {
- Connect(m_last_scenes);
- }
- }
-
- public void PrivMsg(string from, string region, string msg)
- {
- // One message to the IRC server
-
- try
- {
- if (m_privmsgformat == null)
- {
- m_writer.WriteLine("PRIVMSG {0} :<{1} in {2}>: {3}", m_channel, from, region, msg);
- }
- else
- {
- m_writer.WriteLine(m_privmsgformat, m_channel, from, region, msg);
- }
- m_writer.Flush();
- m_log.Info("[IRC]: PrivMsg " + from + " in " + region + " :" + msg);
- }
- catch (IOException)
- {
- m_log.Error("[IRC]: Disconnected from IRC server.(PrivMsg)");
- Reconnect();
- }
- catch (Exception ex)
- {
- m_log.Error("[IRC]: PrivMsg exception trap:" + ex.ToString());
- }
- }
-
- private Dictionary ExtractMsg(string input)
- {
- //examines IRC commands and extracts any private messages
- // which will then be reboadcast in the Sim
-
- m_log.Info("[IRC]: ExtractMsg: " + input);
- Dictionary result = null;
- //string regex = @":(?\w*)!~(?\S*) PRIVMSG (?\S+) :(?.*)";
- string regex = @":(?\w*)!(?\S*) PRIVMSG (?\S+) :(?.*)";
- Regex RE = new Regex(regex, RegexOptions.Multiline);
- MatchCollection matches = RE.Matches(input);
- // Get some direct matches $1 $4 is a
- if ((matches.Count == 1) && (matches[0].Groups.Count == 5))
- {
- result = new Dictionary();
- result.Add("nick", matches[0].Groups[1].Value);
- result.Add("user", matches[0].Groups[2].Value);
- result.Add("channel", matches[0].Groups[3].Value);
- result.Add("msg", matches[0].Groups[4].Value);
- }
- else
- {
- m_log.Info("[IRC]: Number of matches: " + matches.Count);
- if (matches.Count > 0)
- {
- m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count);
- }
- }
- return result;
- }
-
- public void PingRun()
- {
- // IRC keep alive thread
- // send PING ever 15 seconds
- while (true)
- {
- try
- {
- if (m_connected == true)
- {
- m_writer.WriteLine("PING :" + m_server);
- m_writer.Flush();
- Thread.Sleep(15000);
- }
- }
- catch (IOException)
- {
- m_log.Error("[IRC]: Disconnected from IRC server.(PingRun)");
- Reconnect();
- }
- catch (Exception ex)
- {
- m_log.Error("[IRC]: PingRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace);
- }
- }
- }
-
- public void ListenerRun()
- {
- string inputLine;
- LLVector3 pos = new LLVector3(128, 128, 20);
- while (true)
- {
- try
- {
- while ((m_connected == true) && ((inputLine = m_reader.ReadLine()) != null))
- {
- // Console.WriteLine(inputLine);
- if (inputLine.Contains(m_channel))
- {
- Dictionary data = ExtractMsg(inputLine);
- // Any chat ???
- if (data != null)
- {
- foreach (Scene m_scene in m_scenes)
- {
- m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
- {
- if (!avatar.IsChildAgent)
- {
- avatar.ControllingClient.SendChatMessage(
- Helpers.StringToField(data["msg"]), 255,
- pos, data["nick"],
- LLUUID.Zero);
- }
- });
- }
- }
- else
- {
- // Was an command from the IRC server
- ProcessIRCCommand(inputLine);
- }
- }
- else
- {
- // Was an command from the IRC server
- ProcessIRCCommand(inputLine);
- }
- Thread.Sleep(150);
- }
- }
- catch (IOException)
- {
- m_log.Error("[IRC]: ListenerRun IOException. Disconnected from IRC server ??? (ListenerRun)");
- Reconnect();
- }
- catch (Exception ex)
- {
- m_log.Error("[IRC]: ListenerRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace);
- }
- }
- }
-
- public void BroadcastSim(string message, string sender)
- {
- LLVector3 pos = new LLVector3(128, 128, 20);
- try
- {
- foreach (Scene m_scene in m_scenes)
- {
- m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
- {
- if (!avatar.IsChildAgent)
- {
- avatar.ControllingClient.SendChatMessage(
- Helpers.StringToField(message), 255,
- pos, sender,
- LLUUID.Zero);
- }
- });
- }
- }
- catch (Exception ex) // IRC gate should not crash Sim
- {
- m_log.Error("[IRC]: BroadcastSim Exception Trap:" + ex.ToString() + "\n" + ex.StackTrace);
- }
- }
-
- public void ProcessIRCCommand(string command)
- {
- //m_log.Info("[IRC]: ProcessIRCCommand:" + command);
-
- string[] commArgs = new string[command.Split(' ').Length];
- string c_server = m_server;
-
- commArgs = command.Split(' ');
- if (commArgs[0].Substring(0, 1) == ":")
- {
- commArgs[0] = commArgs[0].Remove(0, 1);
- }
-
- if (commArgs[1] == "002")
- {
- // fetch the correct servername
- // ex: irc.freenode.net -> brown.freenode.net/kornbluth.freenode.net/...
- // irc.bluewin.ch -> irc1.bluewin.ch/irc2.bluewin.ch
-
- c_server = (commArgs[6].Split('['))[0];
- m_server = c_server;
- }
-
- if (commArgs[0] == "ERROR")
- {
- m_log.Error("[IRC]: IRC SERVER ERROR:" + command);
- }
-
- if (commArgs[0] == "PING")
- {
- string p_reply = "";
-
- for (int i = 1; i < commArgs.Length; i++)
- {
- p_reply += commArgs[i] + " ";
- }
-
- m_writer.WriteLine("PONG " + p_reply);
- m_writer.Flush();
- }
- else if (commArgs[0] == c_server)
- {
- // server message
- try
- {
- Int32 commandCode = Int32.Parse(commArgs[1]);
- switch (commandCode)
- {
- case (int) ErrorReplies.NicknameInUse:
- // Gen a new name
- m_nick = m_basenick + Util.RandomClass.Next(1, 99);
- m_log.Error("[IRC]: IRC SERVER reports NicknameInUse, trying " + m_nick);
- // Retry
- m_writer.WriteLine("NICK " + m_nick);
- m_writer.Flush();
- m_writer.WriteLine("JOIN " + m_channel);
- m_writer.Flush();
- break;
- case (int) ErrorReplies.NotRegistered:
- break;
- case (int) Replies.EndOfMotd:
- break;
- }
- }
- catch (Exception)
- {
- }
- }
- else
- {
- // Normal message
- string commAct = commArgs[1];
- switch (commAct)
- {
- case "JOIN":
- eventIrcJoin(commArgs);
- break;
- case "PART":
- eventIrcPart(commArgs);
- break;
- case "MODE":
- eventIrcMode(commArgs);
- break;
- case "NICK":
- eventIrcNickChange(commArgs);
- break;
- case "KICK":
- eventIrcKick(commArgs);
- break;
- case "QUIT":
- eventIrcQuit(commArgs);
- break;
- case "PONG":
- break; // that's nice
- }
- }
- }
-
- public void eventIrcJoin(string[] commArgs)
- {
- string IrcChannel = commArgs[2];
- string IrcUser = commArgs[0].Split('!')[0];
- BroadcastSim(IrcUser + " is joining " + IrcChannel, m_nick);
- }
-
- public void eventIrcPart(string[] commArgs)
- {
- string IrcChannel = commArgs[2];
- string IrcUser = commArgs[0].Split('!')[0];
- BroadcastSim(IrcUser + " is parting " + IrcChannel, m_nick);
- }
-
- public void eventIrcMode(string[] commArgs)
- {
- string IrcChannel = commArgs[2];
- string IrcUser = commArgs[0].Split('!')[0];
- string UserMode = "";
- for (int i = 3; i < commArgs.Length; i++)
- {
- UserMode += commArgs[i] + " ";
- }
-
- if (UserMode.Substring(0, 1) == ":")
- {
- UserMode = UserMode.Remove(0, 1);
- }
- }
-
- public void eventIrcNickChange(string[] commArgs)
- {
- string UserOldNick = commArgs[0].Split('!')[0];
- string UserNewNick = commArgs[2].Remove(0, 1);
- BroadcastSim(UserOldNick + " changed their nick to " + UserNewNick, m_nick);
- }
-
- public void eventIrcKick(string[] commArgs)
- {
- string UserKicker = commArgs[0].Split('!')[0];
- string UserKicked = commArgs[3];
- string IrcChannel = commArgs[2];
- string KickMessage = "";
- for (int i = 4; i < commArgs.Length; i++)
- {
- KickMessage += commArgs[i] + " ";
- }
- BroadcastSim(UserKicker + " kicked " + UserKicked + " on " + IrcChannel + " saying " + KickMessage, m_nick);
- if (UserKicked == m_nick)
- {
- BroadcastSim("Hey, that was me!!!", m_nick);
- }
- }
-
- public void eventIrcQuit(string[] commArgs)
- {
- string IrcUser = commArgs[0].Split('!')[0];
- string QuitMessage = "";
-
- for (int i = 2; i < commArgs.Length; i++)
- {
- QuitMessage += commArgs[i] + " ";
- }
- BroadcastSim(IrcUser + " quits saying " + QuitMessage, m_nick);
- }
-
- public void Close()
- {
- m_connected = false;
- m_writer.WriteLine("QUIT :" + m_nick + " to " + m_channel + " wormhole with " + m_server + " closing");
- m_writer.Flush();
- listener.Abort();
- pingSender.Abort();
- m_writer.Close();
- m_reader.Close();
- m_tcp.Close();
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Threading;
+using libsecondlife;
+using log4net;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Avatar.Chat
+{
+ public class ChatModule : IRegionModule, ISimChat
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private string m_defaultzone = null;
+
+ private IRCChatModule m_irc = null;
+ private Thread m_irc_connector = null;
+
+ private string m_last_leaving_user = null;
+ private string m_last_new_user = null;
+ private int m_saydistance = 30;
+ private List m_scenes = new List();
+ private int m_shoutdistance = 100;
+ internal object m_syncInit = new object();
+ internal object m_syncLogout = new object();
+ private int m_whisperdistance = 10;
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ lock (m_syncInit)
+ {
+ if (!m_scenes.Contains(scene))
+ {
+ m_scenes.Add(scene);
+ scene.EventManager.OnNewClient += NewClient;
+ scene.RegisterModuleInterface(this);
+ }
+
+ // wrap this in a try block so that defaults will work if
+ // the config file doesn't specify otherwise.
+ try
+ {
+ m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
+ m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
+ m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
+ }
+ catch (Exception)
+ {
+ }
+
+ try
+ {
+ m_defaultzone = config.Configs["IRC"].GetString("nick", "Sim");
+ }
+ catch (Exception)
+ {
+ }
+
+ // setup IRC Relay
+ if (m_irc == null)
+ {
+ m_irc = new IRCChatModule(config);
+ }
+ if (m_irc_connector == null)
+ {
+ m_irc_connector = new Thread(IRCConnectRun);
+ m_irc_connector.Name = "IRCConnectorThread";
+ m_irc_connector.IsBackground = true;
+ }
+ }
+ }
+
+ public void PostInitialise()
+ {
+ if (m_irc.Enabled)
+ {
+ try
+ {
+ //m_irc.Connect(m_scenes);
+ if (m_irc_connector == null)
+ {
+ m_irc_connector = new Thread(IRCConnectRun);
+ m_irc_connector.Name = "IRCConnectorThread";
+ m_irc_connector.IsBackground = true;
+ }
+ if (!m_irc_connector.IsAlive)
+ {
+ m_irc_connector.Start();
+ ThreadTracker.Add(m_irc_connector);
+ }
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ public void Close()
+ {
+ m_irc.Close();
+ }
+
+ public string Name
+ {
+ get { return "ChatModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return true; }
+ }
+
+ #endregion
+
+ #region ISimChat Members
+
+ public void SimChat(Object sender, ChatFromViewerArgs e)
+ {
+ // FROM: Sim TO: IRC
+
+ ScenePresence avatar = null;
+
+ //TODO: Move ForEachScenePresence and others into IScene.
+ Scene scene = (Scene) e.Scene;
+
+ //TODO: Remove the need for this check
+ if (scene == null)
+ scene = m_scenes[0];
+
+ // Filled in since it's easier than rewriting right now.
+ LLVector3 fromPos = e.Position;
+ LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
+
+ string fromName = e.From;
+ string message = e.Message;
+ LLUUID fromAgentID = LLUUID.Zero;
+
+ if (e.Sender != null)
+ {
+ avatar = scene.GetScenePresence(e.Sender.AgentId);
+ }
+
+ if (avatar != null)
+ {
+ fromPos = avatar.AbsolutePosition;
+ regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
+ fromName = avatar.Firstname + " " + avatar.Lastname;
+ fromAgentID = e.Sender.AgentId;
+ }
+
+ // Try to reconnect to server if not connected
+ if (m_irc.Enabled && !m_irc.Connected)
+ {
+ // In a non-blocking way. Eventually the connector will get it started
+ try
+ {
+ if (m_irc_connector == null)
+ {
+ m_irc_connector = new Thread(IRCConnectRun);
+ m_irc_connector.Name = "IRCConnectorThread";
+ m_irc_connector.IsBackground = true;
+ }
+ if (!m_irc_connector.IsAlive)
+ {
+ m_irc_connector.Start();
+ ThreadTracker.Add(m_irc_connector);
+ }
+ }
+ catch (Exception)
+ {
+ }
+ }
+
+
+ // We only want to relay stuff on channel 0
+ if (e.Channel == 0)
+ {
+ // IRC stuff
+ if (e.Message.Length > 0)
+ {
+ if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC
+ {
+ m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message);
+ }
+ }
+
+ foreach (Scene s in m_scenes)
+ {
+ s.ForEachScenePresence(delegate(ScenePresence presence)
+ {
+ TrySendChatMessage(presence, fromPos, regionPos,
+ fromAgentID, fromName, e.Type, message);
+ });
+ }
+ }
+ }
+
+ #endregion
+
+ public void NewClient(IClientAPI client)
+ {
+ try
+ {
+ client.OnChatFromViewer += SimChat;
+
+ if ((m_irc.Enabled) && (m_irc.Connected))
+ {
+ string clientName = client.FirstName + " " + client.LastName;
+ // handles simple case. May not work for hundred connecting in per second.
+ // and the NewClients calles getting interleved
+ // but filters out multiple reports
+ if (clientName != m_last_new_user)
+ {
+ m_last_new_user = clientName;
+ string clientRegion = FindClientRegion(client.FirstName, client.LastName);
+ m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " in " + clientRegion);
+ }
+ }
+ client.OnLogout += ClientLoggedOut;
+ client.OnConnectionClosed += ClientLoggedOut;
+ client.OnLogout += ClientLoggedOut;
+ }
+ catch (Exception ex)
+ {
+ m_log.Error("[IRC]: NewClient exception trap:" + ex.ToString());
+ }
+ }
+
+ public void ClientLoggedOut(IClientAPI client)
+ {
+ lock (m_syncLogout)
+ {
+ try
+ {
+ if ((m_irc.Enabled) && (m_irc.Connected))
+ {
+ string clientName = client.FirstName + " " + client.LastName;
+ string clientRegion = FindClientRegion(client.FirstName, client.LastName);
+ // handles simple case. May not work for hundred connecting in per second.
+ // and the NewClients calles getting interleved
+ // but filters out multiple reports
+ if (clientName != m_last_leaving_user)
+ {
+ m_last_leaving_user = clientName;
+ m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " left " + clientRegion);
+ m_log.Info("[IRC]: IRC watcher notices " + clientName + " left " + clientRegion);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ m_log.Error("[IRC]: ClientLoggedOut exception trap:" + ex.ToString());
+ }
+ }
+ }
+
+ private void TrySendChatMessage(ScenePresence presence, LLVector3 fromPos, LLVector3 regionPos,
+ LLUUID fromAgentID, string fromName, ChatTypeEnum type, string message)
+ {
+ if (!presence.IsChildAgent)
+ {
+ LLVector3 fromRegionPos = fromPos + regionPos;
+ LLVector3 toRegionPos = presence.AbsolutePosition + regionPos;
+ int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos));
+
+ if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
+ type == ChatTypeEnum.Say && dis > m_saydistance ||
+ type == ChatTypeEnum.Shout && dis > m_shoutdistance)
+ {
+ return;
+ }
+
+ // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
+ presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, fromAgentID);
+ }
+ }
+
+ // if IRC is enabled then just keep trying using a monitor thread
+ public void IRCConnectRun()
+ {
+ while (true)
+ {
+ if ((m_irc.Enabled) && (!m_irc.Connected))
+ {
+ m_irc.Connect(m_scenes);
+ }
+ Thread.Sleep(15000);
+ }
+ }
+
+ public string FindClientRegion(string client_FirstName, string client_LastName)
+ {
+ string sourceRegion = null;
+ foreach (Scene s in m_scenes)
+ {
+ s.ForEachScenePresence(delegate(ScenePresence presence)
+ {
+ if ((presence.IsChildAgent == false)
+ && (presence.Firstname == client_FirstName)
+ && (presence.Lastname == client_LastName))
+ {
+ sourceRegion = presence.Scene.RegionInfo.RegionName;
+ //sourceRegion= s.RegionInfo.RegionName;
+ }
+ });
+ if (sourceRegion != null) return sourceRegion;
+ }
+ if (m_defaultzone == null)
+ {
+ m_defaultzone = "Sim";
+ }
+ return m_defaultzone;
+ }
+ }
+
+ internal class IRCChatModule
+ {
+ #region ErrorReplies enum
+
+ public enum ErrorReplies
+ {
+ NotRegistered = 451, // ":You have not registered"
+ NicknameInUse = 433 // " :Nickname is already in use"
+ }
+
+ #endregion
+
+ #region Replies enum
+
+ public enum Replies
+ {
+ MotdStart = 375, // ":- Message of the day - "
+ Motd = 372, // ":- "
+ EndOfMotd = 376 // ":End of /MOTD command"
+ }
+
+ #endregion
+
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private Thread listener;
+
+ private string m_basenick = null;
+ private string m_channel = null;
+ private bool m_connected = false;
+ private bool m_enabled = false;
+ private List m_last_scenes = null;
+ private string m_nick = null;
+ private uint m_port = 6668;
+ private string m_privmsgformat = "PRIVMSG {0} :<{1} in {2}>: {3}";
+ private StreamReader m_reader;
+ private List m_scenes = null;
+ private string m_server = null;
+
+ private NetworkStream m_stream;
+ internal object m_syncConnect = new object();
+ private TcpClient m_tcp;
+ private string m_user = "USER OpenSimBot 8 * :I'm a OpenSim to irc bot";
+ private StreamWriter m_writer;
+
+ private Thread pingSender;
+
+ public IRCChatModule(IConfigSource config)
+ {
+ m_nick = "OSimBot" + Util.RandomClass.Next(1, 99);
+ m_tcp = null;
+ m_writer = null;
+ m_reader = null;
+
+ // configuration in OpenSim.ini
+ // [IRC]
+ // server = chat.freenode.net
+ // nick = OSimBot_mysim
+ // ;username = USER OpenSimBot 8 * :I'm a OpenSim to irc bot
+ // ; username is the IRC command line sent
+ // ; USER * :
+ // channel = #opensim-regions
+ // port = 6667
+ // ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message
+ // ;for : :
+ // ;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}"
+ // ;for : - :
+ // ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}"
+ // ;for : - from :
+ // ;msgformat = "PRIVMSG {0} : {3} - from {1}"
+ // Traps I/O disconnects so it does not crash the sim
+ // Trys to reconnect if disconnected and someone says something
+ // Tells IRC server "QUIT" when doing a close (just to be nice)
+ // Default port back to 6667
+
+ try
+ {
+ m_server = config.Configs["IRC"].GetString("server");
+ m_nick = config.Configs["IRC"].GetString("nick");
+ m_basenick = m_nick;
+ m_channel = config.Configs["IRC"].GetString("channel");
+ m_port = (uint) config.Configs["IRC"].GetInt("port", (int) m_port);
+ m_user = config.Configs["IRC"].GetString("username", m_user);
+ m_privmsgformat = config.Configs["IRC"].GetString("msgformat", m_privmsgformat);
+ if (m_server != null && m_nick != null && m_channel != null)
+ {
+ m_nick = m_nick + Util.RandomClass.Next(1, 99);
+ m_enabled = true;
+ }
+ }
+ catch (Exception)
+ {
+ m_log.Info("[CHAT]: No IRC config information, skipping IRC bridge configuration");
+ }
+ }
+
+ public bool Enabled
+ {
+ get { return m_enabled; }
+ }
+
+ public bool Connected
+ {
+ get { return m_connected; }
+ }
+
+ public string Nick
+ {
+ get { return m_nick; }
+ }
+
+ public bool Connect(List scenes)
+ {
+ lock (m_syncConnect)
+ {
+ try
+ {
+ if (m_connected) return true;
+ m_scenes = scenes;
+ if (m_last_scenes == null)
+ {
+ m_last_scenes = scenes;
+ }
+
+ m_tcp = new TcpClient(m_server, (int) m_port);
+ m_log.Info("[IRC]: Connecting...");
+ m_stream = m_tcp.GetStream();
+ m_log.Info("[IRC]: Connected to " + m_server);
+ m_reader = new StreamReader(m_stream);
+ m_writer = new StreamWriter(m_stream);
+
+ pingSender = new Thread(new ThreadStart(PingRun));
+ pingSender.Name = "PingSenderThread";
+ pingSender.IsBackground = true;
+ pingSender.Start();
+ ThreadTracker.Add(pingSender);
+
+ listener = new Thread(new ThreadStart(ListenerRun));
+ listener.Name = "IRCChatModuleListenerThread";
+ listener.IsBackground = true;
+ listener.Start();
+ ThreadTracker.Add(listener);
+
+ m_writer.WriteLine(m_user);
+ m_writer.Flush();
+ m_writer.WriteLine("NICK " + m_nick);
+ m_writer.Flush();
+ m_writer.WriteLine("JOIN " + m_channel);
+ m_writer.Flush();
+ m_log.Info("[IRC]: Connection fully established");
+ m_connected = true;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ return m_connected;
+ }
+ }
+
+ public void Reconnect()
+ {
+ m_connected = false;
+ listener.Abort();
+ pingSender.Abort();
+ m_writer.Close();
+ m_reader.Close();
+ m_tcp.Close();
+ if (m_enabled)
+ {
+ Connect(m_last_scenes);
+ }
+ }
+
+ public void PrivMsg(string from, string region, string msg)
+ {
+ // One message to the IRC server
+
+ try
+ {
+ if (m_privmsgformat == null)
+ {
+ m_writer.WriteLine("PRIVMSG {0} :<{1} in {2}>: {3}", m_channel, from, region, msg);
+ }
+ else
+ {
+ m_writer.WriteLine(m_privmsgformat, m_channel, from, region, msg);
+ }
+ m_writer.Flush();
+ m_log.Info("[IRC]: PrivMsg " + from + " in " + region + " :" + msg);
+ }
+ catch (IOException)
+ {
+ m_log.Error("[IRC]: Disconnected from IRC server.(PrivMsg)");
+ Reconnect();
+ }
+ catch (Exception ex)
+ {
+ m_log.Error("[IRC]: PrivMsg exception trap:" + ex.ToString());
+ }
+ }
+
+ private Dictionary ExtractMsg(string input)
+ {
+ //examines IRC commands and extracts any private messages
+ // which will then be reboadcast in the Sim
+
+ m_log.Info("[IRC]: ExtractMsg: " + input);
+ Dictionary result = null;
+ //string regex = @":(?\w*)!~(?\S*) PRIVMSG (?\S+) :(?.*)";
+ string regex = @":(?\w*)!(?\S*) PRIVMSG (?\S+) :(?.*)";
+ Regex RE = new Regex(regex, RegexOptions.Multiline);
+ MatchCollection matches = RE.Matches(input);
+ // Get some direct matches $1 $4 is a
+ if ((matches.Count == 1) && (matches[0].Groups.Count == 5))
+ {
+ result = new Dictionary();
+ result.Add("nick", matches[0].Groups[1].Value);
+ result.Add("user", matches[0].Groups[2].Value);
+ result.Add("channel", matches[0].Groups[3].Value);
+ result.Add("msg", matches[0].Groups[4].Value);
+ }
+ else
+ {
+ m_log.Info("[IRC]: Number of matches: " + matches.Count);
+ if (matches.Count > 0)
+ {
+ m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count);
+ }
+ }
+ return result;
+ }
+
+ public void PingRun()
+ {
+ // IRC keep alive thread
+ // send PING ever 15 seconds
+ while (true)
+ {
+ try
+ {
+ if (m_connected == true)
+ {
+ m_writer.WriteLine("PING :" + m_server);
+ m_writer.Flush();
+ Thread.Sleep(15000);
+ }
+ }
+ catch (IOException)
+ {
+ m_log.Error("[IRC]: Disconnected from IRC server.(PingRun)");
+ Reconnect();
+ }
+ catch (Exception ex)
+ {
+ m_log.Error("[IRC]: PingRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace);
+ }
+ }
+ }
+
+ public void ListenerRun()
+ {
+ string inputLine;
+ LLVector3 pos = new LLVector3(128, 128, 20);
+ while (true)
+ {
+ try
+ {
+ while ((m_connected == true) && ((inputLine = m_reader.ReadLine()) != null))
+ {
+ // Console.WriteLine(inputLine);
+ if (inputLine.Contains(m_channel))
+ {
+ Dictionary data = ExtractMsg(inputLine);
+ // Any chat ???
+ if (data != null)
+ {
+ foreach (Scene m_scene in m_scenes)
+ {
+ m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
+ {
+ if (!avatar.IsChildAgent)
+ {
+ avatar.ControllingClient.SendChatMessage(
+ Helpers.StringToField(data["msg"]), 255,
+ pos, data["nick"],
+ LLUUID.Zero);
+ }
+ });
+ }
+ }
+ else
+ {
+ // Was an command from the IRC server
+ ProcessIRCCommand(inputLine);
+ }
+ }
+ else
+ {
+ // Was an command from the IRC server
+ ProcessIRCCommand(inputLine);
+ }
+ Thread.Sleep(150);
+ }
+ }
+ catch (IOException)
+ {
+ m_log.Error("[IRC]: ListenerRun IOException. Disconnected from IRC server ??? (ListenerRun)");
+ Reconnect();
+ }
+ catch (Exception ex)
+ {
+ m_log.Error("[IRC]: ListenerRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace);
+ }
+ }
+ }
+
+ public void BroadcastSim(string message, string sender)
+ {
+ LLVector3 pos = new LLVector3(128, 128, 20);
+ try
+ {
+ foreach (Scene m_scene in m_scenes)
+ {
+ m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
+ {
+ if (!avatar.IsChildAgent)
+ {
+ avatar.ControllingClient.SendChatMessage(
+ Helpers.StringToField(message), 255,
+ pos, sender,
+ LLUUID.Zero);
+ }
+ });
+ }
+ }
+ catch (Exception ex) // IRC gate should not crash Sim
+ {
+ m_log.Error("[IRC]: BroadcastSim Exception Trap:" + ex.ToString() + "\n" + ex.StackTrace);
+ }
+ }
+
+ public void ProcessIRCCommand(string command)
+ {
+ //m_log.Info("[IRC]: ProcessIRCCommand:" + command);
+
+ string[] commArgs = new string[command.Split(' ').Length];
+ string c_server = m_server;
+
+ commArgs = command.Split(' ');
+ if (commArgs[0].Substring(0, 1) == ":")
+ {
+ commArgs[0] = commArgs[0].Remove(0, 1);
+ }
+
+ if (commArgs[1] == "002")
+ {
+ // fetch the correct servername
+ // ex: irc.freenode.net -> brown.freenode.net/kornbluth.freenode.net/...
+ // irc.bluewin.ch -> irc1.bluewin.ch/irc2.bluewin.ch
+
+ c_server = (commArgs[6].Split('['))[0];
+ m_server = c_server;
+ }
+
+ if (commArgs[0] == "ERROR")
+ {
+ m_log.Error("[IRC]: IRC SERVER ERROR:" + command);
+ }
+
+ if (commArgs[0] == "PING")
+ {
+ string p_reply = "";
+
+ for (int i = 1; i < commArgs.Length; i++)
+ {
+ p_reply += commArgs[i] + " ";
+ }
+
+ m_writer.WriteLine("PONG " + p_reply);
+ m_writer.Flush();
+ }
+ else if (commArgs[0] == c_server)
+ {
+ // server message
+ try
+ {
+ Int32 commandCode = Int32.Parse(commArgs[1]);
+ switch (commandCode)
+ {
+ case (int) ErrorReplies.NicknameInUse:
+ // Gen a new name
+ m_nick = m_basenick + Util.RandomClass.Next(1, 99);
+ m_log.Error("[IRC]: IRC SERVER reports NicknameInUse, trying " + m_nick);
+ // Retry
+ m_writer.WriteLine("NICK " + m_nick);
+ m_writer.Flush();
+ m_writer.WriteLine("JOIN " + m_channel);
+ m_writer.Flush();
+ break;
+ case (int) ErrorReplies.NotRegistered:
+ break;
+ case (int) Replies.EndOfMotd:
+ break;
+ }
+ }
+ catch (Exception)
+ {
+ }
+ }
+ else
+ {
+ // Normal message
+ string commAct = commArgs[1];
+ switch (commAct)
+ {
+ case "JOIN":
+ eventIrcJoin(commArgs);
+ break;
+ case "PART":
+ eventIrcPart(commArgs);
+ break;
+ case "MODE":
+ eventIrcMode(commArgs);
+ break;
+ case "NICK":
+ eventIrcNickChange(commArgs);
+ break;
+ case "KICK":
+ eventIrcKick(commArgs);
+ break;
+ case "QUIT":
+ eventIrcQuit(commArgs);
+ break;
+ case "PONG":
+ break; // that's nice
+ }
+ }
+ }
+
+ public void eventIrcJoin(string[] commArgs)
+ {
+ string IrcChannel = commArgs[2];
+ string IrcUser = commArgs[0].Split('!')[0];
+ BroadcastSim(IrcUser + " is joining " + IrcChannel, m_nick);
+ }
+
+ public void eventIrcPart(string[] commArgs)
+ {
+ string IrcChannel = commArgs[2];
+ string IrcUser = commArgs[0].Split('!')[0];
+ BroadcastSim(IrcUser + " is parting " + IrcChannel, m_nick);
+ }
+
+ public void eventIrcMode(string[] commArgs)
+ {
+ string IrcChannel = commArgs[2];
+ string IrcUser = commArgs[0].Split('!')[0];
+ string UserMode = "";
+ for (int i = 3; i < commArgs.Length; i++)
+ {
+ UserMode += commArgs[i] + " ";
+ }
+
+ if (UserMode.Substring(0, 1) == ":")
+ {
+ UserMode = UserMode.Remove(0, 1);
+ }
+ }
+
+ public void eventIrcNickChange(string[] commArgs)
+ {
+ string UserOldNick = commArgs[0].Split('!')[0];
+ string UserNewNick = commArgs[2].Remove(0, 1);
+ BroadcastSim(UserOldNick + " changed their nick to " + UserNewNick, m_nick);
+ }
+
+ public void eventIrcKick(string[] commArgs)
+ {
+ string UserKicker = commArgs[0].Split('!')[0];
+ string UserKicked = commArgs[3];
+ string IrcChannel = commArgs[2];
+ string KickMessage = "";
+ for (int i = 4; i < commArgs.Length; i++)
+ {
+ KickMessage += commArgs[i] + " ";
+ }
+ BroadcastSim(UserKicker + " kicked " + UserKicked + " on " + IrcChannel + " saying " + KickMessage, m_nick);
+ if (UserKicked == m_nick)
+ {
+ BroadcastSim("Hey, that was me!!!", m_nick);
+ }
+ }
+
+ public void eventIrcQuit(string[] commArgs)
+ {
+ string IrcUser = commArgs[0].Split('!')[0];
+ string QuitMessage = "";
+
+ for (int i = 2; i < commArgs.Length; i++)
+ {
+ QuitMessage += commArgs[i] + " ";
+ }
+ BroadcastSim(IrcUser + " quits saying " + QuitMessage, m_nick);
+ }
+
+ public void Close()
+ {
+ m_connected = false;
+ m_writer.WriteLine("QUIT :" + m_nick + " to " + m_channel + " wormhole with " + m_server + " closing");
+ m_writer.Flush();
+ listener.Abort();
+ pingSender.Abort();
+ m_writer.Close();
+ m_reader.Close();
+ m_tcp.Close();
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs
index 181984e..966c5e2 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs
@@ -1,1470 +1,1470 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Net;
-using System.Net.Sockets;
-using System.Reflection;
-using System.Xml;
-using libsecondlife;
-using log4net;
-using Nini.Config;
-using Nwc.XmlRpc;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney
-{
- ///
- /// Demo Economy/Money Module. This is not a production quality money/economy module!
- /// This is a demo for you to use when making one that works for you.
- /// // To use the following you need to add:
- /// -helperuri
- /// to the command line parameters you use to start up your client
- /// This commonly looks like -helperuri http://127.0.0.1:9000/
- ///
- /// Centralized grid structure example using OpenSimWi Redux revision 9+
- /// svn co https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux
- ///
- public delegate void ObjectPaid(LLUUID objectID, LLUUID agentID, int amount);
-
- public interface IMoneyModule : IRegionModule
- {
- bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID toID, int amount);
-
- event ObjectPaid OnObjectPaid;
- }
-
- public class SampleMoneyModule : IMoneyModule
- {
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- ///
- /// Where Stipends come from and Fees go to.
- ///
- private LLUUID EconomyBaseAccount = LLUUID.Zero;
-
- private float EnergyEfficiency = 0f;
- private bool gridmode = false;
- private ObjectPaid handerOnObjectPaid;
- private bool m_enabled = true;
-
- private IConfigSource m_gConfig;
-
- private bool m_keepMoneyAcrossLogins = true;
- private Dictionary m_KnownClientFunds = new Dictionary();
- private string m_LandAddress = String.Empty;
-
- private int m_minFundsBeforeRefresh = 100;
- private string m_MoneyAddress = String.Empty;
-
- ///
- /// Region UUIDS indexed by AgentID
- ///
- private Dictionary m_rootAgents = new Dictionary();
-
- ///
- /// Scenes by Region Handle
- ///
- private Dictionary m_scenel = new Dictionary();
-
- private int m_stipend = 1000;
-
- private int ObjectCapacity = 45000;
- private int ObjectCount = 0;
- private int PriceEnergyUnit = 0;
- private int PriceGroupCreate = 0;
- private int PriceObjectClaim = 0;
- private float PriceObjectRent = 0f;
- private float PriceObjectScaleFactor = 0f;
- private int PriceParcelClaim = 0;
- private float PriceParcelClaimFactor = 0f;
- private int PriceParcelRent = 0;
- private int PricePublicObjectDecay = 0;
- private int PricePublicObjectDelete = 0;
- private int PriceRentLight = 0;
- private int PriceUpload = 0;
- private int TeleportMinPrice = 0;
-
- private float TeleportPriceExponent = 0f;
- private int UserLevelPaysFees = 2;
- private Scene XMLRPCHandler;
-
- #region IMoneyModule Members
-
- public event ObjectPaid OnObjectPaid;
-
- ///
- /// Startup
- ///
- ///
- ///
- public void Initialise(Scene scene, IConfigSource config)
- {
- m_gConfig = config;
-
- IConfig startupConfig = m_gConfig.Configs["Startup"];
- IConfig economyConfig = m_gConfig.Configs["Economy"];
-
- scene.RegisterModuleInterface(this);
-
- ReadConfigAndPopulate(scene, startupConfig, "Startup");
- ReadConfigAndPopulate(scene, economyConfig, "Economy");
-
- if (m_enabled)
- {
- lock (m_scenel)
- {
- if (m_scenel.Count == 0)
- {
- XMLRPCHandler = scene;
-
- // To use the following you need to add:
- // -helperuri
- // to the command line parameters you use to start up your client
- // This commonly looks like -helperuri http://127.0.0.1:9000/
-
- if (m_MoneyAddress.Length > 0)
- {
- // Centralized grid structure using OpenSimWi Redux revision 9+
- // https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux
- scene.AddXmlRPCHandler("balanceUpdateRequest", GridMoneyUpdate);
- scene.AddXmlRPCHandler("userAlert", UserAlert);
- }
- else
- {
- // Local Server.. enables functionality only.
- scene.AddXmlRPCHandler("getCurrencyQuote", quote_func);
- scene.AddXmlRPCHandler("buyCurrency", buy_func);
- scene.AddXmlRPCHandler("preflightBuyLandPrep", preflightBuyLandPrep_func);
- scene.AddXmlRPCHandler("buyLandPrep", landBuy_func);
- }
- }
-
- if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle))
- {
- m_scenel[scene.RegionInfo.RegionHandle] = scene;
- }
- else
- {
- m_scenel.Add(scene.RegionInfo.RegionHandle, scene);
- }
- }
-
- scene.EventManager.OnNewClient += OnNewClient;
- scene.EventManager.OnMoneyTransfer += MoneyTransferAction;
- scene.EventManager.OnClientClosed += ClientClosed;
- scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
- scene.EventManager.OnMakeChildAgent += MakeChildAgent;
- scene.EventManager.OnClientClosed += ClientLoggedOut;
- scene.EventManager.OnValidateLandBuy += ValidateLandBuy;
- scene.EventManager.OnLandBuy += processLandBuy;
- }
- }
-
- public bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID toID, int amount)
- {
- string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID));
-
- bool give_result = doMoneyTransfer(fromID, toID, amount, 2, description);
-
- if (m_MoneyAddress.Length == 0)
- BalanceUpdate(fromID, toID, give_result, description);
-
- return give_result;
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "BetaGridLikeMoneyModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return true; }
- }
-
- #endregion
-
- ///
- /// Parse Configuration
- ///
- ///
- ///
- ///
- private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string config)
- {
- if (config == "Startup" && startupConfig != null)
- {
- gridmode = startupConfig.GetBoolean("gridmode", false);
- m_enabled = (startupConfig.GetString("economymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule");
- }
-
- if (config == "Economy" && startupConfig != null)
- {
- ObjectCapacity = startupConfig.GetInt("ObjectCapacity", 45000);
- PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100);
- PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10);
- PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4);
- PricePublicObjectDelete = startupConfig.GetInt("PricePublicObjectDelete", 4);
- PriceParcelClaim = startupConfig.GetInt("PriceParcelClaim", 1);
- PriceParcelClaimFactor = startupConfig.GetFloat("PriceParcelClaimFactor", 1f);
- PriceUpload = startupConfig.GetInt("PriceUpload", 0);
- PriceRentLight = startupConfig.GetInt("PriceRentLight", 5);
- TeleportMinPrice = startupConfig.GetInt("TeleportMinPrice", 2);
- TeleportPriceExponent = startupConfig.GetFloat("TeleportPriceExponent", 2f);
- EnergyEfficiency = startupConfig.GetFloat("EnergyEfficiency", 1);
- PriceObjectRent = startupConfig.GetFloat("PriceObjectRent", 1);
- PriceObjectScaleFactor = startupConfig.GetFloat("PriceObjectScaleFactor", 10);
- PriceParcelRent = startupConfig.GetInt("PriceParcelRent", 1);
- PriceGroupCreate = startupConfig.GetInt("PriceGroupCreate", -1);
- string EBA = startupConfig.GetString("EconomyBaseAccount", LLUUID.Zero.ToString());
- Helpers.TryParse(EBA, out EconomyBaseAccount);
-
- UserLevelPaysFees = startupConfig.GetInt("UserLevelPaysFees", -1);
- m_stipend = startupConfig.GetInt("UserStipend", 500);
- m_minFundsBeforeRefresh = startupConfig.GetInt("IssueStipendWhenClientIsBelowAmount", 10);
- m_keepMoneyAcrossLogins = startupConfig.GetBoolean("KeepMoneyAcrossLogins", true);
- m_MoneyAddress = startupConfig.GetString("CurrencyServer", String.Empty);
- m_LandAddress = startupConfig.GetString("LandServer", String.Empty);
- }
-
- // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter.
- scene.SetObjectCapacity(ObjectCapacity);
- }
-
- ///
- /// New Client Event Handler
- ///
- ///
- private void OnNewClient(IClientAPI client)
- {
- // Here we check if we're in grid mode
- // I imagine that the 'check balance'
- // function for the client should be here or shortly after
-
- if (gridmode)
- {
- if (m_MoneyAddress.Length == 0)
- {
- CheckExistAndRefreshFunds(client.AgentId);
- }
- else
- {
- bool childYN = true;
- ScenePresence agent = null;
- //client.SecureSessionId;
- Scene s = LocateSceneClientIn(client.AgentId);
- if (s != null)
- {
- agent = s.GetScenePresence(client.AgentId);
- if (agent != null)
- childYN = agent.IsChildAgent;
- }
- if (s != null && agent != null && childYN == false)
- {
- //s.RegionInfo.RegionHandle;
- LLUUID agentID = LLUUID.Zero;
- int funds = 0;
-
- Hashtable hbinfo =
- GetBalanceForUserFromMoneyServer(client.AgentId, client.SecureSessionId, s.RegionInfo.originRegionID.ToString(),
- s.RegionInfo.regionSecret);
- if ((bool) hbinfo["success"] == true)
- {
- Helpers.TryParse((string) hbinfo["agentId"], out agentID);
- try
- {
- funds = (Int32) hbinfo["funds"];
- }
- catch (ArgumentException)
- {
- }
- catch (FormatException)
- {
- }
- catch (OverflowException)
- {
- m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentID);
- client.SendAlertMessage("Unable to get your money balance, money operations will be unavailable");
- }
- catch (InvalidCastException)
- {
- funds = 0;
- }
-
- m_KnownClientFunds[agentID] = funds;
- }
- else
- {
- m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentID,
- (string) hbinfo["errorMessage"]);
- client.SendAlertMessage((string) hbinfo["errorMessage"]);
- }
- SendMoneyBalance(client, agentID, client.SessionId, LLUUID.Zero);
- }
- }
- }
- else
- {
- CheckExistAndRefreshFunds(client.AgentId);
- }
-
- // Subscribe to Money messages
- client.OnEconomyDataRequest += EconomyDataRequestHandler;
- client.OnMoneyBalanceRequest += SendMoneyBalance;
- client.OnRequestPayPrice += requestPayPrice;
- client.OnLogout += ClientClosed;
- }
-
- ///
- /// Transfer money
- ///
- ///
- ///
- ///
- ///
- private bool doMoneyTransfer(LLUUID Sender, LLUUID Receiver, int amount, int transactiontype, string description)
- {
- bool result = false;
- if (amount >= 0)
- {
- lock (m_KnownClientFunds)
- {
- // If we don't know about the sender, then the sender can't
- // actually be here and therefore this is likely fraud or outdated.
- if (m_MoneyAddress.Length == 0)
- {
- if (m_KnownClientFunds.ContainsKey(Sender))
- {
- // Does the sender have enough funds to give?
- if (m_KnownClientFunds[Sender] >= amount)
- {
- // Subtract the funds from the senders account
- m_KnownClientFunds[Sender] -= amount;
-
- // do we know about the receiver?
- if (!m_KnownClientFunds.ContainsKey(Receiver))
- {
- // Make a record for them so they get the updated balance when they login
- CheckExistAndRefreshFunds(Receiver);
- }
- if (m_enabled)
- {
- //Add the amount to the Receiver's funds
- m_KnownClientFunds[Receiver] += amount;
- result = true;
- }
- }
- else
- {
- // These below are redundant to make this clearer to read
- result = false;
- }
- }
- else
- {
- result = false;
- }
- }
- else
- {
- result = TransferMoneyonMoneyServer(Sender, Receiver, amount, transactiontype, description);
- }
- }
- }
- return result;
- }
-
-
- ///
- /// Sends the the stored money balance to the client
- ///
- ///
- ///
- ///
- ///
- public void SendMoneyBalance(IClientAPI client, LLUUID agentID, LLUUID SessionID, LLUUID TransactionID)
- {
- if (client.AgentId == agentID && client.SessionId == SessionID)
- {
- int returnfunds = 0;
-
- try
- {
- returnfunds = GetFundsForAgentID(agentID);
- }
- catch (Exception e)
- {
- client.SendAlertMessage(e.Message + " ");
- }
-
- client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds);
- }
- else
- {
- client.SendAlertMessage("Unable to send your money balance to you!");
- }
- }
-
- ///
- /// Gets the current balance for the user from the Grid Money Server
- ///
- ///
- ///
- ///
- ///
- ///
- public Hashtable GetBalanceForUserFromMoneyServer(LLUUID agentId, LLUUID secureSessionID, LLUUID regionId, string regionSecret)
- {
- Hashtable MoneyBalanceRequestParams = new Hashtable();
- MoneyBalanceRequestParams["agentId"] = agentId.ToString();
- MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString();
- MoneyBalanceRequestParams["regionId"] = regionId.ToString();
- MoneyBalanceRequestParams["secret"] = regionSecret;
- MoneyBalanceRequestParams["currencySecret"] = ""; // per - region/user currency secret gotten from the money system
-
- Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorUserBalanceRequest");
-
- return MoneyRespData;
- }
-
-
- ///
- /// Generic XMLRPC client abstraction
- ///
- /// Hashtable containing parameters to the method
- /// Method to invoke
- /// Hashtable with success=>bool and other values
- public Hashtable genericCurrencyXMLRPCRequest(Hashtable ReqParams, string method)
- {
- ArrayList SendParams = new ArrayList();
- SendParams.Add(ReqParams);
- // Send Request
- XmlRpcResponse MoneyResp;
- try
- {
- XmlRpcRequest BalanceRequestReq = new XmlRpcRequest(method, SendParams);
- MoneyResp = BalanceRequestReq.Send(m_MoneyAddress, 30000);
- }
- catch (WebException ex)
- {
- m_log.ErrorFormat(
- "[MONEY]: Unable to connect to Money Server {0}. Exception {1}",
- m_MoneyAddress, ex);
-
- Hashtable ErrorHash = new Hashtable();
- ErrorHash["success"] = false;
- ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
- ErrorHash["errorURI"] = "";
-
- return ErrorHash;
- //throw (ex);
- }
- catch (SocketException ex)
- {
- m_log.ErrorFormat(
- "[MONEY]: Unable to connect to Money Server {0}. Exception {1}",
- m_MoneyAddress, ex);
-
- Hashtable ErrorHash = new Hashtable();
- ErrorHash["success"] = false;
- ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
- ErrorHash["errorURI"] = "";
-
- return ErrorHash;
- //throw (ex);
- }
- catch (XmlException ex)
- {
- m_log.ErrorFormat(
- "[MONEY]: Unable to connect to Money Server {0}. Exception {1}",
- m_MoneyAddress, ex);
-
- Hashtable ErrorHash = new Hashtable();
- ErrorHash["success"] = false;
- ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
- ErrorHash["errorURI"] = "";
-
- return ErrorHash;
- }
- if (MoneyResp.IsFault)
- {
- Hashtable ErrorHash = new Hashtable();
- ErrorHash["success"] = false;
- ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
- ErrorHash["errorURI"] = "";
-
- return ErrorHash;
- }
- Hashtable MoneyRespData = (Hashtable) MoneyResp.Value;
-
- return MoneyRespData;
- }
-
- ///
- /// This informs the Money Grid Server that the avatar is in this simulator
- ///
- ///
- ///
- ///
- ///
- ///
- public Hashtable claim_user(LLUUID agentId, LLUUID secureSessionID, LLUUID regionId, string regionSecret)
- {
- Hashtable MoneyBalanceRequestParams = new Hashtable();
- MoneyBalanceRequestParams["agentId"] = agentId.ToString();
- MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString();
- MoneyBalanceRequestParams["regionId"] = regionId.ToString();
- MoneyBalanceRequestParams["secret"] = regionSecret;
-
- Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorClaimUserRequest");
- IClientAPI sendMoneyBal = LocateClientObject(agentId);
- if (sendMoneyBal != null)
- {
- SendMoneyBalance(sendMoneyBal, agentId, sendMoneyBal.SessionId, LLUUID.Zero);
- }
- return MoneyRespData;
- }
-
- private SceneObjectPart findPrim(LLUUID objectID)
- {
- lock (m_scenel)
- {
- foreach (Scene s in m_scenel.Values)
- {
- SceneObjectPart part = s.GetSceneObjectPart(objectID);
- if (part != null)
- {
- return part;
- }
- }
- }
- return null;
- }
-
- private string resolveObjectName(LLUUID objectID)
- {
- SceneObjectPart part = findPrim(objectID);
- if (part != null)
- {
- return part.Name;
- }
- return String.Empty;
- }
-
- private string resolveAgentName(LLUUID agentID)
- {
- // try avatar username surname
- Scene scene = GetRandomScene();
- UserProfileData profile = scene.CommsManager.UserService.GetUserProfile(agentID);
- if (profile != null)
- {
- string avatarname = profile.FirstName + " " + profile.SurName;
- return avatarname;
- }
- return String.Empty;
- }
-
- private void BalanceUpdate(LLUUID senderID, LLUUID receiverID, bool transactionresult, string description)
- {
- IClientAPI sender = LocateClientObject(senderID);
- IClientAPI receiver = LocateClientObject(receiverID);
-
- if (senderID != receiverID)
- {
- if (sender != null)
- {
- sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(description), GetFundsForAgentID(senderID));
- }
-
- if (receiver != null)
- {
- receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(description), GetFundsForAgentID(receiverID));
- }
- }
- }
-
- ///
- /// Informs the Money Grid Server of a transfer.
- ///
- ///
- ///
- ///
- ///
- public bool TransferMoneyonMoneyServer(LLUUID sourceId, LLUUID destId, int amount, int transactiontype, string description)
- {
- int aggregatePermInventory = 0;
- int aggregatePermNextOwner = 0;
- int flags = 0;
- bool rvalue = false;
-
- IClientAPI cli = LocateClientObject(sourceId);
- if (cli != null)
- {
- Scene userScene = null;
- lock (m_rootAgents)
- {
- userScene = GetSceneByUUID(m_rootAgents[sourceId]);
- }
- if (userScene != null)
- {
- Hashtable ht = new Hashtable();
- ht["agentId"] = sourceId.ToString();
- ht["secureSessionId"] = cli.SecureSessionId.ToString();
- ht["regionId"] = userScene.RegionInfo.originRegionID.ToString();
- ht["secret"] = userScene.RegionInfo.regionSecret;
- ht["currencySecret"] = " ";
- ht["destId"] = destId.ToString();
- ht["cash"] = amount;
- ht["aggregatePermInventory"] = aggregatePermInventory;
- ht["aggregatePermNextOwner"] = aggregatePermNextOwner;
- ht["flags"] = flags;
- ht["transactionType"] = transactiontype;
- ht["description"] = description;
-
- Hashtable hresult = genericCurrencyXMLRPCRequest(ht, "regionMoveMoney");
-
- if ((bool) hresult["success"] == true)
- {
- int funds1 = 0;
- int funds2 = 0;
- try
- {
- funds1 = (Int32) hresult["funds"];
- }
- catch (InvalidCastException)
- {
- funds1 = 0;
- }
- SetLocalFundsForAgentID(sourceId, funds1);
- if (m_KnownClientFunds.ContainsKey(destId))
- {
- try
- {
- funds2 = (Int32) hresult["funds2"];
- }
- catch (InvalidCastException)
- {
- funds2 = 0;
- }
- SetLocalFundsForAgentID(destId, funds2);
- }
-
-
- rvalue = true;
- }
- else
- {
- cli.SendAgentAlertMessage((string) hresult["errorMessage"], true);
- }
- }
- }
- else
- {
- m_log.ErrorFormat("[MONEY]: Client {0} not found", sourceId.ToString());
- }
-
- return rvalue;
- }
-
- public int GetRemoteBalance(LLUUID agentId)
- {
- int funds = 0;
-
- IClientAPI aClient = LocateClientObject(agentId);
- if (aClient != null)
- {
- Scene s = LocateSceneClientIn(agentId);
- if (s != null)
- {
- if (m_MoneyAddress.Length > 0)
- {
- Hashtable hbinfo =
- GetBalanceForUserFromMoneyServer(aClient.AgentId, aClient.SecureSessionId, s.RegionInfo.originRegionID.ToString(),
- s.RegionInfo.regionSecret);
- if ((bool) hbinfo["success"] == true)
- {
- try
- {
- funds = (Int32) hbinfo["funds"];
- }
- catch (ArgumentException)
- {
- }
- catch (FormatException)
- {
- }
- catch (OverflowException)
- {
- m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentId);
- aClient.SendAlertMessage("Unable to get your money balance, money operations will be unavailable");
- }
- catch (InvalidCastException)
- {
- funds = 0;
- }
- }
- else
- {
- m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentId,
- (string) hbinfo["errorMessage"]);
- aClient.SendAlertMessage((string) hbinfo["errorMessage"]);
- }
- }
-
- SetLocalFundsForAgentID(agentId, funds);
- SendMoneyBalance(aClient, agentId, aClient.SessionId, LLUUID.Zero);
- }
- else
- {
- m_log.Debug("[MONEY]: Got balance request update for agent that is here, but couldn't find which scene.");
- }
- }
- else
- {
- m_log.Debug("[MONEY]: Got balance request update for agent that isn't here.");
- }
- return funds;
- }
-
- public XmlRpcResponse GridMoneyUpdate(XmlRpcRequest request)
- {
- m_log.Debug("[MONEY]: Dynamic balance update called.");
- Hashtable requestData = (Hashtable) request.Params[0];
-
- if (requestData.ContainsKey("agentId"))
- {
- LLUUID agentId = LLUUID.Zero;
-
- Helpers.TryParse((string) requestData["agentId"], out agentId);
- if (agentId != LLUUID.Zero)
- {
- GetRemoteBalance(agentId);
- }
- else
- {
- m_log.Debug("[MONEY]: invalid agentId specified, dropping.");
- }
- }
- else
- {
- m_log.Debug("[MONEY]: no agentId specified, dropping.");
- }
- XmlRpcResponse r = new XmlRpcResponse();
- Hashtable rparms = new Hashtable();
- rparms["success"] = true;
-
- r.Value = rparms;
- return r;
- }
-
- ///
- /// XMLRPC handler to send alert message and sound to client
- ///
- public XmlRpcResponse UserAlert(XmlRpcRequest request)
- {
- XmlRpcResponse ret = new XmlRpcResponse();
- Hashtable retparam = new Hashtable();
- Hashtable requestData = (Hashtable) request.Params[0];
-
- LLUUID agentId = LLUUID.Zero;
- LLUUID soundId = LLUUID.Zero;
-
- Helpers.TryParse((string) requestData["agentId"], out agentId);
- Helpers.TryParse((string) requestData["soundId"], out soundId);
- string text = (string) requestData["text"];
- string secret = (string) requestData["secret"];
-
- Scene userScene = GetRandomScene();
- if (userScene.RegionInfo.regionSecret.ToString() == secret)
- {
- IClientAPI client = LocateClientObject(agentId);
-
- if (client != null)
- {
- if (soundId != LLUUID.Zero)
- client.SendPlayAttachedSound(soundId, LLUUID.Zero, LLUUID.Zero, 1.0f, 0);
- client.SendBlueBoxMessage(LLUUID.Zero, LLUUID.Zero, "", text);
- retparam.Add("success", true);
- }
- else
- {
- retparam.Add("success", false);
- }
- }
- else
- {
- retparam.Add("success", false);
- }
- ret.Value = retparam;
-
- return ret;
- }
-
- # region Standalone box enablers only
-
- public XmlRpcResponse quote_func(XmlRpcRequest request)
- {
- Hashtable requestData = (Hashtable) request.Params[0];
- LLUUID agentId = LLUUID.Zero;
- int amount = 0;
- Hashtable quoteResponse = new Hashtable();
- XmlRpcResponse returnval = new XmlRpcResponse();
-
- if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy"))
- {
- Helpers.TryParse((string) requestData["agentId"], out agentId);
- try
- {
- amount = (Int32) requestData["currencyBuy"];
- }
- catch (InvalidCastException)
- {
- }
- Hashtable currencyResponse = new Hashtable();
- currencyResponse.Add("estimatedCost", 0);
- currencyResponse.Add("currencyBuy", amount);
-
- quoteResponse.Add("success", true);
- quoteResponse.Add("currency", currencyResponse);
- quoteResponse.Add("confirm", "asdfad9fj39ma9fj");
-
- returnval.Value = quoteResponse;
- return returnval;
- }
-
-
- quoteResponse.Add("success", false);
- quoteResponse.Add("errorMessage", "Invalid parameters passed to the quote box");
- quoteResponse.Add("errorURI", "http://www.opensimulator.org/wiki");
- returnval.Value = quoteResponse;
- return returnval;
- }
-
- public XmlRpcResponse buy_func(XmlRpcRequest request)
- {
- Hashtable requestData = (Hashtable) request.Params[0];
- LLUUID agentId = LLUUID.Zero;
- int amount = 0;
- if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy"))
- {
- Helpers.TryParse((string) requestData["agentId"], out agentId);
- try
- {
- amount = (Int32) requestData["currencyBuy"];
- }
- catch (InvalidCastException)
- {
- }
- if (agentId != LLUUID.Zero)
- {
- lock (m_KnownClientFunds)
- {
- if (m_KnownClientFunds.ContainsKey(agentId))
- {
- m_KnownClientFunds[agentId] += amount;
- }
- else
- {
- m_KnownClientFunds.Add(agentId, amount);
- }
- }
- IClientAPI client = LocateClientObject(agentId);
- if (client != null)
- {
- SendMoneyBalance(client, agentId, client.SessionId, LLUUID.Zero);
- }
- }
- }
- XmlRpcResponse returnval = new XmlRpcResponse();
- Hashtable returnresp = new Hashtable();
- returnresp.Add("success", true);
- returnval.Value = returnresp;
- return returnval;
- }
-
- public XmlRpcResponse preflightBuyLandPrep_func(XmlRpcRequest request)
- {
- XmlRpcResponse ret = new XmlRpcResponse();
- Hashtable retparam = new Hashtable();
- Hashtable membershiplevels = new Hashtable();
- ArrayList levels = new ArrayList();
- Hashtable level = new Hashtable();
- level.Add("id", "00000000-0000-0000-0000-000000000000");
- level.Add("description", "some level");
- levels.Add(level);
- //membershiplevels.Add("levels",levels);
-
- Hashtable landuse = new Hashtable();
- landuse.Add("upgrade", false);
- landuse.Add("action", "http://invaliddomaininvalid.com/");
-
- Hashtable currency = new Hashtable();
- currency.Add("estimatedCost", 0);
-
- Hashtable membership = new Hashtable();
- membershiplevels.Add("upgrade", false);
- membershiplevels.Add("action", "http://invaliddomaininvalid.com/");
- membershiplevels.Add("levels", membershiplevels);
-
- retparam.Add("success", true);
- retparam.Add("currency", currency);
- retparam.Add("membership", membership);
- retparam.Add("landuse", landuse);
- retparam.Add("confirm", "asdfajsdkfjasdkfjalsdfjasdf");
-
- ret.Value = retparam;
-
- return ret;
- }
-
- public XmlRpcResponse landBuy_func(XmlRpcRequest request)
- {
- XmlRpcResponse ret = new XmlRpcResponse();
- Hashtable retparam = new Hashtable();
- Hashtable requestData = (Hashtable) request.Params[0];
-
- LLUUID agentId = LLUUID.Zero;
- int amount = 0;
- if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy"))
- {
- Helpers.TryParse((string) requestData["agentId"], out agentId);
- try
- {
- amount = (Int32) requestData["currencyBuy"];
- }
- catch (InvalidCastException)
- {
- }
- if (agentId != LLUUID.Zero)
- {
- lock (m_KnownClientFunds)
- {
- if (m_KnownClientFunds.ContainsKey(agentId))
- {
- m_KnownClientFunds[agentId] += amount;
- }
- else
- {
- m_KnownClientFunds.Add(agentId, amount);
- }
- }
- IClientAPI client = LocateClientObject(agentId);
- if (client != null)
- {
- SendMoneyBalance(client, agentId, client.SessionId, LLUUID.Zero);
- }
- }
- }
- retparam.Add("success", true);
- ret.Value = retparam;
-
- return ret;
- }
-
- #endregion
-
- #region local Fund Management
-
- ///
- /// Ensures that the agent accounting data is set up in this instance.
- ///
- ///
- private void CheckExistAndRefreshFunds(LLUUID agentID)
- {
- lock (m_KnownClientFunds)
- {
- if (!m_KnownClientFunds.ContainsKey(agentID))
- {
- m_KnownClientFunds.Add(agentID, m_stipend);
- }
- else
- {
- if (m_KnownClientFunds[agentID] <= m_minFundsBeforeRefresh)
- {
- m_KnownClientFunds[agentID] = m_stipend;
- }
- }
- }
- }
-
- ///
- /// Gets the amount of Funds for an agent
- ///
- ///
- ///
- private int GetFundsForAgentID(LLUUID AgentID)
- {
- int returnfunds = 0;
- lock (m_KnownClientFunds)
- {
- if (m_KnownClientFunds.ContainsKey(AgentID))
- {
- returnfunds = m_KnownClientFunds[AgentID];
- }
- else
- {
- //throw new Exception("Unable to get funds.");
- }
- }
- return returnfunds;
- }
-
- private void SetLocalFundsForAgentID(LLUUID AgentID, int amount)
- {
- lock (m_KnownClientFunds)
- {
- if (m_KnownClientFunds.ContainsKey(AgentID))
- {
- m_KnownClientFunds[AgentID] = amount;
- }
- else
- {
- m_KnownClientFunds.Add(AgentID, amount);
- }
- }
- }
-
- #endregion
-
- #region Utility Helpers
-
- ///
- /// Locates a IClientAPI for the client specified
- ///
- ///
- ///
- private IClientAPI LocateClientObject(LLUUID AgentID)
- {
- ScenePresence tPresence = null;
- IClientAPI rclient = null;
-
- lock (m_scenel)
- {
- foreach (Scene _scene in m_scenel.Values)
- {
- tPresence = _scene.GetScenePresence(AgentID);
- if (tPresence != null)
- {
- if (!tPresence.IsChildAgent)
- {
- rclient = tPresence.ControllingClient;
- }
- }
- if (rclient != null)
- {
- return rclient;
- }
- }
- }
- return null;
- }
-
- private Scene LocateSceneClientIn(LLUUID AgentId)
- {
- lock (m_scenel)
- {
- foreach (Scene _scene in m_scenel.Values)
- {
- ScenePresence tPresence = _scene.GetScenePresence(AgentId);
- if (tPresence != null)
- {
- if (!tPresence.IsChildAgent)
- {
- return _scene;
- }
- }
- }
- }
- return null;
- }
-
- ///
- /// Utility function Gets a Random scene in the instance. For when which scene exactly you're doing something with doesn't matter
- ///
- ///
- public Scene GetRandomScene()
- {
- lock (m_scenel)
- {
- foreach (Scene rs in m_scenel.Values)
- return rs;
- }
- return null;
- }
-
- ///
- /// Utility function to get a Scene by RegionID in a module
- ///
- ///
- ///
- public Scene GetSceneByUUID(LLUUID RegionID)
- {
- lock (m_scenel)
- {
- foreach (Scene rs in m_scenel.Values)
- {
- if (rs.RegionInfo.originRegionID == RegionID)
- {
- return rs;
- }
- }
- }
- return null;
- }
-
- #endregion
-
- #region event Handlers
-
- public void requestPayPrice(IClientAPI client, LLUUID objectID)
- {
- Scene scene = LocateSceneClientIn(client.AgentId);
- if (scene == null)
- return;
-
- SceneObjectPart task = scene.GetSceneObjectPart(objectID);
- if (task == null)
- return;
- SceneObjectGroup group = task.ParentGroup;
- SceneObjectPart root = group.RootPart;
-
- client.SendPayPrice(objectID, root.PayPrice);
- }
-
- ///
- /// When the client closes the connection we remove their accounting info from memory to free up resources.
- ///
- ///
- public void ClientClosed(LLUUID AgentID)
- {
- lock (m_KnownClientFunds)
- {
- if (m_keepMoneyAcrossLogins && m_MoneyAddress.Length == 0)
- {
- }
- else
- {
- m_KnownClientFunds.Remove(AgentID);
- }
- }
- }
-
- ///
- /// Event called Economy Data Request handler.
- ///
- ///
- public void EconomyDataRequestHandler(LLUUID agentId)
- {
- IClientAPI user = LocateClientObject(agentId);
-
- if (user != null)
- {
- user.SendEconomyData(EnergyEfficiency, ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate,
- PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor,
- PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload,
- TeleportMinPrice, TeleportPriceExponent);
- }
- }
-
- private void ValidateLandBuy(Object osender, EventManager.LandBuyArgs e)
- {
- if (m_MoneyAddress.Length == 0)
- {
- lock (m_KnownClientFunds)
- {
- if (m_KnownClientFunds.ContainsKey(e.agentId))
- {
- // Does the sender have enough funds to give?
- if (m_KnownClientFunds[e.agentId] >= e.parcelPrice)
- {
- lock (e)
- {
- e.economyValidated = true;
- }
- }
- }
- }
- }
- else
- {
- if (GetRemoteBalance(e.agentId) >= e.parcelPrice)
- {
- lock (e)
- {
- e.economyValidated = true;
- }
- }
- }
- }
-
- private void processLandBuy(Object osender, EventManager.LandBuyArgs e)
- {
- lock (e)
- {
- if (e.economyValidated == true && e.transactionID == 0)
- {
- e.transactionID = Util.UnixTimeSinceEpoch();
-
- if (doMoneyTransfer(e.agentId, e.parcelOwnerID, e.parcelPrice, 0, "Land purchase"))
- {
- lock (e)
- {
- e.amountDebited = e.parcelPrice;
- }
- }
- }
- }
- }
-
- ///
- /// THis method gets called when someone pays someone else as a gift.
- ///
- ///
- ///
- private void MoneyTransferAction(Object osender, EventManager.MoneyTransferArgs e)
- {
- IClientAPI sender = null;
- IClientAPI receiver = null;
-
- if (m_MoneyAddress.Length > 0) // Handled on server
- e.description = String.Empty;
-
- if (e.transactiontype == 5008) // Object gets paid
- {
- sender = LocateClientObject(e.sender);
- if (sender != null)
- {
- SceneObjectPart part = findPrim(e.receiver);
- if (part == null)
- return;
-
- string name = resolveAgentName(part.OwnerID);
- if (name == String.Empty)
- name = "(hippos)";
-
- receiver = LocateClientObject(part.OwnerID);
-
- string description = String.Format("Paid {0} via object {1}", name, e.description);
- bool transactionresult = doMoneyTransfer(e.sender, part.OwnerID, e.amount, e.transactiontype, description);
-
- if (transactionresult)
- {
- ObjectPaid handlerOnObjectPaid = OnObjectPaid;
- if (handlerOnObjectPaid != null)
- {
- handlerOnObjectPaid(e.receiver, e.sender, e.amount);
- }
- }
-
- if (e.sender != e.receiver)
- {
- sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender));
- }
- if (receiver != null)
- {
- receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(part.OwnerID));
- }
- }
- return;
- }
-
- sender = LocateClientObject(e.sender);
- if (sender != null)
- {
- receiver = LocateClientObject(e.receiver);
-
- bool transactionresult = doMoneyTransfer(e.sender, e.receiver, e.amount, e.transactiontype, e.description);
-
- if (e.sender != e.receiver)
- {
- if (sender != null)
- {
- sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender));
- }
- }
-
- if (receiver != null)
- {
- receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.receiver));
- }
- }
- else
- {
- m_log.Warn("[MONEY]: Potential Fraud Warning, got money transfer request for avatar that isn't in this simulator - Details; Sender:" +
- e.sender.ToString() + " Receiver: " + e.receiver.ToString() + " Amount: " + e.amount.ToString());
- }
- }
-
- ///
- /// Event Handler for when a root agent becomes a child agent
- ///
- ///
- private void MakeChildAgent(ScenePresence avatar)
- {
- lock (m_rootAgents)
- {
- if (m_rootAgents.ContainsKey(avatar.UUID))
- {
- if (m_rootAgents[avatar.UUID] == avatar.Scene.RegionInfo.originRegionID)
- {
- m_rootAgents.Remove(avatar.UUID);
- m_log.Info("[MONEY]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent");
- }
- }
- }
- }
-
- ///
- /// Event Handler for when the client logs out.
- ///
- ///
- private void ClientLoggedOut(LLUUID AgentId)
- {
- lock (m_rootAgents)
- {
- if (m_rootAgents.ContainsKey(AgentId))
- {
- m_rootAgents.Remove(AgentId);
- //m_log.Info("[MONEY]: Removing " + AgentId + ". Agent logged out.");
- }
- }
- }
-
- ///
- /// Call this when the client disconnects.
- ///
- ///
- public void ClientClosed(IClientAPI client)
- {
- ClientClosed(client.AgentId);
- }
-
- ///
- /// Event Handler for when an Avatar enters one of the parcels in the simulator.
- ///
- ///
- ///
- ///
- private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID)
- {
- lock (m_rootAgents)
- {
- if (m_rootAgents.ContainsKey(avatar.UUID))
- {
- if (avatar.Scene.RegionInfo.originRegionID != m_rootAgents[avatar.UUID])
- {
- m_rootAgents[avatar.UUID] = avatar.Scene.RegionInfo.originRegionID;
- //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + ".");
- // Claim User! my user! Mine mine mine!
- if (m_MoneyAddress.Length > 0)
- {
- Scene RegionItem = GetSceneByUUID(regionID);
- if (RegionItem != null)
- {
- Hashtable hresult =
- claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret);
- if ((bool) hresult["success"] == true)
- {
- int funds = 0;
- try
- {
- funds = (Int32) hresult["funds"];
- }
- catch (InvalidCastException)
- {
- }
- SetLocalFundsForAgentID(avatar.UUID, funds);
- }
- else
- {
- avatar.ControllingClient.SendAgentAlertMessage((string) hresult["errorMessage"], true);
- }
- }
- }
- }
- }
- else
- {
- lock (m_rootAgents)
- {
- m_rootAgents.Add(avatar.UUID, avatar.Scene.RegionInfo.originRegionID);
- }
- if (m_MoneyAddress.Length > 0)
- {
- Scene RegionItem = GetSceneByUUID(regionID);
- if (RegionItem != null)
- {
- Hashtable hresult = claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret);
- if ((bool) hresult["success"] == true)
- {
- int funds = 0;
- try
- {
- funds = (Int32) hresult["funds"];
- }
- catch (InvalidCastException)
- {
- }
- SetLocalFundsForAgentID(avatar.UUID, funds);
- }
- else
- {
- avatar.ControllingClient.SendAgentAlertMessage((string) hresult["errorMessage"], true);
- }
- }
- }
-
- //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + ".");
- }
- }
- //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString());
- }
-
- #endregion
- }
-
- public enum TransactionType : int
- {
- SystemGenerated = 0,
- RegionMoneyRequest = 1,
- Gift = 2,
- Purchase = 3
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Xml;
+using libsecondlife;
+using log4net;
+using Nini.Config;
+using Nwc.XmlRpc;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney
+{
+ ///
+ /// Demo Economy/Money Module. This is not a production quality money/economy module!
+ /// This is a demo for you to use when making one that works for you.
+ /// // To use the following you need to add:
+ /// -helperuri
+ /// to the command line parameters you use to start up your client
+ /// This commonly looks like -helperuri http://127.0.0.1:9000/
+ ///
+ /// Centralized grid structure example using OpenSimWi Redux revision 9+
+ /// svn co https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux
+ ///
+ public delegate void ObjectPaid(LLUUID objectID, LLUUID agentID, int amount);
+
+ public interface IMoneyModule : IRegionModule
+ {
+ bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID toID, int amount);
+
+ event ObjectPaid OnObjectPaid;
+ }
+
+ public class SampleMoneyModule : IMoneyModule
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ ///
+ /// Where Stipends come from and Fees go to.
+ ///
+ private LLUUID EconomyBaseAccount = LLUUID.Zero;
+
+ private float EnergyEfficiency = 0f;
+ private bool gridmode = false;
+ private ObjectPaid handerOnObjectPaid;
+ private bool m_enabled = true;
+
+ private IConfigSource m_gConfig;
+
+ private bool m_keepMoneyAcrossLogins = true;
+ private Dictionary m_KnownClientFunds = new Dictionary();
+ private string m_LandAddress = String.Empty;
+
+ private int m_minFundsBeforeRefresh = 100;
+ private string m_MoneyAddress = String.Empty;
+
+ ///
+ /// Region UUIDS indexed by AgentID
+ ///
+ private Dictionary m_rootAgents = new Dictionary();
+
+ ///
+ /// Scenes by Region Handle
+ ///
+ private Dictionary m_scenel = new Dictionary();
+
+ private int m_stipend = 1000;
+
+ private int ObjectCapacity = 45000;
+ private int ObjectCount = 0;
+ private int PriceEnergyUnit = 0;
+ private int PriceGroupCreate = 0;
+ private int PriceObjectClaim = 0;
+ private float PriceObjectRent = 0f;
+ private float PriceObjectScaleFactor = 0f;
+ private int PriceParcelClaim = 0;
+ private float PriceParcelClaimFactor = 0f;
+ private int PriceParcelRent = 0;
+ private int PricePublicObjectDecay = 0;
+ private int PricePublicObjectDelete = 0;
+ private int PriceRentLight = 0;
+ private int PriceUpload = 0;
+ private int TeleportMinPrice = 0;
+
+ private float TeleportPriceExponent = 0f;
+ private int UserLevelPaysFees = 2;
+ private Scene XMLRPCHandler;
+
+ #region IMoneyModule Members
+
+ public event ObjectPaid OnObjectPaid;
+
+ ///
+ /// Startup
+ ///
+ ///
+ ///
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ m_gConfig = config;
+
+ IConfig startupConfig = m_gConfig.Configs["Startup"];
+ IConfig economyConfig = m_gConfig.Configs["Economy"];
+
+ scene.RegisterModuleInterface(this);
+
+ ReadConfigAndPopulate(scene, startupConfig, "Startup");
+ ReadConfigAndPopulate(scene, economyConfig, "Economy");
+
+ if (m_enabled)
+ {
+ lock (m_scenel)
+ {
+ if (m_scenel.Count == 0)
+ {
+ XMLRPCHandler = scene;
+
+ // To use the following you need to add:
+ // -helperuri
+ // to the command line parameters you use to start up your client
+ // This commonly looks like -helperuri http://127.0.0.1:9000/
+
+ if (m_MoneyAddress.Length > 0)
+ {
+ // Centralized grid structure using OpenSimWi Redux revision 9+
+ // https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux
+ scene.AddXmlRPCHandler("balanceUpdateRequest", GridMoneyUpdate);
+ scene.AddXmlRPCHandler("userAlert", UserAlert);
+ }
+ else
+ {
+ // Local Server.. enables functionality only.
+ scene.AddXmlRPCHandler("getCurrencyQuote", quote_func);
+ scene.AddXmlRPCHandler("buyCurrency", buy_func);
+ scene.AddXmlRPCHandler("preflightBuyLandPrep", preflightBuyLandPrep_func);
+ scene.AddXmlRPCHandler("buyLandPrep", landBuy_func);
+ }
+ }
+
+ if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle))
+ {
+ m_scenel[scene.RegionInfo.RegionHandle] = scene;
+ }
+ else
+ {
+ m_scenel.Add(scene.RegionInfo.RegionHandle, scene);
+ }
+ }
+
+ scene.EventManager.OnNewClient += OnNewClient;
+ scene.EventManager.OnMoneyTransfer += MoneyTransferAction;
+ scene.EventManager.OnClientClosed += ClientClosed;
+ scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
+ scene.EventManager.OnMakeChildAgent += MakeChildAgent;
+ scene.EventManager.OnClientClosed += ClientLoggedOut;
+ scene.EventManager.OnValidateLandBuy += ValidateLandBuy;
+ scene.EventManager.OnLandBuy += processLandBuy;
+ }
+ }
+
+ public bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID toID, int amount)
+ {
+ string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID));
+
+ bool give_result = doMoneyTransfer(fromID, toID, amount, 2, description);
+
+ if (m_MoneyAddress.Length == 0)
+ BalanceUpdate(fromID, toID, give_result, description);
+
+ return give_result;
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "BetaGridLikeMoneyModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return true; }
+ }
+
+ #endregion
+
+ ///
+ /// Parse Configuration
+ ///
+ ///
+ ///
+ ///
+ private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string config)
+ {
+ if (config == "Startup" && startupConfig != null)
+ {
+ gridmode = startupConfig.GetBoolean("gridmode", false);
+ m_enabled = (startupConfig.GetString("economymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule");
+ }
+
+ if (config == "Economy" && startupConfig != null)
+ {
+ ObjectCapacity = startupConfig.GetInt("ObjectCapacity", 45000);
+ PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100);
+ PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10);
+ PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4);
+ PricePublicObjectDelete = startupConfig.GetInt("PricePublicObjectDelete", 4);
+ PriceParcelClaim = startupConfig.GetInt("PriceParcelClaim", 1);
+ PriceParcelClaimFactor = startupConfig.GetFloat("PriceParcelClaimFactor", 1f);
+ PriceUpload = startupConfig.GetInt("PriceUpload", 0);
+ PriceRentLight = startupConfig.GetInt("PriceRentLight", 5);
+ TeleportMinPrice = startupConfig.GetInt("TeleportMinPrice", 2);
+ TeleportPriceExponent = startupConfig.GetFloat("TeleportPriceExponent", 2f);
+ EnergyEfficiency = startupConfig.GetFloat("EnergyEfficiency", 1);
+ PriceObjectRent = startupConfig.GetFloat("PriceObjectRent", 1);
+ PriceObjectScaleFactor = startupConfig.GetFloat("PriceObjectScaleFactor", 10);
+ PriceParcelRent = startupConfig.GetInt("PriceParcelRent", 1);
+ PriceGroupCreate = startupConfig.GetInt("PriceGroupCreate", -1);
+ string EBA = startupConfig.GetString("EconomyBaseAccount", LLUUID.Zero.ToString());
+ Helpers.TryParse(EBA, out EconomyBaseAccount);
+
+ UserLevelPaysFees = startupConfig.GetInt("UserLevelPaysFees", -1);
+ m_stipend = startupConfig.GetInt("UserStipend", 500);
+ m_minFundsBeforeRefresh = startupConfig.GetInt("IssueStipendWhenClientIsBelowAmount", 10);
+ m_keepMoneyAcrossLogins = startupConfig.GetBoolean("KeepMoneyAcrossLogins", true);
+ m_MoneyAddress = startupConfig.GetString("CurrencyServer", String.Empty);
+ m_LandAddress = startupConfig.GetString("LandServer", String.Empty);
+ }
+
+ // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter.
+ scene.SetObjectCapacity(ObjectCapacity);
+ }
+
+ ///
+ /// New Client Event Handler
+ ///
+ ///
+ private void OnNewClient(IClientAPI client)
+ {
+ // Here we check if we're in grid mode
+ // I imagine that the 'check balance'
+ // function for the client should be here or shortly after
+
+ if (gridmode)
+ {
+ if (m_MoneyAddress.Length == 0)
+ {
+ CheckExistAndRefreshFunds(client.AgentId);
+ }
+ else
+ {
+ bool childYN = true;
+ ScenePresence agent = null;
+ //client.SecureSessionId;
+ Scene s = LocateSceneClientIn(client.AgentId);
+ if (s != null)
+ {
+ agent = s.GetScenePresence(client.AgentId);
+ if (agent != null)
+ childYN = agent.IsChildAgent;
+ }
+ if (s != null && agent != null && childYN == false)
+ {
+ //s.RegionInfo.RegionHandle;
+ LLUUID agentID = LLUUID.Zero;
+ int funds = 0;
+
+ Hashtable hbinfo =
+ GetBalanceForUserFromMoneyServer(client.AgentId, client.SecureSessionId, s.RegionInfo.originRegionID.ToString(),
+ s.RegionInfo.regionSecret);
+ if ((bool) hbinfo["success"] == true)
+ {
+ Helpers.TryParse((string) hbinfo["agentId"], out agentID);
+ try
+ {
+ funds = (Int32) hbinfo["funds"];
+ }
+ catch (ArgumentException)
+ {
+ }
+ catch (FormatException)
+ {
+ }
+ catch (OverflowException)
+ {
+ m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentID);
+ client.SendAlertMessage("Unable to get your money balance, money operations will be unavailable");
+ }
+ catch (InvalidCastException)
+ {
+ funds = 0;
+ }
+
+ m_KnownClientFunds[agentID] = funds;
+ }
+ else
+ {
+ m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentID,
+ (string) hbinfo["errorMessage"]);
+ client.SendAlertMessage((string) hbinfo["errorMessage"]);
+ }
+ SendMoneyBalance(client, agentID, client.SessionId, LLUUID.Zero);
+ }
+ }
+ }
+ else
+ {
+ CheckExistAndRefreshFunds(client.AgentId);
+ }
+
+ // Subscribe to Money messages
+ client.OnEconomyDataRequest += EconomyDataRequestHandler;
+ client.OnMoneyBalanceRequest += SendMoneyBalance;
+ client.OnRequestPayPrice += requestPayPrice;
+ client.OnLogout += ClientClosed;
+ }
+
+ ///
+ /// Transfer money
+ ///
+ ///
+ ///
+ ///
+ ///
+ private bool doMoneyTransfer(LLUUID Sender, LLUUID Receiver, int amount, int transactiontype, string description)
+ {
+ bool result = false;
+ if (amount >= 0)
+ {
+ lock (m_KnownClientFunds)
+ {
+ // If we don't know about the sender, then the sender can't
+ // actually be here and therefore this is likely fraud or outdated.
+ if (m_MoneyAddress.Length == 0)
+ {
+ if (m_KnownClientFunds.ContainsKey(Sender))
+ {
+ // Does the sender have enough funds to give?
+ if (m_KnownClientFunds[Sender] >= amount)
+ {
+ // Subtract the funds from the senders account
+ m_KnownClientFunds[Sender] -= amount;
+
+ // do we know about the receiver?
+ if (!m_KnownClientFunds.ContainsKey(Receiver))
+ {
+ // Make a record for them so they get the updated balance when they login
+ CheckExistAndRefreshFunds(Receiver);
+ }
+ if (m_enabled)
+ {
+ //Add the amount to the Receiver's funds
+ m_KnownClientFunds[Receiver] += amount;
+ result = true;
+ }
+ }
+ else
+ {
+ // These below are redundant to make this clearer to read
+ result = false;
+ }
+ }
+ else
+ {
+ result = false;
+ }
+ }
+ else
+ {
+ result = TransferMoneyonMoneyServer(Sender, Receiver, amount, transactiontype, description);
+ }
+ }
+ }
+ return result;
+ }
+
+
+ ///
+ /// Sends the the stored money balance to the client
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void SendMoneyBalance(IClientAPI client, LLUUID agentID, LLUUID SessionID, LLUUID TransactionID)
+ {
+ if (client.AgentId == agentID && client.SessionId == SessionID)
+ {
+ int returnfunds = 0;
+
+ try
+ {
+ returnfunds = GetFundsForAgentID(agentID);
+ }
+ catch (Exception e)
+ {
+ client.SendAlertMessage(e.Message + " ");
+ }
+
+ client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds);
+ }
+ else
+ {
+ client.SendAlertMessage("Unable to send your money balance to you!");
+ }
+ }
+
+ ///
+ /// Gets the current balance for the user from the Grid Money Server
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Hashtable GetBalanceForUserFromMoneyServer(LLUUID agentId, LLUUID secureSessionID, LLUUID regionId, string regionSecret)
+ {
+ Hashtable MoneyBalanceRequestParams = new Hashtable();
+ MoneyBalanceRequestParams["agentId"] = agentId.ToString();
+ MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString();
+ MoneyBalanceRequestParams["regionId"] = regionId.ToString();
+ MoneyBalanceRequestParams["secret"] = regionSecret;
+ MoneyBalanceRequestParams["currencySecret"] = ""; // per - region/user currency secret gotten from the money system
+
+ Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorUserBalanceRequest");
+
+ return MoneyRespData;
+ }
+
+
+ ///
+ /// Generic XMLRPC client abstraction
+ ///
+ /// Hashtable containing parameters to the method
+ /// Method to invoke
+ /// Hashtable with success=>bool and other values
+ public Hashtable genericCurrencyXMLRPCRequest(Hashtable ReqParams, string method)
+ {
+ ArrayList SendParams = new ArrayList();
+ SendParams.Add(ReqParams);
+ // Send Request
+ XmlRpcResponse MoneyResp;
+ try
+ {
+ XmlRpcRequest BalanceRequestReq = new XmlRpcRequest(method, SendParams);
+ MoneyResp = BalanceRequestReq.Send(m_MoneyAddress, 30000);
+ }
+ catch (WebException ex)
+ {
+ m_log.ErrorFormat(
+ "[MONEY]: Unable to connect to Money Server {0}. Exception {1}",
+ m_MoneyAddress, ex);
+
+ Hashtable ErrorHash = new Hashtable();
+ ErrorHash["success"] = false;
+ ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
+ ErrorHash["errorURI"] = "";
+
+ return ErrorHash;
+ //throw (ex);
+ }
+ catch (SocketException ex)
+ {
+ m_log.ErrorFormat(
+ "[MONEY]: Unable to connect to Money Server {0}. Exception {1}",
+ m_MoneyAddress, ex);
+
+ Hashtable ErrorHash = new Hashtable();
+ ErrorHash["success"] = false;
+ ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
+ ErrorHash["errorURI"] = "";
+
+ return ErrorHash;
+ //throw (ex);
+ }
+ catch (XmlException ex)
+ {
+ m_log.ErrorFormat(
+ "[MONEY]: Unable to connect to Money Server {0}. Exception {1}",
+ m_MoneyAddress, ex);
+
+ Hashtable ErrorHash = new Hashtable();
+ ErrorHash["success"] = false;
+ ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
+ ErrorHash["errorURI"] = "";
+
+ return ErrorHash;
+ }
+ if (MoneyResp.IsFault)
+ {
+ Hashtable ErrorHash = new Hashtable();
+ ErrorHash["success"] = false;
+ ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
+ ErrorHash["errorURI"] = "";
+
+ return ErrorHash;
+ }
+ Hashtable MoneyRespData = (Hashtable) MoneyResp.Value;
+
+ return MoneyRespData;
+ }
+
+ ///
+ /// This informs the Money Grid Server that the avatar is in this simulator
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Hashtable claim_user(LLUUID agentId, LLUUID secureSessionID, LLUUID regionId, string regionSecret)
+ {
+ Hashtable MoneyBalanceRequestParams = new Hashtable();
+ MoneyBalanceRequestParams["agentId"] = agentId.ToString();
+ MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString();
+ MoneyBalanceRequestParams["regionId"] = regionId.ToString();
+ MoneyBalanceRequestParams["secret"] = regionSecret;
+
+ Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorClaimUserRequest");
+ IClientAPI sendMoneyBal = LocateClientObject(agentId);
+ if (sendMoneyBal != null)
+ {
+ SendMoneyBalance(sendMoneyBal, agentId, sendMoneyBal.SessionId, LLUUID.Zero);
+ }
+ return MoneyRespData;
+ }
+
+ private SceneObjectPart findPrim(LLUUID objectID)
+ {
+ lock (m_scenel)
+ {
+ foreach (Scene s in m_scenel.Values)
+ {
+ SceneObjectPart part = s.GetSceneObjectPart(objectID);
+ if (part != null)
+ {
+ return part;
+ }
+ }
+ }
+ return null;
+ }
+
+ private string resolveObjectName(LLUUID objectID)
+ {
+ SceneObjectPart part = findPrim(objectID);
+ if (part != null)
+ {
+ return part.Name;
+ }
+ return String.Empty;
+ }
+
+ private string resolveAgentName(LLUUID agentID)
+ {
+ // try avatar username surname
+ Scene scene = GetRandomScene();
+ UserProfileData profile = scene.CommsManager.UserService.GetUserProfile(agentID);
+ if (profile != null)
+ {
+ string avatarname = profile.FirstName + " " + profile.SurName;
+ return avatarname;
+ }
+ return String.Empty;
+ }
+
+ private void BalanceUpdate(LLUUID senderID, LLUUID receiverID, bool transactionresult, string description)
+ {
+ IClientAPI sender = LocateClientObject(senderID);
+ IClientAPI receiver = LocateClientObject(receiverID);
+
+ if (senderID != receiverID)
+ {
+ if (sender != null)
+ {
+ sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(description), GetFundsForAgentID(senderID));
+ }
+
+ if (receiver != null)
+ {
+ receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(description), GetFundsForAgentID(receiverID));
+ }
+ }
+ }
+
+ ///
+ /// Informs the Money Grid Server of a transfer.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool TransferMoneyonMoneyServer(LLUUID sourceId, LLUUID destId, int amount, int transactiontype, string description)
+ {
+ int aggregatePermInventory = 0;
+ int aggregatePermNextOwner = 0;
+ int flags = 0;
+ bool rvalue = false;
+
+ IClientAPI cli = LocateClientObject(sourceId);
+ if (cli != null)
+ {
+ Scene userScene = null;
+ lock (m_rootAgents)
+ {
+ userScene = GetSceneByUUID(m_rootAgents[sourceId]);
+ }
+ if (userScene != null)
+ {
+ Hashtable ht = new Hashtable();
+ ht["agentId"] = sourceId.ToString();
+ ht["secureSessionId"] = cli.SecureSessionId.ToString();
+ ht["regionId"] = userScene.RegionInfo.originRegionID.ToString();
+ ht["secret"] = userScene.RegionInfo.regionSecret;
+ ht["currencySecret"] = " ";
+ ht["destId"] = destId.ToString();
+ ht["cash"] = amount;
+ ht["aggregatePermInventory"] = aggregatePermInventory;
+ ht["aggregatePermNextOwner"] = aggregatePermNextOwner;
+ ht["flags"] = flags;
+ ht["transactionType"] = transactiontype;
+ ht["description"] = description;
+
+ Hashtable hresult = genericCurrencyXMLRPCRequest(ht, "regionMoveMoney");
+
+ if ((bool) hresult["success"] == true)
+ {
+ int funds1 = 0;
+ int funds2 = 0;
+ try
+ {
+ funds1 = (Int32) hresult["funds"];
+ }
+ catch (InvalidCastException)
+ {
+ funds1 = 0;
+ }
+ SetLocalFundsForAgentID(sourceId, funds1);
+ if (m_KnownClientFunds.ContainsKey(destId))
+ {
+ try
+ {
+ funds2 = (Int32) hresult["funds2"];
+ }
+ catch (InvalidCastException)
+ {
+ funds2 = 0;
+ }
+ SetLocalFundsForAgentID(destId, funds2);
+ }
+
+
+ rvalue = true;
+ }
+ else
+ {
+ cli.SendAgentAlertMessage((string) hresult["errorMessage"], true);
+ }
+ }
+ }
+ else
+ {
+ m_log.ErrorFormat("[MONEY]: Client {0} not found", sourceId.ToString());
+ }
+
+ return rvalue;
+ }
+
+ public int GetRemoteBalance(LLUUID agentId)
+ {
+ int funds = 0;
+
+ IClientAPI aClient = LocateClientObject(agentId);
+ if (aClient != null)
+ {
+ Scene s = LocateSceneClientIn(agentId);
+ if (s != null)
+ {
+ if (m_MoneyAddress.Length > 0)
+ {
+ Hashtable hbinfo =
+ GetBalanceForUserFromMoneyServer(aClient.AgentId, aClient.SecureSessionId, s.RegionInfo.originRegionID.ToString(),
+ s.RegionInfo.regionSecret);
+ if ((bool) hbinfo["success"] == true)
+ {
+ try
+ {
+ funds = (Int32) hbinfo["funds"];
+ }
+ catch (ArgumentException)
+ {
+ }
+ catch (FormatException)
+ {
+ }
+ catch (OverflowException)
+ {
+ m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentId);
+ aClient.SendAlertMessage("Unable to get your money balance, money operations will be unavailable");
+ }
+ catch (InvalidCastException)
+ {
+ funds = 0;
+ }
+ }
+ else
+ {
+ m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentId,
+ (string) hbinfo["errorMessage"]);
+ aClient.SendAlertMessage((string) hbinfo["errorMessage"]);
+ }
+ }
+
+ SetLocalFundsForAgentID(agentId, funds);
+ SendMoneyBalance(aClient, agentId, aClient.SessionId, LLUUID.Zero);
+ }
+ else
+ {
+ m_log.Debug("[MONEY]: Got balance request update for agent that is here, but couldn't find which scene.");
+ }
+ }
+ else
+ {
+ m_log.Debug("[MONEY]: Got balance request update for agent that isn't here.");
+ }
+ return funds;
+ }
+
+ public XmlRpcResponse GridMoneyUpdate(XmlRpcRequest request)
+ {
+ m_log.Debug("[MONEY]: Dynamic balance update called.");
+ Hashtable requestData = (Hashtable) request.Params[0];
+
+ if (requestData.ContainsKey("agentId"))
+ {
+ LLUUID agentId = LLUUID.Zero;
+
+ Helpers.TryParse((string) requestData["agentId"], out agentId);
+ if (agentId != LLUUID.Zero)
+ {
+ GetRemoteBalance(agentId);
+ }
+ else
+ {
+ m_log.Debug("[MONEY]: invalid agentId specified, dropping.");
+ }
+ }
+ else
+ {
+ m_log.Debug("[MONEY]: no agentId specified, dropping.");
+ }
+ XmlRpcResponse r = new XmlRpcResponse();
+ Hashtable rparms = new Hashtable();
+ rparms["success"] = true;
+
+ r.Value = rparms;
+ return r;
+ }
+
+ ///
+ /// XMLRPC handler to send alert message and sound to client
+ ///
+ public XmlRpcResponse UserAlert(XmlRpcRequest request)
+ {
+ XmlRpcResponse ret = new XmlRpcResponse();
+ Hashtable retparam = new Hashtable();
+ Hashtable requestData = (Hashtable) request.Params[0];
+
+ LLUUID agentId = LLUUID.Zero;
+ LLUUID soundId = LLUUID.Zero;
+
+ Helpers.TryParse((string) requestData["agentId"], out agentId);
+ Helpers.TryParse((string) requestData["soundId"], out soundId);
+ string text = (string) requestData["text"];
+ string secret = (string) requestData["secret"];
+
+ Scene userScene = GetRandomScene();
+ if (userScene.RegionInfo.regionSecret.ToString() == secret)
+ {
+ IClientAPI client = LocateClientObject(agentId);
+
+ if (client != null)
+ {
+ if (soundId != LLUUID.Zero)
+ client.SendPlayAttachedSound(soundId, LLUUID.Zero, LLUUID.Zero, 1.0f, 0);
+ client.SendBlueBoxMessage(LLUUID.Zero, LLUUID.Zero, "", text);
+ retparam.Add("success", true);
+ }
+ else
+ {
+ retparam.Add("success", false);
+ }
+ }
+ else
+ {
+ retparam.Add("success", false);
+ }
+ ret.Value = retparam;
+
+ return ret;
+ }
+
+ # region Standalone box enablers only
+
+ public XmlRpcResponse quote_func(XmlRpcRequest request)
+ {
+ Hashtable requestData = (Hashtable) request.Params[0];
+ LLUUID agentId = LLUUID.Zero;
+ int amount = 0;
+ Hashtable quoteResponse = new Hashtable();
+ XmlRpcResponse returnval = new XmlRpcResponse();
+
+ if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy"))
+ {
+ Helpers.TryParse((string) requestData["agentId"], out agentId);
+ try
+ {
+ amount = (Int32) requestData["currencyBuy"];
+ }
+ catch (InvalidCastException)
+ {
+ }
+ Hashtable currencyResponse = new Hashtable();
+ currencyResponse.Add("estimatedCost", 0);
+ currencyResponse.Add("currencyBuy", amount);
+
+ quoteResponse.Add("success", true);
+ quoteResponse.Add("currency", currencyResponse);
+ quoteResponse.Add("confirm", "asdfad9fj39ma9fj");
+
+ returnval.Value = quoteResponse;
+ return returnval;
+ }
+
+
+ quoteResponse.Add("success", false);
+ quoteResponse.Add("errorMessage", "Invalid parameters passed to the quote box");
+ quoteResponse.Add("errorURI", "http://www.opensimulator.org/wiki");
+ returnval.Value = quoteResponse;
+ return returnval;
+ }
+
+ public XmlRpcResponse buy_func(XmlRpcRequest request)
+ {
+ Hashtable requestData = (Hashtable) request.Params[0];
+ LLUUID agentId = LLUUID.Zero;
+ int amount = 0;
+ if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy"))
+ {
+ Helpers.TryParse((string) requestData["agentId"], out agentId);
+ try
+ {
+ amount = (Int32) requestData["currencyBuy"];
+ }
+ catch (InvalidCastException)
+ {
+ }
+ if (agentId != LLUUID.Zero)
+ {
+ lock (m_KnownClientFunds)
+ {
+ if (m_KnownClientFunds.ContainsKey(agentId))
+ {
+ m_KnownClientFunds[agentId] += amount;
+ }
+ else
+ {
+ m_KnownClientFunds.Add(agentId, amount);
+ }
+ }
+ IClientAPI client = LocateClientObject(agentId);
+ if (client != null)
+ {
+ SendMoneyBalance(client, agentId, client.SessionId, LLUUID.Zero);
+ }
+ }
+ }
+ XmlRpcResponse returnval = new XmlRpcResponse();
+ Hashtable returnresp = new Hashtable();
+ returnresp.Add("success", true);
+ returnval.Value = returnresp;
+ return returnval;
+ }
+
+ public XmlRpcResponse preflightBuyLandPrep_func(XmlRpcRequest request)
+ {
+ XmlRpcResponse ret = new XmlRpcResponse();
+ Hashtable retparam = new Hashtable();
+ Hashtable membershiplevels = new Hashtable();
+ ArrayList levels = new ArrayList();
+ Hashtable level = new Hashtable();
+ level.Add("id", "00000000-0000-0000-0000-000000000000");
+ level.Add("description", "some level");
+ levels.Add(level);
+ //membershiplevels.Add("levels",levels);
+
+ Hashtable landuse = new Hashtable();
+ landuse.Add("upgrade", false);
+ landuse.Add("action", "http://invaliddomaininvalid.com/");
+
+ Hashtable currency = new Hashtable();
+ currency.Add("estimatedCost", 0);
+
+ Hashtable membership = new Hashtable();
+ membershiplevels.Add("upgrade", false);
+ membershiplevels.Add("action", "http://invaliddomaininvalid.com/");
+ membershiplevels.Add("levels", membershiplevels);
+
+ retparam.Add("success", true);
+ retparam.Add("currency", currency);
+ retparam.Add("membership", membership);
+ retparam.Add("landuse", landuse);
+ retparam.Add("confirm", "asdfajsdkfjasdkfjalsdfjasdf");
+
+ ret.Value = retparam;
+
+ return ret;
+ }
+
+ public XmlRpcResponse landBuy_func(XmlRpcRequest request)
+ {
+ XmlRpcResponse ret = new XmlRpcResponse();
+ Hashtable retparam = new Hashtable();
+ Hashtable requestData = (Hashtable) request.Params[0];
+
+ LLUUID agentId = LLUUID.Zero;
+ int amount = 0;
+ if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy"))
+ {
+ Helpers.TryParse((string) requestData["agentId"], out agentId);
+ try
+ {
+ amount = (Int32) requestData["currencyBuy"];
+ }
+ catch (InvalidCastException)
+ {
+ }
+ if (agentId != LLUUID.Zero)
+ {
+ lock (m_KnownClientFunds)
+ {
+ if (m_KnownClientFunds.ContainsKey(agentId))
+ {
+ m_KnownClientFunds[agentId] += amount;
+ }
+ else
+ {
+ m_KnownClientFunds.Add(agentId, amount);
+ }
+ }
+ IClientAPI client = LocateClientObject(agentId);
+ if (client != null)
+ {
+ SendMoneyBalance(client, agentId, client.SessionId, LLUUID.Zero);
+ }
+ }
+ }
+ retparam.Add("success", true);
+ ret.Value = retparam;
+
+ return ret;
+ }
+
+ #endregion
+
+ #region local Fund Management
+
+ ///
+ /// Ensures that the agent accounting data is set up in this instance.
+ ///
+ ///
+ private void CheckExistAndRefreshFunds(LLUUID agentID)
+ {
+ lock (m_KnownClientFunds)
+ {
+ if (!m_KnownClientFunds.ContainsKey(agentID))
+ {
+ m_KnownClientFunds.Add(agentID, m_stipend);
+ }
+ else
+ {
+ if (m_KnownClientFunds[agentID] <= m_minFundsBeforeRefresh)
+ {
+ m_KnownClientFunds[agentID] = m_stipend;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Gets the amount of Funds for an agent
+ ///
+ ///
+ ///
+ private int GetFundsForAgentID(LLUUID AgentID)
+ {
+ int returnfunds = 0;
+ lock (m_KnownClientFunds)
+ {
+ if (m_KnownClientFunds.ContainsKey(AgentID))
+ {
+ returnfunds = m_KnownClientFunds[AgentID];
+ }
+ else
+ {
+ //throw new Exception("Unable to get funds.");
+ }
+ }
+ return returnfunds;
+ }
+
+ private void SetLocalFundsForAgentID(LLUUID AgentID, int amount)
+ {
+ lock (m_KnownClientFunds)
+ {
+ if (m_KnownClientFunds.ContainsKey(AgentID))
+ {
+ m_KnownClientFunds[AgentID] = amount;
+ }
+ else
+ {
+ m_KnownClientFunds.Add(AgentID, amount);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Utility Helpers
+
+ ///
+ /// Locates a IClientAPI for the client specified
+ ///
+ ///
+ ///
+ private IClientAPI LocateClientObject(LLUUID AgentID)
+ {
+ ScenePresence tPresence = null;
+ IClientAPI rclient = null;
+
+ lock (m_scenel)
+ {
+ foreach (Scene _scene in m_scenel.Values)
+ {
+ tPresence = _scene.GetScenePresence(AgentID);
+ if (tPresence != null)
+ {
+ if (!tPresence.IsChildAgent)
+ {
+ rclient = tPresence.ControllingClient;
+ }
+ }
+ if (rclient != null)
+ {
+ return rclient;
+ }
+ }
+ }
+ return null;
+ }
+
+ private Scene LocateSceneClientIn(LLUUID AgentId)
+ {
+ lock (m_scenel)
+ {
+ foreach (Scene _scene in m_scenel.Values)
+ {
+ ScenePresence tPresence = _scene.GetScenePresence(AgentId);
+ if (tPresence != null)
+ {
+ if (!tPresence.IsChildAgent)
+ {
+ return _scene;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Utility function Gets a Random scene in the instance. For when which scene exactly you're doing something with doesn't matter
+ ///
+ ///
+ public Scene GetRandomScene()
+ {
+ lock (m_scenel)
+ {
+ foreach (Scene rs in m_scenel.Values)
+ return rs;
+ }
+ return null;
+ }
+
+ ///
+ /// Utility function to get a Scene by RegionID in a module
+ ///
+ ///
+ ///
+ public Scene GetSceneByUUID(LLUUID RegionID)
+ {
+ lock (m_scenel)
+ {
+ foreach (Scene rs in m_scenel.Values)
+ {
+ if (rs.RegionInfo.originRegionID == RegionID)
+ {
+ return rs;
+ }
+ }
+ }
+ return null;
+ }
+
+ #endregion
+
+ #region event Handlers
+
+ public void requestPayPrice(IClientAPI client, LLUUID objectID)
+ {
+ Scene scene = LocateSceneClientIn(client.AgentId);
+ if (scene == null)
+ return;
+
+ SceneObjectPart task = scene.GetSceneObjectPart(objectID);
+ if (task == null)
+ return;
+ SceneObjectGroup group = task.ParentGroup;
+ SceneObjectPart root = group.RootPart;
+
+ client.SendPayPrice(objectID, root.PayPrice);
+ }
+
+ ///
+ /// When the client closes the connection we remove their accounting info from memory to free up resources.
+ ///
+ ///
+ public void ClientClosed(LLUUID AgentID)
+ {
+ lock (m_KnownClientFunds)
+ {
+ if (m_keepMoneyAcrossLogins && m_MoneyAddress.Length == 0)
+ {
+ }
+ else
+ {
+ m_KnownClientFunds.Remove(AgentID);
+ }
+ }
+ }
+
+ ///
+ /// Event called Economy Data Request handler.
+ ///
+ ///
+ public void EconomyDataRequestHandler(LLUUID agentId)
+ {
+ IClientAPI user = LocateClientObject(agentId);
+
+ if (user != null)
+ {
+ user.SendEconomyData(EnergyEfficiency, ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate,
+ PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor,
+ PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload,
+ TeleportMinPrice, TeleportPriceExponent);
+ }
+ }
+
+ private void ValidateLandBuy(Object osender, EventManager.LandBuyArgs e)
+ {
+ if (m_MoneyAddress.Length == 0)
+ {
+ lock (m_KnownClientFunds)
+ {
+ if (m_KnownClientFunds.ContainsKey(e.agentId))
+ {
+ // Does the sender have enough funds to give?
+ if (m_KnownClientFunds[e.agentId] >= e.parcelPrice)
+ {
+ lock (e)
+ {
+ e.economyValidated = true;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (GetRemoteBalance(e.agentId) >= e.parcelPrice)
+ {
+ lock (e)
+ {
+ e.economyValidated = true;
+ }
+ }
+ }
+ }
+
+ private void processLandBuy(Object osender, EventManager.LandBuyArgs e)
+ {
+ lock (e)
+ {
+ if (e.economyValidated == true && e.transactionID == 0)
+ {
+ e.transactionID = Util.UnixTimeSinceEpoch();
+
+ if (doMoneyTransfer(e.agentId, e.parcelOwnerID, e.parcelPrice, 0, "Land purchase"))
+ {
+ lock (e)
+ {
+ e.amountDebited = e.parcelPrice;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// THis method gets called when someone pays someone else as a gift.
+ ///
+ ///
+ ///
+ private void MoneyTransferAction(Object osender, EventManager.MoneyTransferArgs e)
+ {
+ IClientAPI sender = null;
+ IClientAPI receiver = null;
+
+ if (m_MoneyAddress.Length > 0) // Handled on server
+ e.description = String.Empty;
+
+ if (e.transactiontype == 5008) // Object gets paid
+ {
+ sender = LocateClientObject(e.sender);
+ if (sender != null)
+ {
+ SceneObjectPart part = findPrim(e.receiver);
+ if (part == null)
+ return;
+
+ string name = resolveAgentName(part.OwnerID);
+ if (name == String.Empty)
+ name = "(hippos)";
+
+ receiver = LocateClientObject(part.OwnerID);
+
+ string description = String.Format("Paid {0} via object {1}", name, e.description);
+ bool transactionresult = doMoneyTransfer(e.sender, part.OwnerID, e.amount, e.transactiontype, description);
+
+ if (transactionresult)
+ {
+ ObjectPaid handlerOnObjectPaid = OnObjectPaid;
+ if (handlerOnObjectPaid != null)
+ {
+ handlerOnObjectPaid(e.receiver, e.sender, e.amount);
+ }
+ }
+
+ if (e.sender != e.receiver)
+ {
+ sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender));
+ }
+ if (receiver != null)
+ {
+ receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(part.OwnerID));
+ }
+ }
+ return;
+ }
+
+ sender = LocateClientObject(e.sender);
+ if (sender != null)
+ {
+ receiver = LocateClientObject(e.receiver);
+
+ bool transactionresult = doMoneyTransfer(e.sender, e.receiver, e.amount, e.transactiontype, e.description);
+
+ if (e.sender != e.receiver)
+ {
+ if (sender != null)
+ {
+ sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender));
+ }
+ }
+
+ if (receiver != null)
+ {
+ receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.receiver));
+ }
+ }
+ else
+ {
+ m_log.Warn("[MONEY]: Potential Fraud Warning, got money transfer request for avatar that isn't in this simulator - Details; Sender:" +
+ e.sender.ToString() + " Receiver: " + e.receiver.ToString() + " Amount: " + e.amount.ToString());
+ }
+ }
+
+ ///
+ /// Event Handler for when a root agent becomes a child agent
+ ///
+ ///
+ private void MakeChildAgent(ScenePresence avatar)
+ {
+ lock (m_rootAgents)
+ {
+ if (m_rootAgents.ContainsKey(avatar.UUID))
+ {
+ if (m_rootAgents[avatar.UUID] == avatar.Scene.RegionInfo.originRegionID)
+ {
+ m_rootAgents.Remove(avatar.UUID);
+ m_log.Info("[MONEY]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent");
+ }
+ }
+ }
+ }
+
+ ///
+ /// Event Handler for when the client logs out.
+ ///
+ ///
+ private void ClientLoggedOut(LLUUID AgentId)
+ {
+ lock (m_rootAgents)
+ {
+ if (m_rootAgents.ContainsKey(AgentId))
+ {
+ m_rootAgents.Remove(AgentId);
+ //m_log.Info("[MONEY]: Removing " + AgentId + ". Agent logged out.");
+ }
+ }
+ }
+
+ ///
+ /// Call this when the client disconnects.
+ ///
+ ///
+ public void ClientClosed(IClientAPI client)
+ {
+ ClientClosed(client.AgentId);
+ }
+
+ ///
+ /// Event Handler for when an Avatar enters one of the parcels in the simulator.
+ ///
+ ///
+ ///
+ ///
+ private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID)
+ {
+ lock (m_rootAgents)
+ {
+ if (m_rootAgents.ContainsKey(avatar.UUID))
+ {
+ if (avatar.Scene.RegionInfo.originRegionID != m_rootAgents[avatar.UUID])
+ {
+ m_rootAgents[avatar.UUID] = avatar.Scene.RegionInfo.originRegionID;
+ //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + ".");
+ // Claim User! my user! Mine mine mine!
+ if (m_MoneyAddress.Length > 0)
+ {
+ Scene RegionItem = GetSceneByUUID(regionID);
+ if (RegionItem != null)
+ {
+ Hashtable hresult =
+ claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret);
+ if ((bool) hresult["success"] == true)
+ {
+ int funds = 0;
+ try
+ {
+ funds = (Int32) hresult["funds"];
+ }
+ catch (InvalidCastException)
+ {
+ }
+ SetLocalFundsForAgentID(avatar.UUID, funds);
+ }
+ else
+ {
+ avatar.ControllingClient.SendAgentAlertMessage((string) hresult["errorMessage"], true);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ lock (m_rootAgents)
+ {
+ m_rootAgents.Add(avatar.UUID, avatar.Scene.RegionInfo.originRegionID);
+ }
+ if (m_MoneyAddress.Length > 0)
+ {
+ Scene RegionItem = GetSceneByUUID(regionID);
+ if (RegionItem != null)
+ {
+ Hashtable hresult = claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret);
+ if ((bool) hresult["success"] == true)
+ {
+ int funds = 0;
+ try
+ {
+ funds = (Int32) hresult["funds"];
+ }
+ catch (InvalidCastException)
+ {
+ }
+ SetLocalFundsForAgentID(avatar.UUID, funds);
+ }
+ else
+ {
+ avatar.ControllingClient.SendAgentAlertMessage((string) hresult["errorMessage"], true);
+ }
+ }
+ }
+
+ //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + ".");
+ }
+ }
+ //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString());
+ }
+
+ #endregion
+ }
+
+ public enum TransactionType : int
+ {
+ SystemGenerated = 0,
+ RegionMoneyRequest = 1,
+ Gift = 2,
+ Purchase = 3
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
index db38d87..dd6a92e 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
@@ -1,501 +1,501 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using libsecondlife;
-using libsecondlife.Packets;
-using log4net;
-using Nini.Config;
-using Nwc.XmlRpc;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Avatar.Friends
-{
- public class FriendsModule : IRegionModule
- {
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- private Dictionary> FriendLists = new Dictionary>();
- private Dictionary m_pendingFriendRequests = new Dictionary();
- private Dictionary m_rootAgents = new Dictionary();
- private List m_scene = new List();
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- lock (m_scene)
- {
- if (m_scene.Count == 0)
- {
- scene.AddXmlRPCHandler("presence_update", processPresenceUpdate);
- }
-
- if (!m_scene.Contains(scene))
- m_scene.Add(scene);
- }
- scene.EventManager.OnNewClient += OnNewClient;
- scene.EventManager.OnGridInstantMessageToFriendsModule += OnGridInstantMessage;
- scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
- scene.EventManager.OnMakeChildAgent += MakeChildAgent;
- scene.EventManager.OnClientClosed += ClientLoggedOut;
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "FriendsModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return true; }
- }
-
- #endregion
-
- public XmlRpcResponse processPresenceUpdate(XmlRpcRequest req)
- {
- m_log.Info("[FRIENDS]: Got Notification about a user! OMG");
- return new XmlRpcResponse();
- }
-
- private void OnNewClient(IClientAPI client)
- {
- // All friends establishment protocol goes over instant message
- // There's no way to send a message from the sim
- // to a user to 'add a friend' without causing dialog box spam
- //
- // The base set of friends are added when the user signs on in their XMLRPC response
- // Generated by LoginService. The friends are retreived from the database by the UserManager
-
- // Subscribe to instant messages
-
- client.OnInstantMessage += OnInstantMessage;
- client.OnApproveFriendRequest += OnApprovedFriendRequest;
- client.OnDenyFriendRequest += OnDenyFriendRequest;
- client.OnTerminateFriendship += OnTerminateFriendship;
-
- List fl = new List();
-
- //bool addFLback = false;
-
- lock (FriendLists)
- {
- if (FriendLists.ContainsKey(client.AgentId))
- {
- fl = FriendLists[client.AgentId];
- }
- else
- {
- fl = m_scene[0].GetFriendList(client.AgentId);
-
- //lock (FriendLists)
- //{
- if (!FriendLists.ContainsKey(client.AgentId))
- FriendLists.Add(client.AgentId, fl);
- //}
- }
- }
-
- List UpdateUsers = new List();
-
- foreach (FriendListItem f in fl)
- {
- if (m_rootAgents.ContainsKey(f.Friend))
- {
- if (f.onlinestatus == false)
- {
- UpdateUsers.Add(f.Friend);
- f.onlinestatus = true;
- }
- }
- }
- foreach (LLUUID user in UpdateUsers)
- {
- ScenePresence av = GetPresenceFromAgentID(user);
- if (av != null)
- {
- List usrfl = new List();
-
- lock (FriendLists)
- {
- usrfl = FriendLists[user];
- }
-
- lock (usrfl)
- {
- foreach (FriendListItem fli in usrfl)
- {
- if (fli.Friend == client.AgentId)
- {
- fli.onlinestatus = true;
- OnlineNotificationPacket onp = new OnlineNotificationPacket();
- OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[1];
- OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock();
- onpbl.AgentID = client.AgentId;
- onpb[0] = onpbl;
- onp.AgentBlock = onpb;
- av.ControllingClient.OutPacket(onp, ThrottleOutPacketType.Task);
- }
- }
- }
- }
- }
-
- if (UpdateUsers.Count > 0)
- {
- OnlineNotificationPacket onp = new OnlineNotificationPacket();
- OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[UpdateUsers.Count];
- for (int i = 0; i < UpdateUsers.Count; i++)
- {
- OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock();
- onpbl.AgentID = UpdateUsers[i];
- onpb[i] = onpbl;
- }
- onp.AgentBlock = onpb;
- client.OutPacket(onp, ThrottleOutPacketType.Task);
- }
- }
-
- private void ClientLoggedOut(LLUUID AgentId)
- {
- lock (m_rootAgents)
- {
- if (m_rootAgents.ContainsKey(AgentId))
- {
- m_rootAgents.Remove(AgentId);
- m_log.Info("[FRIEND]: Removing " + AgentId + ". Agent logged out.");
- }
- }
- List lfli = new List();
- lock (FriendLists)
- {
- if (FriendLists.ContainsKey(AgentId))
- {
- lfli = FriendLists[AgentId];
- }
- }
- List updateUsers = new List();
- foreach (FriendListItem fli in lfli)
- {
- if (fli.onlinestatus == true)
- {
- updateUsers.Add(fli.Friend);
- }
- }
- lock (updateUsers)
- {
- for (int i = 0; i < updateUsers.Count; i++)
- {
- List flfli = new List();
- try
- {
- lock (FriendLists)
- {
- if (FriendLists.ContainsKey(updateUsers[i]))
- flfli = FriendLists[updateUsers[i]];
- }
- }
- catch (IndexOutOfRangeException)
- {
- // Ignore the index out of range exception.
- // This causes friend lists to get out of sync slightly.. however
- // prevents a sim crash.
- m_log.Info("[FRIEND]: Unable to enumerate last friendlist user. User logged off");
- }
-
- for (int j = 0; j < flfli.Count; j++)
- {
- try
- {
- if (flfli[i].Friend == AgentId)
- {
- flfli[i].onlinestatus = false;
- }
- }
-
- catch (IndexOutOfRangeException)
- {
- // Ignore the index out of range exception.
- // This causes friend lists to get out of sync slightly.. however
- // prevents a sim crash.
- m_log.Info("[FRIEND]: Unable to enumerate last friendlist user. User logged off");
- }
- }
- }
-
- for (int i = 0; i < updateUsers.Count; i++)
- {
- ScenePresence av = GetPresenceFromAgentID(updateUsers[i]);
- if (av != null)
- {
- OfflineNotificationPacket onp = new OfflineNotificationPacket();
- OfflineNotificationPacket.AgentBlockBlock[] onpb = new OfflineNotificationPacket.AgentBlockBlock[1];
- OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock();
- onpbl.AgentID = AgentId;
- onpb[0] = onpbl;
- onp.AgentBlock = onpb;
- av.ControllingClient.OutPacket(onp, ThrottleOutPacketType.Task);
- }
- }
- }
- lock (FriendLists)
- {
- FriendLists.Remove(AgentId);
- }
- }
-
- private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID)
- {
- lock (m_rootAgents)
- {
- if (m_rootAgents.ContainsKey(avatar.UUID))
- {
- if (avatar.RegionHandle != m_rootAgents[avatar.UUID])
- {
- m_rootAgents[avatar.UUID] = avatar.RegionHandle;
- m_log.Info("[FRIEND]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + ".");
- if (avatar.JID.Length > 0)
- {
- JId avatarID = new JId(avatar.JID);
- // REST Post XMPP Stanzas!
- }
- // Claim User! my user! Mine mine mine!
- }
- }
- else
- {
- m_rootAgents.Add(avatar.UUID, avatar.RegionHandle);
- m_log.Info("[FRIEND]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + ".");
- }
- }
- //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString());
- }
-
- private void MakeChildAgent(ScenePresence avatar)
- {
- lock (m_rootAgents)
- {
- if (m_rootAgents.ContainsKey(avatar.UUID))
- {
- if (m_rootAgents[avatar.UUID] == avatar.RegionHandle)
- {
- m_rootAgents.Remove(avatar.UUID);
- m_log.Info("[FRIEND]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent");
- }
- }
- }
- }
-
- private ScenePresence GetPresenceFromAgentID(LLUUID AgentID)
- {
- ScenePresence returnAgent = null;
- lock (m_scene)
- {
- ScenePresence queryagent = null;
- for (int i = 0; i < m_scene.Count; i++)
- {
- queryagent = m_scene[i].GetScenePresence(AgentID);
- if (queryagent != null)
- {
- if (!queryagent.IsChildAgent)
- {
- returnAgent = queryagent;
- break;
- }
- }
- }
- }
- return returnAgent;
- }
-
- #region FriendRequestHandling
-
- private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
- LLUUID fromAgentSession, LLUUID toAgentID,
- LLUUID imSessionID, uint timestamp, string fromAgentName,
- string message, byte dialog, bool fromGroup, byte offline,
- uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
- byte[] binaryBucket)
- {
- // Friend Requests go by Instant Message.. using the dialog param
- // https://wiki.secondlife.com/wiki/ImprovedInstantMessage
-
- // 38 == Offer friendship
- if (dialog == (byte) 38)
- {
- LLUUID friendTransactionID = LLUUID.Random();
-
- m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
-
- m_log.Info("[FRIEND]: 38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" +
- message);
- GridInstantMessage msg = new GridInstantMessage();
- msg.fromAgentID = fromAgentID.UUID;
- msg.fromAgentSession = fromAgentSession.UUID;
- msg.toAgentID = toAgentID.UUID;
- msg.imSessionID = friendTransactionID.UUID; // This is the item we're mucking with here
- m_log.Info("[FRIEND]: Filling Session: " + msg.imSessionID.ToString());
- msg.timestamp = timestamp;
- if (client != null)
- {
- msg.fromAgentName = client.FirstName + " " + client.LastName; // fromAgentName;
- }
- else
- {
- msg.fromAgentName = "(hippos)"; // Added for posterity. This means that we can't figure out who sent it
- }
- msg.message = message;
- msg.dialog = dialog;
- msg.fromGroup = fromGroup;
- msg.offline = offline;
- msg.ParentEstateID = ParentEstateID;
- msg.Position = new sLLVector3(Position);
- msg.RegionID = RegionID.UUID;
- msg.binaryBucket = binaryBucket;
- // We don't really care which scene we pipe it through.
- m_scene[0].TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
- }
-
- // 39 == Accept Friendship
- if (dialog == (byte) 39)
- {
- m_log.Info("[FRIEND]: 39 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" +
- message);
- }
-
- // 40 == Decline Friendship
- if (dialog == (byte) 40)
- {
- m_log.Info("[FRIEND]: 40 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" +
- message);
- }
- }
-
- private void OnApprovedFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List callingCardFolders)
- {
- if (m_pendingFriendRequests.ContainsKey(transactionID))
- {
- // Found Pending Friend Request with that Transaction..
- Scene SceneAgentIn = m_scene[0];
-
- // Found Pending Friend Request with that Transaction..
- ScenePresence agentpresence = GetPresenceFromAgentID(agentID);
- if (agentpresence != null)
- {
- SceneAgentIn = agentpresence.Scene;
- }
-
- // Compose response to other agent.
- GridInstantMessage msg = new GridInstantMessage();
- msg.toAgentID = m_pendingFriendRequests[transactionID].UUID;
- msg.fromAgentID = agentID.UUID;
- msg.fromAgentName = client.FirstName + " " + client.LastName;
- msg.fromAgentSession = client.SessionId.UUID;
- msg.fromGroup = false;
- msg.imSessionID = transactionID.UUID;
- msg.message = agentID.UUID.ToString();
- msg.ParentEstateID = 0;
- msg.timestamp = (uint) Util.UnixTimeSinceEpoch();
- msg.RegionID = SceneAgentIn.RegionInfo.RegionID.UUID;
- msg.dialog = (byte) 39; // Approved friend request
- msg.Position = new sLLVector3();
- msg.offline = (byte) 0;
- msg.binaryBucket = new byte[0];
- // We don't really care which scene we pipe it through, it goes to the shared IM Module and/or the database
-
- SceneAgentIn.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
- SceneAgentIn.StoreAddFriendship(m_pendingFriendRequests[transactionID], agentID, (uint) 1);
- m_pendingFriendRequests.Remove(transactionID);
-
- // TODO: Inform agent that the friend is online
- }
- }
-
- private void OnDenyFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List callingCardFolders)
- {
- if (m_pendingFriendRequests.ContainsKey(transactionID))
- {
- Scene SceneAgentIn = m_scene[0];
-
- // Found Pending Friend Request with that Transaction..
- ScenePresence agentpresence = GetPresenceFromAgentID(agentID);
- if (agentpresence != null)
- {
- SceneAgentIn = agentpresence.Scene;
- }
- // Compose response to other agent.
- GridInstantMessage msg = new GridInstantMessage();
- msg.toAgentID = m_pendingFriendRequests[transactionID].UUID;
- msg.fromAgentID = agentID.UUID;
- msg.fromAgentName = client.FirstName + " " + client.LastName;
- msg.fromAgentSession = client.SessionId.UUID;
- msg.fromGroup = false;
- msg.imSessionID = transactionID.UUID;
- msg.message = agentID.UUID.ToString();
- msg.ParentEstateID = 0;
- msg.timestamp = (uint) Util.UnixTimeSinceEpoch();
- msg.RegionID = SceneAgentIn.RegionInfo.RegionID.UUID;
- msg.dialog = (byte) 40; // Deny friend request
- msg.Position = new sLLVector3();
- msg.offline = (byte) 0;
- msg.binaryBucket = new byte[0];
- SceneAgentIn.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
- m_pendingFriendRequests.Remove(transactionID);
- }
- }
-
- private void OnTerminateFriendship(IClientAPI client, LLUUID agent, LLUUID exfriendID)
- {
- m_scene[0].StoreRemoveFriendship(agent, exfriendID);
- // TODO: Inform the client that the ExFriend is offline
- }
-
- private void OnGridInstantMessage(GridInstantMessage msg)
- {
- // Trigger the above event handler
- OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
- new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
- msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
- new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
- msg.binaryBucket);
- }
-
- #endregion
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using libsecondlife;
+using libsecondlife.Packets;
+using log4net;
+using Nini.Config;
+using Nwc.XmlRpc;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Avatar.Friends
+{
+ public class FriendsModule : IRegionModule
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private Dictionary> FriendLists = new Dictionary>();
+ private Dictionary m_pendingFriendRequests = new Dictionary();
+ private Dictionary m_rootAgents = new Dictionary();
+ private List m_scene = new List();
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ lock (m_scene)
+ {
+ if (m_scene.Count == 0)
+ {
+ scene.AddXmlRPCHandler("presence_update", processPresenceUpdate);
+ }
+
+ if (!m_scene.Contains(scene))
+ m_scene.Add(scene);
+ }
+ scene.EventManager.OnNewClient += OnNewClient;
+ scene.EventManager.OnGridInstantMessageToFriendsModule += OnGridInstantMessage;
+ scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
+ scene.EventManager.OnMakeChildAgent += MakeChildAgent;
+ scene.EventManager.OnClientClosed += ClientLoggedOut;
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "FriendsModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return true; }
+ }
+
+ #endregion
+
+ public XmlRpcResponse processPresenceUpdate(XmlRpcRequest req)
+ {
+ m_log.Info("[FRIENDS]: Got Notification about a user! OMG");
+ return new XmlRpcResponse();
+ }
+
+ private void OnNewClient(IClientAPI client)
+ {
+ // All friends establishment protocol goes over instant message
+ // There's no way to send a message from the sim
+ // to a user to 'add a friend' without causing dialog box spam
+ //
+ // The base set of friends are added when the user signs on in their XMLRPC response
+ // Generated by LoginService. The friends are retreived from the database by the UserManager
+
+ // Subscribe to instant messages
+
+ client.OnInstantMessage += OnInstantMessage;
+ client.OnApproveFriendRequest += OnApprovedFriendRequest;
+ client.OnDenyFriendRequest += OnDenyFriendRequest;
+ client.OnTerminateFriendship += OnTerminateFriendship;
+
+ List fl = new List();
+
+ //bool addFLback = false;
+
+ lock (FriendLists)
+ {
+ if (FriendLists.ContainsKey(client.AgentId))
+ {
+ fl = FriendLists[client.AgentId];
+ }
+ else
+ {
+ fl = m_scene[0].GetFriendList(client.AgentId);
+
+ //lock (FriendLists)
+ //{
+ if (!FriendLists.ContainsKey(client.AgentId))
+ FriendLists.Add(client.AgentId, fl);
+ //}
+ }
+ }
+
+ List UpdateUsers = new List();
+
+ foreach (FriendListItem f in fl)
+ {
+ if (m_rootAgents.ContainsKey(f.Friend))
+ {
+ if (f.onlinestatus == false)
+ {
+ UpdateUsers.Add(f.Friend);
+ f.onlinestatus = true;
+ }
+ }
+ }
+ foreach (LLUUID user in UpdateUsers)
+ {
+ ScenePresence av = GetPresenceFromAgentID(user);
+ if (av != null)
+ {
+ List usrfl = new List();
+
+ lock (FriendLists)
+ {
+ usrfl = FriendLists[user];
+ }
+
+ lock (usrfl)
+ {
+ foreach (FriendListItem fli in usrfl)
+ {
+ if (fli.Friend == client.AgentId)
+ {
+ fli.onlinestatus = true;
+ OnlineNotificationPacket onp = new OnlineNotificationPacket();
+ OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[1];
+ OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock();
+ onpbl.AgentID = client.AgentId;
+ onpb[0] = onpbl;
+ onp.AgentBlock = onpb;
+ av.ControllingClient.OutPacket(onp, ThrottleOutPacketType.Task);
+ }
+ }
+ }
+ }
+ }
+
+ if (UpdateUsers.Count > 0)
+ {
+ OnlineNotificationPacket onp = new OnlineNotificationPacket();
+ OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[UpdateUsers.Count];
+ for (int i = 0; i < UpdateUsers.Count; i++)
+ {
+ OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock();
+ onpbl.AgentID = UpdateUsers[i];
+ onpb[i] = onpbl;
+ }
+ onp.AgentBlock = onpb;
+ client.OutPacket(onp, ThrottleOutPacketType.Task);
+ }
+ }
+
+ private void ClientLoggedOut(LLUUID AgentId)
+ {
+ lock (m_rootAgents)
+ {
+ if (m_rootAgents.ContainsKey(AgentId))
+ {
+ m_rootAgents.Remove(AgentId);
+ m_log.Info("[FRIEND]: Removing " + AgentId + ". Agent logged out.");
+ }
+ }
+ List lfli = new List();
+ lock (FriendLists)
+ {
+ if (FriendLists.ContainsKey(AgentId))
+ {
+ lfli = FriendLists[AgentId];
+ }
+ }
+ List updateUsers = new List();
+ foreach (FriendListItem fli in lfli)
+ {
+ if (fli.onlinestatus == true)
+ {
+ updateUsers.Add(fli.Friend);
+ }
+ }
+ lock (updateUsers)
+ {
+ for (int i = 0; i < updateUsers.Count; i++)
+ {
+ List flfli = new List();
+ try
+ {
+ lock (FriendLists)
+ {
+ if (FriendLists.ContainsKey(updateUsers[i]))
+ flfli = FriendLists[updateUsers[i]];
+ }
+ }
+ catch (IndexOutOfRangeException)
+ {
+ // Ignore the index out of range exception.
+ // This causes friend lists to get out of sync slightly.. however
+ // prevents a sim crash.
+ m_log.Info("[FRIEND]: Unable to enumerate last friendlist user. User logged off");
+ }
+
+ for (int j = 0; j < flfli.Count; j++)
+ {
+ try
+ {
+ if (flfli[i].Friend == AgentId)
+ {
+ flfli[i].onlinestatus = false;
+ }
+ }
+
+ catch (IndexOutOfRangeException)
+ {
+ // Ignore the index out of range exception.
+ // This causes friend lists to get out of sync slightly.. however
+ // prevents a sim crash.
+ m_log.Info("[FRIEND]: Unable to enumerate last friendlist user. User logged off");
+ }
+ }
+ }
+
+ for (int i = 0; i < updateUsers.Count; i++)
+ {
+ ScenePresence av = GetPresenceFromAgentID(updateUsers[i]);
+ if (av != null)
+ {
+ OfflineNotificationPacket onp = new OfflineNotificationPacket();
+ OfflineNotificationPacket.AgentBlockBlock[] onpb = new OfflineNotificationPacket.AgentBlockBlock[1];
+ OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock();
+ onpbl.AgentID = AgentId;
+ onpb[0] = onpbl;
+ onp.AgentBlock = onpb;
+ av.ControllingClient.OutPacket(onp, ThrottleOutPacketType.Task);
+ }
+ }
+ }
+ lock (FriendLists)
+ {
+ FriendLists.Remove(AgentId);
+ }
+ }
+
+ private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID)
+ {
+ lock (m_rootAgents)
+ {
+ if (m_rootAgents.ContainsKey(avatar.UUID))
+ {
+ if (avatar.RegionHandle != m_rootAgents[avatar.UUID])
+ {
+ m_rootAgents[avatar.UUID] = avatar.RegionHandle;
+ m_log.Info("[FRIEND]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + ".");
+ if (avatar.JID.Length > 0)
+ {
+ JId avatarID = new JId(avatar.JID);
+ // REST Post XMPP Stanzas!
+ }
+ // Claim User! my user! Mine mine mine!
+ }
+ }
+ else
+ {
+ m_rootAgents.Add(avatar.UUID, avatar.RegionHandle);
+ m_log.Info("[FRIEND]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + ".");
+ }
+ }
+ //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString());
+ }
+
+ private void MakeChildAgent(ScenePresence avatar)
+ {
+ lock (m_rootAgents)
+ {
+ if (m_rootAgents.ContainsKey(avatar.UUID))
+ {
+ if (m_rootAgents[avatar.UUID] == avatar.RegionHandle)
+ {
+ m_rootAgents.Remove(avatar.UUID);
+ m_log.Info("[FRIEND]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent");
+ }
+ }
+ }
+ }
+
+ private ScenePresence GetPresenceFromAgentID(LLUUID AgentID)
+ {
+ ScenePresence returnAgent = null;
+ lock (m_scene)
+ {
+ ScenePresence queryagent = null;
+ for (int i = 0; i < m_scene.Count; i++)
+ {
+ queryagent = m_scene[i].GetScenePresence(AgentID);
+ if (queryagent != null)
+ {
+ if (!queryagent.IsChildAgent)
+ {
+ returnAgent = queryagent;
+ break;
+ }
+ }
+ }
+ }
+ return returnAgent;
+ }
+
+ #region FriendRequestHandling
+
+ private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
+ LLUUID fromAgentSession, LLUUID toAgentID,
+ LLUUID imSessionID, uint timestamp, string fromAgentName,
+ string message, byte dialog, bool fromGroup, byte offline,
+ uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
+ byte[] binaryBucket)
+ {
+ // Friend Requests go by Instant Message.. using the dialog param
+ // https://wiki.secondlife.com/wiki/ImprovedInstantMessage
+
+ // 38 == Offer friendship
+ if (dialog == (byte) 38)
+ {
+ LLUUID friendTransactionID = LLUUID.Random();
+
+ m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
+
+ m_log.Info("[FRIEND]: 38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" +
+ message);
+ GridInstantMessage msg = new GridInstantMessage();
+ msg.fromAgentID = fromAgentID.UUID;
+ msg.fromAgentSession = fromAgentSession.UUID;
+ msg.toAgentID = toAgentID.UUID;
+ msg.imSessionID = friendTransactionID.UUID; // This is the item we're mucking with here
+ m_log.Info("[FRIEND]: Filling Session: " + msg.imSessionID.ToString());
+ msg.timestamp = timestamp;
+ if (client != null)
+ {
+ msg.fromAgentName = client.FirstName + " " + client.LastName; // fromAgentName;
+ }
+ else
+ {
+ msg.fromAgentName = "(hippos)"; // Added for posterity. This means that we can't figure out who sent it
+ }
+ msg.message = message;
+ msg.dialog = dialog;
+ msg.fromGroup = fromGroup;
+ msg.offline = offline;
+ msg.ParentEstateID = ParentEstateID;
+ msg.Position = new sLLVector3(Position);
+ msg.RegionID = RegionID.UUID;
+ msg.binaryBucket = binaryBucket;
+ // We don't really care which scene we pipe it through.
+ m_scene[0].TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
+ }
+
+ // 39 == Accept Friendship
+ if (dialog == (byte) 39)
+ {
+ m_log.Info("[FRIEND]: 39 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" +
+ message);
+ }
+
+ // 40 == Decline Friendship
+ if (dialog == (byte) 40)
+ {
+ m_log.Info("[FRIEND]: 40 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" +
+ message);
+ }
+ }
+
+ private void OnApprovedFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List callingCardFolders)
+ {
+ if (m_pendingFriendRequests.ContainsKey(transactionID))
+ {
+ // Found Pending Friend Request with that Transaction..
+ Scene SceneAgentIn = m_scene[0];
+
+ // Found Pending Friend Request with that Transaction..
+ ScenePresence agentpresence = GetPresenceFromAgentID(agentID);
+ if (agentpresence != null)
+ {
+ SceneAgentIn = agentpresence.Scene;
+ }
+
+ // Compose response to other agent.
+ GridInstantMessage msg = new GridInstantMessage();
+ msg.toAgentID = m_pendingFriendRequests[transactionID].UUID;
+ msg.fromAgentID = agentID.UUID;
+ msg.fromAgentName = client.FirstName + " " + client.LastName;
+ msg.fromAgentSession = client.SessionId.UUID;
+ msg.fromGroup = false;
+ msg.imSessionID = transactionID.UUID;
+ msg.message = agentID.UUID.ToString();
+ msg.ParentEstateID = 0;
+ msg.timestamp = (uint) Util.UnixTimeSinceEpoch();
+ msg.RegionID = SceneAgentIn.RegionInfo.RegionID.UUID;
+ msg.dialog = (byte) 39; // Approved friend request
+ msg.Position = new sLLVector3();
+ msg.offline = (byte) 0;
+ msg.binaryBucket = new byte[0];
+ // We don't really care which scene we pipe it through, it goes to the shared IM Module and/or the database
+
+ SceneAgentIn.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
+ SceneAgentIn.StoreAddFriendship(m_pendingFriendRequests[transactionID], agentID, (uint) 1);
+ m_pendingFriendRequests.Remove(transactionID);
+
+ // TODO: Inform agent that the friend is online
+ }
+ }
+
+ private void OnDenyFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List callingCardFolders)
+ {
+ if (m_pendingFriendRequests.ContainsKey(transactionID))
+ {
+ Scene SceneAgentIn = m_scene[0];
+
+ // Found Pending Friend Request with that Transaction..
+ ScenePresence agentpresence = GetPresenceFromAgentID(agentID);
+ if (agentpresence != null)
+ {
+ SceneAgentIn = agentpresence.Scene;
+ }
+ // Compose response to other agent.
+ GridInstantMessage msg = new GridInstantMessage();
+ msg.toAgentID = m_pendingFriendRequests[transactionID].UUID;
+ msg.fromAgentID = agentID.UUID;
+ msg.fromAgentName = client.FirstName + " " + client.LastName;
+ msg.fromAgentSession = client.SessionId.UUID;
+ msg.fromGroup = false;
+ msg.imSessionID = transactionID.UUID;
+ msg.message = agentID.UUID.ToString();
+ msg.ParentEstateID = 0;
+ msg.timestamp = (uint) Util.UnixTimeSinceEpoch();
+ msg.RegionID = SceneAgentIn.RegionInfo.RegionID.UUID;
+ msg.dialog = (byte) 40; // Deny friend request
+ msg.Position = new sLLVector3();
+ msg.offline = (byte) 0;
+ msg.binaryBucket = new byte[0];
+ SceneAgentIn.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
+ m_pendingFriendRequests.Remove(transactionID);
+ }
+ }
+
+ private void OnTerminateFriendship(IClientAPI client, LLUUID agent, LLUUID exfriendID)
+ {
+ m_scene[0].StoreRemoveFriendship(agent, exfriendID);
+ // TODO: Inform the client that the ExFriend is offline
+ }
+
+ private void OnGridInstantMessage(GridInstantMessage msg)
+ {
+ // Trigger the above event handler
+ OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
+ new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
+ msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
+ new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
+ msg.binaryBucket);
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs
index c4906d2..6edc44d 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs
@@ -1,273 +1,273 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using libsecondlife;
-using log4net;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Avatar.Groups
-{
- public class GroupsModule : IRegionModule
- {
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- private Dictionary m_grouplistmap = new Dictionary();
- private Dictionary m_groupmap = new Dictionary();
- private Dictionary m_iclientmap = new Dictionary();
- private List m_scene = new List();
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- lock (m_scene)
- {
- m_scene.Add(scene);
- }
- scene.EventManager.OnNewClient += OnNewClient;
- scene.EventManager.OnClientClosed += OnClientClosed;
- scene.EventManager.OnGridInstantMessageToGroupsModule += OnGridInstantMessage;
- //scene.EventManager.
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- m_log.Info("[GROUP]: Shutting down group module.");
- lock (m_iclientmap)
- {
- m_iclientmap.Clear();
- }
-
- lock (m_groupmap)
- {
- m_groupmap.Clear();
- }
-
- lock (m_grouplistmap)
- {
- m_grouplistmap.Clear();
- }
- GC.Collect();
- }
-
- public string Name
- {
- get { return "GroupsModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return true; }
- }
-
- #endregion
-
- private void OnNewClient(IClientAPI client)
- {
- // All friends establishment protocol goes over instant message
- // There's no way to send a message from the sim
- // to a user to 'add a friend' without causing dialog box spam
- //
- // The base set of friends are added when the user signs on in their XMLRPC response
- // Generated by LoginService. The friends are retreived from the database by the UserManager
-
- // Subscribe to instant messages
- client.OnInstantMessage += OnInstantMessage;
- client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
- lock (m_iclientmap)
- {
- if (!m_iclientmap.ContainsKey(client.AgentId))
- {
- m_iclientmap.Add(client.AgentId, client);
- }
- }
- GroupData OpenSimulatorGroup = new GroupData();
- OpenSimulatorGroup.ActiveGroupTitle = "OpenSimulator Tester";
- OpenSimulatorGroup.GroupID = new LLUUID("00000000-68f9-1111-024e-222222111120");
- OpenSimulatorGroup.GroupMembers.Add(client.AgentId);
- OpenSimulatorGroup.groupName = "OpenSimulator Testing";
- OpenSimulatorGroup.ActiveGroupPowers = GroupPowers.LandAllowSetHome;
- OpenSimulatorGroup.GroupTitles.Add("OpenSimulator Tester");
- lock (m_groupmap)
- {
- if (!m_groupmap.ContainsKey(client.AgentId))
- {
- m_groupmap.Add(client.AgentId, OpenSimulatorGroup);
- }
- }
- GroupList testGroupList = new GroupList();
- testGroupList.m_GroupList.Add(new LLUUID("00000000-68f9-1111-024e-222222111120"));
-
- lock (m_grouplistmap)
- {
- if (!m_grouplistmap.ContainsKey(client.AgentId))
- {
- m_grouplistmap.Add(client.AgentId, testGroupList);
- }
- }
- m_log.Info("[GROUP]: Adding " + client.FirstName + " " + client.LastName + " to OpenSimulator Tester group");
- }
-
- private void OnAgentDataUpdateRequest(IClientAPI remoteClient, LLUUID AgentID, LLUUID SessionID)
- {
- string firstname = remoteClient.FirstName;
- string lastname = remoteClient.LastName;
-
- LLUUID ActiveGroupID = LLUUID.Zero;
- uint ActiveGroupPowers = 0;
- string ActiveGroupName = "";
- string ActiveGroupTitle = "";
-
- bool foundUser = false;
-
- lock (m_iclientmap)
- {
- if (m_iclientmap.ContainsKey(remoteClient.AgentId))
- {
- foundUser = true;
- }
- }
- if (foundUser)
- {
- lock (m_groupmap)
- {
- if (m_groupmap.ContainsKey(remoteClient.AgentId))
- {
- GroupData grp = m_groupmap[remoteClient.AgentId];
- if (grp != null)
- {
- ActiveGroupID = grp.GroupID;
- ActiveGroupName = grp.groupName;
- ActiveGroupPowers = grp.groupPowers;
- ActiveGroupTitle = grp.ActiveGroupTitle;
- }
-
- //remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, lastname, ActiveGroupPowers, ActiveGroupName, ActiveGroupTitle);
- }
- }
- }
- }
-
- private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
- LLUUID fromAgentSession, LLUUID toAgentID,
- LLUUID imSessionID, uint timestamp, string fromAgentName,
- string message, byte dialog, bool fromGroup, byte offline,
- uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
- byte[] binaryBucket)
- {
- }
-
- private void OnGridInstantMessage(GridInstantMessage msg)
- {
- // Trigger the above event handler
- OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
- new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
- msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
- new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
- msg.binaryBucket);
- }
-
- private void OnClientClosed(LLUUID agentID)
- {
- lock (m_iclientmap)
- {
- if (m_iclientmap.ContainsKey(agentID))
- {
- IClientAPI cli = m_iclientmap[agentID];
- if (cli != null)
- {
- m_log.Info("[GROUP]: Removing all reference to groups for " + cli.FirstName + " " + cli.LastName);
- }
- else
- {
- m_log.Info("[GROUP]: Removing all reference to groups for " + agentID.ToString());
- }
- m_iclientmap.Remove(agentID);
- }
- }
-
- lock (m_groupmap)
- {
- if (m_groupmap.ContainsKey(agentID))
- {
- m_groupmap.Remove(agentID);
- }
- }
-
- lock (m_grouplistmap)
- {
- if (m_grouplistmap.ContainsKey(agentID))
- {
- m_grouplistmap.Remove(agentID);
- }
- }
- GC.Collect();
- }
- }
-
- public class GroupData
- {
- public string ActiveGroupTitle;
- public LLUUID GroupID;
- public List GroupMembers;
- public string groupName;
- public uint groupPowers = (uint) (GroupPowers.LandAllowLandmark | GroupPowers.LandAllowSetHome);
- public List GroupTitles;
-
- public GroupData()
- {
- GroupTitles = new List();
- GroupMembers = new List();
- }
-
- public GroupPowers ActiveGroupPowers
- {
- set { groupPowers = (uint) value; }
- get { return (GroupPowers) groupPowers; }
- }
- }
-
- public class GroupList
- {
- public List m_GroupList;
-
- public GroupList()
- {
- m_GroupList = new List();
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using libsecondlife;
+using log4net;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Avatar.Groups
+{
+ public class GroupsModule : IRegionModule
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private Dictionary m_grouplistmap = new Dictionary();
+ private Dictionary m_groupmap = new Dictionary();
+ private Dictionary m_iclientmap = new Dictionary();
+ private List m_scene = new List();
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ lock (m_scene)
+ {
+ m_scene.Add(scene);
+ }
+ scene.EventManager.OnNewClient += OnNewClient;
+ scene.EventManager.OnClientClosed += OnClientClosed;
+ scene.EventManager.OnGridInstantMessageToGroupsModule += OnGridInstantMessage;
+ //scene.EventManager.
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ m_log.Info("[GROUP]: Shutting down group module.");
+ lock (m_iclientmap)
+ {
+ m_iclientmap.Clear();
+ }
+
+ lock (m_groupmap)
+ {
+ m_groupmap.Clear();
+ }
+
+ lock (m_grouplistmap)
+ {
+ m_grouplistmap.Clear();
+ }
+ GC.Collect();
+ }
+
+ public string Name
+ {
+ get { return "GroupsModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return true; }
+ }
+
+ #endregion
+
+ private void OnNewClient(IClientAPI client)
+ {
+ // All friends establishment protocol goes over instant message
+ // There's no way to send a message from the sim
+ // to a user to 'add a friend' without causing dialog box spam
+ //
+ // The base set of friends are added when the user signs on in their XMLRPC response
+ // Generated by LoginService. The friends are retreived from the database by the UserManager
+
+ // Subscribe to instant messages
+ client.OnInstantMessage += OnInstantMessage;
+ client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
+ lock (m_iclientmap)
+ {
+ if (!m_iclientmap.ContainsKey(client.AgentId))
+ {
+ m_iclientmap.Add(client.AgentId, client);
+ }
+ }
+ GroupData OpenSimulatorGroup = new GroupData();
+ OpenSimulatorGroup.ActiveGroupTitle = "OpenSimulator Tester";
+ OpenSimulatorGroup.GroupID = new LLUUID("00000000-68f9-1111-024e-222222111120");
+ OpenSimulatorGroup.GroupMembers.Add(client.AgentId);
+ OpenSimulatorGroup.groupName = "OpenSimulator Testing";
+ OpenSimulatorGroup.ActiveGroupPowers = GroupPowers.LandAllowSetHome;
+ OpenSimulatorGroup.GroupTitles.Add("OpenSimulator Tester");
+ lock (m_groupmap)
+ {
+ if (!m_groupmap.ContainsKey(client.AgentId))
+ {
+ m_groupmap.Add(client.AgentId, OpenSimulatorGroup);
+ }
+ }
+ GroupList testGroupList = new GroupList();
+ testGroupList.m_GroupList.Add(new LLUUID("00000000-68f9-1111-024e-222222111120"));
+
+ lock (m_grouplistmap)
+ {
+ if (!m_grouplistmap.ContainsKey(client.AgentId))
+ {
+ m_grouplistmap.Add(client.AgentId, testGroupList);
+ }
+ }
+ m_log.Info("[GROUP]: Adding " + client.FirstName + " " + client.LastName + " to OpenSimulator Tester group");
+ }
+
+ private void OnAgentDataUpdateRequest(IClientAPI remoteClient, LLUUID AgentID, LLUUID SessionID)
+ {
+ string firstname = remoteClient.FirstName;
+ string lastname = remoteClient.LastName;
+
+ LLUUID ActiveGroupID = LLUUID.Zero;
+ uint ActiveGroupPowers = 0;
+ string ActiveGroupName = "";
+ string ActiveGroupTitle = "";
+
+ bool foundUser = false;
+
+ lock (m_iclientmap)
+ {
+ if (m_iclientmap.ContainsKey(remoteClient.AgentId))
+ {
+ foundUser = true;
+ }
+ }
+ if (foundUser)
+ {
+ lock (m_groupmap)
+ {
+ if (m_groupmap.ContainsKey(remoteClient.AgentId))
+ {
+ GroupData grp = m_groupmap[remoteClient.AgentId];
+ if (grp != null)
+ {
+ ActiveGroupID = grp.GroupID;
+ ActiveGroupName = grp.groupName;
+ ActiveGroupPowers = grp.groupPowers;
+ ActiveGroupTitle = grp.ActiveGroupTitle;
+ }
+
+ //remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, lastname, ActiveGroupPowers, ActiveGroupName, ActiveGroupTitle);
+ }
+ }
+ }
+ }
+
+ private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
+ LLUUID fromAgentSession, LLUUID toAgentID,
+ LLUUID imSessionID, uint timestamp, string fromAgentName,
+ string message, byte dialog, bool fromGroup, byte offline,
+ uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
+ byte[] binaryBucket)
+ {
+ }
+
+ private void OnGridInstantMessage(GridInstantMessage msg)
+ {
+ // Trigger the above event handler
+ OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
+ new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
+ msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
+ new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
+ msg.binaryBucket);
+ }
+
+ private void OnClientClosed(LLUUID agentID)
+ {
+ lock (m_iclientmap)
+ {
+ if (m_iclientmap.ContainsKey(agentID))
+ {
+ IClientAPI cli = m_iclientmap[agentID];
+ if (cli != null)
+ {
+ m_log.Info("[GROUP]: Removing all reference to groups for " + cli.FirstName + " " + cli.LastName);
+ }
+ else
+ {
+ m_log.Info("[GROUP]: Removing all reference to groups for " + agentID.ToString());
+ }
+ m_iclientmap.Remove(agentID);
+ }
+ }
+
+ lock (m_groupmap)
+ {
+ if (m_groupmap.ContainsKey(agentID))
+ {
+ m_groupmap.Remove(agentID);
+ }
+ }
+
+ lock (m_grouplistmap)
+ {
+ if (m_grouplistmap.ContainsKey(agentID))
+ {
+ m_grouplistmap.Remove(agentID);
+ }
+ }
+ GC.Collect();
+ }
+ }
+
+ public class GroupData
+ {
+ public string ActiveGroupTitle;
+ public LLUUID GroupID;
+ public List GroupMembers;
+ public string groupName;
+ public uint groupPowers = (uint) (GroupPowers.LandAllowLandmark | GroupPowers.LandAllowSetHome);
+ public List GroupTitles;
+
+ public GroupData()
+ {
+ GroupTitles = new List();
+ GroupMembers = new List();
+ }
+
+ public GroupPowers ActiveGroupPowers
+ {
+ set { groupPowers = (uint) value; }
+ get { return (GroupPowers) groupPowers; }
+ }
+ }
+
+ public class GroupList
+ {
+ public List m_GroupList;
+
+ public GroupList()
+ {
+ m_GroupList = new List();
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs
index cb58b4c..26586a5 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -1,158 +1,158 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System.Collections.Generic;
-using libsecondlife;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
-{
- public class InstantMessageModule : IRegionModule
- {
- private readonly List m_scenes = new List();
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- lock (m_scenes)
- {
- if (m_scenes.Count == 0)
- {
- //scene.AddXmlRPCHandler("avatar_location_update", processPresenceUpdate);
- }
-
- if (!m_scenes.Contains(scene))
- {
- m_scenes.Add(scene);
- scene.EventManager.OnNewClient += OnNewClient;
- scene.EventManager.OnGridInstantMessageToIMModule += OnGridInstantMessage;
- }
- }
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "InstantMessageModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return true; }
- }
-
- #endregion
-
- private void OnNewClient(IClientAPI client)
- {
- client.OnInstantMessage += OnInstantMessage;
- }
-
- private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
- LLUUID fromAgentSession, LLUUID toAgentID,
- LLUUID imSessionID, uint timestamp, string fromAgentName,
- string message, byte dialog, bool fromGroup, byte offline,
- uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
- byte[] binaryBucket)
- {
- bool dialogHandledElsewhere
- = ((dialog == 38) || (dialog == 39) || (dialog == 40)
- || dialog == (byte) InstantMessageDialog.InventoryOffered
- || dialog == (byte) InstantMessageDialog.InventoryAccepted
- || dialog == (byte) InstantMessageDialog.InventoryDeclined);
-
- // IM dialogs need to be pre-processed and have their sessionID filled by the server
- // so the sim can match the transaction on the return packet.
-
- // Don't send a Friend Dialog IM with a LLUUID.Zero session.
- if (!(dialogHandledElsewhere && imSessionID == LLUUID.Zero))
- {
- // Try root avatar only first
- foreach (Scene scene in m_scenes)
- {
- if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence)
- {
- // Local message
- ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
- if (!user.IsChildAgent)
- {
- user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message,
- toAgentID, imSessionID, fromAgentName, dialog,
- timestamp);
- // Message sent
- return;
- }
- }
- }
-
- // try child avatar second
- foreach (Scene scene in m_scenes)
- {
- if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence)
- {
- // Local message
- ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
-
- user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message,
- toAgentID, imSessionID, fromAgentName, dialog,
- timestamp);
- // Message sent
- return;
- }
- }
- }
-
-
- // Still here, try send via Grid
- // TODO
- }
-
- // Trusty OSG1 called method. This method also gets called from the FriendsModule
- // Turns out the sim has to send an instant message to the user to get it to show an accepted friend.
-
- private void OnGridInstantMessage(GridInstantMessage msg)
- {
- // Trigger the above event handler
- OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
- new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
- msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
- new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
- msg.binaryBucket);
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.Collections.Generic;
+using libsecondlife;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
+{
+ public class InstantMessageModule : IRegionModule
+ {
+ private readonly List m_scenes = new List();
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ lock (m_scenes)
+ {
+ if (m_scenes.Count == 0)
+ {
+ //scene.AddXmlRPCHandler("avatar_location_update", processPresenceUpdate);
+ }
+
+ if (!m_scenes.Contains(scene))
+ {
+ m_scenes.Add(scene);
+ scene.EventManager.OnNewClient += OnNewClient;
+ scene.EventManager.OnGridInstantMessageToIMModule += OnGridInstantMessage;
+ }
+ }
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "InstantMessageModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return true; }
+ }
+
+ #endregion
+
+ private void OnNewClient(IClientAPI client)
+ {
+ client.OnInstantMessage += OnInstantMessage;
+ }
+
+ private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
+ LLUUID fromAgentSession, LLUUID toAgentID,
+ LLUUID imSessionID, uint timestamp, string fromAgentName,
+ string message, byte dialog, bool fromGroup, byte offline,
+ uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
+ byte[] binaryBucket)
+ {
+ bool dialogHandledElsewhere
+ = ((dialog == 38) || (dialog == 39) || (dialog == 40)
+ || dialog == (byte) InstantMessageDialog.InventoryOffered
+ || dialog == (byte) InstantMessageDialog.InventoryAccepted
+ || dialog == (byte) InstantMessageDialog.InventoryDeclined);
+
+ // IM dialogs need to be pre-processed and have their sessionID filled by the server
+ // so the sim can match the transaction on the return packet.
+
+ // Don't send a Friend Dialog IM with a LLUUID.Zero session.
+ if (!(dialogHandledElsewhere && imSessionID == LLUUID.Zero))
+ {
+ // Try root avatar only first
+ foreach (Scene scene in m_scenes)
+ {
+ if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence)
+ {
+ // Local message
+ ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
+ if (!user.IsChildAgent)
+ {
+ user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message,
+ toAgentID, imSessionID, fromAgentName, dialog,
+ timestamp);
+ // Message sent
+ return;
+ }
+ }
+ }
+
+ // try child avatar second
+ foreach (Scene scene in m_scenes)
+ {
+ if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence)
+ {
+ // Local message
+ ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
+
+ user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message,
+ toAgentID, imSessionID, fromAgentName, dialog,
+ timestamp);
+ // Message sent
+ return;
+ }
+ }
+ }
+
+
+ // Still here, try send via Grid
+ // TODO
+ }
+
+ // Trusty OSG1 called method. This method also gets called from the FriendsModule
+ // Turns out the sim has to send an instant message to the user to get it to show an accepted friend.
+
+ private void OnGridInstantMessage(GridInstantMessage msg)
+ {
+ // Trigger the above event handler
+ OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
+ new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
+ msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
+ new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
+ msg.binaryBucket);
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/InventoryModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/InventoryModule.cs
index 2844450..624f307 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/InventoryModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Inventory/InventoryModule.cs
@@ -1,220 +1,220 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System.Collections.Generic;
-using System.Reflection;
-using libsecondlife;
-using log4net;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Avatar.Inventory
-{
- public class InventoryModule : IRegionModule
- {
- private static readonly ILog m_log
- = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- ///
- /// We need to keep track of the pending item offers between clients since the itemId offered only
- /// occurs in the initial offer message, not the accept message. So this dictionary links
- /// IM Session Ids to ItemIds
- ///
- private IDictionary m_pendingOffers = new Dictionary();
-
- private Scene m_scene;
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- m_scene = scene;
- scene.EventManager.OnNewClient += OnNewClient;
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "InventoryModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return false; }
- }
-
- #endregion
-
- private void OnNewClient(IClientAPI client)
- {
- // Inventory giving is conducted via instant message
- client.OnInstantMessage += OnInstantMessage;
- }
-
- private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
- LLUUID fromAgentSession, LLUUID toAgentID,
- LLUUID imSessionID, uint timestamp, string fromAgentName,
- string message, byte dialog, bool fromGroup, byte offline,
- uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
- byte[] binaryBucket)
- {
- if (dialog == (byte) InstantMessageDialog.InventoryOffered)
- {
- m_log.DebugFormat(
- "[AGENT INVENTORY]: Routing inventory offering message from {0}, {1} to {2}",
- client.AgentId, client.Name, toAgentID);
-
- if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence)
- {
- ScenePresence user = (ScenePresence) m_scene.Entities[toAgentID];
-
- if (!user.IsChildAgent)
- {
- //byte[] rawId = new byte[16];
-
- // First byte of the array is probably the item type
- // Next 16 bytes are the UUID
- //Array.Copy(binaryBucket, 1, rawId, 0, 16);
-
- //LLUUID itemId = new LLUUID(new Guid(rawId));
- LLUUID itemId = new LLUUID(binaryBucket, 1);
-
- m_log.DebugFormat(
- "[AGENT INVENTORY]: ItemId for giving is {0}", itemId);
-
- m_pendingOffers[imSessionID] = itemId;
-
- user.ControllingClient.SendInstantMessage(
- fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
- dialog, timestamp, binaryBucket);
-
- return;
- }
- else
- {
- m_log.WarnFormat(
- "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!",
- toAgentID, client.AgentId, client.Name, message);
- }
- }
- else
- {
- m_log.WarnFormat(
- "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}",
- toAgentID, client.AgentId, client.Name, message);
- }
- }
- else if (dialog == (byte) InstantMessageDialog.InventoryAccepted)
- {
- m_log.DebugFormat(
- "[AGENT INVENTORY]: Routing inventory accepted message from {0}, {1} to {2}",
- client.AgentId, client.Name, toAgentID);
-
- if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence)
- {
- ScenePresence user = (ScenePresence) m_scene.Entities[toAgentID];
-
- if (!user.IsChildAgent)
- {
- user.ControllingClient.SendInstantMessage(
- fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
- dialog, timestamp, binaryBucket);
-
- if (m_pendingOffers.ContainsKey(imSessionID))
- {
- m_log.DebugFormat(
- "[AGENT INVENTORY]: Accepted item id {0}", m_pendingOffers[imSessionID]);
-
- // Since the message originates from the accepting client, the toAgentID is
- // the agent giving the item.
- m_scene.GiveInventoryItem(client, toAgentID, m_pendingOffers[imSessionID]);
-
- m_pendingOffers.Remove(imSessionID);
- }
- else
- {
- m_log.ErrorFormat(
- "[AGENT INVENTORY]: Could not find an item associated with session id {0} to accept",
- imSessionID);
- }
-
- return;
- }
- else
- {
- m_log.WarnFormat(
- "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!",
- toAgentID, client.AgentId, client.Name, message);
- }
- }
- else
- {
- m_log.WarnFormat(
- "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}",
- toAgentID, client.AgentId, client.Name, message);
- }
- }
- else if (dialog == (byte) InstantMessageDialog.InventoryDeclined)
- {
- if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence)
- {
- ScenePresence user = (ScenePresence) m_scene.Entities[toAgentID];
-
- if (!user.IsChildAgent)
- {
- user.ControllingClient.SendInstantMessage(
- fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
- dialog, timestamp, binaryBucket);
-
- if (m_pendingOffers.ContainsKey(imSessionID))
- {
- m_log.DebugFormat(
- "[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]);
-
- m_pendingOffers.Remove(imSessionID);
- }
- else
- {
- m_log.ErrorFormat(
- "[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline",
- imSessionID);
- }
- }
- }
- }
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.Collections.Generic;
+using System.Reflection;
+using libsecondlife;
+using log4net;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Avatar.Inventory
+{
+ public class InventoryModule : IRegionModule
+ {
+ private static readonly ILog m_log
+ = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ ///
+ /// We need to keep track of the pending item offers between clients since the itemId offered only
+ /// occurs in the initial offer message, not the accept message. So this dictionary links
+ /// IM Session Ids to ItemIds
+ ///
+ private IDictionary m_pendingOffers = new Dictionary();
+
+ private Scene m_scene;
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ m_scene = scene;
+ scene.EventManager.OnNewClient += OnNewClient;
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "InventoryModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return false; }
+ }
+
+ #endregion
+
+ private void OnNewClient(IClientAPI client)
+ {
+ // Inventory giving is conducted via instant message
+ client.OnInstantMessage += OnInstantMessage;
+ }
+
+ private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
+ LLUUID fromAgentSession, LLUUID toAgentID,
+ LLUUID imSessionID, uint timestamp, string fromAgentName,
+ string message, byte dialog, bool fromGroup, byte offline,
+ uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
+ byte[] binaryBucket)
+ {
+ if (dialog == (byte) InstantMessageDialog.InventoryOffered)
+ {
+ m_log.DebugFormat(
+ "[AGENT INVENTORY]: Routing inventory offering message from {0}, {1} to {2}",
+ client.AgentId, client.Name, toAgentID);
+
+ if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence)
+ {
+ ScenePresence user = (ScenePresence) m_scene.Entities[toAgentID];
+
+ if (!user.IsChildAgent)
+ {
+ //byte[] rawId = new byte[16];
+
+ // First byte of the array is probably the item type
+ // Next 16 bytes are the UUID
+ //Array.Copy(binaryBucket, 1, rawId, 0, 16);
+
+ //LLUUID itemId = new LLUUID(new Guid(rawId));
+ LLUUID itemId = new LLUUID(binaryBucket, 1);
+
+ m_log.DebugFormat(
+ "[AGENT INVENTORY]: ItemId for giving is {0}", itemId);
+
+ m_pendingOffers[imSessionID] = itemId;
+
+ user.ControllingClient.SendInstantMessage(
+ fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
+ dialog, timestamp, binaryBucket);
+
+ return;
+ }
+ else
+ {
+ m_log.WarnFormat(
+ "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!",
+ toAgentID, client.AgentId, client.Name, message);
+ }
+ }
+ else
+ {
+ m_log.WarnFormat(
+ "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}",
+ toAgentID, client.AgentId, client.Name, message);
+ }
+ }
+ else if (dialog == (byte) InstantMessageDialog.InventoryAccepted)
+ {
+ m_log.DebugFormat(
+ "[AGENT INVENTORY]: Routing inventory accepted message from {0}, {1} to {2}",
+ client.AgentId, client.Name, toAgentID);
+
+ if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence)
+ {
+ ScenePresence user = (ScenePresence) m_scene.Entities[toAgentID];
+
+ if (!user.IsChildAgent)
+ {
+ user.ControllingClient.SendInstantMessage(
+ fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
+ dialog, timestamp, binaryBucket);
+
+ if (m_pendingOffers.ContainsKey(imSessionID))
+ {
+ m_log.DebugFormat(
+ "[AGENT INVENTORY]: Accepted item id {0}", m_pendingOffers[imSessionID]);
+
+ // Since the message originates from the accepting client, the toAgentID is
+ // the agent giving the item.
+ m_scene.GiveInventoryItem(client, toAgentID, m_pendingOffers[imSessionID]);
+
+ m_pendingOffers.Remove(imSessionID);
+ }
+ else
+ {
+ m_log.ErrorFormat(
+ "[AGENT INVENTORY]: Could not find an item associated with session id {0} to accept",
+ imSessionID);
+ }
+
+ return;
+ }
+ else
+ {
+ m_log.WarnFormat(
+ "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!",
+ toAgentID, client.AgentId, client.Name, message);
+ }
+ }
+ else
+ {
+ m_log.WarnFormat(
+ "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}",
+ toAgentID, client.AgentId, client.Name, message);
+ }
+ }
+ else if (dialog == (byte) InstantMessageDialog.InventoryDeclined)
+ {
+ if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence)
+ {
+ ScenePresence user = (ScenePresence) m_scene.Entities[toAgentID];
+
+ if (!user.IsChildAgent)
+ {
+ user.ControllingClient.SendInstantMessage(
+ fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
+ dialog, timestamp, binaryBucket);
+
+ if (m_pendingOffers.ContainsKey(imSessionID))
+ {
+ m_log.DebugFormat(
+ "[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]);
+
+ m_pendingOffers.Remove(imSessionID);
+ }
+ else
+ {
+ m_log.ErrorFormat(
+ "[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline",
+ imSessionID);
+ }
+ }
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs
index 1955d2a..15825b6 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs
@@ -1,133 +1,133 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Reflection;
-using libsecondlife;
-using log4net;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-
-namespace OpenSim.Region.Environment.Modules.Avatar.Profiles
-{
- public class AvatarProfilesModule : IRegionModule
- {
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private Scene m_scene;
-
- public AvatarProfilesModule()
- {
- }
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- m_scene = scene;
- m_scene.EventManager.OnNewClient += NewClient;
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "AvatarProfilesModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return false; }
- }
-
- #endregion
-
- public void NewClient(IClientAPI client)
- {
- client.OnRequestAvatarProperties += RequestAvatarProperty;
- client.OnUpdateAvatarProperties += UpdateAvatarProperties;
- }
-
- public void RemoveClient(IClientAPI client)
- {
- client.OnRequestAvatarProperties -= RequestAvatarProperty;
- client.OnUpdateAvatarProperties -= UpdateAvatarProperties;
- }
-
- ///
- ///
- ///
- ///
- ///
- public void RequestAvatarProperty(IClientAPI remoteClient, LLUUID avatarID)
- {
- // FIXME: finish adding fields such as url, masking, etc.
- LLUUID partner = new LLUUID("11111111-1111-0000-0000-000100bba000");
- UserProfileData profile = m_scene.CommsManager.UserService.GetUserProfile(avatarID);
- if (null != profile)
- {
- remoteClient.SendAvatarProperties(profile.ID, profile.AboutText,
- Util.ToDateTime(profile.Created).ToString(),
- String.Empty, profile.FirstLifeAboutText, profile.CanDoMask,
- profile.FirstLifeImage, profile.Image, String.Empty, partner);
- }
- else
- {
- m_log.Debug("[AvatarProfilesModule]: Got null for profile for " + avatarID.ToString());
- }
- }
-
- public void UpdateAvatarProperties(IClientAPI remoteClient, UserProfileData newProfile)
- {
- UserProfileData Profile = m_scene.CommsManager.UserService.GetUserProfile(newProfile.ID);
-
- // if it's the profile of the user requesting the update, then we change only a few things.
- if (remoteClient.AgentId.CompareTo(Profile.ID) == 0)
- {
- Profile.Image = newProfile.Image;
- Profile.FirstLifeImage = newProfile.FirstLifeImage;
- Profile.AboutText = newProfile.AboutText;
- Profile.FirstLifeAboutText = newProfile.FirstLifeAboutText;
- }
- else
- {
- return;
- }
- if (m_scene.CommsManager.UserService.UpdateUserProfileProperties(Profile))
- {
- RequestAvatarProperty(remoteClient, newProfile.ID);
- }
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Reflection;
+using libsecondlife;
+using log4net;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Avatar.Profiles
+{
+ public class AvatarProfilesModule : IRegionModule
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private Scene m_scene;
+
+ public AvatarProfilesModule()
+ {
+ }
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ m_scene = scene;
+ m_scene.EventManager.OnNewClient += NewClient;
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "AvatarProfilesModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return false; }
+ }
+
+ #endregion
+
+ public void NewClient(IClientAPI client)
+ {
+ client.OnRequestAvatarProperties += RequestAvatarProperty;
+ client.OnUpdateAvatarProperties += UpdateAvatarProperties;
+ }
+
+ public void RemoveClient(IClientAPI client)
+ {
+ client.OnRequestAvatarProperties -= RequestAvatarProperty;
+ client.OnUpdateAvatarProperties -= UpdateAvatarProperties;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void RequestAvatarProperty(IClientAPI remoteClient, LLUUID avatarID)
+ {
+ // FIXME: finish adding fields such as url, masking, etc.
+ LLUUID partner = new LLUUID("11111111-1111-0000-0000-000100bba000");
+ UserProfileData profile = m_scene.CommsManager.UserService.GetUserProfile(avatarID);
+ if (null != profile)
+ {
+ remoteClient.SendAvatarProperties(profile.ID, profile.AboutText,
+ Util.ToDateTime(profile.Created).ToString(),
+ String.Empty, profile.FirstLifeAboutText, profile.CanDoMask,
+ profile.FirstLifeImage, profile.Image, String.Empty, partner);
+ }
+ else
+ {
+ m_log.Debug("[AvatarProfilesModule]: Got null for profile for " + avatarID.ToString());
+ }
+ }
+
+ public void UpdateAvatarProperties(IClientAPI remoteClient, UserProfileData newProfile)
+ {
+ UserProfileData Profile = m_scene.CommsManager.UserService.GetUserProfile(newProfile.ID);
+
+ // if it's the profile of the user requesting the update, then we change only a few things.
+ if (remoteClient.AgentId.CompareTo(Profile.ID) == 0)
+ {
+ Profile.Image = newProfile.Image;
+ Profile.FirstLifeImage = newProfile.FirstLifeImage;
+ Profile.AboutText = newProfile.AboutText;
+ Profile.FirstLifeAboutText = newProfile.FirstLifeAboutText;
+ }
+ else
+ {
+ return;
+ }
+ if (m_scene.CommsManager.UserService.UpdateUserProfileProperties(Profile))
+ {
+ RequestAvatarProperty(remoteClient, newProfile.ID);
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs
index 44d67e6..f8f6ec2 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs
@@ -1,290 +1,290 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections;
-using System.Reflection;
-using libsecondlife;
-using log4net;
-using Nini.Config;
-using Nwc.XmlRpc;
-using OpenSim.Framework;
-using OpenSim.Framework.Communications.Cache;
-using OpenSim.Framework.Servers;
-using OpenSim.Region.Capabilities;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-using Caps=OpenSim.Region.Capabilities.Caps;
-
-namespace OpenSim.Region.Environment.Modules.Avatar.Voice.AsterixVoice
-{
- public class AsteriskVoiceModule : IRegionModule
- {
- private static readonly ILog m_log =
- LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- private static readonly string m_parcelVoiceInfoRequestPath = "0007/";
- private static readonly string m_provisionVoiceAccountRequestPath = "0008/";
-
- private string m_asterisk;
- private string m_asterisk_password;
- private string m_asterisk_salt;
- private int m_asterisk_timeout;
- private string m_confDomain;
- private IConfig m_config;
- private Scene m_scene;
- private string m_sipDomain;
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- m_scene = scene;
- m_config = config.Configs["AsteriskVoice"];
-
- if (null == m_config)
- {
- m_log.Info("[ASTERISKVOICE] no config found, plugin disabled");
- return;
- }
-
- if (!m_config.GetBoolean("enabled", false))
- {
- m_log.Info("[ASTERISKVOICE] plugin disabled by configuration");
- return;
- }
- m_log.Info("[ASTERISKVOICE] plugin enabled");
-
- try
- {
- m_sipDomain = m_config.GetString("sip_domain", String.Empty);
- m_log.InfoFormat("[ASTERISKVOICE] using SIP domain {0}", m_sipDomain);
-
- m_confDomain = m_config.GetString("conf_domain", String.Empty);
- m_log.InfoFormat("[ASTERISKVOICE] using conf domain {0}", m_confDomain);
-
- m_asterisk = m_config.GetString("asterisk_frontend", String.Empty);
- m_asterisk_password = m_config.GetString("asterisk_password", String.Empty);
- m_asterisk_timeout = m_config.GetInt("asterisk_timeout", 3000);
- m_asterisk_salt = m_config.GetString("asterisk_salt", "Wuffwuff");
- if (String.IsNullOrEmpty(m_asterisk)) throw new Exception("missing asterisk_frontend config parameter");
- if (String.IsNullOrEmpty(m_asterisk_password)) throw new Exception("missing asterisk_password config parameter");
- m_log.InfoFormat("[ASTERISKVOICE] using asterisk front end {0}", m_asterisk);
-
- scene.EventManager.OnRegisterCaps += OnRegisterCaps;
- }
- catch (Exception e)
- {
- m_log.ErrorFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.Message);
- m_log.DebugFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.ToString());
- return;
- }
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "AsteriskVoiceModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return false; }
- }
-
- #endregion
-
- public void OnRegisterCaps(LLUUID agentID, Caps caps)
- {
- m_log.DebugFormat("[ASTERISKVOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
- string capsBase = "/CAPS/" + caps.CapsObjectPath;
- caps.RegisterHandler("ParcelVoiceInfoRequest",
- new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath,
- delegate(string request, string path, string param)
- {
- return ParcelVoiceInfoRequest(request, path, param,
- agentID, caps);
- }));
- caps.RegisterHandler("ProvisionVoiceAccountRequest",
- new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath,
- delegate(string request, string path, string param)
- {
- return ProvisionVoiceAccountRequest(request, path, param,
- agentID, caps);
- }));
- }
-
- ///
- /// Callback for a client request for ParcelVoiceInfo
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public string ParcelVoiceInfoRequest(string request, string path, string param,
- LLUUID agentID, Caps caps)
- {
- // we need to do:
- // - send channel_uri: as "sip:regionID@m_sipDomain"
- try
- {
- m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}",
- request, path, param);
-
-
- // setup response to client
- Hashtable creds = new Hashtable();
- creds["channel_uri"] = String.Format("sip:{0}@{1}",
- m_scene.RegionInfo.RegionID, m_sipDomain);
-
- string regionName = m_scene.RegionInfo.RegionName;
- ScenePresence avatar = m_scene.GetScenePresence(agentID);
- if (null == m_scene.LandChannel) throw new Exception("land data not yet available");
- LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
-
- LLSDParcelVoiceInfoResponse parcelVoiceInfo =
- new LLSDParcelVoiceInfoResponse(regionName, land.localID, creds);
-
- string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
-
-
- // update region on asterisk-opensim frontend
- Hashtable requestData = new Hashtable();
- requestData["admin_password"] = m_asterisk_password;
- requestData["region"] = m_scene.RegionInfo.RegionID.ToString();
- if (!String.IsNullOrEmpty(m_confDomain))
- {
- requestData["region"] += String.Format("@{0}", m_confDomain);
- }
-
- ArrayList SendParams = new ArrayList();
- SendParams.Add(requestData);
- XmlRpcRequest updateAccountRequest = new XmlRpcRequest("region_update", SendParams);
- XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout);
- Hashtable responseData = (Hashtable) updateAccountResponse.Value;
-
- if (!responseData.ContainsKey("success")) throw new Exception("region_update call failed");
-
- bool success = Convert.ToBoolean((string) responseData["success"]);
- if (!success) throw new Exception("region_update failed");
-
-
- m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: {0}", r);
- return r;
- }
- catch (Exception e)
- {
- m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0}, retry later", e.Message);
- m_log.DebugFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0} failed", e.ToString());
-
- return "undef";
- }
- }
-
- ///
- /// Callback for a client request for Voice Account Details
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public string ProvisionVoiceAccountRequest(string request, string path, string param,
- LLUUID agentID, Caps caps)
- {
- // we need to
- // - get user data from UserProfileCacheService
- // - generate nonce for user voice account password
- // - issue XmlRpc request to asterisk opensim front end:
- // + user: base 64 encoded user name (otherwise SL
- // client is unhappy)
- // + password: nonce
- // - the XmlRpc call to asteris-opensim was successful:
- // send account details back to client
- try
- {
- m_log.DebugFormat("[ASTERISKVOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
- request, path, param);
-
- // get user data & prepare voice account response
- string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes());
- voiceUser = voiceUser.Replace('+', '-').Replace('/', '_');
-
- CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
- if (null == userInfo) throw new Exception("cannot get user details");
-
- // we generate a nonce everytime
- string voicePassword = "$1$" + Util.Md5Hash(DateTime.UtcNow.ToLongTimeString() + m_asterisk_salt);
- LLSDVoiceAccountResponse voiceAccountResponse =
- new LLSDVoiceAccountResponse(voiceUser, voicePassword);
- string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
- m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r);
-
-
- // update user account on asterisk frontend
- Hashtable requestData = new Hashtable();
- requestData["admin_password"] = m_asterisk_password;
- requestData["username"] = voiceUser;
- if (!String.IsNullOrEmpty(m_sipDomain))
- {
- requestData["username"] += String.Format("@{0}", m_sipDomain);
- }
- requestData["password"] = voicePassword;
-
- ArrayList SendParams = new ArrayList();
- SendParams.Add(requestData);
- XmlRpcRequest updateAccountRequest = new XmlRpcRequest("account_update", SendParams);
- XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout);
- Hashtable responseData = (Hashtable) updateAccountResponse.Value;
-
- if (!responseData.ContainsKey("success")) throw new Exception("account_update call failed");
-
- bool success = Convert.ToBoolean((string) responseData["success"]);
- if (!success) throw new Exception("account_update failed");
-
- return r;
- }
- catch (Exception e)
- {
- m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0}, retry later", e.Message);
- m_log.DebugFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0} failed", e.ToString());
-
- return "undef";
- }
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections;
+using System.Reflection;
+using libsecondlife;
+using log4net;
+using Nini.Config;
+using Nwc.XmlRpc;
+using OpenSim.Framework;
+using OpenSim.Framework.Communications.Cache;
+using OpenSim.Framework.Servers;
+using OpenSim.Region.Capabilities;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+using Caps=OpenSim.Region.Capabilities.Caps;
+
+namespace OpenSim.Region.Environment.Modules.Avatar.Voice.AsterixVoice
+{
+ public class AsteriskVoiceModule : IRegionModule
+ {
+ private static readonly ILog m_log =
+ LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private static readonly string m_parcelVoiceInfoRequestPath = "0007/";
+ private static readonly string m_provisionVoiceAccountRequestPath = "0008/";
+
+ private string m_asterisk;
+ private string m_asterisk_password;
+ private string m_asterisk_salt;
+ private int m_asterisk_timeout;
+ private string m_confDomain;
+ private IConfig m_config;
+ private Scene m_scene;
+ private string m_sipDomain;
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ m_scene = scene;
+ m_config = config.Configs["AsteriskVoice"];
+
+ if (null == m_config)
+ {
+ m_log.Info("[ASTERISKVOICE] no config found, plugin disabled");
+ return;
+ }
+
+ if (!m_config.GetBoolean("enabled", false))
+ {
+ m_log.Info("[ASTERISKVOICE] plugin disabled by configuration");
+ return;
+ }
+ m_log.Info("[ASTERISKVOICE] plugin enabled");
+
+ try
+ {
+ m_sipDomain = m_config.GetString("sip_domain", String.Empty);
+ m_log.InfoFormat("[ASTERISKVOICE] using SIP domain {0}", m_sipDomain);
+
+ m_confDomain = m_config.GetString("conf_domain", String.Empty);
+ m_log.InfoFormat("[ASTERISKVOICE] using conf domain {0}", m_confDomain);
+
+ m_asterisk = m_config.GetString("asterisk_frontend", String.Empty);
+ m_asterisk_password = m_config.GetString("asterisk_password", String.Empty);
+ m_asterisk_timeout = m_config.GetInt("asterisk_timeout", 3000);
+ m_asterisk_salt = m_config.GetString("asterisk_salt", "Wuffwuff");
+ if (String.IsNullOrEmpty(m_asterisk)) throw new Exception("missing asterisk_frontend config parameter");
+ if (String.IsNullOrEmpty(m_asterisk_password)) throw new Exception("missing asterisk_password config parameter");
+ m_log.InfoFormat("[ASTERISKVOICE] using asterisk front end {0}", m_asterisk);
+
+ scene.EventManager.OnRegisterCaps += OnRegisterCaps;
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.Message);
+ m_log.DebugFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.ToString());
+ return;
+ }
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "AsteriskVoiceModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return false; }
+ }
+
+ #endregion
+
+ public void OnRegisterCaps(LLUUID agentID, Caps caps)
+ {
+ m_log.DebugFormat("[ASTERISKVOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
+ string capsBase = "/CAPS/" + caps.CapsObjectPath;
+ caps.RegisterHandler("ParcelVoiceInfoRequest",
+ new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath,
+ delegate(string request, string path, string param)
+ {
+ return ParcelVoiceInfoRequest(request, path, param,
+ agentID, caps);
+ }));
+ caps.RegisterHandler("ProvisionVoiceAccountRequest",
+ new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath,
+ delegate(string request, string path, string param)
+ {
+ return ProvisionVoiceAccountRequest(request, path, param,
+ agentID, caps);
+ }));
+ }
+
+ ///
+ /// Callback for a client request for ParcelVoiceInfo
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public string ParcelVoiceInfoRequest(string request, string path, string param,
+ LLUUID agentID, Caps caps)
+ {
+ // we need to do:
+ // - send channel_uri: as "sip:regionID@m_sipDomain"
+ try
+ {
+ m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}",
+ request, path, param);
+
+
+ // setup response to client
+ Hashtable creds = new Hashtable();
+ creds["channel_uri"] = String.Format("sip:{0}@{1}",
+ m_scene.RegionInfo.RegionID, m_sipDomain);
+
+ string regionName = m_scene.RegionInfo.RegionName;
+ ScenePresence avatar = m_scene.GetScenePresence(agentID);
+ if (null == m_scene.LandChannel) throw new Exception("land data not yet available");
+ LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
+
+ LLSDParcelVoiceInfoResponse parcelVoiceInfo =
+ new LLSDParcelVoiceInfoResponse(regionName, land.localID, creds);
+
+ string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
+
+
+ // update region on asterisk-opensim frontend
+ Hashtable requestData = new Hashtable();
+ requestData["admin_password"] = m_asterisk_password;
+ requestData["region"] = m_scene.RegionInfo.RegionID.ToString();
+ if (!String.IsNullOrEmpty(m_confDomain))
+ {
+ requestData["region"] += String.Format("@{0}", m_confDomain);
+ }
+
+ ArrayList SendParams = new ArrayList();
+ SendParams.Add(requestData);
+ XmlRpcRequest updateAccountRequest = new XmlRpcRequest("region_update", SendParams);
+ XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout);
+ Hashtable responseData = (Hashtable) updateAccountResponse.Value;
+
+ if (!responseData.ContainsKey("success")) throw new Exception("region_update call failed");
+
+ bool success = Convert.ToBoolean((string) responseData["success"]);
+ if (!success) throw new Exception("region_update failed");
+
+
+ m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: {0}", r);
+ return r;
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0}, retry later", e.Message);
+ m_log.DebugFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0} failed", e.ToString());
+
+ return "undef";
+ }
+ }
+
+ ///
+ /// Callback for a client request for Voice Account Details
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public string ProvisionVoiceAccountRequest(string request, string path, string param,
+ LLUUID agentID, Caps caps)
+ {
+ // we need to
+ // - get user data from UserProfileCacheService
+ // - generate nonce for user voice account password
+ // - issue XmlRpc request to asterisk opensim front end:
+ // + user: base 64 encoded user name (otherwise SL
+ // client is unhappy)
+ // + password: nonce
+ // - the XmlRpc call to asteris-opensim was successful:
+ // send account details back to client
+ try
+ {
+ m_log.DebugFormat("[ASTERISKVOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
+ request, path, param);
+
+ // get user data & prepare voice account response
+ string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes());
+ voiceUser = voiceUser.Replace('+', '-').Replace('/', '_');
+
+ CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
+ if (null == userInfo) throw new Exception("cannot get user details");
+
+ // we generate a nonce everytime
+ string voicePassword = "$1$" + Util.Md5Hash(DateTime.UtcNow.ToLongTimeString() + m_asterisk_salt);
+ LLSDVoiceAccountResponse voiceAccountResponse =
+ new LLSDVoiceAccountResponse(voiceUser, voicePassword);
+ string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
+ m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r);
+
+
+ // update user account on asterisk frontend
+ Hashtable requestData = new Hashtable();
+ requestData["admin_password"] = m_asterisk_password;
+ requestData["username"] = voiceUser;
+ if (!String.IsNullOrEmpty(m_sipDomain))
+ {
+ requestData["username"] += String.Format("@{0}", m_sipDomain);
+ }
+ requestData["password"] = voicePassword;
+
+ ArrayList SendParams = new ArrayList();
+ SendParams.Add(requestData);
+ XmlRpcRequest updateAccountRequest = new XmlRpcRequest("account_update", SendParams);
+ XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout);
+ Hashtable responseData = (Hashtable) updateAccountResponse.Value;
+
+ if (!responseData.ContainsKey("success")) throw new Exception("account_update call failed");
+
+ bool success = Convert.ToBoolean((string) responseData["success"]);
+ if (!success) throw new Exception("account_update failed");
+
+ return r;
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0}, retry later", e.Message);
+ m_log.DebugFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0} failed", e.ToString());
+
+ return "undef";
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs
index 8d9ba6f..1527f1e 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs
@@ -1,200 +1,200 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections;
-using System.Reflection;
-using libsecondlife;
-using log4net;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Framework.Communications.Cache;
-using OpenSim.Framework.Servers;
-using OpenSim.Region.Capabilities;
-using OpenSim.Region.Environment.Interfaces;
-using OpenSim.Region.Environment.Scenes;
-using Caps=OpenSim.Region.Capabilities.Caps;
-
-namespace OpenSim.Region.Environment.Modules.Avatar.Voice.SIPVoice
-{
- public class SIPVoiceModule : IRegionModule
- {
- private static readonly ILog m_log =
- LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- private static readonly string m_parcelVoiceInfoRequestPath = "0007/";
- private static readonly string m_provisionVoiceAccountRequestPath = "0008/";
- private IConfig m_config;
- private Scene m_scene;
- private string m_sipDomain;
-
- #region IRegionModule Members
-
- public void Initialise(Scene scene, IConfigSource config)
- {
- m_scene = scene;
- m_config = config.Configs["Voice"];
-
- if (null == m_config || !m_config.GetBoolean("enabled", false))
- {
- m_log.Info("[VOICE] plugin disabled");
- return;
- }
- m_log.Info("[VOICE] plugin enabled");
-
- m_sipDomain = m_config.GetString("sip_domain", String.Empty);
- if (String.IsNullOrEmpty(m_sipDomain))
- {
- m_log.Error("[VOICE] plugin mis-configured: missing sip_domain configuration");
- m_log.Info("[VOICE] plugin disabled");
- return;
- }
- m_log.InfoFormat("[VOICE] using SIP domain {0}", m_sipDomain);
-
- scene.EventManager.OnRegisterCaps += OnRegisterCaps;
- }
-
- public void PostInitialise()
- {
- }
-
- public void Close()
- {
- }
-
- public string Name
- {
- get { return "VoiceModule"; }
- }
-
- public bool IsSharedModule
- {
- get { return false; }
- }
-
- #endregion
-
- public void OnRegisterCaps(LLUUID agentID, Caps caps)
- {
- m_log.DebugFormat("[VOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
- string capsBase = "/CAPS/" + caps.CapsObjectPath;
- caps.RegisterHandler("ParcelVoiceInfoRequest",
- new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath,
- delegate(string request, string path, string param)
- {
- return ParcelVoiceInfoRequest(request, path, param,
- agentID, caps);
- }));
- caps.RegisterHandler("ProvisionVoiceAccountRequest",
- new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath,
- delegate(string request, string path, string param)
- {
- return ProvisionVoiceAccountRequest(request, path, param,
- agentID, caps);
- }));
- }
-
- ///
- /// Callback for a client request for ParcelVoiceInfo
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public string ParcelVoiceInfoRequest(string request, string path, string param,
- LLUUID agentID, Caps caps)
- {
- try
- {
- m_log.DebugFormat("[VOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}", request, path, param);
-
- // FIXME: get the creds from region file or from config
- Hashtable creds = new Hashtable();
-
- creds["channel_uri"] = String.Format("sip:{0}@{1}", agentID, m_sipDomain);
-
- string regionName = m_scene.RegionInfo.RegionName;
- ScenePresence avatar = m_scene.GetScenePresence(agentID);
- if (null == m_scene.LandChannel) throw new Exception("land data not yet available");
- LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
-
- LLSDParcelVoiceInfoResponse parcelVoiceInfo =
- new LLSDParcelVoiceInfoResponse(regionName, land.localID, creds);
-
- string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
- m_log.DebugFormat("[VOICE][PARCELVOICE]: {0}", r);
-
- return r;
- }
- catch (Exception e)
- {
- m_log.ErrorFormat("[CAPS]: {0}, try again later", e.ToString());
- }
-
- return null;
- }
-
- ///
- /// Callback for a client request for Voice Account Details
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public string ProvisionVoiceAccountRequest(string request, string path, string param,
- LLUUID agentID, Caps caps)
- {
- try
- {
- m_log.DebugFormat("[VOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
- request, path, param);
-
- string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes());
- voiceUser = voiceUser.Replace('+', '-').Replace('/', '_');
-
- CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
- if (null == userInfo) throw new Exception("cannot get user details");
-
- LLSDVoiceAccountResponse voiceAccountResponse =
- new LLSDVoiceAccountResponse(voiceUser, "$1$" + userInfo.UserProfile.PasswordHash);
- string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
- m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r);
- return r;
- }
- catch (Exception e)
- {
- m_log.ErrorFormat("[CAPS][PROVISIONVOICE]: {0}, retry later", e.Message);
- }
-
- return null;
- }
- }
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections;
+using System.Reflection;
+using libsecondlife;
+using log4net;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Framework.Communications.Cache;
+using OpenSim.Framework.Servers;
+using OpenSim.Region.Capabilities;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+using Caps=OpenSim.Region.Capabilities.Caps;
+
+namespace OpenSim.Region.Environment.Modules.Avatar.Voice.SIPVoice
+{
+ public class SIPVoiceModule : IRegionModule
+ {
+ private static readonly ILog m_log =
+ LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private static readonly string m_parcelVoiceInfoRequestPath = "0007/";
+ private static readonly string m_provisionVoiceAccountRequestPath = "0008/";
+ private IConfig m_config;
+ private Scene m_scene;
+ private string m_sipDomain;
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ m_scene = scene;
+ m_config = config.Configs["Voice"];
+
+ if (null == m_config || !m_config.GetBoolean("enabled", false))
+ {
+ m_log.Info("[VOICE] plugin disabled");
+ return;
+ }
+ m_log.Info("[VOICE] plugin enabled");
+
+ m_sipDomain = m_config.GetString("sip_domain", String.Empty);
+ if (String.IsNullOrEmpty(m_sipDomain))
+ {
+ m_log.Error("[VOICE] plugin mis-configured: missing sip_domain configuration");
+ m_log.Info("[VOICE] plugin disabled");
+ return;
+ }
+ m_log.InfoFormat("[VOICE] using SIP domain {0}", m_sipDomain);
+
+ scene.EventManager.OnRegisterCaps += OnRegisterCaps;
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "VoiceModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return false; }
+ }
+
+ #endregion
+
+ public void OnRegisterCaps(LLUUID agentID, Caps caps)
+ {
+ m_log.DebugFormat("[VOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
+ string capsBase = "/CAPS/" + caps.CapsObjectPath;
+ caps.RegisterHandler("ParcelVoiceInfoRequest",
+ new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath,
+ delegate(string request, string path, string param)
+ {
+ return ParcelVoiceInfoRequest(request, path, param,
+ agentID, caps);
+ }));
+ caps.RegisterHandler("ProvisionVoiceAccountRequest",
+ new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath,
+ delegate(string request, string path, string param)
+ {
+ return ProvisionVoiceAccountRequest(request, path, param,
+ agentID, caps);
+ }));
+ }
+
+ ///
+ /// Callback for a client request for ParcelVoiceInfo
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public string ParcelVoiceInfoRequest(string request, string path, string param,
+ LLUUID agentID, Caps caps)
+ {
+ try
+ {
+ m_log.DebugFormat("[VOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}", request, path, param);
+
+ // FIXME: get the creds from region file or from config
+ Hashtable creds = new Hashtable();
+
+ creds["channel_uri"] = String.Format("sip:{0}@{1}", agentID, m_sipDomain);
+
+ string regionName = m_scene.RegionInfo.RegionName;
+ ScenePresence avatar = m_scene.GetScenePresence(agentID);
+ if (null == m_scene.LandChannel) throw new Exception("land data not yet available");
+ LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
+
+ LLSDParcelVoiceInfoResponse parcelVoiceInfo =
+ new LLSDParcelVoiceInfoResponse(regionName, land.localID, creds);
+
+ string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
+ m_log.DebugFormat("[VOICE][PARCELVOICE]: {0}", r);
+
+ return r;
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[CAPS]: {0}, try again later", e.ToString());
+ }
+
+ return null;
+ }
+
+ ///
+ /// Callback for a client request for Voice Account Details
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public string ProvisionVoiceAccountRequest(string request, string path, string param,
+ LLUUID agentID, Caps caps)
+ {
+ try
+ {
+ m_log.DebugFormat("[VOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
+ request, path, param);
+
+ string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes());
+ voiceUser = voiceUser.Replace('+', '-').Replace('/', '_');
+
+ CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
+ if (null == userInfo) throw new Exception("cannot get user details");
+
+ LLSDVoiceAccountResponse voiceAccountResponse =
+ new LLSDVoiceAccountResponse(voiceUser, "$1$" + userInfo.UserProfile.PasswordHash);
+ string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
+ m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r);
+ return r;
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[CAPS][PROVISIONVOICE]: {0}, retry later", e.Message);
+ }
+
+ return null;
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Framework/Commander.cs b/OpenSim/Region/Environment/Modules/Framework/Commander.cs
index 6cf8298..4430c10 100644
--- a/OpenSim/Region/Environment/Modules/Framework/Commander.cs
+++ b/OpenSim/Region/Environment/Modules/Framework/Commander.cs
@@ -1,308 +1,308 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Text;
-using log4net;
-using OpenSim.Framework;
-using OpenSim.Region.Environment.Interfaces;
-
-namespace OpenSim.Region.Environment.Modules.Framework
-{
- ///
- /// A single function call encapsulated in a class which enforces arguments when passing around as Object[]'s.
- /// Used for console commands and script API generation
- ///
- public class Command : ICommand
- {
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private List m_args = new List();
-
- private Action