Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
						commit
						c7fa637f0d
					
				|  | @ -1,34 +1,36 @@ | |||
| The following people have contributed to OpenSim (Thank you  | ||||
| for your effort!) | ||||
| 
 | ||||
| Add your name in here if you have committed to OpenSim | ||||
| 
 | ||||
| = Current OpenSim Developers (in very rough order of appearance) = | ||||
| These folks represent the current core team for OpenSim, and are the | ||||
| people that make the day to day of OpenSim happen. | ||||
| 
 | ||||
| * justincc | ||||
| * chi11ken (Genkii) | ||||
| * dahlia | ||||
| * Melanie Thielker | ||||
| * Diva (Crista Lopes, University of California, Irvine) | ||||
| * Dan Lake (Intel) | ||||
| * Marck | ||||
| * Mic Bowman (Intel) | ||||
| * BlueWall (James Hughes) | ||||
| 
 | ||||
| = Core Developers Following the White Rabbit = | ||||
| Core developers who have temporarily (we hope) gone chasing the white rabbit.  | ||||
| They are in all similar to the active core developers, except that they haven't | ||||
| been that active lately, so their voting rights are awaiting their come back.  | ||||
| 
 | ||||
| * MW (Tribal Media AB) | ||||
| * Adam Frisby 	(DeepThink Pty Ltd) | ||||
| * MingChen 	(DeepThink Pty Ltd) | ||||
| * lbsa71 (Tribal Media AB) | ||||
| * Sean Dague / sdague (IBM) | ||||
| * Tedd | ||||
| * justincc | ||||
| * Teravus (w3z) | ||||
| * Johan Berntsson (3Di) | ||||
| * Ckrinke (Charles Krinke) | ||||
| * chi11ken (Genkii) | ||||
| * adjohn (Genkii) | ||||
| * Dr Scofield aka Dirk Husemann (IBM Research - Zurich) | ||||
| * dahlia | ||||
| * mikem (3Di) | ||||
| * Melanie Thielker | ||||
| * Homer_Horwitz | ||||
| * idb (Ian Brown) | ||||
| * Diva (Crista Lopes, University of California, Irvine) | ||||
| * nlin (3Di) | ||||
| * Arthur Rodrigo S Valadares (IBM) | ||||
| * BlueWall (James Hughes) | ||||
| * John Hurliman | ||||
| 
 | ||||
| = Past Open Sim Developers = | ||||
| These folks are alumns of the OpenSim core group, but are now | ||||
|  | @ -44,6 +46,12 @@ where we are today. | |||
| * Dalien | ||||
| * Darok | ||||
| * Alondria | ||||
| * Sean Dague / sdague (IBM) | ||||
| * Tedd | ||||
| * MingChen 	(DeepThink Pty Ltd) | ||||
| * adjohn (Genkii) | ||||
| * idb (Ian Brown) | ||||
| * Johan Berntsson (3Di) | ||||
| 
 | ||||
| 
 | ||||
| = Additional OpenSim Contributors = | ||||
|  | @ -102,6 +110,7 @@ what it is today. | |||
| * Misterblue (Intel) | ||||
| * Mircea Kitsune | ||||
| * mpallari | ||||
| * MrMonkE | ||||
| * nornalbion | ||||
| * Omar Vera Ustariz (IBM) | ||||
| * openlifegrid.com | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,131 +0,0 @@ | |||
| /* | ||||
|  * 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 OpenSimulator 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 System.Timers; | ||||
| using log4net; | ||||
| using MXP; | ||||
| using Nini.Config; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Client.MXP.PacketHandler; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| 
 | ||||
| namespace OpenSim.Client.MXP | ||||
| { | ||||
| 
 | ||||
|     /** | ||||
|      * MXP Client Module which adds MXP support to client / region communication. | ||||
|      */ | ||||
|     public class MXPModule : IRegionModule | ||||
|     { | ||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         private MXPPacketServer m_server; | ||||
| 
 | ||||
|         private IConfigSource m_config; | ||||
|         private int m_port = 1253; | ||||
|         private Timer m_ticker; | ||||
| 
 | ||||
|         private readonly Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>(); | ||||
|         private bool m_shutdown; | ||||
| 
 | ||||
|         public void Initialise(Scene scene, IConfigSource source) | ||||
|         { | ||||
|             if (!m_scenes.ContainsKey(scene.RegionInfo.RegionID)) | ||||
|                 m_scenes.Add(scene.RegionInfo.RegionID, scene); | ||||
| 
 | ||||
|             m_config = source; | ||||
|         } | ||||
| 
 | ||||
|         public void PostInitialise() | ||||
|         { | ||||
|             if (m_config.Configs["MXP"] != null) | ||||
|             { | ||||
|                 IConfig con = m_config.Configs["MXP"]; | ||||
| 
 | ||||
|                 if (!con.GetBoolean("Enabled", false)) | ||||
|                     return; | ||||
| 
 | ||||
|                 m_port = con.GetInt("Port", m_port); | ||||
| 
 | ||||
|                 m_server = new MXPPacketServer(m_port, m_scenes,m_config.Configs["StandAlone"].GetBoolean("accounts_authenticate",true)); | ||||
| 
 | ||||
|                 m_ticker = new Timer(100); | ||||
|                 m_ticker.AutoReset = false; | ||||
|                 m_ticker.Elapsed += ticker_Elapsed; | ||||
| 
 | ||||
|                 lock (m_ticker) | ||||
|                     m_ticker.Start(); | ||||
| 
 | ||||
|                 m_log.Info("[MXP ClientStack] MXP Enabled and Listening"); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         void ticker_Elapsed(object sender, ElapsedEventArgs e) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 m_server.Process(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 m_log.Error("[MXP ClientStack]: Unhandled exception in process loop: " + ex.ToString() + " :" + ex.StackTrace.ToString()); | ||||
|             } | ||||
| 
 | ||||
|             if (!m_shutdown) | ||||
|             { | ||||
|                 lock (m_ticker) | ||||
|                     m_ticker.Start(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void Close() | ||||
|         { | ||||
|             m_shutdown = true; | ||||
|             if (m_ticker != null) | ||||
|             { | ||||
|                 lock (m_ticker) | ||||
|                     m_ticker.Stop(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public string Name | ||||
|         { | ||||
|             get { return "MXP ClientStack Module"; } | ||||
|         } | ||||
| 
 | ||||
|         public bool IsSharedModule | ||||
|         { | ||||
|             get { return true; } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | @ -1,42 +0,0 @@ | |||
| /* | ||||
|  * 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 OpenSimulator 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.Text; | ||||
| using OpenMetaverse; | ||||
| 
 | ||||
| namespace OpenSim.Client.MXP | ||||
| { | ||||
|     public static class MXPUtil | ||||
|     { | ||||
|         public static string GenerateMXPURL(string server, int port, UUID bubbleID, Vector3 location) | ||||
|         { | ||||
|             return string.Format("mxp://{0}:{1}/{2}/{3}", server, port, bubbleID.Guid, location); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1,561 +0,0 @@ | |||
| /* | ||||
|  * 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 OpenSimulator 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. | ||||
|  */ | ||||
| 
 | ||||
| /* This file borrows heavily from MXPServer.cs - the reference MXPServer  | ||||
|  * See http://www.bubblecloud.org for a copy of the original file and | ||||
|  * implementation details. */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Reflection; | ||||
| using System.Threading; | ||||
| using log4net; | ||||
| using MXP; | ||||
| using MXP.Messages; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Client.MXP.ClientStack; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Framework.Communications; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using System.Security.Cryptography; | ||||
| 
 | ||||
| namespace OpenSim.Client.MXP.PacketHandler | ||||
| { | ||||
|     public class MXPPacketServer | ||||
|     { | ||||
|         internal static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         #region Fields | ||||
| 
 | ||||
|         private readonly List<MXPClientView> m_clients = new List<MXPClientView>(); | ||||
|         private readonly Dictionary<UUID, Scene> m_scenes; | ||||
|         private readonly Transmitter m_transmitter; | ||||
| 
 | ||||
| //        private readonly Thread m_clientThread; | ||||
| 
 | ||||
|         private readonly IList<Session> m_sessions = new List<Session>(); | ||||
|         private readonly IList<Session> m_sessionsToClient = new List<Session>(); | ||||
|         private readonly IList<MXPClientView> m_sessionsToRemove = new List<MXPClientView>(); | ||||
| 
 | ||||
|         private readonly int m_port; | ||||
| //        private readonly bool m_accountsAuthenticate; | ||||
| 
 | ||||
|         private readonly String m_programName; | ||||
|         private readonly byte m_programMajorVersion; | ||||
|         private readonly byte m_programMinorVersion; | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region Constructors | ||||
| 
 | ||||
|         public MXPPacketServer(int port, Dictionary<UUID, Scene> scenes, bool accountsAuthenticate) | ||||
|         { | ||||
|             m_port = port; | ||||
| //            m_accountsAuthenticate = accountsAuthenticate; | ||||
| 
 | ||||
|             m_scenes = scenes; | ||||
| 
 | ||||
|             m_programMinorVersion = 63; | ||||
|             m_programMajorVersion = 0; | ||||
|             m_programName = "OpenSimulator"; | ||||
| 
 | ||||
|             m_transmitter = new Transmitter(port); | ||||
| 
 | ||||
|             StartListener(); | ||||
|         } | ||||
| 
 | ||||
|         public void StartListener() | ||||
|         { | ||||
|             m_log.Info("[MXP ClientStack] Transmitter starting on UDP server port: " + m_port); | ||||
|             m_transmitter.Startup(); | ||||
|             m_log.Info("[MXP ClientStack] Transmitter started. MXP version: "+MxpConstants.ProtocolMajorVersion+"."+MxpConstants.ProtocolMinorVersion+" Source Revision: "+MxpConstants.ProtocolSourceRevision); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region Properties | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Number of sessions pending. (Process() accepts pending sessions). | ||||
|         /// </summary> | ||||
|         public int PendingSessionCount | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return m_transmitter.PendingSessionCount; | ||||
|             } | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Number of connected sessions. | ||||
|         /// </summary> | ||||
|         public int SessionCount | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return m_sessions.Count; | ||||
|             } | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Property reflecting whether client transmitter threads are alive. | ||||
|         /// </summary> | ||||
|         public bool IsTransmitterAlive | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return m_transmitter != null && m_transmitter.IsAlive; | ||||
|             } | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Number of packets sent. | ||||
|         /// </summary> | ||||
|         public ulong PacketsSent | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return m_transmitter != null ? m_transmitter.PacketsSent : 0; | ||||
|             } | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Number of packets received. | ||||
|         /// </summary> | ||||
|         public ulong PacketsReceived | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return m_transmitter != null ? m_transmitter.PacketsReceived : 0; | ||||
|             } | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Bytes client has received so far. | ||||
|         /// </summary> | ||||
|         public ulong BytesReceived | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return m_transmitter != null ? m_transmitter.BytesReceived : 0; | ||||
|             } | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Bytes client has sent so far. | ||||
|         /// </summary> | ||||
|         public ulong BytesSent | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return m_transmitter != null ? m_transmitter.BytesSent : 0; | ||||
|             } | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Number of bytes received (bytes per second) during past second. | ||||
|         /// </summary> | ||||
|         public double ReceiveRate | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return m_transmitter != null ? m_transmitter.ReceiveRate : 0; | ||||
|             } | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Number of bytes sent (bytes per second) during past second. | ||||
|         /// </summary> | ||||
|         public double SendRate | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return m_transmitter != null ? m_transmitter.SendRate : 0; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region Session Management | ||||
| 
 | ||||
|         public void Disconnect(Session session) | ||||
|         { | ||||
|             if (session.IsConnected) | ||||
|             { | ||||
|                 Message message = MessageFactory.Current.ReserveMessage(typeof(LeaveRequestMessage)); | ||||
|                 session.Send(message); | ||||
|                 MessageFactory.Current.ReleaseMessage(message); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 throw new Exception("Not connected."); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region Processing | ||||
| 
 | ||||
|         public void Process() | ||||
|         { | ||||
|             ProcessMessages(); | ||||
|             Clean(); | ||||
|         } | ||||
| 
 | ||||
|         public void Clean() | ||||
|         { | ||||
|             foreach (MXPClientView clientView in m_clients) | ||||
|             { | ||||
|                 if (clientView.Session.SessionState == SessionState.Disconnected) | ||||
|                 { | ||||
|                     m_sessionsToRemove.Add(clientView); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             foreach (MXPClientView clientView in m_sessionsToRemove) | ||||
|             { | ||||
|                 clientView.Scene.RemoveClient(clientView.AgentId); | ||||
|                 clientView.OnClean(); | ||||
|                 m_clients.Remove(clientView); | ||||
|                 m_sessions.Remove(clientView.Session); | ||||
|             } | ||||
| 
 | ||||
|             m_sessionsToRemove.Clear(); | ||||
|         } | ||||
| 
 | ||||
|         public void ProcessMessages() | ||||
|         { | ||||
|             if (m_transmitter.PendingSessionCount > 0) | ||||
|             { | ||||
|                 Session tmp = m_transmitter.AcceptPendingSession(); | ||||
|                 m_sessions.Add(tmp); | ||||
|                 m_sessionsToClient.Add(tmp); | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             List<Session> tmpRemove = new List<Session>(); | ||||
| 
 | ||||
|             foreach (Session session in m_sessionsToClient) | ||||
|             { | ||||
|                 while (session.AvailableMessages > 0) | ||||
|                 { | ||||
|                     Message message = session.Receive(); | ||||
| 
 | ||||
|                     if (message.GetType() == typeof (JoinRequestMessage)) | ||||
|                     { | ||||
| 
 | ||||
|                         JoinRequestMessage joinRequestMessage = (JoinRequestMessage) message; | ||||
| 
 | ||||
|                         m_log.Info("[MXP ClientStack]: Session join request: " + session.SessionId + " (" + | ||||
|                            (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + | ||||
|                             session.RemoteEndPoint.Port + ")"); | ||||
| 
 | ||||
|                         try | ||||
|                         { | ||||
| 
 | ||||
|                             if (joinRequestMessage.BubbleId == Guid.Empty) | ||||
|                             { | ||||
|                                 foreach (Scene scene in m_scenes.Values) | ||||
|                                 { | ||||
|                                     if (scene.RegionInfo.RegionName == joinRequestMessage.BubbleName) | ||||
|                                     { | ||||
|                                         m_log.Info("[MXP ClientStack]: Resolved region by name: " + joinRequestMessage.BubbleName + " (" + scene.RegionInfo.RegionID + ")"); | ||||
|                                         joinRequestMessage.BubbleId = scene.RegionInfo.RegionID.Guid; | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
| 
 | ||||
|                             if (joinRequestMessage.BubbleId == Guid.Empty) | ||||
|                             { | ||||
|                                 m_log.Warn("[MXP ClientStack]: Failed to resolve region by name: " + joinRequestMessage.BubbleName); | ||||
|                             } | ||||
| 
 | ||||
|                             UUID sceneId = new UUID(joinRequestMessage.BubbleId); | ||||
| 
 | ||||
|                             bool regionExists = true; | ||||
|                             if (!m_scenes.ContainsKey(sceneId)) | ||||
|                             { | ||||
|                                 m_log.Info("[MXP ClientStack]: No such region: " + sceneId); | ||||
|                                 regionExists = false; | ||||
|                             } | ||||
| 
 | ||||
|                             UUID userId = UUID.Zero; | ||||
|                             UserAccount account = null; | ||||
|                             bool authorized = regionExists ? AuthoriseUser(joinRequestMessage.ParticipantName, | ||||
|                                                             joinRequestMessage.ParticipantPassphrase, | ||||
|                                                             new UUID(joinRequestMessage.BubbleId), out account) | ||||
|                                                             : false; | ||||
| 
 | ||||
|                             if (authorized) | ||||
|                             { | ||||
|                                 Scene scene = m_scenes[sceneId]; | ||||
|                                 UUID mxpSessionID = UUID.Random(); | ||||
|                                  | ||||
|                                 string reason; | ||||
| 
 | ||||
|                                 m_log.Debug("[MXP ClientStack]: Session join request success: " + session.SessionId + " (" + | ||||
|                                    (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + | ||||
|                                    session.RemoteEndPoint.Port + ")"); | ||||
| 
 | ||||
|                                 m_log.Debug("[MXP ClientStack]: Attaching UserAgent to UserProfile..."); | ||||
|                                 UUID secureSession = UUID.Zero; | ||||
|                                 AttachUserAgentToUserProfile(account, session, mxpSessionID, sceneId, out secureSession); | ||||
|                                 m_log.Debug("[MXP ClientStack]: Attached UserAgent to UserProfile."); | ||||
|                                 m_log.Debug("[MXP ClientStack]: Preparing Scene to Connection..."); | ||||
|                                 if (!PrepareSceneForConnection(mxpSessionID, secureSession, sceneId, account, out reason)) | ||||
|                                 { | ||||
|                                     m_log.DebugFormat("[MXP ClientStack]: Scene refused connection: {0}", reason); | ||||
|                                     DeclineConnection(session, joinRequestMessage); | ||||
|                                     tmpRemove.Add(session); | ||||
|                                     continue; | ||||
|                                 } | ||||
|                                 m_log.Debug("[MXP ClientStack]: Prepared Scene to Connection."); | ||||
|                                 m_log.Debug("[MXP ClientStack]: Accepting connection..."); | ||||
|                                 AcceptConnection(session, joinRequestMessage, mxpSessionID, userId); | ||||
|                                 m_log.Info("[MXP ClientStack]: Accepted connection."); | ||||
| 
 | ||||
|                                 m_log.Debug("[MXP ClientStack]: Creating ClientView...."); | ||||
|                                 MXPClientView client = new MXPClientView(session, mxpSessionID, userId, scene, account.FirstName, account.LastName); | ||||
|                                 m_clients.Add(client); | ||||
|                                 m_log.Debug("[MXP ClientStack]: Created ClientView."); | ||||
| 
 | ||||
|                                 client.MXPSendSynchronizationBegin(m_scenes[new UUID(joinRequestMessage.BubbleId)].SceneContents.GetTotalObjectsCount()); | ||||
| 
 | ||||
|                                 m_log.Debug("[MXP ClientStack]: Starting ClientView..."); | ||||
|                                 try | ||||
|                                 { | ||||
|                                     client.Start(); | ||||
|                                     m_log.Debug("[MXP ClientStack]: Started ClientView."); | ||||
|                                 } | ||||
|                                 catch (Exception e) | ||||
|                                 { | ||||
|                                     m_log.Error(e); | ||||
|                                 } | ||||
| 
 | ||||
|                                 m_log.Debug("[MXP ClientStack]: Connected"); | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 m_log.Info("[MXP ClientStack]: Session join request failure: " + session.SessionId + " (" + | ||||
|                                            (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + | ||||
|                                            session.RemoteEndPoint.Port + ")"); | ||||
| 
 | ||||
|                                 DeclineConnection(session, joinRequestMessage); | ||||
|                             } | ||||
|                         } | ||||
|                         catch (Exception e) | ||||
|                         { | ||||
|                             m_log.Error("[MXP ClientStack]: Session join request failure: " + session.SessionId + " (" + | ||||
|                                (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + | ||||
|                                session.RemoteEndPoint.Port + "): "+e.ToString()+" :"+e.StackTrace.ToString()); | ||||
|                         } | ||||
|                         tmpRemove.Add(session); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             foreach (Session session in tmpRemove) | ||||
|             { | ||||
|                 m_sessionsToClient.Remove(session); | ||||
|             } | ||||
| 
 | ||||
|             foreach (MXPClientView clientView in m_clients) | ||||
|             { | ||||
|                 int messagesProcessedCount = 0; | ||||
|                 Session session = clientView.Session; | ||||
| 
 | ||||
|                 while (session.AvailableMessages > 0) | ||||
|                 { | ||||
|                     Message message = session.Receive(); | ||||
| 
 | ||||
|                     if (message.GetType() == typeof(LeaveRequestMessage)) | ||||
|                     { | ||||
|                         LeaveResponseMessage leaveResponseMessage = (LeaveResponseMessage)MessageFactory.Current.ReserveMessage( | ||||
|                             typeof(LeaveResponseMessage)); | ||||
| 
 | ||||
|                         m_log.Debug("[MXP ClientStack]: Session leave request: " + session.SessionId + " (" + (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port + ")"); | ||||
| 
 | ||||
|                         leaveResponseMessage.RequestMessageId = message.MessageId; | ||||
|                         leaveResponseMessage.FailureCode = 0; | ||||
|                         session.Send(leaveResponseMessage); | ||||
| 
 | ||||
|                         if (session.SessionState != SessionState.Disconnected) | ||||
|                         { | ||||
|                             session.SetStateDisconnected(); | ||||
|                         } | ||||
| 
 | ||||
|                         m_log.Debug("[MXP ClientStack]: Removing Client from Scene"); | ||||
|                         //clientView.Scene.RemoveClient(clientView.AgentId); | ||||
|                     } | ||||
|                     if (message.GetType() == typeof(LeaveResponseMessage)) | ||||
|                     { | ||||
|                         LeaveResponseMessage leaveResponseMessage = (LeaveResponseMessage)message; | ||||
| 
 | ||||
|                         m_log.Debug("[MXP ClientStack]: Session leave response: " + session.SessionId + " (" + (session.IsIncoming ? "from" : "to") + " " + session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port + ")"); | ||||
| 
 | ||||
|                         if (leaveResponseMessage.FailureCode == 0) | ||||
|                         { | ||||
|                             session.SetStateDisconnected(); | ||||
|                         } | ||||
| 
 | ||||
|                         m_log.Debug("[MXP ClientStack]: Removing Client from Scene"); | ||||
|                         //clientView.Scene.RemoveClient(clientView.AgentId); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         clientView.MXPPRocessMessage(message); | ||||
|                     } | ||||
| 
 | ||||
|                     MessageFactory.Current.ReleaseMessage(message); | ||||
|                     messagesProcessedCount++; | ||||
|                     if (messagesProcessedCount > 1000) | ||||
|                     { | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void AcceptConnection(Session session, JoinRequestMessage joinRequestMessage, UUID mxpSessionID, UUID userId) | ||||
|         { | ||||
|             JoinResponseMessage joinResponseMessage = (JoinResponseMessage)MessageFactory.Current.ReserveMessage( | ||||
|                                                                                typeof(JoinResponseMessage)); | ||||
| 
 | ||||
|             joinResponseMessage.RequestMessageId = joinRequestMessage.MessageId; | ||||
|             joinResponseMessage.FailureCode = MxpResponseCodes.SUCCESS; | ||||
|              | ||||
|             joinResponseMessage.BubbleId = joinRequestMessage.BubbleId; | ||||
|             joinResponseMessage.ParticipantId = userId.Guid; | ||||
|             joinResponseMessage.AvatarId = userId.Guid; | ||||
|             joinResponseMessage.BubbleAssetCacheUrl = "http://" + | ||||
|                                                       NetworkUtil.GetHostFor(session.RemoteEndPoint.Address, | ||||
|                                                                              m_scenes[ | ||||
|                                                                                  new UUID(joinRequestMessage.BubbleId)]. | ||||
|                                                                                  RegionInfo. | ||||
|                                                                                  ExternalHostName) + ":" + | ||||
|                                                       m_scenes[new UUID(joinRequestMessage.BubbleId)].RegionInfo. | ||||
|                                                           HttpPort + "/assets/"; | ||||
| 
 | ||||
|             joinResponseMessage.BubbleName = m_scenes[new UUID(joinRequestMessage.BubbleId)].RegionInfo.RegionName; | ||||
| 
 | ||||
|             joinResponseMessage.BubbleRange = 128; | ||||
|             joinResponseMessage.BubblePerceptionRange = 128 + 256; | ||||
|             joinResponseMessage.BubbleRealTime = 0; | ||||
|             joinResponseMessage.ProgramName = m_programName; | ||||
|             joinResponseMessage.ProgramMajorVersion = m_programMajorVersion; | ||||
|             joinResponseMessage.ProgramMinorVersion = m_programMinorVersion; | ||||
|             joinResponseMessage.ProtocolMajorVersion = MxpConstants.ProtocolMajorVersion; | ||||
|             joinResponseMessage.ProtocolMinorVersion = MxpConstants.ProtocolMinorVersion; | ||||
|             joinResponseMessage.ProtocolSourceRevision = MxpConstants.ProtocolSourceRevision; | ||||
| 
 | ||||
|             session.Send(joinResponseMessage); | ||||
| 
 | ||||
|             session.SetStateConnected(); | ||||
|         } | ||||
| 
 | ||||
|         private void DeclineConnection(Session session, Message joinRequestMessage) | ||||
|         { | ||||
|             JoinResponseMessage joinResponseMessage = (JoinResponseMessage)MessageFactory.Current.ReserveMessage(typeof(JoinResponseMessage)); | ||||
| 
 | ||||
|             joinResponseMessage.RequestMessageId = joinRequestMessage.MessageId; | ||||
|             joinResponseMessage.FailureCode = MxpResponseCodes.UNAUTHORIZED_OPERATION; | ||||
| 
 | ||||
|             joinResponseMessage.ProgramName = m_programName; | ||||
|             joinResponseMessage.ProgramMajorVersion = m_programMajorVersion; | ||||
|             joinResponseMessage.ProgramMinorVersion = m_programMinorVersion; | ||||
|             joinResponseMessage.ProtocolMajorVersion = MxpConstants.ProtocolMajorVersion; | ||||
|             joinResponseMessage.ProtocolMinorVersion = MxpConstants.ProtocolMinorVersion; | ||||
|             joinResponseMessage.ProtocolSourceRevision = MxpConstants.ProtocolSourceRevision; | ||||
| 
 | ||||
|             session.Send(joinResponseMessage); | ||||
| 
 | ||||
|             session.SetStateDisconnected(); | ||||
|         } | ||||
| 
 | ||||
|         public bool AuthoriseUser(string participantName, string password, UUID sceneId, out UserAccount account) | ||||
|         { | ||||
|             string firstName = ""; | ||||
|             string lastName = ""; | ||||
|             account = null; | ||||
| 
 | ||||
|             string[] nameParts = participantName.Split(' '); | ||||
|             if (nameParts.Length != 2) | ||||
|             { | ||||
|                 m_log.Error("[MXP ClientStack]: Login failed as user name is not formed of first and last name separated by space: " + participantName); | ||||
|                 return false; | ||||
|             } | ||||
|             firstName = nameParts[0]; | ||||
|             lastName = nameParts[1]; | ||||
| 
 | ||||
|             account = m_scenes[sceneId].UserAccountService.GetUserAccount(m_scenes[sceneId].RegionInfo.ScopeID, firstName, lastName); | ||||
|             if (account != null) | ||||
|                 return (m_scenes[sceneId].AuthenticationService.Authenticate(account.PrincipalID, password, 1) != string.Empty); | ||||
| 
 | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         private void AttachUserAgentToUserProfile(UserAccount account, Session session, UUID sessionId, UUID sceneId, out UUID secureSessionId) | ||||
|         { | ||||
|             secureSessionId = UUID.Random(); | ||||
|             Scene scene = m_scenes[sceneId]; | ||||
|             scene.PresenceService.LoginAgent(account.PrincipalID.ToString(), sessionId, secureSessionId); | ||||
|         } | ||||
| 
 | ||||
|         private bool PrepareSceneForConnection(UUID sessionId, UUID secureSessionId, UUID sceneId, UserAccount account, out string reason) | ||||
|         { | ||||
|             Scene scene = m_scenes[sceneId]; | ||||
| 
 | ||||
|             AgentCircuitData agent = new AgentCircuitData(); | ||||
|             agent.AgentID = account.PrincipalID; | ||||
|             agent.firstname = account.FirstName; | ||||
|             agent.lastname = account.LastName; | ||||
|             agent.SessionID = sessionId; | ||||
|             agent.SecureSessionID = secureSessionId; | ||||
|             agent.circuitcode = sessionId.CRC(); | ||||
|             agent.BaseFolder = UUID.Zero; | ||||
|             agent.InventoryFolder = UUID.Zero; | ||||
|             agent.startpos = new Vector3(0, 0, 0); // TODO Fill in region start position | ||||
|             agent.CapsPath = "http://localhost/"; | ||||
|             agent.Appearance = scene.AvatarService.GetAppearance(account.PrincipalID); | ||||
| 
 | ||||
|             if (agent.Appearance == null) | ||||
|             { | ||||
|                 m_log.WarnFormat("[INTER]: Appearance not found for {0} {1}. Creating default.", agent.firstname, agent.lastname); | ||||
|                 agent.Appearance = new AvatarAppearance(); | ||||
|             } | ||||
|              | ||||
|             return scene.NewUserConnection(agent, 0, out reason); | ||||
|         } | ||||
| 
 | ||||
|         public void PrintDebugInformation() | ||||
|         { | ||||
|             m_log.Info("[MXP ClientStack]: Statistics report"); | ||||
|             m_log.Info("Pending Sessions: " + PendingSessionCount); | ||||
|             m_log.Info("Sessions: " + SessionCount + " (Clients: " + m_clients.Count + " )"); | ||||
|             m_log.Info("Transmitter Alive?: " + IsTransmitterAlive); | ||||
|             m_log.Info("Packets Sent/Received: " + PacketsSent + " / " + PacketsReceived); | ||||
|             m_log.Info("Bytes Sent/Received: " + BytesSent + " / " + BytesReceived); | ||||
|             m_log.Info("Send/Receive Rate (bps): " + SendRate + " / " + ReceiveRate); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
|      | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,133 +0,0 @@ | |||
| /* | ||||
|  * 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 OpenSimulator 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.Text; | ||||
| using Nini.Config; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Client.VWoHTTP.ClientStack; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Servers; | ||||
| using OpenSim.Framework.Servers.HttpServer; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| 
 | ||||
| namespace OpenSim.Client.VWoHTTP | ||||
| { | ||||
|     class VWoHTTPModule : IRegionModule, IHttpAgentHandler | ||||
|     { | ||||
|         private bool m_disabled = true; | ||||
| 
 | ||||
|         private IHttpServer m_httpd; | ||||
| 
 | ||||
|         private readonly List<Scene> m_scenes = new List<Scene>(); | ||||
| 
 | ||||
|         private Dictionary<UUID, VWHClientView> m_clients = new Dictionary<UUID, VWHClientView>(); | ||||
| 
 | ||||
|         #region Implementation of IRegionModule | ||||
| 
 | ||||
|         public void Initialise(Scene scene, IConfigSource source) | ||||
|         { | ||||
|             if (m_disabled) | ||||
|                 return; | ||||
| 
 | ||||
|             m_scenes.Add(scene); | ||||
| 
 | ||||
|             m_httpd = MainServer.Instance; | ||||
|         } | ||||
| 
 | ||||
|         public void PostInitialise() | ||||
|         { | ||||
|             if (m_disabled) | ||||
|                 return; | ||||
| 
 | ||||
|             m_httpd.AddAgentHandler("vwohttp", this); | ||||
|         } | ||||
| 
 | ||||
|         public void Close() | ||||
|         { | ||||
|             if (m_disabled) | ||||
|                 return; | ||||
| 
 | ||||
|             m_httpd.RemoveAgentHandler("vwohttp", this); | ||||
|         } | ||||
| 
 | ||||
|         public string Name | ||||
|         { | ||||
|             get { return "VWoHTTP ClientStack"; } | ||||
|         } | ||||
| 
 | ||||
|         public bool IsSharedModule | ||||
|         { | ||||
|             get { return true; } | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region Implementation of IHttpAgentHandler | ||||
| 
 | ||||
|         public bool Handle(OSHttpRequest req, OSHttpResponse resp) | ||||
|         { | ||||
|             string[] urlparts = req.Url.AbsolutePath.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries); | ||||
| 
 | ||||
|             if (urlparts.Length < 2) | ||||
|                 return false; | ||||
| 
 | ||||
|             if (urlparts[1] == "connect") | ||||
|             { | ||||
|                 UUID sessID = UUID.Random(); | ||||
| 
 | ||||
|                 VWHClientView client = new VWHClientView(sessID, UUID.Random(), "VWoHTTPClient", m_scenes[0]); | ||||
| 
 | ||||
|                 m_clients.Add(sessID, client); | ||||
| 
 | ||||
|                 return true; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (urlparts.Length < 3) | ||||
|                     return false; | ||||
| 
 | ||||
|                 UUID sessionID; | ||||
|                 if (!UUID.TryParse(urlparts[1], out sessionID)) | ||||
|                     return false; | ||||
| 
 | ||||
|                 if (!m_clients.ContainsKey(sessionID)) | ||||
|                     return false; | ||||
| 
 | ||||
|                 return m_clients[sessionID].ProcessInMsg(req, resp); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public bool Match(OSHttpRequest req, OSHttpResponse resp) | ||||
|         { | ||||
|             return req.Url.ToString().Contains("vwohttp"); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
|  | @ -56,15 +56,15 @@ namespace OpenSim.Data.MSSQL | |||
|                 string realm, string storeName) | ||||
|         { | ||||
|             m_Realm = realm; | ||||
|              | ||||
|             m_ConnectionString = connectionString; | ||||
| 
 | ||||
|             if (storeName != String.Empty) | ||||
|             { | ||||
|                 Assembly assem = GetType().Assembly; | ||||
|                 m_ConnectionString = connectionString; | ||||
|                 using (SqlConnection conn = new SqlConnection(m_ConnectionString)) | ||||
|                 { | ||||
|                     conn.Open(); | ||||
|                     Migration m = new Migration(conn, assem, storeName); | ||||
|                     Migration m = new Migration(conn, GetType().Assembly, storeName); | ||||
|                     m.Update(); | ||||
|                 } | ||||
| 
 | ||||
|  |  | |||
|  | @ -61,7 +61,8 @@ namespace OpenSim.Data.MSSQL | |||
|                 } | ||||
|                 catch | ||||
|                 { | ||||
|                     // Something went wrong, so we're version 0 | ||||
|                     // Return -1 to indicate table does not exist | ||||
|                     return -1; | ||||
|                 } | ||||
|             } | ||||
|             return version; | ||||
|  |  | |||
|  | @ -492,12 +492,11 @@ ELSE | |||
|             using (SqlConnection conn = new SqlConnection(m_connectionString)) | ||||
|             using (SqlCommand cmd = new SqlCommand(sql, conn)) | ||||
|             { | ||||
|                 conn.Open(); | ||||
|                 foreach (TaskInventoryItem taskItem in items) | ||||
|                 { | ||||
|                     cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem)); | ||||
|                     conn.Open(); | ||||
|                     cmd.ExecuteNonQuery(); | ||||
| 
 | ||||
|                     cmd.Parameters.Clear(); | ||||
|                 } | ||||
|             } | ||||
|  | @ -1154,9 +1153,9 @@ VALUES | |||
|             PrimitiveBaseShape baseShape = new PrimitiveBaseShape(); | ||||
| 
 | ||||
|             baseShape.Scale = new Vector3( | ||||
|                         Convert.ToSingle(shapeRow["ScaleX"]), | ||||
|                         Convert.ToSingle(shapeRow["ScaleY"]), | ||||
|                         Convert.ToSingle(shapeRow["ScaleZ"])); | ||||
|                         (float)Convert.ToDouble(shapeRow["ScaleX"]), | ||||
|                         (float)Convert.ToDouble(shapeRow["ScaleY"]), | ||||
|                         (float)Convert.ToDouble(shapeRow["ScaleZ"])); | ||||
| 
 | ||||
|             // paths | ||||
|             baseShape.PCode = Convert.ToByte(shapeRow["PCode"]); | ||||
|  | @ -1193,8 +1192,11 @@ VALUES | |||
|             { | ||||
|             } | ||||
| 
 | ||||
|             if (!(shapeRow["Media"] is System.DBNull)) | ||||
|             if (!(shapeRow["Media"] is System.DBNull) ) | ||||
|             { | ||||
|                 baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]); | ||||
|             } | ||||
|                  | ||||
| 
 | ||||
|             return baseShape; | ||||
|         } | ||||
|  | @ -1573,7 +1575,16 @@ VALUES | |||
|             parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry)); | ||||
|             parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams)); | ||||
|             parameters.Add(_Database.CreateParameter("State", s.State)); | ||||
|             parameters.Add(_Database.CreateParameter("Media", null == s.Media ? null : s.Media.ToXml())); | ||||
| 
 | ||||
|             if(null == s.Media ) | ||||
|             { | ||||
|                 parameters.Add(_Database.CreateParameter("Media", DBNull.Value));     | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml()));     | ||||
|             } | ||||
|              | ||||
| 
 | ||||
|             return parameters.ToArray(); | ||||
|         } | ||||
|  |  | |||
|  | @ -22,7 +22,11 @@ COMMIT | |||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| 
 | ||||
| INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users; | ||||
| IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[users]') AND type in (N'U')) | ||||
| 	INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users; | ||||
| 
 | ||||
| COMMIT | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| COMMIT | ||||
|  | @ -13,5 +13,28 @@ PRIMARY KEY CLUSTERED | |||
| ) ON [PRIMARY] | ||||
| 
 | ||||
| 
 | ||||
| COMMIT | ||||
| 
 | ||||
| :VERSION 2 | ||||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| 
 | ||||
| CREATE TABLE dbo.Tmp_Avatars | ||||
| 	( | ||||
| 	PrincipalID uniqueidentifier NOT NULL, | ||||
| 	[Name] varchar(32) NOT NULL,  | ||||
| 	Value text NOT NULL DEFAULT '', | ||||
| 	)  ON [PRIMARY] | ||||
| 	 TEXTIMAGE_ON [PRIMARY] | ||||
| 
 | ||||
| IF EXISTS(SELECT * FROM dbo.Avatars) | ||||
| 	 EXEC('INSERT INTO dbo.Tmp_Avatars (PrincipalID, Name, Value) | ||||
| 		SELECT PrincipalID, CONVERT(text, Name), Value FROM dbo.Avatars WITH (HOLDLOCK TABLOCKX)') | ||||
| 
 | ||||
| DROP TABLE dbo.Avatars | ||||
| 
 | ||||
| EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT'  | ||||
| 
 | ||||
| COMMIT | ||||
| 
 | ||||
| 
 | ||||
| COMMIT | ||||
|  | @ -15,6 +15,8 @@ COMMIT | |||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| 
 | ||||
| INSERT INTO Friends (PrincipalID, Friend, Flags, Offered) SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends; | ||||
| IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[userfriends]') AND type in (N'U')) | ||||
| INSERT INTO Friends (PrincipalID, Friend, Flags, Offered)  | ||||
| SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends; | ||||
| 
 | ||||
| COMMIT | ||||
|  | @ -222,4 +222,17 @@ ALTER TABLE [regions] ADD [Token] varchar(255) NOT NULL DEFAULT 0; | |||
| 
 | ||||
| COMMIT | ||||
| 
 | ||||
| :VERSION 8 | ||||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| ALTER TABLE regions ALTER COLUMN regionName VarChar(128)  | ||||
| 
 | ||||
| DROP INDEX IX_regions_name ON dbo.regions | ||||
| ALTER TABLE regions ALTER COLUMN regionName VarChar(128) null | ||||
| 
 | ||||
| CREATE NONCLUSTERED INDEX IX_regions_name ON dbo.regions | ||||
| 	( | ||||
| 	regionName | ||||
| 	) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] | ||||
| 
 | ||||
| COMMIT | ||||
|  | @ -238,7 +238,10 @@ alter table inventoryitems | |||
| 
 | ||||
| COMMIT	 | ||||
|     | ||||
|   | ||||
| 
 | ||||
| 
 | ||||
| :VERSION 8 | ||||
| 
 | ||||
| ALTER TABLE inventoryitems | ||||
| ADD CONSTRAINT DF_inventoryitems_creatorID  | ||||
| DEFAULT '00000000-0000-0000-0000-000000000000' FOR creatorID | ||||
|     | ||||
| :GO | ||||
|  | @ -7,14 +7,7 @@ CREATE TABLE [Presence] ( | |||
| [RegionID] uniqueidentifier NOT NULL,  | ||||
| [SessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', | ||||
| [SecureSessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', | ||||
| [Online] char(5) NOT NULL DEFAULT 'false', | ||||
| [Login] char(16) NOT NULL DEFAULT '0', | ||||
| [Logout] char(16) NOT NULL DEFAULT '0', | ||||
| [Position] char(64) NOT NULL DEFAULT '<0,0,0>', | ||||
| [LookAt] char(64) NOT NULL DEFAULT '<0,0,0>', | ||||
| [HomeRegionID] uniqueidentifier NOT NULL, | ||||
| [HomePosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>', | ||||
| [HomeLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>', | ||||
| 
 | ||||
| ) | ||||
|  ON [PRIMARY] | ||||
| 
 | ||||
|  | @ -27,4 +20,12 @@ BEGIN TRANSACTION | |||
| CREATE UNIQUE INDEX SessionID ON Presence(SessionID); | ||||
| CREATE INDEX UserID ON Presence(UserID); | ||||
| 
 | ||||
| COMMIT | ||||
| 
 | ||||
| :VERSION 2 | ||||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| 
 | ||||
| ALTER TABLE Presence ADD LastSeen DateTime | ||||
| 
 | ||||
| COMMIT | ||||
|  | @ -1,4 +1,3 @@ | |||
| 
 | ||||
| :VERSION 1 | ||||
| 
 | ||||
| CREATE TABLE [dbo].[prims]( | ||||
|  | @ -926,11 +925,121 @@ ALTER TABLE regionsettings ADD loaded_creation_datetime int NOT NULL default 0 | |||
| COMMIT | ||||
| 
 | ||||
| :VERSION 24 | ||||
| -- Added post 0.7 | ||||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| 
 | ||||
| ALTER TABLE prims ADD COLUMN MediaURL varchar(255) | ||||
| ALTER TABLE primshapes ADD COLUMN Media TEXT | ||||
| ALTER TABLE prims ADD  MediaURL varchar(255) | ||||
| ALTER TABLE primshapes ADD Media TEXT NULL | ||||
| 
 | ||||
| COMMIT | ||||
| COMMIT | ||||
| 
 | ||||
| :VERSION 25 | ||||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| CREATE TABLE "regionwindlight" ( | ||||
|   "region_id" varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000', | ||||
|   "water_color_r" [float] NOT NULL DEFAULT '4.000000', | ||||
|   "water_color_g" [float] NOT NULL DEFAULT '38.000000', | ||||
|   "water_color_b" [float] NOT NULL DEFAULT '64.000000', | ||||
|   "water_fog_density_exponent" [float] NOT NULL DEFAULT '4.0', | ||||
|   "underwater_fog_modifier" [float] NOT NULL DEFAULT '0.25', | ||||
|   "reflection_wavelet_scale_1" [float] NOT NULL DEFAULT '2.0', | ||||
|   "reflection_wavelet_scale_2" [float] NOT NULL DEFAULT '2.0', | ||||
|   "reflection_wavelet_scale_3" [float] NOT NULL DEFAULT '2.0', | ||||
|   "fresnel_scale" [float] NOT NULL DEFAULT '0.40', | ||||
|   "fresnel_offset" [float] NOT NULL DEFAULT '0.50', | ||||
|   "refract_scale_above" [float] NOT NULL DEFAULT '0.03', | ||||
|   "refract_scale_below" [float] NOT NULL DEFAULT '0.20', | ||||
|   "blur_multiplier" [float] NOT NULL DEFAULT '0.040', | ||||
|   "big_wave_direction_x" [float] NOT NULL DEFAULT '1.05', | ||||
|   "big_wave_direction_y" [float] NOT NULL DEFAULT '-0.42', | ||||
|   "little_wave_direction_x" [float] NOT NULL DEFAULT '1.11', | ||||
|   "little_wave_direction_y" [float] NOT NULL DEFAULT '-1.16', | ||||
|   "normal_map_texture" varchar(36) NOT NULL DEFAULT '822ded49-9a6c-f61c-cb89-6df54f42cdf4', | ||||
|   "horizon_r" [float] NOT NULL DEFAULT '0.25', | ||||
|   "horizon_g" [float] NOT NULL DEFAULT '0.25', | ||||
|   "horizon_b" [float] NOT NULL DEFAULT '0.32', | ||||
|   "horizon_i" [float] NOT NULL DEFAULT '0.32', | ||||
|   "haze_horizon" [float] NOT NULL DEFAULT '0.19', | ||||
|   "blue_density_r" [float] NOT NULL DEFAULT '0.12', | ||||
|   "blue_density_g" [float] NOT NULL DEFAULT '0.22', | ||||
|   "blue_density_b" [float] NOT NULL DEFAULT '0.38', | ||||
|   "blue_density_i" [float] NOT NULL DEFAULT '0.38', | ||||
|   "haze_density" [float] NOT NULL DEFAULT '0.70', | ||||
|   "density_multiplier" [float] NOT NULL DEFAULT '0.18', | ||||
|   "distance_multiplier" [float] NOT NULL DEFAULT '0.8', | ||||
|   "max_altitude" int NOT NULL DEFAULT '1605', | ||||
|   "sun_moon_color_r" [float] NOT NULL DEFAULT '0.24', | ||||
|   "sun_moon_color_g" [float] NOT NULL DEFAULT '0.26', | ||||
|   "sun_moon_color_b" [float] NOT NULL DEFAULT '0.30', | ||||
|   "sun_moon_color_i" [float] NOT NULL DEFAULT '0.30', | ||||
|   "sun_moon_position" [float] NOT NULL DEFAULT '0.317', | ||||
|   "ambient_r" [float] NOT NULL DEFAULT '0.35', | ||||
|   "ambient_g" [float] NOT NULL DEFAULT '0.35', | ||||
|   "ambient_b" [float] NOT NULL DEFAULT '0.35', | ||||
|   "ambient_i" [float] NOT NULL DEFAULT '0.35', | ||||
|   "east_angle" [float] NOT NULL DEFAULT '0.00', | ||||
|   "sun_glow_focus" [float] NOT NULL DEFAULT '0.10', | ||||
|   "sun_glow_size" [float] NOT NULL DEFAULT '1.75', | ||||
|   "scene_gamma" [float] NOT NULL DEFAULT '1.00', | ||||
|   "star_brightness" [float] NOT NULL DEFAULT '0.00', | ||||
|   "cloud_color_r" [float] NOT NULL DEFAULT '0.41', | ||||
|   "cloud_color_g" [float] NOT NULL DEFAULT '0.41', | ||||
|   "cloud_color_b" [float] NOT NULL DEFAULT '0.41', | ||||
|   "cloud_color_i" [float] NOT NULL DEFAULT '0.41', | ||||
|   "cloud_x" [float] NOT NULL DEFAULT '1.00', | ||||
|   "cloud_y" [float] NOT NULL DEFAULT '0.53', | ||||
|   "cloud_density" [float] NOT NULL DEFAULT '1.00', | ||||
|   "cloud_coverage" [float] NOT NULL DEFAULT '0.27', | ||||
|   "cloud_scale" [float] NOT NULL DEFAULT '0.42', | ||||
|   "cloud_detail_x" [float] NOT NULL DEFAULT '1.00', | ||||
|   "cloud_detail_y" [float] NOT NULL DEFAULT '0.53', | ||||
|   "cloud_detail_density" [float] NOT NULL DEFAULT '0.12', | ||||
|   "cloud_scroll_x" [float] NOT NULL DEFAULT '0.20', | ||||
|   "cloud_scroll_x_lock" tinyint NOT NULL DEFAULT '0', | ||||
|   "cloud_scroll_y" [float] NOT NULL DEFAULT '0.01', | ||||
|   "cloud_scroll_y_lock" tinyint NOT NULL DEFAULT '0', | ||||
|   "draw_classic_clouds" tinyint NOT NULL DEFAULT '1', | ||||
|   PRIMARY KEY ("region_id") | ||||
| ) | ||||
| 
 | ||||
| COMMIT TRANSACTION | ||||
| 
 | ||||
| :VERSION 26 | ||||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| 
 | ||||
| ALTER TABLE regionsettings ADD map_tile_ID CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000' | ||||
| 
 | ||||
| COMMIT | ||||
| 
 | ||||
| :VERSION 27         #--------------------- | ||||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| ALTER TABLE land ADD MediaType VARCHAR(32) NOT NULL DEFAULT 'none/none'  | ||||
| ALTER TABLE land ADD MediaDescription VARCHAR(255) NOT NULL DEFAULT '' | ||||
| ALTER TABLE land ADD MediaSize VARCHAR(16) NOT NULL DEFAULT '0,0' | ||||
| ALTER TABLE land ADD MediaLoop bit NOT NULL DEFAULT 0 | ||||
| ALTER TABLE land ADD ObscureMusic bit NOT NULL DEFAULT 0 | ||||
| ALTER TABLE land ADD ObscureMedia bit NOT NULL DEFAULT 0 | ||||
| COMMIT | ||||
| 
 | ||||
| :VERSION 28         #--------------------- | ||||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| 
 | ||||
| ALTER TABLE prims  | ||||
| ADD CONSTRAINT DF_prims_CreatorID  | ||||
| DEFAULT '00000000-0000-0000-0000-000000000000'  | ||||
| FOR CreatorID | ||||
| 
 | ||||
| ALTER TABLE prims  ALTER COLUMN CreatorID uniqueidentifier NOT NULL | ||||
| 
 | ||||
| ALTER TABLE primitems | ||||
| ADD CONSTRAINT DF_primitems_CreatorID  | ||||
| DEFAULT '00000000-0000-0000-0000-000000000000'  | ||||
| FOR CreatorID | ||||
| 
 | ||||
| ALTER TABLE primitems ALTER COLUMN CreatorID uniqueidentifier NOT NULL | ||||
| 
 | ||||
| COMMIT | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ CREATE TABLE [UserAccounts] ( | |||
| :VERSION 2 | ||||
| 
 | ||||
| BEGIN TRANSACTION | ||||
| 
 | ||||
| IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[users]') AND type in (N'U')) | ||||
| INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT [UUID] AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID,  | ||||
| username AS FirstName,  | ||||
| lastname AS LastName,  | ||||
|  |  | |||
|  | @ -592,9 +592,7 @@ namespace OpenSim.Framework.Console | |||
|             string line = ReadLine(m_defaultPrompt + "# ", true, true); | ||||
| 
 | ||||
|             if (line != String.Empty) | ||||
|             { | ||||
|                 m_log.Info("[CONSOLE] Invalid command"); | ||||
|             } | ||||
|                 Output("Invalid command"); | ||||
|         } | ||||
| 
 | ||||
|         public void RunCommand(string cmd) | ||||
|  |  | |||
|  | @ -572,34 +572,69 @@ namespace OpenSim.Framework | |||
| 
 | ||||
|     public class IEntityUpdate | ||||
|     { | ||||
|         public ISceneEntity Entity; | ||||
|         public uint Flags; | ||||
|         private ISceneEntity m_entity; | ||||
|         private uint m_flags; | ||||
|         private int m_updateTime; | ||||
| 
 | ||||
|         public ISceneEntity Entity | ||||
|         { | ||||
|             get { return m_entity; } | ||||
|         } | ||||
| 
 | ||||
|         public uint Flags | ||||
|         { | ||||
|             get { return m_flags; } | ||||
|         } | ||||
| 
 | ||||
|         public int UpdateTime | ||||
|         { | ||||
|             get { return m_updateTime; } | ||||
|         } | ||||
| 
 | ||||
|         public virtual void Update(IEntityUpdate update) | ||||
|         { | ||||
|             this.Flags |= update.Flags; | ||||
|             m_flags |= update.Flags; | ||||
| 
 | ||||
|             // Use the older of the updates as the updateTime | ||||
|             if (Util.EnvironmentTickCountCompare(UpdateTime, update.UpdateTime) > 0) | ||||
|                 m_updateTime = update.UpdateTime; | ||||
|         } | ||||
| 
 | ||||
|         public IEntityUpdate(ISceneEntity entity, uint flags) | ||||
|         { | ||||
|             Entity = entity; | ||||
|             Flags = flags; | ||||
|             m_entity = entity; | ||||
|             m_flags = flags; | ||||
|             m_updateTime = Util.EnvironmentTickCount(); | ||||
|         } | ||||
| 
 | ||||
|         public IEntityUpdate(ISceneEntity entity, uint flags, Int32 updateTime) | ||||
|         { | ||||
|             m_entity = entity; | ||||
|             m_flags = flags; | ||||
|             m_updateTime = updateTime; | ||||
|         } | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     public class EntityUpdate : IEntityUpdate | ||||
|     { | ||||
|         // public ISceneEntity Entity; | ||||
|         // public PrimUpdateFlags Flags; | ||||
|         public float TimeDilation; | ||||
|         private float m_timeDilation; | ||||
| 
 | ||||
|         public float TimeDilation | ||||
|         { | ||||
|             get { return m_timeDilation; } | ||||
|         } | ||||
| 
 | ||||
|         public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation) | ||||
|             : base(entity,(uint)flags) | ||||
|             : base(entity, (uint)flags) | ||||
|         { | ||||
|             //Entity = entity; | ||||
|             // Flags = flags; | ||||
|             TimeDilation = timedilation; | ||||
|             m_timeDilation = timedilation; | ||||
|         } | ||||
| 
 | ||||
|         public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation, Int32 updateTime) | ||||
|             : base(entity,(uint)flags,updateTime) | ||||
|         { | ||||
|             m_timeDilation = timedilation; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -34,50 +34,81 @@ using OpenSim.Framework; | |||
| using OpenSim.Framework.Client; | ||||
| using log4net; | ||||
| 
 | ||||
| namespace OpenSim.Region.ClientStack.LindenUDP | ||||
| namespace OpenSim.Framework | ||||
| { | ||||
|     public class PriorityQueue | ||||
|     { | ||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity); | ||||
|         public delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity); | ||||
| 
 | ||||
|         // Heap[0] for self updates | ||||
|         // Heap[1..12] for entity updates | ||||
|         /// <summary> | ||||
|         /// Total number of queues (priorities) available | ||||
|         /// </summary> | ||||
|         public const uint NumberOfQueues = 12; | ||||
| 
 | ||||
|         internal const uint m_numberOfQueues = 12; | ||||
|         /// <summary> | ||||
|         /// Number of queuest (priorities) that are processed immediately | ||||
|         /// </summary. | ||||
|         public const uint NumberOfImmediateQueues = 2; | ||||
| 
 | ||||
|         private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[m_numberOfQueues]; | ||||
|         private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[NumberOfQueues]; | ||||
|         private Dictionary<uint, LookupItem> m_lookupTable; | ||||
| 
 | ||||
|         // internal state used to ensure the deqeues are spread across the priority | ||||
|         // queues "fairly". queuecounts is the amount to pull from each queue in  | ||||
|         // each pass. weighted towards the higher priority queues | ||||
|         private uint m_nextQueue = 0; | ||||
|         private uint m_countFromQueue = 0; | ||||
|         private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 }; | ||||
| 
 | ||||
|         // next request is a counter of the number of updates queued, it provides | ||||
|         // a total ordering on the updates coming through the queue and is more | ||||
|         // lightweight (and more discriminating) than tick count | ||||
|         private UInt64 m_nextRequest = 0; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Lock for enqueue and dequeue operations on the priority queue | ||||
|         /// </summary> | ||||
|         private object m_syncRoot = new object(); | ||||
|         public object SyncRoot { | ||||
|             get { return this.m_syncRoot; } | ||||
|         } | ||||
| 
 | ||||
|         internal PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { } | ||||
| #region constructor | ||||
|         public PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { } | ||||
| 
 | ||||
|         internal PriorityQueue(int capacity) | ||||
|         public PriorityQueue(int capacity) | ||||
|         { | ||||
|             m_lookupTable = new Dictionary<uint, LookupItem>(capacity); | ||||
| 
 | ||||
|             for (int i = 0; i < m_heaps.Length; ++i) | ||||
|                 m_heaps[i] = new MinHeap<MinHeapItem>(capacity); | ||||
|         } | ||||
| 
 | ||||
|         internal int Count | ||||
|             m_nextQueue = NumberOfImmediateQueues; | ||||
|             m_countFromQueue = m_queueCounts[m_nextQueue]; | ||||
|         } | ||||
| #endregion Constructor | ||||
| 
 | ||||
| #region PublicMethods | ||||
|         /// <summary> | ||||
|         /// Return the number of items in the queues | ||||
|         /// </summary> | ||||
|         public int Count | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 int count = 0; | ||||
|                 for (int i = 0; i < m_heaps.Length; ++i) | ||||
|                     count += m_heaps[i].Count; | ||||
|                  | ||||
|                 return count; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Enqueue an item into the specified priority queue | ||||
|         /// </summary> | ||||
|         public bool Enqueue(uint pqueue, IEntityUpdate value) | ||||
|         { | ||||
|             LookupItem lookup; | ||||
|  | @ -91,7 +122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                 lookup.Heap.Remove(lookup.Handle); | ||||
|             } | ||||
| 
 | ||||
|             pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1); | ||||
|             pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1); | ||||
|             lookup.Heap = m_heaps[pqueue]; | ||||
|             lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle); | ||||
|             m_lookupTable[localid] = lookup; | ||||
|  | @ -99,20 +130,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         internal bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue) | ||||
|         /// <summary> | ||||
|         /// Remove an item from one of the queues. Specifically, it removes the | ||||
|         /// oldest item from the next queue in order to provide fair access to | ||||
|         /// all of the queues | ||||
|         /// </summary> | ||||
|         public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue) | ||||
|         { | ||||
|             for (int i = 0; i < m_numberOfQueues; ++i) | ||||
|             // If there is anything in priority queue 0, return it first no | ||||
|             // matter what else. Breaks fairness. But very useful. | ||||
|             for (int iq = 0; iq < NumberOfImmediateQueues; iq++) | ||||
|             { | ||||
|                 // To get the fair queing, we cycle through each of the | ||||
|                 // queues when finding an element to dequeue, this code | ||||
|                 // assumes that the distribution of updates in the queues | ||||
|                 // is polynomial, probably quadractic (eg distance of PI * R^2) | ||||
|                 uint h = (uint)((m_nextQueue + i) % m_numberOfQueues); | ||||
|                 if (m_heaps[h].Count > 0) | ||||
|                 if (m_heaps[iq].Count > 0) | ||||
|                 { | ||||
|                     m_nextQueue = (uint)((h + 1) % m_numberOfQueues); | ||||
|                     MinHeapItem item = m_heaps[iq].RemoveMin(); | ||||
|                     m_lookupTable.Remove(item.Value.Entity.LocalId); | ||||
|                     timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); | ||||
|                     value = item.Value; | ||||
| 
 | ||||
|                     MinHeapItem item = m_heaps[h].RemoveMin(); | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             // To get the fair queing, we cycle through each of the | ||||
|             // queues when finding an element to dequeue.  | ||||
|             // We pull (NumberOfQueues - QueueIndex) items from each queue in order | ||||
|             // to give lower numbered queues a higher priority and higher percentage | ||||
|             // of the bandwidth.  | ||||
|              | ||||
|             // Check for more items to be pulled from the current queue | ||||
|             if (m_heaps[m_nextQueue].Count > 0 && m_countFromQueue > 0) | ||||
|             { | ||||
|                 m_countFromQueue--; | ||||
|                  | ||||
|                 MinHeapItem item = m_heaps[m_nextQueue].RemoveMin(); | ||||
|                 m_lookupTable.Remove(item.Value.Entity.LocalId); | ||||
|                 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); | ||||
|                 value = item.Value; | ||||
|                  | ||||
|                 return true; | ||||
|             } | ||||
|              | ||||
|             // Find the next non-immediate queue with updates in it | ||||
|             for (int i = 0; i < NumberOfQueues; ++i) | ||||
|             { | ||||
|                 m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues); | ||||
|                 m_countFromQueue = m_queueCounts[m_nextQueue]; | ||||
| 
 | ||||
|                 // if this is one of the immediate queues, just skip it | ||||
|                 if (m_nextQueue < NumberOfImmediateQueues) | ||||
|                     continue; | ||||
|                  | ||||
|                 if (m_heaps[m_nextQueue].Count > 0) | ||||
|                 { | ||||
|                     m_countFromQueue--; | ||||
| 
 | ||||
|                     MinHeapItem item = m_heaps[m_nextQueue].RemoveMin(); | ||||
|                     m_lookupTable.Remove(item.Value.Entity.LocalId); | ||||
|                     timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); | ||||
|                     value = item.Value; | ||||
|  | @ -126,7 +199,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         internal void Reprioritize(UpdatePriorityHandler handler) | ||||
|         /// <summary> | ||||
|         /// Reapply the prioritization function to each of the updates currently | ||||
|         /// stored in the priority queues.  | ||||
|         /// </summary | ||||
|         public void Reprioritize(UpdatePriorityHandler handler) | ||||
|         { | ||||
|             MinHeapItem item; | ||||
|             foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values)) | ||||
|  | @ -140,7 +217,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                     { | ||||
|                         // unless the priority queue has changed, there is no need to modify | ||||
|                         // the entry | ||||
|                         pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1); | ||||
|                         pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1); | ||||
|                         if (pqueue != item.PriorityQueue) | ||||
|                         { | ||||
|                             lookup.Heap.Remove(lookup.Handle); | ||||
|  | @ -161,17 +238,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// </summary> | ||||
|         public override string ToString() | ||||
|         { | ||||
|             string s = ""; | ||||
|             for (int i = 0; i < m_numberOfQueues; i++) | ||||
|             { | ||||
|                 if (s != "") s += ","; | ||||
|                 s += m_heaps[i].Count.ToString(); | ||||
|             } | ||||
|             for (int i = 0; i < NumberOfQueues; i++) | ||||
|                 s += String.Format("{0,7} ",m_heaps[i].Count); | ||||
|             return s; | ||||
|         } | ||||
| 
 | ||||
| #endregion PublicMethods | ||||
| 
 | ||||
| #region MinHeapItem | ||||
|         private struct MinHeapItem : IComparable<MinHeapItem> | ||||
|         { | ||||
|  | @ -369,6 +369,7 @@ namespace OpenSim.Framework | |||
|         private int m_physPrimMax = 0; | ||||
|         private bool m_clampPrimSize = false; | ||||
|         private int m_objectCapacity = 0; | ||||
|         private int m_agentCapacity = 0; | ||||
|         private string m_regionType = String.Empty; | ||||
|         private RegionLightShareData m_windlight = new RegionLightShareData(); | ||||
|         protected uint m_httpPort; | ||||
|  | @ -547,6 +548,11 @@ namespace OpenSim.Framework | |||
|             get { return m_objectCapacity; } | ||||
|         } | ||||
| 
 | ||||
|         public int AgentCapacity | ||||
|         { | ||||
|             get { return m_agentCapacity; } | ||||
|         } | ||||
| 
 | ||||
|         public byte AccessLevel | ||||
|         { | ||||
|             get { return (byte)Util.ConvertMaturityToAccessLevel((uint)RegionSettings.Maturity); } | ||||
|  | @ -821,6 +827,8 @@ namespace OpenSim.Framework | |||
| 
 | ||||
|             m_objectCapacity = config.GetInt("MaxPrims", 15000); | ||||
| 
 | ||||
|             m_agentCapacity = config.GetInt("MaxAgents", 100); | ||||
| 
 | ||||
| 
 | ||||
|             // Multi-tenancy | ||||
|             // | ||||
|  | @ -857,6 +865,9 @@ namespace OpenSim.Framework | |||
|             if (m_objectCapacity != 0) | ||||
|                 config.Set("MaxPrims", m_objectCapacity); | ||||
| 
 | ||||
|             if (m_agentCapacity != 0) | ||||
|                 config.Set("MaxAgents", m_agentCapacity); | ||||
| 
 | ||||
|             if (ScopeID != UUID.Zero) | ||||
|                 config.Set("ScopeID", ScopeID.ToString()); | ||||
| 
 | ||||
|  | @ -943,6 +954,9 @@ namespace OpenSim.Framework | |||
|             configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, | ||||
|                                                 "Max objects this sim will hold", m_objectCapacity.ToString(), true); | ||||
| 
 | ||||
|             configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, | ||||
|                                                 "Max avatars this sim will hold", m_agentCapacity.ToString(), true); | ||||
| 
 | ||||
|             configMember.addConfigurationOption("scope_id", ConfigurationOption.ConfigurationTypes.TYPE_UUID, | ||||
|                                                 "Scope ID for this region", ScopeID.ToString(), true); | ||||
| 
 | ||||
|  | @ -1055,6 +1069,9 @@ namespace OpenSim.Framework | |||
|                 case "object_capacity": | ||||
|                     m_objectCapacity = (int)configuration_result; | ||||
|                     break; | ||||
|                 case "agent_capacity": | ||||
|                     m_agentCapacity = (int)configuration_result; | ||||
|                     break; | ||||
|                 case "scope_id": | ||||
|                     ScopeID = (UUID)configuration_result; | ||||
|                     break; | ||||
|  |  | |||
|  | @ -430,7 +430,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
|                 string path = request.RawUrl; | ||||
|                 string handlerKey = GetHandlerKey(request.HttpMethod, path); | ||||
| 
 | ||||
|                 //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); | ||||
| //                m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); | ||||
| 
 | ||||
|                 if (TryGetStreamHandler(handlerKey, out requestHandler)) | ||||
|                 { | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ namespace OpenSim | |||
| { | ||||
|     public class VersionInfo | ||||
|     { | ||||
|         private const string VERSION_NUMBER = "0.7.1"; | ||||
|         private const string VERSION_NUMBER = "0.7.2"; | ||||
|         private const Flavour VERSION_FLAVOUR = Flavour.Dev; | ||||
| 
 | ||||
|         public enum Flavour | ||||
|  |  | |||
|  | @ -1537,6 +1537,23 @@ namespace OpenSim.Framework | |||
|             return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1); | ||||
|         } | ||||
| 
 | ||||
|         // Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount | ||||
|         // Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount(). | ||||
|         // A positive return value indicates A occured later than B | ||||
|         public static Int32 EnvironmentTickCountCompare(Int32 tcA, Int32 tcB) | ||||
|         { | ||||
|             // A, B and TC are all between 0 and 0x3fffffff | ||||
|             int tc = EnvironmentTickCount(); | ||||
| 
 | ||||
|             if (tc - tcA >= 0) | ||||
|                 tcA += EnvironmentTickCountMask + 1; | ||||
| 
 | ||||
|             if (tc - tcB >= 0) | ||||
|                 tcB += EnvironmentTickCountMask + 1; | ||||
| 
 | ||||
|             return tcA - tcB; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Prints the call stack at any given point. Useful for debugging. | ||||
|         /// </summary> | ||||
|  |  | |||
|  | @ -384,6 +384,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } | ||||
|         public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Entity update queues | ||||
|         /// </summary> | ||||
|         public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } } | ||||
|          | ||||
|         /// <summary> | ||||
|         /// First name of the agent/avatar represented by the client | ||||
|         /// </summary> | ||||
|  | @ -3561,6 +3566,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Requeue an EntityUpdate when it was not acknowledged by the client.  | ||||
|         /// We will update the priority and put it in the correct queue, merging update flags  | ||||
|         /// with any other updates that may be queued for the same entity.  | ||||
|         /// The original update time is used for the merged update. | ||||
|         /// </summary> | ||||
|         private void ResendPrimUpdate(EntityUpdate update) | ||||
|         { | ||||
|             // If the update exists in priority queue, it will be updated. | ||||
|             // If it does not exist then it will be added with the current (rather than its original) priority | ||||
|             uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); | ||||
| 
 | ||||
|             lock (m_entityUpdates.SyncRoot) | ||||
|                 m_entityUpdates.Enqueue(priority, update); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Requeue a list of EntityUpdates when they were not acknowledged by the client.  | ||||
|         /// We will update the priority and put it in the correct queue, merging update flags  | ||||
|         /// with any other updates that may be queued for the same entity.  | ||||
|         /// The original update time is used for the merged update. | ||||
|         /// </summary> | ||||
|         private void ResendPrimUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket) | ||||
|         { | ||||
|             // m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime); | ||||
| 
 | ||||
|             // Remove the update packet from the list of packets waiting for acknowledgement | ||||
|             // because we are requeuing the list of updates. They will be resent in new packets | ||||
|             // with the most recent state and priority. | ||||
|             m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); | ||||
| 
 | ||||
|             // Count this as a resent packet since we are going to requeue all of the updates contained in it | ||||
|             Interlocked.Increment(ref m_udpClient.PacketsResent); | ||||
| 
 | ||||
|             foreach (EntityUpdate update in updates) | ||||
|                 ResendPrimUpdate(update); | ||||
|         } | ||||
| 
 | ||||
|         private void ProcessEntityUpdates(int maxUpdates) | ||||
|         { | ||||
|             OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); | ||||
|  | @ -3568,6 +3611,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); | ||||
|             OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); | ||||
| 
 | ||||
|             OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||||
|             OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||||
|             OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||||
|             OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||||
| 
 | ||||
|             // Check to see if this is a flush | ||||
|             if (maxUpdates <= 0) | ||||
|             { | ||||
|  | @ -3583,7 +3631,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                 float avgTimeDilation = 1.0f; | ||||
|                 IEntityUpdate iupdate; | ||||
|                 Int32 timeinqueue; // this is just debugging code & can be dropped later | ||||
|                  | ||||
| 
 | ||||
|                 while (updatesThisCall < maxUpdates) | ||||
|                 { | ||||
|                     lock (m_entityUpdates.SyncRoot) | ||||
|  | @ -3688,24 +3736,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                         if (update.Entity is ScenePresence) | ||||
|                         { | ||||
|                             objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); | ||||
|                             objectUpdates.Value.Add(update); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); | ||||
|                             objectUpdates.Value.Add(update); | ||||
|                         } | ||||
|                     } | ||||
|                     else if (!canUseImproved) | ||||
|                     { | ||||
|                         compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); | ||||
|                         compressedUpdates.Value.Add(update); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) | ||||
|                         { | ||||
|                             // Self updates go into a special list | ||||
|                             terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); | ||||
|                             terseAgentUpdates.Value.Add(update); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             // Everything else goes here | ||||
|                             terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); | ||||
|                             terseUpdates.Value.Add(update); | ||||
|                         } | ||||
|                     } | ||||
|      | ||||
|                     #endregion Block Construction | ||||
|  | @ -3713,28 +3770,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                  | ||||
|      | ||||
|                 #region Packet Sending | ||||
|          | ||||
|                 //const float TIME_DILATION = 1.0f; | ||||
| 
 | ||||
| 
 | ||||
|                 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); | ||||
|      | ||||
| 
 | ||||
|                 if (terseAgentUpdateBlocks.IsValueCreated) | ||||
|                 { | ||||
|                     List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; | ||||
|      | ||||
| 
 | ||||
|                     ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); | ||||
|                     packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | ||||
|                     packet.RegionData.TimeDilation = timeDilation; | ||||
|                     packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | ||||
|      | ||||
| 
 | ||||
|                     for (int i = 0; i < blocks.Count; i++) | ||||
|                         packet.ObjectData[i] = blocks[i]; | ||||
| 
 | ||||
|                      | ||||
|                     OutPacket(packet, ThrottleOutPacketType.Unknown, true); | ||||
|                     // If any of the packets created from this call go unacknowledged, all of the updates will be resent | ||||
|                     OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); | ||||
|                 } | ||||
|      | ||||
| 
 | ||||
|                 if (objectUpdateBlocks.IsValueCreated) | ||||
|                 { | ||||
|                     List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; | ||||
|  | @ -3746,8 +3798,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|          | ||||
|                     for (int i = 0; i < blocks.Count; i++) | ||||
|                         packet.ObjectData[i] = blocks[i]; | ||||
|          | ||||
|                     OutPacket(packet, ThrottleOutPacketType.Task, true); | ||||
|                     // If any of the packets created from this call go unacknowledged, all of the updates will be resent | ||||
|                     OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); }); | ||||
|                 } | ||||
|          | ||||
|                 if (compressedUpdateBlocks.IsValueCreated) | ||||
|  | @ -3761,10 +3813,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|          | ||||
|                     for (int i = 0; i < blocks.Count; i++) | ||||
|                         packet.ObjectData[i] = blocks[i]; | ||||
|          | ||||
|                     OutPacket(packet, ThrottleOutPacketType.Task, true); | ||||
|                     // If any of the packets created from this call go unacknowledged, all of the updates will be resent | ||||
|                     OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); }); | ||||
|                 } | ||||
|          | ||||
| 
 | ||||
|                 if (terseUpdateBlocks.IsValueCreated) | ||||
|                 { | ||||
|                     List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; | ||||
|  | @ -3776,8 +3828,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|          | ||||
|                     for (int i = 0; i < blocks.Count; i++) | ||||
|                         packet.ObjectData[i] = blocks[i]; | ||||
|          | ||||
|                     OutPacket(packet, ThrottleOutPacketType.Task, true); | ||||
|                     // If any of the packets created from this call go unacknowledged, all of the updates will be resent | ||||
|                     OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|  | @ -3969,7 +4021,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             { | ||||
|                 SendFamilyProps = SendFamilyProps || update.SendFamilyProps; | ||||
|                 SendObjectProps = SendObjectProps || update.SendObjectProps; | ||||
|                 Flags |= update.Flags; | ||||
|                 // other properties may need to be updated by base class | ||||
|                 base.Update(update); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|  | @ -3980,6 +4033,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); | ||||
|         } | ||||
| 
 | ||||
|         private void ResendPropertyUpdate(ObjectPropertyUpdate update) | ||||
|         { | ||||
|             uint priority = 0; | ||||
|             lock (m_entityProps.SyncRoot) | ||||
|                 m_entityProps.Enqueue(priority, update); | ||||
|         } | ||||
| 
 | ||||
|         private void ResendPropertyUpdates(List<ObjectPropertyUpdate> updates, OutgoingPacket oPacket) | ||||
|         { | ||||
|             // m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime); | ||||
| 
 | ||||
|             // Remove the update packet from the list of packets waiting for acknowledgement | ||||
|             // because we are requeuing the list of updates. They will be resent in new packets | ||||
|             // with the most recent state. | ||||
|             m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); | ||||
| 
 | ||||
|             // Count this as a resent packet since we are going to requeue all of the updates contained in it | ||||
|             Interlocked.Increment(ref m_udpClient.PacketsResent); | ||||
| 
 | ||||
|             foreach (ObjectPropertyUpdate update in updates) | ||||
|                 ResendPropertyUpdate(update); | ||||
|         } | ||||
|          | ||||
|         public void SendObjectPropertiesReply(ISceneEntity entity) | ||||
|         { | ||||
|             uint priority = 0;  // time based ordering only | ||||
|  | @ -3995,6 +4071,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks = | ||||
|                 new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>(); | ||||
| 
 | ||||
|             OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates = | ||||
|                 new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>(); | ||||
| 
 | ||||
|             OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates = | ||||
|                 new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>(); | ||||
|              | ||||
|             IEntityUpdate iupdate; | ||||
|             Int32 timeinqueue; // this is just debugging code & can be dropped later | ||||
| 
 | ||||
|  | @ -4013,6 +4095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                         SceneObjectPart sop = (SceneObjectPart)update.Entity; | ||||
|                         ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); | ||||
|                         objectFamilyBlocks.Value.Add(objPropDB); | ||||
|                         familyUpdates.Value.Add(update); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|  | @ -4023,6 +4106,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                         SceneObjectPart sop = (SceneObjectPart)update.Entity; | ||||
|                         ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); | ||||
|                         objectPropertiesBlocks.Value.Add(objPropDB); | ||||
|                         propertyUpdates.Value.Add(update); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|  | @ -4030,12 +4114,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             } | ||||
|              | ||||
| 
 | ||||
|             Int32 ppcnt = 0; | ||||
|             Int32 pbcnt = 0; | ||||
|             // Int32 ppcnt = 0; | ||||
|             // Int32 pbcnt = 0; | ||||
|              | ||||
|             if (objectPropertiesBlocks.IsValueCreated) | ||||
|             { | ||||
|                 List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value; | ||||
|                 List<ObjectPropertyUpdate> updates = propertyUpdates.Value; | ||||
| 
 | ||||
|                 ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); | ||||
|                 packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count]; | ||||
|  | @ -4043,28 +4128,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                     packet.ObjectData[i] = blocks[i]; | ||||
| 
 | ||||
|                 packet.Header.Zerocoded = true; | ||||
|                 OutPacket(packet, ThrottleOutPacketType.Task, true); | ||||
| 
 | ||||
|                 pbcnt += blocks.Count; | ||||
|                 ppcnt++; | ||||
|                 // Pass in the delegate so that if this packet needs to be resent, we send the current properties | ||||
|                 // of the object rather than the properties when the packet was created | ||||
|                 OutPacket(packet, ThrottleOutPacketType.Task, true, | ||||
|                           delegate(OutgoingPacket oPacket) | ||||
|                           { | ||||
|                               ResendPropertyUpdates(updates, oPacket); | ||||
|                           }); | ||||
| 
 | ||||
|                 // pbcnt += blocks.Count; | ||||
|                 // ppcnt++; | ||||
|             } | ||||
|              | ||||
|             Int32 fpcnt = 0; | ||||
|             Int32 fbcnt = 0; | ||||
|             // Int32 fpcnt = 0; | ||||
|             // Int32 fbcnt = 0; | ||||
|              | ||||
|             if (objectFamilyBlocks.IsValueCreated) | ||||
|             { | ||||
|                 List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value; | ||||
| 
 | ||||
|                 // ObjectPropertiesFamilyPacket objPropFamilyPack = | ||||
|                 //     (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); | ||||
|                 // | ||||
|                 // objPropFamilyPack.ObjectData = new ObjectPropertiesFamilyPacket.ObjectDataBlock[blocks.Count]; | ||||
|                 // for (int i = 0; i < blocks.Count; i++) | ||||
|                 //     objPropFamilyPack.ObjectData[i] = blocks[i]; | ||||
|                 // | ||||
|                 // OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task, true); | ||||
| 
 | ||||
|                  | ||||
|                 // one packet per object block... uggh... | ||||
|                 for (int i = 0; i < blocks.Count; i++) | ||||
|                 { | ||||
|  | @ -4073,10 +4156,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
| 
 | ||||
|                     packet.ObjectData = blocks[i]; | ||||
|                     packet.Header.Zerocoded = true; | ||||
|                     OutPacket(packet, ThrottleOutPacketType.Task); | ||||
| 
 | ||||
|                     fpcnt++; | ||||
|                     fbcnt++; | ||||
|                     // Pass in the delegate so that if this packet needs to be resent, we send the current properties | ||||
|                     // of the object rather than the properties when the packet was created | ||||
|                     List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); | ||||
|                     updates.Add(familyUpdates.Value[i]); | ||||
|                     OutPacket(packet, ThrottleOutPacketType.Task, true, | ||||
|                               delegate(OutgoingPacket oPacket) | ||||
|                               { | ||||
|                                   ResendPropertyUpdates(updates, oPacket); | ||||
|                               }); | ||||
| 
 | ||||
|                     // fpcnt++; | ||||
|                     // fbcnt++; | ||||
|                 } | ||||
|                  | ||||
|             } | ||||
|  | @ -4113,7 +4205,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
| 
 | ||||
|             return block; | ||||
|         } | ||||
| 
 | ||||
|      | ||||
|         private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop) | ||||
|         { | ||||
|             //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); | ||||
|  | @ -4764,7 +4856,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             data.RelativePosition.ToBytes(objectData, 0); | ||||
|             data.Velocity.ToBytes(objectData, 12); | ||||
|             data.Acceleration.ToBytes(objectData, 24); | ||||
|             data.RotationOffset.ToBytes(objectData, 36); | ||||
|             try | ||||
|             { | ||||
|                 data.RotationOffset.ToBytes(objectData, 36); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString()); | ||||
|                 OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36); | ||||
|             } | ||||
|             data.AngularVelocity.ToBytes(objectData, 48); | ||||
| 
 | ||||
|             ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); | ||||
|  | @ -11328,7 +11428,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// <returns></returns> | ||||
|         public byte[] GetThrottlesPacked(float multiplier) | ||||
|         { | ||||
|             return m_udpClient.GetThrottlesPacked(); | ||||
|             return m_udpClient.GetThrottlesPacked(multiplier); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -11362,6 +11462,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// packets (the default), or false to disable splitting if the calling code | ||||
|         /// handles splitting manually</param> | ||||
|         protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) | ||||
|         { | ||||
|             OutPacket(packet, throttlePacketType, doAutomaticSplitting, null); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// This is the starting point for sending a simulator packet out to the client | ||||
|         /// </summary> | ||||
|         /// <param name="packet">Packet to send</param> | ||||
|         /// <param name="throttlePacketType">Throttling category for the packet</param> | ||||
|         /// <param name="doAutomaticSplitting">True to automatically split oversized | ||||
|         /// packets (the default), or false to disable splitting if the calling code | ||||
|         /// handles splitting manually</param> | ||||
|         /// <param name="method">The method to be called in the event this packet is reliable | ||||
|         /// and unacknowledged. The server will provide normal resend capability if you do not | ||||
|         /// provide your own method.</param> | ||||
|         protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) | ||||
|         { | ||||
|             if (m_debugPacketLevel > 0) | ||||
|             { | ||||
|  | @ -11388,7 +11504,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                     m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); | ||||
|             } | ||||
|              | ||||
|             m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); | ||||
|             m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); | ||||
|         } | ||||
| 
 | ||||
|         public bool AddMoney(int debit) | ||||
|  |  | |||
|  | @ -135,7 +135,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         private int m_nextOnQueueEmpty = 1; | ||||
| 
 | ||||
|         /// <summary>Throttle bucket for this agent's connection</summary> | ||||
|         private readonly TokenBucket m_throttleClient; | ||||
|         private readonly AdaptiveTokenBucket m_throttleClient; | ||||
|         public AdaptiveTokenBucket FlowThrottle | ||||
|         { | ||||
|             get { return m_throttleClient; } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary>Throttle bucket for this agent's connection</summary> | ||||
|         private readonly TokenBucket m_throttleCategory; | ||||
|         /// <summary>Throttle buckets for each packet category</summary> | ||||
|  | @ -176,9 +181,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                 m_maxRTO = maxRTO; | ||||
| 
 | ||||
|             // Create a token bucket throttle for this client that has the scene token bucket as a parent | ||||
|             m_throttleClient = new TokenBucket(parentThrottle, rates.TotalLimit); | ||||
|             m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled); | ||||
|             // Create a token bucket throttle for the total categary with the client bucket as a throttle | ||||
|             m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit); | ||||
|             m_throttleCategory = new TokenBucket(m_throttleClient, 0); | ||||
|             // Create an array of token buckets for this clients different throttle categories | ||||
|             m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; | ||||
| 
 | ||||
|  | @ -189,7 +194,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                 // Initialize the packet outboxes, where packets sit while they are waiting for tokens | ||||
|                 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); | ||||
|                 // Initialize the token buckets that control the throttling for each category | ||||
|                 m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetLimit(type)); | ||||
|                 m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type)); | ||||
|             } | ||||
| 
 | ||||
|             // Default the retransmission timeout to three seconds | ||||
|  | @ -223,26 +228,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// <returns>Information about the client connection</returns> | ||||
|         public ClientInfo GetClientInfo() | ||||
|         { | ||||
| ///<mic> | ||||
|             TokenBucket tb; | ||||
| 
 | ||||
|             tb = m_throttleClient.Parent; | ||||
|             m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"ROOT"); | ||||
| 
 | ||||
|             tb = m_throttleClient; | ||||
|             m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"  CLIENT"); | ||||
| 
 | ||||
|             tb = m_throttleCategory; | ||||
|             m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"    CATEGORY"); | ||||
| 
 | ||||
|             for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) | ||||
|             { | ||||
|                 tb = m_throttleCategories[i]; | ||||
|                 m_log.WarnFormat("[TOKENS] {4} <{0}:{1}>: Actual={2},Requested={3}",AgentID,i,tb.DripRate,tb.RequestedDripRate,"      BUCKET"); | ||||
|             } | ||||
|                  | ||||
| ///</mic> | ||||
| 
 | ||||
|             // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists | ||||
|             // of pending and needed ACKs for every client every time some method wants information about | ||||
|             // this connection is a recipe for poor performance | ||||
|  | @ -254,12 +239,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; | ||||
|             info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; | ||||
|             info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; | ||||
|             // info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; | ||||
|             info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; | ||||
|             info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; | ||||
|             info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; | ||||
|             info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + | ||||
|                 info.taskThrottle + info.assetThrottle + info.textureThrottle; | ||||
|             info.totalThrottle = (int)m_throttleCategory.DripRate; | ||||
| 
 | ||||
|             return info; | ||||
|         } | ||||
|  | @ -346,8 +329,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); | ||||
|             // State is a subcategory of task that we allocate a percentage to | ||||
|             int state = 0; | ||||
|             // int state = (int)((float)task * STATE_TASK_PERCENTAGE); | ||||
|             // task -= state; | ||||
| 
 | ||||
|             // Make sure none of the throttles are set below our packet MTU, | ||||
|             // otherwise a throttle could become permanently clogged | ||||
|  | @ -358,19 +339,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             task = Math.Max(task, LLUDPServer.MTU); | ||||
|             texture = Math.Max(texture, LLUDPServer.MTU); | ||||
|             asset = Math.Max(asset, LLUDPServer.MTU); | ||||
|             state = Math.Max(state, LLUDPServer.MTU); | ||||
| 
 | ||||
|             int total = resend + land + wind + cloud + task + texture + asset + state; | ||||
| 
 | ||||
|             //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}", | ||||
|             //    AgentID, resend, land, wind, cloud, task, texture, asset, state, total); | ||||
|             //int total = resend + land + wind + cloud + task + texture + asset; | ||||
|             //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", | ||||
|             //                  AgentID, resend, land, wind, cloud, task, texture, asset, total); | ||||
| 
 | ||||
|             // Update the token buckets with new throttle values | ||||
|             TokenBucket bucket; | ||||
| 
 | ||||
|             bucket = m_throttleCategory; | ||||
|             bucket.RequestedDripRate = total; | ||||
| 
 | ||||
|             bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; | ||||
|             bucket.RequestedDripRate = resend; | ||||
| 
 | ||||
|  | @ -399,22 +375,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             m_packedThrottles = null; | ||||
|         } | ||||
| 
 | ||||
|         public byte[] GetThrottlesPacked() | ||||
|         public byte[] GetThrottlesPacked(float multiplier) | ||||
|         { | ||||
|             byte[] data = m_packedThrottles; | ||||
| 
 | ||||
|             if (data == null) | ||||
|             { | ||||
|                 float rate; | ||||
| 
 | ||||
|                 data = new byte[7 * 4]; | ||||
|                 int i = 0; | ||||
| 
 | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 0, data, i, 4); i += 4; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate), 0, data, i, 4); i += 4; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate), 0, data, i, 4); i += 4; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4; | ||||
|                 // multiply by 8 to convert bytes back to bits | ||||
|                 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||||
| 
 | ||||
|                 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||||
| 
 | ||||
|                 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||||
| 
 | ||||
|                 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||||
| 
 | ||||
|                 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||||
| 
 | ||||
|                 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||||
| 
 | ||||
|                 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier; | ||||
|                 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; | ||||
| 
 | ||||
|                 m_packedThrottles = data; | ||||
|             } | ||||
|  |  | |||
|  | @ -297,7 +297,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                         delegate(IClientAPI client) | ||||
|                         { | ||||
|                             if (client is LLClientView) | ||||
|                                 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); | ||||
|                                 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|  | @ -309,7 +309,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                     delegate(IClientAPI client) | ||||
|                     { | ||||
|                         if (client is LLClientView) | ||||
|                             SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); | ||||
|                             SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|  | @ -322,7 +322,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// <param name="packet"></param> | ||||
|         /// <param name="category"></param> | ||||
|         /// <param name="allowSplitting"></param> | ||||
|         public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting) | ||||
|         public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method) | ||||
|         { | ||||
|             // CoarseLocationUpdate packets cannot be split in an automated way | ||||
|             if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) | ||||
|  | @ -339,13 +339,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                 for (int i = 0; i < packetCount; i++) | ||||
|                 { | ||||
|                     byte[] data = datas[i]; | ||||
|                     SendPacketData(udpClient, data, packet.Type, category); | ||||
|                     SendPacketData(udpClient, data, packet.Type, category, method); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 byte[] data = packet.ToBytes(); | ||||
|                 SendPacketData(udpClient, data, packet.Type, category); | ||||
|                 SendPacketData(udpClient, data, packet.Type, category, method); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -356,7 +356,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// <param name="data"></param> | ||||
|         /// <param name="type"></param> | ||||
|         /// <param name="category"></param>         | ||||
|         public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category) | ||||
|         public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method) | ||||
|         { | ||||
|             int dataLength = data.Length; | ||||
|             bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; | ||||
|  | @ -411,7 +411,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
| 
 | ||||
|             #region Queue or Send | ||||
| 
 | ||||
|             OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); | ||||
|             OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); | ||||
|             // If we were not provided a method for handling unacked, use the UDPServer default method | ||||
|             outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); | ||||
| 
 | ||||
|             // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will  | ||||
|             // continue to display the deleted object until relog.  Therefore, we need to always queue a kill object | ||||
|  | @ -445,7 +447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                 packet.Header.Reliable = false; | ||||
|                 packet.Packets = blocks.ToArray(); | ||||
| 
 | ||||
|                 SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true); | ||||
|                 SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true, null); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -458,17 +460,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit | ||||
|             pc.PingID.OldestUnacked = 0; | ||||
| 
 | ||||
|             SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false); | ||||
|             SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null); | ||||
|         } | ||||
| 
 | ||||
|         public void CompletePing(LLUDPClient udpClient, byte pingID) | ||||
|         { | ||||
|             CompletePingCheckPacket completePing = new CompletePingCheckPacket(); | ||||
|             completePing.PingID.PingID = pingID; | ||||
|             SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false); | ||||
|             SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); | ||||
|         } | ||||
| 
 | ||||
|         public void ResendUnacked(LLUDPClient udpClient) | ||||
|         public void HandleUnacked(LLUDPClient udpClient) | ||||
|         { | ||||
|             if (!udpClient.IsConnected) | ||||
|                 return; | ||||
|  | @ -488,33 +490,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
| 
 | ||||
|             if (expiredPackets != null) | ||||
|             { | ||||
|                 //m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); | ||||
| 
 | ||||
|                 //m_log.Debug("[LLUDPSERVER]: Handling " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); | ||||
|                 // Exponential backoff of the retransmission timeout | ||||
|                 udpClient.BackoffRTO(); | ||||
| 
 | ||||
|                 // Resend packets | ||||
|                 for (int i = 0; i < expiredPackets.Count; i++) | ||||
|                 { | ||||
|                     OutgoingPacket outgoingPacket = expiredPackets[i]; | ||||
| 
 | ||||
|                     //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed", | ||||
|                     //    outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount); | ||||
| 
 | ||||
|                     // Set the resent flag | ||||
|                     outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT); | ||||
|                     outgoingPacket.Category = ThrottleOutPacketType.Resend; | ||||
| 
 | ||||
|                     // Bump up the resend count on this packet | ||||
|                     Interlocked.Increment(ref outgoingPacket.ResendCount); | ||||
| 
 | ||||
|                     // Requeue or resend the packet | ||||
|                     if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) | ||||
|                         SendPacketFinal(outgoingPacket); | ||||
|                 } | ||||
|                 for (int i = 0; i < expiredPackets.Count; ++i) | ||||
|                     expiredPackets[i].UnackedMethod(expiredPackets[i]); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void ResendUnacked(OutgoingPacket outgoingPacket) | ||||
|         { | ||||
|             //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed", | ||||
|             //    outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount); | ||||
| 
 | ||||
|             // Set the resent flag | ||||
|             outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT); | ||||
|             outgoingPacket.Category = ThrottleOutPacketType.Resend; | ||||
| 
 | ||||
|             // Bump up the resend count on this packet | ||||
|             Interlocked.Increment(ref outgoingPacket.ResendCount); | ||||
| 
 | ||||
|             // Requeue or resend the packet | ||||
|             if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) | ||||
|                 SendPacketFinal(outgoingPacket); | ||||
|         } | ||||
| 
 | ||||
|         public void Flush(LLUDPClient udpClient) | ||||
|         { | ||||
|             // FIXME: Implement? | ||||
|  | @ -672,7 +672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             if (packet.Header.AppendedAcks && packet.Header.AckList != null) | ||||
|             { | ||||
|                 for (int i = 0; i < packet.Header.AckList.Length; i++) | ||||
|                     udpClient.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent); | ||||
|                     udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); | ||||
|             } | ||||
| 
 | ||||
|             // Handle PacketAck packets | ||||
|  | @ -681,7 +681,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                 PacketAckPacket ackPacket = (PacketAckPacket)packet; | ||||
| 
 | ||||
|                 for (int i = 0; i < ackPacket.Packets.Length; i++) | ||||
|                     udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent); | ||||
|                     udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); | ||||
| 
 | ||||
|                 // We don't need to do anything else with PacketAck packets | ||||
|                 return; | ||||
|  | @ -1096,7 +1096,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                     if (udpClient.IsConnected) | ||||
|                     { | ||||
|                         if (m_resendUnacked) | ||||
|                             ResendUnacked(udpClient); | ||||
|                             HandleUnacked(udpClient); | ||||
| 
 | ||||
|                         if (m_sendAcks) | ||||
|                             SendAcks(udpClient); | ||||
|  | @ -1152,7 +1152,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                             nticksUnack++; | ||||
|                             watch2.Start(); | ||||
| 
 | ||||
|                             ResendUnacked(udpClient); | ||||
|                             HandleUnacked(udpClient); | ||||
| 
 | ||||
|                             watch2.Stop(); | ||||
|                             avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); | ||||
|  |  | |||
|  | @ -31,6 +31,8 @@ using OpenMetaverse; | |||
| 
 | ||||
| namespace OpenSim.Region.ClientStack.LindenUDP | ||||
| { | ||||
| 
 | ||||
|     public delegate void UnackedPacketMethod(OutgoingPacket oPacket); | ||||
|     /// <summary> | ||||
|     /// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is | ||||
|     /// destined for, along with the serialized packet data, sequence number | ||||
|  | @ -52,6 +54,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         public int TickCount; | ||||
|         /// <summary>Category this packet belongs to</summary> | ||||
|         public ThrottleOutPacketType Category; | ||||
|         /// <summary>The delegate to be called if this packet is determined to be unacknowledged</summary> | ||||
|         public UnackedPacketMethod UnackedMethod; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Default constructor | ||||
|  | @ -60,11 +64,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// <param name="buffer">Serialized packet data. If the flags or sequence number | ||||
|         /// need to be updated, they will be injected directly into this binary buffer</param> | ||||
|         /// <param name="category">Throttling category for this packet</param> | ||||
|         public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category) | ||||
|         public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method) | ||||
|         { | ||||
|             Client = client; | ||||
|             Buffer = buffer; | ||||
|             Category = category; | ||||
|             UnackedMethod = method; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -52,30 +52,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         public int Texture; | ||||
|         /// <summary>Drip rate for asset packets</summary> | ||||
|         public int Asset; | ||||
|         /// <summary>Drip rate for state packets</summary> | ||||
|         public int State; | ||||
| 
 | ||||
|         /// <summary>Drip rate for the parent token bucket</summary> | ||||
|         public int Total; | ||||
| 
 | ||||
|         /// <summary>Maximum burst rate for resent packets</summary> | ||||
|         public int ResendLimit; | ||||
|         /// <summary>Maximum burst rate for land packets</summary> | ||||
|         public int LandLimit; | ||||
|         /// <summary>Maximum burst rate for wind packets</summary> | ||||
|         public int WindLimit; | ||||
|         /// <summary>Maximum burst rate for cloud packets</summary> | ||||
|         public int CloudLimit; | ||||
|         /// <summary>Maximum burst rate for task (state and transaction) packets</summary> | ||||
|         public int TaskLimit; | ||||
|         /// <summary>Maximum burst rate for texture packets</summary> | ||||
|         public int TextureLimit; | ||||
|         /// <summary>Maximum burst rate for asset packets</summary> | ||||
|         public int AssetLimit; | ||||
|         /// <summary>Maximum burst rate for state packets</summary> | ||||
|         public int StateLimit; | ||||
|         /// <summary>Burst rate for the parent token bucket</summary> | ||||
|         public int TotalLimit; | ||||
| 
 | ||||
|         /// <summary>Flag used to enable adaptive throttles</summary> | ||||
|         public bool AdaptiveThrottlesEnabled; | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Default constructor | ||||
|         /// </summary> | ||||
|  | @ -86,26 +69,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             { | ||||
|                 IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; | ||||
| 
 | ||||
|                 Resend = throttleConfig.GetInt("resend_default", 12500); | ||||
|                 Land = throttleConfig.GetInt("land_default", 1000); | ||||
|                 Wind = throttleConfig.GetInt("wind_default", 1000); | ||||
|                 Cloud = throttleConfig.GetInt("cloud_default", 1000); | ||||
|                 Task = throttleConfig.GetInt("task_default", 1000); | ||||
|                 Texture = throttleConfig.GetInt("texture_default", 1000); | ||||
|                 Asset = throttleConfig.GetInt("asset_default", 1000); | ||||
|                 State = throttleConfig.GetInt("state_default", 1000); | ||||
| 
 | ||||
|                 ResendLimit = throttleConfig.GetInt("resend_limit", 18750); | ||||
|                 LandLimit = throttleConfig.GetInt("land_limit", 29750); | ||||
|                 WindLimit = throttleConfig.GetInt("wind_limit", 18750); | ||||
|                 CloudLimit = throttleConfig.GetInt("cloud_limit", 18750); | ||||
|                 TaskLimit = throttleConfig.GetInt("task_limit", 18750); | ||||
|                 TextureLimit = throttleConfig.GetInt("texture_limit", 55750); | ||||
|                 AssetLimit = throttleConfig.GetInt("asset_limit", 27500); | ||||
|                 StateLimit = throttleConfig.GetInt("state_limit", 37000); | ||||
|                 Resend = throttleConfig.GetInt("resend_default", 6625); | ||||
|                 Land = throttleConfig.GetInt("land_default", 9125); | ||||
|                 Wind = throttleConfig.GetInt("wind_default", 1750); | ||||
|                 Cloud = throttleConfig.GetInt("cloud_default", 1750); | ||||
|                 Task = throttleConfig.GetInt("task_default", 18500); | ||||
|                 Texture = throttleConfig.GetInt("texture_default", 18500); | ||||
|                 Asset = throttleConfig.GetInt("asset_default", 10500); | ||||
| 
 | ||||
|                 Total = throttleConfig.GetInt("client_throttle_max_bps", 0); | ||||
|                 TotalLimit = Total; | ||||
| 
 | ||||
|                 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); | ||||
|             } | ||||
|             catch (Exception) { } | ||||
|         } | ||||
|  | @ -128,34 +102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                     return Texture; | ||||
|                 case ThrottleOutPacketType.Asset: | ||||
|                     return Asset; | ||||
|                 case ThrottleOutPacketType.State: | ||||
|                     return State; | ||||
|                 case ThrottleOutPacketType.Unknown: | ||||
|                 default: | ||||
|                     return 0; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public int GetLimit(ThrottleOutPacketType type) | ||||
|         { | ||||
|             switch (type) | ||||
|             { | ||||
|                 case ThrottleOutPacketType.Resend: | ||||
|                     return ResendLimit; | ||||
|                 case ThrottleOutPacketType.Land: | ||||
|                     return LandLimit; | ||||
|                 case ThrottleOutPacketType.Wind: | ||||
|                     return WindLimit; | ||||
|                 case ThrottleOutPacketType.Cloud: | ||||
|                     return CloudLimit; | ||||
|                 case ThrottleOutPacketType.Task: | ||||
|                     return TaskLimit; | ||||
|                 case ThrottleOutPacketType.Texture: | ||||
|                     return TextureLimit; | ||||
|                 case ThrottleOutPacketType.Asset: | ||||
|                     return AssetLimit; | ||||
|                 case ThrottleOutPacketType.State: | ||||
|                     return StateLimit; | ||||
|                 case ThrottleOutPacketType.Unknown: | ||||
|                 default: | ||||
|                     return 0; | ||||
|  |  | |||
|  | @ -29,6 +29,8 @@ using System; | |||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.Reflection; | ||||
| using OpenSim.Framework; | ||||
| 
 | ||||
| using log4net; | ||||
| 
 | ||||
| namespace OpenSim.Region.ClientStack.LindenUDP | ||||
|  | @ -48,31 +50,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// Number of ticks (ms) per quantum, drip rate and max burst | ||||
|         /// are defined over this interval. | ||||
|         /// </summary> | ||||
|         private const Int32 m_ticksPerQuantum = 1000; | ||||
|         protected const Int32 m_ticksPerQuantum = 1000; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// This is the number of quantums worth of packets that can | ||||
|         /// be accommodated during a burst | ||||
|         /// </summary> | ||||
|         private const Double m_quantumsPerBurst = 1.5; | ||||
|         protected const Double m_quantumsPerBurst = 1.5; | ||||
|                  | ||||
|         /// <summary> | ||||
|         /// </summary> | ||||
|         private const Int32 m_minimumDripRate = 1400; | ||||
|         protected const Int32 m_minimumDripRate = 1400; | ||||
|          | ||||
|         /// <summary>Time of the last drip, in system ticks</summary> | ||||
|         private Int32 m_lastDrip; | ||||
|         protected Int32 m_lastDrip; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The number of bytes that can be sent at this moment. This is the | ||||
|         /// current number of tokens in the bucket | ||||
|         /// </summary> | ||||
|         private Int64 m_tokenCount; | ||||
|         protected Int64 m_tokenCount; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Map of children buckets and their requested maximum burst rate | ||||
|         /// </summary> | ||||
|         private Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); | ||||
|         protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); | ||||
|          | ||||
| #region Properties | ||||
| 
 | ||||
|  | @ -81,7 +83,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// parent. The parent bucket will limit the aggregate bandwidth of all | ||||
|         /// of its children buckets | ||||
|         /// </summary> | ||||
|         private TokenBucket m_parent; | ||||
|         protected TokenBucket m_parent; | ||||
|         public TokenBucket Parent | ||||
|         { | ||||
|             get { return m_parent; } | ||||
|  | @ -93,7 +95,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// of tokens that can accumulate in the bucket at any one time. This  | ||||
|         /// also sets the total request for leaf nodes | ||||
|         /// </summary> | ||||
|         private Int64 m_burstRate; | ||||
|         protected Int64 m_burstRate; | ||||
|         public Int64 RequestedBurstRate | ||||
|         { | ||||
|             get { return m_burstRate; } | ||||
|  | @ -118,8 +120,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// <remarks>Tokens are added to the bucket any time  | ||||
|         /// <seealso cref="RemoveTokens"/> is called, at the granularity of | ||||
|         /// the system tick interval (typically around 15-22ms)</remarks> | ||||
|         private Int64 m_dripRate; | ||||
|         public Int64 RequestedDripRate | ||||
|         protected Int64 m_dripRate; | ||||
|         public virtual Int64 RequestedDripRate | ||||
|         { | ||||
|             get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); } | ||||
|             set { | ||||
|  | @ -131,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public Int64 DripRate | ||||
|         public virtual Int64 DripRate | ||||
|         { | ||||
|             get { | ||||
|                 if (m_parent == null) | ||||
|  | @ -149,7 +151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// The current total of the requested maximum burst rates of  | ||||
|         /// this bucket's children buckets. | ||||
|         /// </summary> | ||||
|         private Int64 m_totalDripRequest; | ||||
|         protected Int64 m_totalDripRequest; | ||||
|         public Int64 TotalDripRequest  | ||||
|             { | ||||
|                 get { return m_totalDripRequest; } | ||||
|  | @ -177,7 +179,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             RequestedDripRate = dripRate; | ||||
|             // TotalDripRequest = dripRate; // this will be overwritten when a child node registers | ||||
|             // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); | ||||
|             m_lastDrip = Environment.TickCount & Int32.MaxValue; | ||||
|             m_lastDrip = Util.EnvironmentTickCount(); | ||||
|         } | ||||
| 
 | ||||
| #endregion Constructor | ||||
|  | @ -189,7 +191,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// hierarchy. However, if any of the parents is over-booked, then | ||||
|         /// the modifier will be less than 1. | ||||
|         /// </summary> | ||||
|         private double DripRateModifier() | ||||
|         protected double DripRateModifier() | ||||
|         { | ||||
|             Int64 driprate = DripRate; | ||||
|             return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; | ||||
|  | @ -197,7 +199,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
| 
 | ||||
|         /// <summary> | ||||
|         /// </summary> | ||||
|         private double BurstRateModifier() | ||||
|         protected double BurstRateModifier() | ||||
|         { | ||||
|             // for now... burst rate is always m_quantumsPerBurst (constant) | ||||
|             // larger than drip rate so the ratio of burst requests is the | ||||
|  | @ -211,12 +213,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// </summary> | ||||
|         public void RegisterRequest(TokenBucket child, Int64 request) | ||||
|         { | ||||
|             m_children[child] = request; | ||||
|             // m_totalDripRequest = m_children.Values.Sum(); | ||||
|             lock (m_children) | ||||
|             { | ||||
|                 m_children[child] = request; | ||||
|                 // m_totalDripRequest = m_children.Values.Sum(); | ||||
| 
 | ||||
|             m_totalDripRequest = 0; | ||||
|             foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) | ||||
|                 m_totalDripRequest += cref.Value; | ||||
|                 m_totalDripRequest = 0; | ||||
|                 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) | ||||
|                     m_totalDripRequest += cref.Value; | ||||
|             } | ||||
|              | ||||
|             // Pass the new values up to the parent | ||||
|             if (m_parent != null) | ||||
|  | @ -229,12 +234,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// </summary> | ||||
|         public void UnregisterRequest(TokenBucket child) | ||||
|         { | ||||
|             m_children.Remove(child); | ||||
|             // m_totalDripRequest = m_children.Values.Sum(); | ||||
|             lock (m_children) | ||||
|             { | ||||
|                 m_children.Remove(child); | ||||
|                 // m_totalDripRequest = m_children.Values.Sum(); | ||||
| 
 | ||||
|             m_totalDripRequest = 0; | ||||
|             foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) | ||||
|                 m_totalDripRequest += cref.Value; | ||||
|                 m_totalDripRequest = 0; | ||||
|                 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) | ||||
|                     m_totalDripRequest += cref.Value; | ||||
|             } | ||||
|              | ||||
| 
 | ||||
|             // Pass the new values up to the parent | ||||
|             if (m_parent != null) | ||||
|  | @ -268,7 +277,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// Deposit tokens into the bucket from a child bucket that did | ||||
|         /// not use all of its available tokens | ||||
|         /// </summary> | ||||
|         private void Deposit(Int64 count) | ||||
|         protected void Deposit(Int64 count) | ||||
|         { | ||||
|             m_tokenCount += count; | ||||
| 
 | ||||
|  | @ -285,7 +294,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// call to Drip | ||||
|         /// </summary> | ||||
|         /// <returns>True if tokens were added to the bucket, otherwise false</returns> | ||||
|         private void Drip() | ||||
|         protected void Drip() | ||||
|         { | ||||
|             // This should never happen... means we are a leaf node and were created | ||||
|             // with no drip rate... | ||||
|  | @ -297,10 +306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|              | ||||
|             // Determine the interval over which we are adding tokens, never add | ||||
|             // more than a single quantum of tokens | ||||
|             Int32 now = Environment.TickCount & Int32.MaxValue; | ||||
|             Int32 deltaMS = Math.Min(now - m_lastDrip, m_ticksPerQuantum); | ||||
| 
 | ||||
|             m_lastDrip = now; | ||||
|             Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum); | ||||
|             m_lastDrip = Util.EnvironmentTickCount(); | ||||
| 
 | ||||
|             // This can be 0 in the very unusual case that the timer wrapped | ||||
|             // It can be 0 if we try add tokens at a sub-tick rate | ||||
|  | @ -310,4 +317,77 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             Deposit(deltaMS * DripRate / m_ticksPerQuantum); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public class AdaptiveTokenBucket : TokenBucket | ||||
|     { | ||||
|         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The minimum rate for flow control. Minimum drip rate is one | ||||
|         /// packet per second. Open the throttle to 15 packets per second | ||||
|         /// or about 160kbps. | ||||
|         /// </summary> | ||||
|         protected const Int64 m_minimumFlow = m_minimumDripRate * 15; | ||||
| 
 | ||||
|         // <summary> | ||||
|         // The maximum rate for flow control. Drip rate can never be | ||||
|         // greater than this. | ||||
|         // </summary> | ||||
|         protected Int64 m_maxDripRate = 0; | ||||
|         protected Int64 MaxDripRate | ||||
|         { | ||||
|             get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); } | ||||
|             set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); } | ||||
|         } | ||||
|          | ||||
|         private bool m_enabled = false; | ||||
|          | ||||
|         // <summary> | ||||
|         //  | ||||
|         // </summary> | ||||
|         public virtual Int64 AdjustedDripRate | ||||
|         { | ||||
|             get { return m_dripRate; } | ||||
|             set { | ||||
|                 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value,m_minimumFlow,MaxDripRate); | ||||
|                 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); | ||||
|                 if (m_parent != null) | ||||
|                     m_parent.RegisterRequest(this,m_dripRate); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // <summary> | ||||
|         //  | ||||
|         // </summary> | ||||
|         public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate) | ||||
|         { | ||||
|             m_enabled = enabled; | ||||
| 
 | ||||
|             if (m_enabled) | ||||
|             { | ||||
|                 // m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled"); | ||||
|                 MaxDripRate = maxDripRate; | ||||
|                 AdjustedDripRate = m_minimumFlow; | ||||
|             } | ||||
|         } | ||||
|                  | ||||
|         // <summary> | ||||
|         //  | ||||
|         // </summary> | ||||
|         public void ExpirePackets(Int32 count) | ||||
|         { | ||||
|             // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count); | ||||
|             if (m_enabled) | ||||
|                 AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count)); | ||||
|         } | ||||
| 
 | ||||
|         // <summary> | ||||
|         //  | ||||
|         // </summary> | ||||
|         public void AcknowledgePackets(Int32 count) | ||||
|         { | ||||
|             if (m_enabled) | ||||
|                 AdjustedDripRate = AdjustedDripRate + count; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -65,7 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|         /// <summary>Holds packets that need to be added to the unacknowledged list</summary> | ||||
|         private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>(); | ||||
|         /// <summary>Holds information about pending acknowledgements</summary> | ||||
|         private LocklessQueue<PendingAck> m_pendingRemoves = new LocklessQueue<PendingAck>(); | ||||
|         private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>(); | ||||
|         /// <summary>Holds information about pending removals</summary> | ||||
|         private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>(); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Add an unacked packet to the collection | ||||
|  | @ -83,15 +85,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
| 
 | ||||
|         /// <summary> | ||||
|         /// Marks a packet as acknowledged | ||||
|         /// This method is used when an acknowledgement is received from the network for a previously | ||||
|         /// sent packet. Effects of removal this way are to update unacked byte count, adjust RTT | ||||
|         /// and increase throttle to the coresponding client. | ||||
|         /// </summary> | ||||
|         /// <param name="sequenceNumber">Sequence number of the packet to | ||||
|         /// acknowledge</param> | ||||
|         /// <param name="currentTime">Current value of Environment.TickCount</param> | ||||
|         /// <remarks>This does not immediately acknowledge the packet, it only | ||||
|         /// queues the ack so it can be handled in a thread-safe way later</remarks> | ||||
|         public void Remove(uint sequenceNumber, int currentTime, bool fromResend) | ||||
|         public void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend) | ||||
|         { | ||||
|             m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); | ||||
|             m_pendingAcknowledgements.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Marks a packet as no longer needing acknowledgement without a received acknowledgement. | ||||
|         /// This method is called when a packet expires and we no longer need an acknowledgement. | ||||
|         /// When some reliable packet types expire, they are handled in a way other than simply  | ||||
|         /// resending them. The only effect of removal this way is to update unacked byte count. | ||||
|         /// </summary> | ||||
|         /// <param name="sequenceNumber">Sequence number of the packet to | ||||
|         /// acknowledge</param> | ||||
|         /// <remarks>The does not immediately remove the packet, it only queues the removal | ||||
|         /// so it can be handled in a thread safe way later</remarks> | ||||
|         public void Remove(uint sequenceNumber) | ||||
|         { | ||||
|             m_pendingRemoves.Enqueue(sequenceNumber); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -130,6 +150,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                         // is actually sent out again | ||||
|                         packet.TickCount = 0; | ||||
| 
 | ||||
|                         // As with other network applications, assume that an expired packet is | ||||
|                         // an indication of some network problem, slow transmission | ||||
|                         packet.Client.FlowThrottle.ExpirePackets(1); | ||||
|                          | ||||
|                         expiredPackets.Add(packet); | ||||
|                     } | ||||
|                 } | ||||
|  | @ -147,29 +171,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|                     m_packets[pendingAdd.SequenceNumber] = pendingAdd; | ||||
|              | ||||
|             // Process all the pending removes, including updating statistics and round-trip times | ||||
|             PendingAck pendingRemove; | ||||
|             OutgoingPacket ackedPacket; | ||||
|             while (m_pendingRemoves.TryDequeue(out pendingRemove)) | ||||
|             PendingAck pendingAcknowledgement; | ||||
|             while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement)) | ||||
|             { | ||||
|                 if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) | ||||
|                 OutgoingPacket ackedPacket; | ||||
|                 if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket)) | ||||
|                 { | ||||
|                     if (ackedPacket != null) | ||||
|                     { | ||||
|                         m_packets.Remove(pendingRemove.SequenceNumber); | ||||
|                         m_packets.Remove(pendingAcknowledgement.SequenceNumber); | ||||
| 
 | ||||
|                         // As with other network applications, assume that an acknowledged packet is an | ||||
|                         // indication that the network can handle a little more load, speed up the transmission | ||||
|                         ackedPacket.Client.FlowThrottle.AcknowledgePackets(ackedPacket.Buffer.DataLength); | ||||
| 
 | ||||
|                         // Update stats | ||||
|                         Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); | ||||
| 
 | ||||
|                         if (!pendingRemove.FromResend) | ||||
|                         if (!pendingAcknowledgement.FromResend) | ||||
|                         { | ||||
|                             // Calculate the round-trip time for this packet and its ACK | ||||
|                             int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; | ||||
|                             int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount; | ||||
|                             if (rtt > 0) | ||||
|                                 ackedPacket.Client.UpdateRoundTrip(rtt); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             uint pendingRemove; | ||||
|             while(m_pendingRemoves.TryDequeue(out pendingRemove)) | ||||
|             { | ||||
|                 OutgoingPacket removedPacket; | ||||
|                 if (m_packets.TryGetValue(pendingRemove, out removedPacket)) | ||||
|                 { | ||||
|                     if (removedPacket != null) | ||||
|                     { | ||||
|                         m_packets.Remove(pendingRemove); | ||||
| 
 | ||||
|                         // Update stats | ||||
|                         Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -41,8 +41,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
|     /// </summary> | ||||
|     public class AgentAssetTransactions | ||||
|     { | ||||
| //        private static readonly ILog m_log = LogManager.GetLogger( | ||||
| //                MethodBase.GetCurrentMethod().DeclaringType); | ||||
| //        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         // Fields | ||||
|         private bool m_dumpAssetsToFile; | ||||
|  | @ -149,6 +148,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
| 
 | ||||
|                 if (asset != null) | ||||
|                 { | ||||
| //                    m_log.DebugFormat( | ||||
| //                        "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}",  | ||||
| //                        item.Name, part.Name, transactionID); | ||||
|                      | ||||
|                     asset.FullID = UUID.Random(); | ||||
|                     asset.Name = item.Name; | ||||
|                     asset.Description = item.Description; | ||||
|  | @ -156,8 +159,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
|                     item.AssetID = asset.FullID; | ||||
| 
 | ||||
|                     m_Scene.AssetService.Store(asset); | ||||
| 
 | ||||
|                     part.Inventory.UpdateInventoryItem(item); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  |  | |||
|  | @ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets | |||
|             if (meshConfig == null) | ||||
|                 return; | ||||
| 
 | ||||
|             m_enabled = meshConfig.GetBoolean("ColladaMesh", true); | ||||
|             m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true); | ||||
|         } | ||||
| 
 | ||||
|         public void AddRegion(Scene pScene) | ||||
|  |  | |||
|  | @ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets | |||
|             if (meshConfig == null) | ||||
|                 return; | ||||
| 
 | ||||
|             m_enabled = meshConfig.GetBoolean("ColladaMesh", true); | ||||
|             m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true); | ||||
|         } | ||||
| 
 | ||||
|         public void AddRegion(Scene pScene) | ||||
|  |  | |||
|  | @ -182,9 +182,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory | |||
|         public InventoryCollection GetFolderContent(UUID userID, UUID folderID) | ||||
|         { | ||||
|             InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID); | ||||
|             if (UserManager != null) | ||||
|                 foreach (InventoryItemBase item in invCol.Items) | ||||
|                     UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); | ||||
|             Util.FireAndForget(delegate | ||||
|             { | ||||
|                 if (UserManager != null) | ||||
|                     foreach (InventoryItemBase item in invCol.Items) | ||||
|                         UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); | ||||
|             }); | ||||
| 
 | ||||
|             return invCol; | ||||
|         } | ||||
|  |  | |||
|  | @ -46,10 +46,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory | |||
|                 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|         private bool m_Enabled = false; | ||||
|         private bool m_Initialized = false; | ||||
| //        private Scene m_Scene; | ||||
|         private Scene m_Scene; | ||||
|         private XInventoryServicesConnector m_RemoteConnector; | ||||
| 
 | ||||
|         private IUserManagement m_UserManager; | ||||
|         private IUserManagement UserManager | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 if (m_UserManager == null) | ||||
|                 { | ||||
|                     m_UserManager = m_Scene.RequestModuleInterface<IUserManagement>(); | ||||
|                 } | ||||
|                 return m_UserManager; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public Type ReplaceableInterface  | ||||
|         { | ||||
|             get { return null; } | ||||
|  | @ -114,12 +126,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory | |||
|             if (!m_Enabled) | ||||
|                 return; | ||||
| 
 | ||||
|             if (!m_Initialized) | ||||
|             { | ||||
|                 m_Initialized = true; | ||||
|             } | ||||
| 
 | ||||
|             scene.RegisterModuleInterface<IInventoryService>(this); | ||||
| 
 | ||||
|             if (m_Scene == null) | ||||
|                 m_Scene = scene; | ||||
|         } | ||||
| 
 | ||||
|         public void RemoveRegion(Scene scene) | ||||
|  | @ -173,7 +183,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory | |||
| 
 | ||||
|         public  InventoryCollection GetFolderContent(UUID userID, UUID folderID) | ||||
|         { | ||||
|             return m_RemoteConnector.GetFolderContent(userID, folderID); | ||||
|             InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); | ||||
|             Util.FireAndForget(delegate | ||||
|             { | ||||
|                 if (UserManager != null) | ||||
|                     foreach (InventoryItemBase item in invCol.Items) | ||||
|                         UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); | ||||
|             }); | ||||
| 
 | ||||
|             return invCol; | ||||
|         } | ||||
| 
 | ||||
|         public  List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) | ||||
|  |  | |||
|  | @ -125,7 +125,10 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
|             else | ||||
|                 Scene.RegionInfo.RegionSettings.AllowLandResell = true; | ||||
| 
 | ||||
|             Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; | ||||
|             if((byte)maxAgents <= Scene.RegionInfo.AgentCapacity) | ||||
|                 Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; | ||||
| 			else | ||||
|                 Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity; | ||||
| 
 | ||||
|             Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor; | ||||
| 
 | ||||
|  |  | |||
|  | @ -119,16 +119,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|         private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity) | ||||
|         { | ||||
|             return 1; | ||||
|             // And anything attached to this avatar gets top priority as well | ||||
|             if (entity is SceneObjectPart) | ||||
|             { | ||||
|                 SceneObjectPart sop = (SceneObjectPart)entity; | ||||
|                 if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar) | ||||
|                     return 1; | ||||
|             } | ||||
| 
 | ||||
|             return PriorityQueue.NumberOfImmediateQueues; // first queue past the immediate queues | ||||
|         } | ||||
| 
 | ||||
|         private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity) | ||||
|         { | ||||
|             // And anything attached to this avatar gets top priority as well | ||||
|             if (entity is SceneObjectPart) | ||||
|             { | ||||
|                 SceneObjectPart sop = (SceneObjectPart)entity; | ||||
|                 if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar) | ||||
|                     return 1; | ||||
|             } | ||||
| 
 | ||||
|             return ComputeDistancePriority(client,entity,false); | ||||
|         } | ||||
|          | ||||
|         private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) | ||||
|         { | ||||
|             // And anything attached to this avatar gets top priority as well | ||||
|             if (entity is SceneObjectPart) | ||||
|             { | ||||
|                 SceneObjectPart sop = (SceneObjectPart)entity; | ||||
|                 if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar) | ||||
|                     return 1; | ||||
|             } | ||||
| 
 | ||||
|             return ComputeDistancePriority(client,entity,true); | ||||
|         } | ||||
| 
 | ||||
|  | @ -141,18 +165,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
|             { | ||||
|                 if (!presence.IsChildAgent) | ||||
|                 { | ||||
|                     // All avatars other than our own go into pqueue 1 | ||||
|                     if (entity is ScenePresence) | ||||
|                         return 1; | ||||
|                      | ||||
|                     if (entity is SceneObjectPart) | ||||
|                     { | ||||
|                         // Attachments are high priority,  | ||||
|                         if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) | ||||
|                             return 1; | ||||
| 
 | ||||
|                         // Non physical prims are lower priority than physical prims | ||||
|                         PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; | ||||
|                         if (physActor == null || !physActor.IsPhysical) | ||||
|                             pqueue++; | ||||
| 
 | ||||
|                         // Attachments are high priority,  | ||||
|                         // MIC: shouldn't these already be in the highest priority queue already | ||||
|                         // since their root position is same as the avatars? | ||||
|                         if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) | ||||
|                             pqueue = 1; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | @ -172,7 +198,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|                 // m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId); | ||||
|                 // throw new InvalidOperationException("Prioritization agent not defined"); | ||||
|                 return Int32.MaxValue; | ||||
|                 return PriorityQueue.NumberOfQueues - 1; | ||||
|             } | ||||
|                  | ||||
|             // Use group position for child prims, since we are putting child prims in | ||||
|  | @ -197,8 +223,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|             // And convert the distance to a priority queue, this computation gives queues | ||||
|             // at 10, 20, 40, 80, 160, 320, 640, and 1280m | ||||
|             uint pqueue = 1; | ||||
|             for (int i = 0; i < 8; i++) | ||||
|             uint pqueue = PriorityQueue.NumberOfImmediateQueues; | ||||
|             uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; | ||||
|              | ||||
|             for (int i = 0; i < queues - 1; i++) | ||||
|             { | ||||
|                 if (distance < 10 * Math.Pow(2.0,i)) | ||||
|                     break; | ||||
|  |  | |||
|  | @ -1430,6 +1430,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                 } | ||||
|                 else // Updating existing item with new perms etc | ||||
|                 { | ||||
| //                    m_log.DebugFormat( | ||||
| //                        "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()",  | ||||
| //                        currentItem.Name, part.Name); | ||||
|                      | ||||
|                     IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); | ||||
|                     if (agentTransactions != null) | ||||
|                     { | ||||
|  | @ -2039,6 +2043,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
|             if (rot != null) | ||||
|                 group.UpdateGroupRotationR((Quaternion)rot); | ||||
|              | ||||
|             // TODO: This needs to be refactored with the similar code in  | ||||
|             // SceneGraph.AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) | ||||
|             // possibly by allowing this method to take a null rotation. | ||||
|             if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero) | ||||
|                 group.RootPart.ApplyImpulse((vel * group.GetMass()), false); | ||||
|              | ||||
|             // We can only call this after adding the scene object, since the scene object references the scene | ||||
|             // to find out if scripts should be activated at all. | ||||
|             group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); | ||||
|  |  | |||
|  | @ -3665,6 +3665,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|             int num = m_sceneGraph.GetNumberOfScenePresences(); | ||||
| 
 | ||||
|             if (num >= RegionInfo.RegionSettings.AgentLimit) | ||||
|             { | ||||
|                 if (!Permissions.IsAdministrator(cAgentData.AgentID)) | ||||
|                     return false; | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); | ||||
| 
 | ||||
|             if (childAgentUpdate != null) | ||||
|  | @ -4966,6 +4975,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         // child agent creation, thereby emulating the SL behavior. | ||||
|         public bool QueryAccess(UUID agentID, Vector3 position, out string reason) | ||||
|         { | ||||
|             int num = m_sceneGraph.GetNumberOfScenePresences(); | ||||
| 
 | ||||
|             if (num >= RegionInfo.RegionSettings.AgentLimit) | ||||
|             { | ||||
|                 if (!Permissions.IsAdministrator(agentID)) | ||||
|                 { | ||||
|                     reason = "The region is full"; | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             reason = String.Empty; | ||||
|             return true; | ||||
|         } | ||||
|  |  | |||
|  | @ -800,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
|             return m_scenePresenceArray; | ||||
|         } | ||||
| 
 | ||||
|         public int GetNumberOfScenePresences() | ||||
|         { | ||||
|             return m_scenePresenceArray.Count; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Request a scene presence by UUID. Fast, indexed lookup. | ||||
|         /// </summary> | ||||
|  |  | |||
|  | @ -81,16 +81,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Add an inventory item to a prim in this group. | ||||
|         /// Add an inventory item from a user's inventory to a prim in this scene object. | ||||
|         /// </summary> | ||||
|         /// <param name="remoteClient"></param> | ||||
|         /// <param name="localID"></param> | ||||
|         /// <param name="item"></param> | ||||
|         /// <param name="remoteClient">The client adding the item.</param> | ||||
|         /// <param name="localID">The local ID of the part receiving the add.</param> | ||||
|         /// <param name="item">The user inventory item being added.</param> | ||||
|         /// <param name="copyItemID">The item UUID that should be used by the new item.</param> | ||||
|         /// <returns></returns> | ||||
|         public bool AddInventoryItem(IClientAPI remoteClient, uint localID, | ||||
|                                      InventoryItemBase item, UUID copyItemID) | ||||
|         { | ||||
| //            m_log.DebugFormat( | ||||
| //                "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}",  | ||||
| //                item.Name, remoteClient.Name, localID); | ||||
|              | ||||
|             UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID; | ||||
| 
 | ||||
|             SceneObjectPart part = GetChildPart(localID); | ||||
|  | @ -132,15 +136,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                     taskItem.GroupPermissions = item.GroupPermissions; | ||||
|                     taskItem.NextPermissions = item.NextPermissions; | ||||
|                 } | ||||
| 
 | ||||
|                            | ||||
|                 taskItem.Flags = item.Flags; | ||||
| 
 | ||||
| //                m_log.DebugFormat( | ||||
| //                    "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}",  | ||||
| //                    taskItem.Flags, taskItem.Name, localID, remoteClient.Name);                       | ||||
|                  | ||||
|                 // TODO: These are pending addition of those fields to TaskInventoryItem | ||||
| //                taskItem.SalePrice = item.SalePrice; | ||||
| //                taskItem.SaleType = item.SaleType; | ||||
|                 taskItem.CreationDate = (uint)item.CreationDate; | ||||
| 
 | ||||
|                 bool addFromAllowedDrop = false; | ||||
|                 if (remoteClient!=null)  | ||||
|                 if (remoteClient != null)  | ||||
|                 { | ||||
|                     addFromAllowedDrop = remoteClient.AgentId != part.OwnerID; | ||||
|                 } | ||||
|  |  | |||
|  | @ -693,8 +693,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         { | ||||
|             TaskInventoryItem it = GetInventoryItem(item.ItemID); | ||||
|             if (it != null) | ||||
| 
 | ||||
|             { | ||||
| //                m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); | ||||
|                  | ||||
|                 item.ParentID = m_part.UUID; | ||||
|                 item.ParentPartID = m_part.UUID; | ||||
| 
 | ||||
|  | @ -711,14 +712,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                     m_items[item.ItemID] = item; | ||||
|                     m_inventorySerial++; | ||||
|                 } | ||||
| 
 | ||||
|                  | ||||
|                 if (fireScriptEvents) | ||||
|                     m_part.TriggerScriptChangedEvent(Changed.INVENTORY); | ||||
|                  | ||||
|                 if (considerChanged) | ||||
|                 { | ||||
|                     HasInventoryChanged = true; | ||||
|                     m_part.ParentGroup.HasGroupChanged = true; | ||||
|                 } | ||||
|                  | ||||
|                 return true; | ||||
|             } | ||||
|             else | ||||
|  |  | |||
|  | @ -2340,12 +2340,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|         #region Update Client(s) | ||||
| 
 | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Sends a location update to the client connected to this scenePresence | ||||
|         /// </summary> | ||||
|         /// <param name="remoteClient"></param> | ||||
|         public void SendTerseUpdateToClient(IClientAPI remoteClient) | ||||
|         { | ||||
| 
 | ||||
|             // If the client is inactive, it's getting its updates from another | ||||
|             // server. | ||||
|             if (remoteClient.IsActive) | ||||
|  | @ -2358,8 +2360,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                 //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); | ||||
| 
 | ||||
|                 remoteClient.SendPrimUpdate( | ||||
|                     this,  | ||||
|                     PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity  | ||||
|                     this, | ||||
|                     PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||||
|                     | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); | ||||
| 
 | ||||
|                 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); | ||||
|  | @ -2367,16 +2369,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         // vars to support reduced update frequency when velocity is unchanged | ||||
|         private Vector3 lastVelocitySentToAllClients = Vector3.Zero; | ||||
|         private int lastTerseUpdateToAllClientsTick = Util.EnvironmentTickCount(); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Send a location/velocity/accelleration update to all agents in scene | ||||
|         /// </summary> | ||||
|         public void SendTerseUpdateToAllClients() | ||||
|         { | ||||
|             m_perfMonMS = Util.EnvironmentTickCount(); | ||||
|              | ||||
|             m_scene.ForEachClient(SendTerseUpdateToClient); | ||||
|             int currentTick = Util.EnvironmentTickCount(); | ||||
| 
 | ||||
|             m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); | ||||
|             // decrease update frequency when avatar is moving but velocity is not changing | ||||
|             if (m_velocity.Length() < 0.01f | ||||
|                 || Vector3.Distance(lastVelocitySentToAllClients, m_velocity) > 0.01f | ||||
|                 || currentTick - lastTerseUpdateToAllClientsTick > 1500) | ||||
|             { | ||||
|                 m_perfMonMS = currentTick; | ||||
|                 lastVelocitySentToAllClients = m_velocity; | ||||
|                 lastTerseUpdateToAllClientsTick = currentTick; | ||||
| 
 | ||||
|                 m_scene.ForEachClient(SendTerseUpdateToClient); | ||||
| 
 | ||||
|                 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs) | ||||
|  | @ -2632,18 +2649,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                 cadu.GroupAccess = 0; | ||||
|                 cadu.Position = AbsolutePosition; | ||||
|                 cadu.regionHandle = m_rootRegionHandle; | ||||
|                 float multiplier = 1; | ||||
|                 int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); | ||||
|                 if (innacurateNeighbors != 0) | ||||
|                 { | ||||
|                     multiplier = 1f / (float)innacurateNeighbors; | ||||
|                 } | ||||
|                 if (multiplier <= 0f) | ||||
|                 { | ||||
|                     multiplier = 0.25f; | ||||
|                 } | ||||
| 
 | ||||
|                 //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); | ||||
|                 // Throttles  | ||||
|                 float multiplier = 1; | ||||
|                 int childRegions = m_knownChildRegions.Count; | ||||
|                 if (childRegions != 0) | ||||
|                     multiplier = 1f / childRegions; | ||||
| 
 | ||||
|                 // Minimum throttle for a child region is 1/4 of the root region throttle | ||||
|                 if (multiplier <= 0.25f) | ||||
|                     multiplier = 0.25f; | ||||
| 
 | ||||
|                 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); | ||||
|                 cadu.Velocity = Velocity; | ||||
| 
 | ||||
|  | @ -3039,16 +3055,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|             // Throttles  | ||||
|             float multiplier = 1; | ||||
|             int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); | ||||
|             if (innacurateNeighbors != 0) | ||||
|             { | ||||
|                 multiplier = 1f / innacurateNeighbors; | ||||
|             } | ||||
|             if (multiplier <= 0f) | ||||
|             { | ||||
|             int childRegions = m_knownChildRegions.Count; | ||||
|             if (childRegions != 0) | ||||
|                 multiplier = 1f / childRegions; | ||||
| 
 | ||||
|             // Minimum throttle for a child region is 1/4 of the root region throttle | ||||
|             if (multiplier <= 0.25f) | ||||
|                 multiplier = 0.25f; | ||||
|             } | ||||
|             //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); | ||||
| 
 | ||||
|             cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); | ||||
| 
 | ||||
|             cAgent.HeadRotation = m_headrotation; | ||||
|  | @ -3271,10 +3285,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|                 m_updateflag = true; | ||||
| 
 | ||||
|                 // The magic constant 0.95f seems to make walking feel less jerky, | ||||
|                 // probably because it hackishly accounts for the overall latency of | ||||
|                 // these Velocity updates -- Diva | ||||
|                 Velocity = force * .95F; | ||||
|                 Velocity = force; | ||||
| 
 | ||||
|                 m_forceToApply = null; | ||||
|             } | ||||
|  |  | |||
|  | @ -117,29 +117,40 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
|             {                 | ||||
|                 using (XmlTextReader reader = new XmlTextReader(sr)) | ||||
|                 { | ||||
|                     reader.Read(); | ||||
|                     if (reader.Name != "CoalescedObject") | ||||
|                     try | ||||
|                     { | ||||
| //                        m_log.DebugFormat( | ||||
| //                            "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false",  | ||||
| //                            reader.Name); | ||||
|                         reader.Read(); | ||||
|                         if (reader.Name != "CoalescedObject") | ||||
|                         { | ||||
|     //                        m_log.DebugFormat( | ||||
|     //                            "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false",  | ||||
|     //                            reader.Name); | ||||
|                              | ||||
|                             return false; | ||||
|                         } | ||||
|                          | ||||
|                         coa = new CoalescedSceneObjects(UUID.Zero);                     | ||||
|                         reader.Read();                                             | ||||
|                          | ||||
|                         while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject") | ||||
|                         { | ||||
|                             if (reader.Name == "SceneObjectGroup") | ||||
|                             { | ||||
|                                 string soXml = reader.ReadOuterXml(); | ||||
|                                 coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml)); | ||||
|                             } | ||||
|                         } | ||||
|                          | ||||
|                         reader.ReadEndElement(); // CoalescedObject | ||||
|                     } | ||||
|                     catch (Exception e) | ||||
|                     { | ||||
|                         m_log.ErrorFormat( | ||||
|                             "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed with {0} {1}",  | ||||
|                             e.Message, e.StackTrace); | ||||
|                          | ||||
|                         return false; | ||||
|                     } | ||||
|                      | ||||
|                     coa = new CoalescedSceneObjects(UUID.Zero);                     | ||||
|                     reader.Read();                                             | ||||
|                      | ||||
|                     while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject") | ||||
|                     { | ||||
|                         if (reader.Name == "SceneObjectGroup") | ||||
|                         { | ||||
|                             string soXml = reader.ReadOuterXml(); | ||||
|                             coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml)); | ||||
|                         } | ||||
|                     } | ||||
|                      | ||||
|                     reader.ReadEndElement(); // CoalescedObject | ||||
|                     }                         | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|  |  | |||
|  | @ -298,10 +298,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
|             if (null != objectAsset) | ||||
|             { | ||||
|                 string xml = Utils.BytesToString(objectAsset.Data); | ||||
|                 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); | ||||
| 
 | ||||
|                 if (null != sog) | ||||
|                     GatherAssetUuids(sog, assetUuids); | ||||
|                  | ||||
|                 CoalescedSceneObjects coa; | ||||
|                 if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa)) | ||||
|                 { | ||||
|                     foreach (SceneObjectGroup sog in coa.Objects) | ||||
|                         GatherAssetUuids(sog, assetUuids); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); | ||||
|      | ||||
|                     if (null != sog) | ||||
|                         GatherAssetUuids(sog, assetUuids); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -81,6 +81,14 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
|             lock (m_scenes) | ||||
|                 m_scenes[scene.RegionInfo.RegionID] = scene;             | ||||
| 
 | ||||
|             scene.AddCommand( | ||||
|                 this, "show pqueues", | ||||
|                 "show pqueues [full]", | ||||
|                 "Show priority queue data for each client",  | ||||
|                 "Without the 'full' option, only root agents are shown." | ||||
|                   + "  With the 'full' option child agents are also shown.",                                           | ||||
|                 ShowPQueuesReport);    | ||||
|              | ||||
|             scene.AddCommand( | ||||
|                 this, "show queues", | ||||
|                 "show queues [full]", | ||||
|  | @ -119,6 +127,11 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
| //            m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); | ||||
|         }                  | ||||
| 
 | ||||
|         protected void ShowPQueuesReport(string module, string[] cmd) | ||||
|         {                        | ||||
|             MainConsole.Instance.Output(GetPQueuesReport(cmd)); | ||||
|         } | ||||
|          | ||||
|         protected void ShowQueuesReport(string module, string[] cmd) | ||||
|         {                        | ||||
|             MainConsole.Instance.Output(GetQueuesReport(cmd)); | ||||
|  | @ -155,6 +168,80 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
|                 ""); | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Generate UDP Queue data report for each client | ||||
|         /// </summary> | ||||
|         /// <param name="showParams"></param> | ||||
|         /// <returns></returns> | ||||
|         protected string GetPQueuesReport(string[] showParams) | ||||
|         { | ||||
|             bool showChildren = false; | ||||
|             string pname = ""; | ||||
|              | ||||
|             if (showParams.Length > 2 && showParams[2] == "full") | ||||
|                 showChildren = true;                | ||||
|             else if (showParams.Length > 3) | ||||
|                 pname = showParams[2] + " " + showParams[3]; | ||||
|              | ||||
|             StringBuilder report = new StringBuilder();             | ||||
| 
 | ||||
|             int columnPadding = 2; | ||||
|             int maxNameLength = 18;                                     | ||||
|             int maxRegionNameLength = 14; | ||||
|             int maxTypeLength = 4; | ||||
|             int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding;                         | ||||
|                                      | ||||
|             report.Append(GetColumnEntry("User", maxNameLength, columnPadding)); | ||||
|             report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding)); | ||||
|             report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); | ||||
|              | ||||
|             report.AppendFormat( | ||||
|                 "{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7} {10,7} {11,7}\n", | ||||
|                 "Pri 0", | ||||
|                 "Pri 1", | ||||
|                 "Pri 2",                                 | ||||
|                 "Pri 3", | ||||
|                 "Pri 4", | ||||
|                 "Pri 5", | ||||
|                 "Pri 6", | ||||
|                 "Pri 7", | ||||
|                 "Pri 8", | ||||
|                 "Pri 9", | ||||
|                 "Pri 10", | ||||
|                 "Pri 11"); | ||||
| 
 | ||||
|             lock (m_scenes) | ||||
|             { | ||||
|                 foreach (Scene scene in m_scenes.Values) | ||||
|                 { | ||||
|                     scene.ForEachClient( | ||||
|                         delegate(IClientAPI client) | ||||
|                         { | ||||
|                             if (client is LLClientView) | ||||
|                             { | ||||
|                                 bool isChild = scene.PresenceChildStatus(client.AgentId); | ||||
|                                 if (isChild && !showChildren) | ||||
|                                     return; | ||||
|                          | ||||
|                                 string name = client.Name; | ||||
|                                 if (pname != "" && name != pname) | ||||
|                                     return; | ||||
|                                  | ||||
|                                 string regionName = scene.RegionInfo.RegionName; | ||||
|                                  | ||||
|                                 report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); | ||||
|                                 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding)); | ||||
|                                 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));                                   | ||||
|                                 report.AppendLine(((LLClientView)client).EntityUpdateQueue.ToString()); | ||||
|                             } | ||||
|                         }); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return report.ToString(); | ||||
|         } | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Generate UDP Queue data report for each client | ||||
|         /// </summary> | ||||
|  | @ -163,10 +250,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
|         protected string GetQueuesReport(string[] showParams) | ||||
|         { | ||||
|             bool showChildren = false; | ||||
|             string pname = ""; | ||||
|              | ||||
|             if (showParams.Length > 2 && showParams[2] == "full") | ||||
|                 showChildren = true;                | ||||
|                  | ||||
|             else if (showParams.Length > 3) | ||||
|                 pname = showParams[2] + " " + showParams[3]; | ||||
|              | ||||
|             StringBuilder report = new StringBuilder();             | ||||
|              | ||||
|             int columnPadding = 2; | ||||
|  | @ -224,6 +314,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
|                                     return; | ||||
|                          | ||||
|                                 string name = client.Name; | ||||
|                                 if (pname != "" && name != pname) | ||||
|                                     return; | ||||
| 
 | ||||
|                                 string regionName = scene.RegionInfo.RegionName; | ||||
|                                  | ||||
|                                 report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); | ||||
|  | @ -249,10 +342,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
|         protected string GetThrottlesReport(string[] showParams) | ||||
|         { | ||||
|             bool showChildren = false; | ||||
|             string pname = ""; | ||||
|              | ||||
|             if (showParams.Length > 2 && showParams[2] == "full") | ||||
|                 showChildren = true;                | ||||
|                  | ||||
|             else if (showParams.Length > 3) | ||||
|                 pname = showParams[2] + " " + showParams[3]; | ||||
|              | ||||
|             StringBuilder report = new StringBuilder();                | ||||
|              | ||||
|             int columnPadding = 2; | ||||
|  | @ -302,7 +398,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
|                             if (client is LLClientView) | ||||
|                             { | ||||
|                                 LLClientView llClient = client as LLClientView; | ||||
|                              | ||||
| 
 | ||||
|                                 if (firstClient) | ||||
|                                 { | ||||
|                                     report.AppendLine(GetServerThrottlesReport(llClient.UDPServer)); | ||||
|  | @ -314,6 +410,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
|                                     return; | ||||
|                          | ||||
|                                 string name = client.Name; | ||||
|                                 if (pname != "" && name != pname) | ||||
|                                     return; | ||||
| 
 | ||||
|                                 string regionName = scene.RegionInfo.RegionName; | ||||
|                              | ||||
|                                 LLUDPClient llUdpClient = llClient.UDPClient; | ||||
|  | @ -352,7 +451,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
|             int maxRegionNameLength = 14; | ||||
|             int maxTypeLength = 4; | ||||
|              | ||||
|             string name = "SERVER AGENT LIMITS"; | ||||
|             string name = "SERVER AGENT RATES"; | ||||
|                                  | ||||
|             report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); | ||||
|             report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding)); | ||||
|  | @ -362,13 +461,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
|             report.AppendFormat( | ||||
|                 "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", | ||||
|                 (throttleRates.Total * 8) / 1000, | ||||
|                 (throttleRates.ResendLimit * 8) / 1000, | ||||
|                 (throttleRates.LandLimit * 8) / 1000, | ||||
|                 (throttleRates.WindLimit * 8) / 1000, | ||||
|                 (throttleRates.CloudLimit * 8) / 1000, | ||||
|                 (throttleRates.TaskLimit * 8) / 1000, | ||||
|                 (throttleRates.TextureLimit  * 8) / 1000, | ||||
|                 (throttleRates.AssetLimit  * 8) / 1000);   | ||||
|                 (throttleRates.Resend * 8) / 1000, | ||||
|                 (throttleRates.Land * 8) / 1000, | ||||
|                 (throttleRates.Wind * 8) / 1000, | ||||
|                 (throttleRates.Cloud * 8) / 1000, | ||||
|                 (throttleRates.Task * 8) / 1000, | ||||
|                 (throttleRates.Texture  * 8) / 1000, | ||||
|                 (throttleRates.Asset  * 8) / 1000);   | ||||
| 
 | ||||
|             return report.ToString(); | ||||
|         }         | ||||
|  |  | |||
|  | @ -118,7 +118,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
| 
 | ||||
|                 if (serviceDll == String.Empty) | ||||
|                 { | ||||
|                     m_log.Error("[FreeSwitchVoice]: No LocalServiceModule named in section FreeSwitchVoice"); | ||||
|                     m_log.Error("[FreeSwitchVoice]: No LocalServiceModule named in section FreeSwitchVoice.  Not starting."); | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|  | @ -143,8 +143,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|                 if (String.IsNullOrEmpty(m_freeSwitchRealm) || | ||||
|                     String.IsNullOrEmpty(m_freeSwitchAPIPrefix)) | ||||
|                 { | ||||
|                     m_log.Error("[FreeSwitchVoice] plugin mis-configured"); | ||||
|                     m_log.Info("[FreeSwitchVoice] plugin disabled: incomplete configuration"); | ||||
|                     m_log.Error("[FreeSwitchVoice]: Freeswitch service mis-configured.  Not starting.");                     | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|  | @ -164,24 +163,24 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|                 // String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), FreeSwitchSLVoiceGetPreloginHTTPHandler); | ||||
|                 //  MainServer.Instance.AddStreamHandler(h); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                 MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_signin.php", m_freeSwitchAPIPrefix), | ||||
|                                  FreeSwitchSLVoiceSigninHTTPHandler); | ||||
| 
 | ||||
|                 MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix), | ||||
|                                  FreeSwitchSLVoiceBuddyHTTPHandler); | ||||
|                  | ||||
|                 MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_watcher.php", m_freeSwitchAPIPrefix), | ||||
|                                  FreeSwitchSLVoiceWatcherHTTPHandler);                 | ||||
| 
 | ||||
|                 m_log.InfoFormat("[FreeSwitchVoice] using FreeSwitch server {0}", m_freeSwitchRealm); | ||||
|                 m_log.InfoFormat("[FreeSwitchVoice]: using FreeSwitch server {0}", m_freeSwitchRealm); | ||||
| 
 | ||||
|                 m_Enabled = true; | ||||
| 
 | ||||
|                 m_log.Info("[FreeSwitchVoice] plugin enabled"); | ||||
|                 m_log.Info("[FreeSwitchVoice]: plugin enabled"); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.ErrorFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.Message); | ||||
|                 m_log.DebugFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.ToString()); | ||||
|                 m_log.ErrorFormat("[FreeSwitchVoice]: plugin initialization failed: {0} {1}", e.Message, e.StackTrace); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|  | @ -240,7 +239,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|         { | ||||
|             if (m_Enabled) | ||||
|             { | ||||
|                 m_log.Info("[FreeSwitchVoice] registering IVoiceModule with the scene"); | ||||
|                 m_log.Info("[FreeSwitchVoice]: registering IVoiceModule with the scene"); | ||||
| 
 | ||||
|                 // register the voice interface for this module, so the script engine can call us | ||||
|                 scene.RegisterModuleInterface<IVoiceModule>(this); | ||||
|  | @ -302,7 +301,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|         // </summary> | ||||
|         public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps) | ||||
|         { | ||||
|             m_log.DebugFormat("[FreeSwitchVoice] OnRegisterCaps: agentID {0} caps {1}", agentID, caps); | ||||
|             m_log.DebugFormat( | ||||
|                 "[FreeSwitchVoice]: OnRegisterCaps() called with agentID {0} caps {1} in scene {2}",  | ||||
|                 agentID, caps, scene.RegionInfo.RegionName); | ||||
| 
 | ||||
|             string capsBase = "/CAPS/" + caps.CapsObjectPath; | ||||
|             caps.RegisterHandler("ProvisionVoiceAccountRequest", | ||||
|  | @ -344,6 +345,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|         public string ProvisionVoiceAccountRequest(Scene scene, string request, string path, string param, | ||||
|                                                    UUID agentID, Caps caps) | ||||
|         { | ||||
|             m_log.DebugFormat( | ||||
|                 "[FreeSwitchVoice][PROVISIONVOICE]: ProvisionVoiceAccountRequest() request: {0}, path: {1}, param: {2}", request, path, param); | ||||
|              | ||||
|             ScenePresence avatar = scene.GetScenePresence(agentID); | ||||
|             if (avatar == null) | ||||
|             { | ||||
|  | @ -357,9 +361,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 //m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", | ||||
|                 //                  request, path, param); | ||||
| 
 | ||||
|                 //XmlElement    resp; | ||||
|                 string agentname = "x" + Convert.ToBase64String(agentID.GetBytes()); | ||||
|                 string password  = "1234";//temp hack//new UUID(Guid.NewGuid()).ToString().Replace('-','Z').Substring(0,16); | ||||
|  | @ -390,7 +391,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
| 
 | ||||
|                 string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); | ||||
| 
 | ||||
|                 m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); | ||||
| //                m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); | ||||
| 
 | ||||
|                 return r; | ||||
|             } | ||||
|  | @ -416,6 +417,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|         public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param, | ||||
|                                              UUID agentID, Caps caps) | ||||
|         { | ||||
| //            m_log.DebugFormat( | ||||
| //                "[FreeSwitchVoice][PARCELVOICE]: ParcelVoiceInfoRequest() on {0} for {1}",  | ||||
| //                scene.RegionInfo.RegionName, agentID); | ||||
|              | ||||
|             ScenePresence avatar = scene.GetScenePresence(agentID); | ||||
|             string avatarName = avatar.Name; | ||||
| 
 | ||||
|  | @ -453,8 +458,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
| 
 | ||||
|                 if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0) | ||||
|                 { | ||||
|                     m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", | ||||
|                                       scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); | ||||
| //                    m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", | ||||
| //                                      scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); | ||||
|                     channelUri = String.Empty; | ||||
|                 } | ||||
|                 else | ||||
|  | @ -469,8 +474,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|                 parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); | ||||
|                 string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); | ||||
| 
 | ||||
|                 m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", | ||||
|                                   scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); | ||||
| //                m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", | ||||
| //                                  scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); | ||||
|                 return r; | ||||
|             } | ||||
|             catch (Exception e) | ||||
|  | @ -502,6 +507,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
| 
 | ||||
|             m_log.DebugFormat("[FreeSwitchVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}", | ||||
|                               avatarName, request, path, param); | ||||
|              | ||||
|             return "<llsd>true</llsd>"; | ||||
|         } | ||||
| 
 | ||||
|  | @ -555,10 +561,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|             return response; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request) | ||||
|         { | ||||
|             m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceGetPreloginHTTPHandler called"); | ||||
|             m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceGetPreloginHTTPHandler called"); | ||||
| 
 | ||||
|             Hashtable response = new Hashtable(); | ||||
|             response["content_type"] = "text/xml"; | ||||
|  | @ -592,6 +597,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
| 
 | ||||
|         public Hashtable FreeSwitchSLVoiceBuddyHTTPHandler(Hashtable request) | ||||
|         { | ||||
|             m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceBuddyHTTPHandler called"); | ||||
|              | ||||
|             Hashtable response = new Hashtable(); | ||||
|             response["int_response_code"] = 200; | ||||
|             response["str_response_string"] = string.Empty; | ||||
|  | @ -650,21 +657,64 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|                                     <bdy_status>A</bdy_status> | ||||
|                                     <modified_ts>{3}</modified_ts> | ||||
|                                     <b2g_group_id></b2g_group_id> | ||||
|                                 </level3>", ids[i],i,m_freeSwitchRealm,dt));
 | ||||
|                                 </level3>", ids[i], i ,m_freeSwitchRealm, dt));
 | ||||
|             } | ||||
| 
 | ||||
|             resp.Append("</buddies><groups></groups></body></level0></response>"); | ||||
| 
 | ||||
|             response["str_response_string"] = resp.ToString(); | ||||
| //            Regex normalizeEndLines = new Regex(@"\r\n", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline); | ||||
| 
 | ||||
|             //m_log.DebugFormat("[FREESWITCH]: {0}", normalizeEndLines.Replace((string)response["str_response_string"],"")); | ||||
| //            Regex normalizeEndLines = new Regex(@"(\r\n|\n)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline); | ||||
| // | ||||
| //            m_log.DebugFormat( | ||||
| //                "[FREESWITCH]: FreeSwitchSLVoiceBuddyHTTPHandler() response {0}",  | ||||
| //                normalizeEndLines.Replace((string)response["str_response_string"],"")); | ||||
|              | ||||
|             return response; | ||||
|         } | ||||
| 
 | ||||
|         public Hashtable FreeSwitchSLVoiceWatcherHTTPHandler(Hashtable request) | ||||
|         { | ||||
|             m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceWatcherHTTPHandler called"); | ||||
|              | ||||
|             Hashtable response = new Hashtable(); | ||||
|             response["int_response_code"] = 200; | ||||
|             response["content-type"] = "text/xml"; | ||||
| 
 | ||||
|             Hashtable requestBody = ParseRequestBody((string)request["body"]); | ||||
| 
 | ||||
|             string auth_token = (string)requestBody["auth_token"]; | ||||
|             //string[] auth_tokenvals = auth_token.Split(':'); | ||||
|             //string username = auth_tokenvals[0]; | ||||
| 
 | ||||
|             StringBuilder resp = new StringBuilder(); | ||||
|             resp.Append("<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?><response xmlns=\"http://www.vivox.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation= \"/xsd/buddy_list.xsd\">"); | ||||
|              | ||||
|             // FIXME: This is enough of a response to stop viewer 2 complaining about a login failure and get voice to work.  If we don't  | ||||
|             // give an OK response, then viewer 2 engages in an continuous viv_signin.php, viv_buddy.php, viv_watcher.php loop | ||||
|             // Viewer 1 appeared happy to ignore the lack of reply and still works with this reply. | ||||
|             // | ||||
|             // However, really we need to fill in whatever watcher data should be here (whatever that is). | ||||
|             resp.Append(string.Format(@"<level0>
 | ||||
|                         <status>OK</status> | ||||
|                         <cookie_name>lib_session</cookie_name> | ||||
|                         <cookie>{0}</cookie> | ||||
|                         <auth_token>{0}</auth_token> | ||||
|                         <body/></level0></response>", auth_token));            
 | ||||
|              | ||||
|             response["str_response_string"] = resp.ToString(); | ||||
|              | ||||
| //            Regex normalizeEndLines = new Regex(@"(\r\n|\n)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline); | ||||
| // | ||||
| //            m_log.DebugFormat( | ||||
| //                "[FREESWITCH]: FreeSwitchSLVoiceWatcherHTTPHandler() response {0}",  | ||||
| //                normalizeEndLines.Replace((string)response["str_response_string"],"")); | ||||
|              | ||||
|             return response; | ||||
|         } | ||||
|          | ||||
|         public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request) | ||||
|         { | ||||
|             m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceSigninHTTPHandler called"); | ||||
|             m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceSigninHTTPHandler called"); | ||||
| //            string requestbody = (string)request["body"]; | ||||
| //            string uri = (string)request["uri"]; | ||||
| //            string contenttype = (string)request["content-type"]; | ||||
|  | @ -709,7 +759,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|                     </level0> | ||||
|                 </response>", userid, pos, avatarName);
 | ||||
| 
 | ||||
|             response["int_response_code"] = 200; | ||||
|             response["int_response_code"] = 200;             | ||||
|              | ||||
| //            m_log.DebugFormat("[FreeSwitchVoice]: Sending FreeSwitchSLVoiceSigninHTTPHandler response"); | ||||
|              | ||||
|             return response; | ||||
|         } | ||||
| 
 | ||||
|  | @ -795,16 +848,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
|             response["keepalive"] = false; | ||||
|             response["int_response_code"] = 500; | ||||
| 
 | ||||
|             Hashtable requestBody = ParseRequestBody((string) request["body"]); | ||||
|             Hashtable requestBody = ParseRequestBody((string)request["body"]);                                    | ||||
| 
 | ||||
|             string section = (string) requestBody["section"]; | ||||
|             string section = (string) requestBody["section"];                        | ||||
| 
 | ||||
|             if (section == "directory") | ||||
|             { | ||||
|                 string eventCallingFunction = (string)requestBody["Event-Calling-Function"]; | ||||
|                 m_log.DebugFormat( | ||||
|                     "[FreeSwitchVoice]: Received request for config section directory, event calling function '{0}'",  | ||||
|                     eventCallingFunction);                             | ||||
|                  | ||||
|                 response = m_FreeswitchService.HandleDirectoryRequest(requestBody); | ||||
|             } | ||||
|             else if (section == "dialplan") | ||||
|             {      | ||||
|                 m_log.DebugFormat("[FreeSwitchVoice]: Received request for config section dialplan"); | ||||
|                  | ||||
|                 response = m_FreeswitchService.HandleDialplanRequest(requestBody); | ||||
|             } | ||||
|             else | ||||
|                 m_log.WarnFormat("[FreeSwitchVoice]: section was {0}", section); | ||||
|                 m_log.WarnFormat("[FreeSwitchVoice]: Unknown section {0} was requested from config.", section); | ||||
| 
 | ||||
|             return response; | ||||
|         } | ||||
|  | @ -821,4 +885,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
| 
 | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -84,10 +84,11 @@ namespace OpenSim.Region.Physics.Meshing | |||
|         public Meshmerizer(IConfigSource config) | ||||
|         { | ||||
|             IConfig start_config = config.Configs["Startup"]; | ||||
|             IConfig mesh_config = config.Configs["Mesh"]; | ||||
| 
 | ||||
|             decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); | ||||
|             cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); | ||||
|             useMeshiesPhysicsMesh = start_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | ||||
|             useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|  |  | |||
|  | @ -62,6 +62,8 @@ namespace PrimMesher | |||
| 
 | ||||
|             bool needsScaling = false; | ||||
| 
 | ||||
|             bool smallMap = bmW * bmH <= lod * lod; | ||||
| 
 | ||||
|             width = bmW; | ||||
|             height = bmH; | ||||
|             while (width * height > numLodPixels) | ||||
|  | @ -104,9 +106,14 @@ namespace PrimMesher | |||
|                 { | ||||
|                     for (int x = 0; x <= width; x++) | ||||
|                     { | ||||
|                         int bmY = y < height ? y * 2 : y * 2 - 1; | ||||
|                         int bmX = x < width ? x * 2 : x * 2 - 1; | ||||
|                         Color c = bm.GetPixel(bmX, bmY); | ||||
|                         Color c; | ||||
| 
 | ||||
|                         if (smallMap) | ||||
|                             c = bm.GetPixel(x < width ? x : x - 1, | ||||
|                                             y < height ? y : y - 1); | ||||
|                         else | ||||
|                             c = bm.GetPixel(x < width ? x * 2 : x * 2 - 1, | ||||
|                                             y < height ? y * 2 : y * 2 - 1); | ||||
| 
 | ||||
|                         redBytes[byteNdx] = c.R; | ||||
|                         greenBytes[byteNdx] = c.G; | ||||
|  |  | |||
|  | @ -158,7 +158,10 @@ namespace OpenSim.Services.Connectors | |||
|         public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) | ||||
|         { | ||||
|             InventoryCollection inventory = new InventoryCollection(); | ||||
|              | ||||
|             inventory.Folders = new List<InventoryFolderBase>(); | ||||
|             inventory.Items = new List<InventoryItemBase>(); | ||||
|             inventory.UserID = principalID; | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT", | ||||
|  | @ -172,11 +175,6 @@ namespace OpenSim.Services.Connectors | |||
|                 if (ret.Count == 0) | ||||
|                     return null; | ||||
| 
 | ||||
|                  | ||||
|                 inventory.Folders = new List<InventoryFolderBase>(); | ||||
|                 inventory.Items = new List<InventoryItemBase>(); | ||||
|                 inventory.UserID = principalID; | ||||
|                  | ||||
|                 Dictionary<string,object> folders = | ||||
|                         (Dictionary<string,object>)ret["FOLDERS"]; | ||||
|                 Dictionary<string,object> items = | ||||
|  |  | |||
|  | @ -50,13 +50,13 @@ namespace OpenSim.Services.FreeswitchService | |||
| 
 | ||||
|         public Hashtable HandleDialplanRequest(Hashtable request) | ||||
|         { | ||||
|             m_log.DebugFormat("[FreeSwitchVoice] HandleDialplanRequest called with {0}",request.ToString()); | ||||
|             m_log.DebugFormat("[FreeSwitchVoice]: HandleDialplanRequest called with {0}",request.ToString()); | ||||
| 
 | ||||
|             Hashtable response = new Hashtable(); | ||||
| 
 | ||||
|             foreach (DictionaryEntry item in request) | ||||
|             { | ||||
|                m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}",item.Key, item.Value); | ||||
| //               m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value); | ||||
|             } | ||||
| 
 | ||||
|             string requestcontext = (string) request["Hunt-Context"]; | ||||
|  | @ -66,7 +66,7 @@ namespace OpenSim.Services.FreeswitchService | |||
| 
 | ||||
|             if (m_freeSwitchContext != String.Empty && m_freeSwitchContext != requestcontext) | ||||
|             { | ||||
|                 m_log.Debug("[FreeSwitchDirectory] returning empty as it's for another context"); | ||||
|                 m_log.Debug("[FreeSwitchDirectory]: returning empty as it's for another context"); | ||||
|                 response["str_response_string"] = ""; | ||||
|             } | ||||
|             else | ||||
|  | @ -116,13 +116,16 @@ namespace OpenSim.Services.FreeswitchService | |||
|         { | ||||
|             Hashtable response = new Hashtable(); | ||||
|             string domain = (string) request["domain"]; | ||||
|             if (domain != m_freeSwitchRealm) { | ||||
|             if (domain != m_freeSwitchRealm)  | ||||
|             { | ||||
|                 response["content_type"] = "text/xml"; | ||||
|                 response["keepalive"] = false; | ||||
|                 response["int_response_code"] = 200; | ||||
|                 response["str_response_string"] = ""; | ||||
|             } else { | ||||
|                  m_log.DebugFormat("[FreeSwitchDirectory] HandleDirectoryRequest called with {0}",request.ToString()); | ||||
|             }  | ||||
|             else  | ||||
|             { | ||||
| //                 m_log.DebugFormat("[FreeSwitchDirectory]: HandleDirectoryRequest called with {0}",request.ToString()); | ||||
|              | ||||
|                  // information in the request we might be interested in | ||||
|               | ||||
|  | @ -143,10 +146,8 @@ namespace OpenSim.Services.FreeswitchService | |||
|                  //domain=9.20.151.43 | ||||
|                  //ip=9.167.220.137    // this is the correct IP rather than sip_contact_host above when through a vpn or NAT setup | ||||
|               | ||||
|                  foreach (DictionaryEntry item in request) | ||||
|                  { | ||||
|                     m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}", item.Key, item.Value); | ||||
|                  } | ||||
| //                 foreach (DictionaryEntry item in request) | ||||
| //                    m_log.DebugFormat("[FreeSwitchDirectory]: requestBody item {0} {1}", item.Key, item.Value); | ||||
|               | ||||
|                  string eventCallingFunction = (string) request["Event-Calling-Function"]; | ||||
|                  if (eventCallingFunction == null) | ||||
|  | @ -173,7 +174,7 @@ namespace OpenSim.Services.FreeswitchService | |||
|                      } | ||||
|                      else | ||||
|                      { | ||||
|                          m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown sip_auth_method {0}",sipAuthMethod); | ||||
|                          m_log.ErrorFormat("[FreeSwitchVoice]: HandleDirectoryRequest unknown sip_auth_method {0}",sipAuthMethod); | ||||
|                          response["int_response_code"] = 404; | ||||
|                          response["content_type"] = "text/xml"; | ||||
|                          response["str_response_string"] = ""; | ||||
|  | @ -205,7 +206,7 @@ namespace OpenSim.Services.FreeswitchService | |||
|                  } | ||||
|                  else | ||||
|                  { | ||||
|                      m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown Event-Calling-Function {0}",eventCallingFunction); | ||||
|                      m_log.ErrorFormat("[FreeSwitchVoice]: HandleDirectoryRequest unknown Event-Calling-Function {0}",eventCallingFunction); | ||||
|                      response["int_response_code"] = 404; | ||||
|                      response["keepalive"] = false; | ||||
|                      response["content_type"] = "text/xml"; | ||||
|  | @ -217,7 +218,7 @@ namespace OpenSim.Services.FreeswitchService | |||
|          | ||||
|         private Hashtable HandleRegister(string Context, string Realm, Hashtable request) | ||||
|         { | ||||
|             m_log.Info("[FreeSwitchDirectory] HandleRegister called"); | ||||
|             m_log.Info("[FreeSwitchDirectory]: HandleRegister called"); | ||||
|              | ||||
|             // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||||
|             string password = "1234"; | ||||
|  | @ -254,7 +255,7 @@ namespace OpenSim.Services.FreeswitchService | |||
|          | ||||
|         private Hashtable HandleInvite(string Context, string Realm, Hashtable request) | ||||
|         { | ||||
|             m_log.Info("[FreeSwitchDirectory] HandleInvite called"); | ||||
|             m_log.Info("[FreeSwitchDirectory]: HandleInvite called"); | ||||
|              | ||||
|             // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||||
|             string password = "1234"; | ||||
|  | @ -301,7 +302,7 @@ namespace OpenSim.Services.FreeswitchService | |||
| 
 | ||||
|         private Hashtable HandleLocateUser(String Realm, Hashtable request) | ||||
|         { | ||||
|             m_log.Info("[FreeSwitchDirectory] HandleLocateUser called"); | ||||
|             m_log.Info("[FreeSwitchDirectory]: HandleLocateUser called"); | ||||
|              | ||||
|             // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||||
|             string domain = (string) request["domain"]; | ||||
|  | @ -335,7 +336,7 @@ namespace OpenSim.Services.FreeswitchService | |||
|         | ||||
|         private Hashtable HandleConfigSofia(string Context, string Realm, Hashtable request) | ||||
|         { | ||||
|             m_log.Info("[FreeSwitchDirectory] HandleConfigSofia called"); | ||||
|             m_log.Info("[FreeSwitchDirectory]: HandleConfigSofia called."); | ||||
|              | ||||
|             // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||||
|             string domain = (string) request["domain"]; | ||||
|  |  | |||
|  | @ -64,7 +64,7 @@ namespace OpenSim.Services.FreeswitchService | |||
|                 m_freeSwitchDefaultWellKnownIP = freeswitchConfig.GetString("ServerAddress", String.Empty); | ||||
|                 if (m_freeSwitchDefaultWellKnownIP == String.Empty) | ||||
|                 { | ||||
|                     m_log.Error("[FREESWITCH]: No FreeswitchServerAddress given, can't continue"); | ||||
|                     m_log.Error("[FREESWITCH]: No ServerAddress given, cannot start service."); | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ using System; | |||
| using System.Collections.Generic; | ||||
| using System.Net; | ||||
| using System.Reflection; | ||||
| using System.Text.RegularExpressions; | ||||
| 
 | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Services.Interfaces; | ||||
|  | @ -57,6 +58,9 @@ namespace OpenSim.Services.HypergridService | |||
|         private static IUserAgentService m_UserAgentService; | ||||
|         private static ISimulationService m_SimulationService; | ||||
| 
 | ||||
|         protected string m_AllowedClients = string.Empty; | ||||
|         protected string m_DeniedClients = string.Empty; | ||||
| 
 | ||||
|         private static UUID m_ScopeID; | ||||
|         private static bool m_AllowTeleportsToAnyRegion; | ||||
|         private static string m_ExternalName; | ||||
|  | @ -104,6 +108,9 @@ namespace OpenSim.Services.HypergridService | |||
|                 else if (simulationService != string.Empty) | ||||
|                         m_SimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args); | ||||
| 
 | ||||
|                 m_AllowedClients = serverConfig.GetString("AllowedClients", string.Empty); | ||||
|                 m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty); | ||||
| 
 | ||||
|                 if (m_GridService == null || m_PresenceService == null || m_SimulationService == null) | ||||
|                     throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function."); | ||||
| 
 | ||||
|  | @ -181,8 +188,36 @@ namespace OpenSim.Services.HypergridService | |||
|             string authURL = string.Empty; | ||||
|             if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) | ||||
|                 authURL = aCircuit.ServiceURLs["HomeURI"].ToString(); | ||||
|             m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to login foreign agent {0} {1} @ {2} ({3}) at destination {4}",  | ||||
|                 aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName); | ||||
|             m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9}", | ||||
|                 aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName, | ||||
|                 aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0); | ||||
|              | ||||
|             // | ||||
|             // Check client | ||||
|             // | ||||
|             if (m_AllowedClients != string.Empty) | ||||
|             { | ||||
|                 Regex arx = new Regex(m_AllowedClients); | ||||
|                 Match am = arx.Match(aCircuit.Viewer); | ||||
| 
 | ||||
|                 if (!am.Success) | ||||
|                 { | ||||
|                     m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", aCircuit.Viewer); | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (m_DeniedClients != string.Empty) | ||||
|             { | ||||
|                 Regex drx = new Regex(m_DeniedClients); | ||||
|                 Match dm = drx.Match(aCircuit.Viewer); | ||||
| 
 | ||||
|                 if (dm.Success) | ||||
|                 { | ||||
|                     m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", aCircuit.Viewer); | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // | ||||
|             // Authenticate the user | ||||
|  |  | |||
|  | @ -244,7 +244,7 @@ namespace OpenSim.Services.InventoryService | |||
|             // connector. So we disregard the principal and look | ||||
|             // by ID. | ||||
|             // | ||||
|             m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString()); | ||||
|             //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString()); | ||||
|             InventoryCollection inventory = new InventoryCollection(); | ||||
|             inventory.UserID = principalID; | ||||
|             inventory.Folders = new List<InventoryFolderBase>(); | ||||
|  |  | |||
|  | @ -77,7 +77,11 @@ namespace OpenSim.Services.LLLoginService | |||
|         protected string m_MapTileURL; | ||||
|         protected string m_SearchURL; | ||||
| 
 | ||||
|         protected string m_AllowedClients; | ||||
|         protected string m_DeniedClients; | ||||
| 
 | ||||
|         IConfig m_LoginServerConfig; | ||||
|         IConfig m_ClientsConfig; | ||||
| 
 | ||||
|         public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService) | ||||
|         { | ||||
|  | @ -105,7 +109,10 @@ namespace OpenSim.Services.LLLoginService | |||
|             m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty); | ||||
|             m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty); | ||||
|             m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty); | ||||
|              | ||||
| 
 | ||||
|             m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty); | ||||
|             m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty); | ||||
| 
 | ||||
|             // These are required; the others aren't | ||||
|             if (accountService == string.Empty || authService == string.Empty) | ||||
|                 throw new Exception("LoginService is missing service specifications"); | ||||
|  | @ -215,10 +222,37 @@ namespace OpenSim.Services.LLLoginService | |||
|             bool success = false; | ||||
|             UUID session = UUID.Random(); | ||||
| 
 | ||||
|             m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} from {2} with user agent {3} starting in {4}",  | ||||
|                 firstName, lastName, clientIP.Address.ToString(), clientVersion, startLocation); | ||||
|             m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} at {2} using viewer {3}, channel {4}, IP {5}, Mac {6}, Id0 {7}", | ||||
|                 firstName, lastName, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0); | ||||
|             try | ||||
|             { | ||||
|                 // | ||||
|                 // Check client | ||||
|                 // | ||||
|                 if (m_AllowedClients != string.Empty) | ||||
|                 { | ||||
|                     Regex arx = new Regex(m_AllowedClients); | ||||
|                     Match am = arx.Match(clientVersion); | ||||
| 
 | ||||
|                     if (!am.Success) | ||||
|                     { | ||||
|                         m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is not allowed", clientVersion); | ||||
|                         return LLFailedLoginResponse.LoginBlockedProblem; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (m_DeniedClients != string.Empty) | ||||
|                 { | ||||
|                     Regex drx = new Regex(m_DeniedClients); | ||||
|                     Match dm = drx.Match(clientVersion); | ||||
| 
 | ||||
|                     if (dm.Success) | ||||
|                     { | ||||
|                         m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is denied", clientVersion); | ||||
|                         return LLFailedLoginResponse.LoginBlockedProblem; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 // | ||||
|                 // Get the account and check that it exists | ||||
|                 // | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ Now see the "Configuring OpenSim" section | |||
| === Running OpenSim on Linux === | ||||
| ================================ | ||||
| 
 | ||||
| You will need Mono >= 2.4.2 to run OpenSim.  On some Linux distributions you | ||||
| You will need Mono >= 2.4.3 to run OpenSim.  On some Linux distributions you | ||||
| may need to install additional packages.  See http://opensimulator.org/wiki/Dependencies | ||||
| for more information. | ||||
| 
 | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bin/DotSets.dll
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								bin/DotSets.dll
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bin/MXP.dll
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								bin/MXP.dll
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -621,31 +621,49 @@ | |||
| 
 | ||||
|     ;; You need to load a local service for a standalone, and a remote service | ||||
|     ;; for a grid region. Use one of the lines below, as appropriate | ||||
|     ;; If you're using Freeswitch on a standalone then you will also need to configure the [FreeswitchService] section | ||||
|     ; LocalServiceModule = OpenSim.Services.FreeswitchService.dll:FreeswitchService | ||||
|     ; LocalServiceModule = OpenSim.Services.Connectors.dll:RemoteFreeswitchConnector | ||||
| 
 | ||||
|     ;; If using a remote module, specify the server URL | ||||
|     ; FreeswitchServiceURL = http://my.grid.server:8003/fsapi | ||||
|     ;; If using a remote connector, specify the server URL | ||||
|     ; FreeswitchServiceURL = http://my.grid.server:8004/fsapi | ||||
| 
 | ||||
| 
 | ||||
| [FreeswitchService] | ||||
|     ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! | ||||
|     ;; !!!!!!STANDALONE ONLY!!!!!! | ||||
|     ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! | ||||
|     ;; IP of your FS server | ||||
|     ;ServerAddress = 85.25.142.92 | ||||
|     ;; The IP address of your FreeSWITCH server.  The common case is for this to be the same as the server running the OpenSim standalone | ||||
|     ;; This has to be set for the FreeSWITCH service to work | ||||
|     ;ServerAddress = 127.0.0.1 | ||||
| 
 | ||||
|     ;; All other options are - well - optional | ||||
|     ; Realm = "127.0.0.1" | ||||
|     ; SIPProxy = "127.0.0.1:5060" | ||||
|     ; EchoServer = "127.0.0.1" | ||||
|     ; EchoPort = 50505 | ||||
|     ; AttemptSTUN = "false" | ||||
|     ;; The following configuration parameters are optional | ||||
| 
 | ||||
|     ;; By default, this is the same as the ServerAddress | ||||
|     ; Realm = 127.0.0.1 | ||||
| 
 | ||||
|     ;; By default, this is the same as the ServerAddress on port 5060 | ||||
|     ; SIPProxy = 127.0.0.1:5060 | ||||
| 
 | ||||
|     ;; Default is 5000ms | ||||
|     ; DefaultTimeout = 5000 | ||||
|     ; Context = "default" | ||||
|     ; UserName = "freeswitch" | ||||
|     ; Password = "password" | ||||
| 
 | ||||
|     ;; The dial plan context.  Default is "default" | ||||
|     ; Context = default | ||||
| 
 | ||||
|     ;; Currently unused | ||||
|     ; UserName = freeswitch | ||||
| 
 | ||||
|     ;; Currently unused | ||||
|     ; Password = password | ||||
| 
 | ||||
|     ;; The following parameters are for STUN = Simple Traversal of UDP through NATs | ||||
|     ;; See http://wiki.freeswitch.org/wiki/NAT_Traversal | ||||
|     ;; stun.freeswitch.org is not guaranteed to be running so use it in | ||||
|     ;; production at your own risk     | ||||
|     ; EchoServer = 127.0.0.1 | ||||
|     ; EchoPort = 50505 | ||||
|     ; AttemptSTUN = false | ||||
| 
 | ||||
| [Groups] | ||||
|     ;# {Enabled} {} {Enable groups?} {true false} false | ||||
|  |  | |||
|  | @ -149,12 +149,6 @@ | |||
|     ; to false if you have compatibility problems. | ||||
|     ;CacheSculptMaps = true | ||||
|      | ||||
|     ; if you use Meshmerizer and want collisions for meshies, setting this to true | ||||
|     ; will cause OpenSim to attempt to decode meshies assets, extract the physics | ||||
|     ; mesh, and use it for collisions. This is currently experimental code and enabling | ||||
|     ; it may cause unexpected physics problems. | ||||
|     ;UseMeshiesPhysicsMesh = false | ||||
| 
 | ||||
|     ; Choose one of the physics engines below | ||||
|     ; OpenDynamicsEngine is by some distance the most developed physics engine | ||||
|     ; basicphysics effectively does not model physics at all, making all objects phantom | ||||
|  | @ -368,30 +362,24 @@ | |||
|     ; | ||||
|     ;client_throttle_max_bps = 196608 | ||||
| 
 | ||||
|     ; Per-client bytes per second rates for the various throttle categories. | ||||
|     ; These are default values that will be overriden by clients | ||||
|     ; Adaptive throttling attempts to limit network overload when multiple | ||||
|     ; clients login by starting each connection more slowly. Disabled by | ||||
|     ; default | ||||
|     ; | ||||
|     ;resend_default = 12500 | ||||
|     ;land_default = 1000 | ||||
|     ;wind_default = 1000 | ||||
|     ;cloud_default = 1000 | ||||
|     ;task_default = 1000 | ||||
|     ;texture_default = 1000 | ||||
|     ;asset_default = 1000 | ||||
|     ;state_default = 1000 | ||||
|     ;enable_adaptive_throttles = true | ||||
| 
 | ||||
|     ; Per-client maximum burst rates in bytes per second for the various | ||||
|     ; throttle categories. These are default values that will be overriden by | ||||
|     ; clients | ||||
|     ; | ||||
|     ;resend_limit = 18750 | ||||
|     ;land_limit = 29750 | ||||
|     ;wind_limit = 18750 | ||||
|     ;cloud_limit = 18750 | ||||
|     ;task_limit = 18750 | ||||
|     ;texture_limit = 55750 | ||||
|     ;asset_limit = 27500 | ||||
|     ;state_limit = 37000 | ||||
|     ; Per-client bytes per second rates for the various throttle categories. | ||||
|     ; These are default values that will be overriden by clients. These | ||||
|     ; defaults are approximately equivalent to the throttles set by the Imprudence | ||||
|     ; viewer when maximum bandwidth is set to 350kbps | ||||
| 
 | ||||
|     ;resend_default = 6625 | ||||
|     ;land_default = 9125 | ||||
|     ;wind_default = 1750 | ||||
|     ;cloud_default = 1750 | ||||
|     ;task_default = 18500 | ||||
|     ;texture_default = 18500 | ||||
|     ;asset_default = 10500 | ||||
| 
 | ||||
|     ; Configures how ObjectUpdates are aggregated. These numbers | ||||
|     ; do not literally mean how many updates will be put in each | ||||
|  | @ -459,7 +447,13 @@ | |||
| [Mesh] | ||||
|     ; enable / disable Collada mesh support | ||||
|     ; default is true | ||||
|     ; ColladaMesh = true | ||||
|     ; AllowMeshUpload = true | ||||
| 
 | ||||
|     ; if you use Meshmerizer and want collisions for meshies, setting this to true | ||||
|     ; will cause OpenSim to attempt to decode meshies assets, extract the physics | ||||
|     ; mesh, and use it for collisions. This is currently experimental code and enabling | ||||
|     ; it may cause unexpected physics problems. | ||||
|     ;UseMeshiesPhysicsMesh = false | ||||
| 
 | ||||
| 
 | ||||
| [ODEPhysicsSettings] | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	 Dan Lake
						Dan Lake