//Faux destructor public void Close() { m_shuttingdown = true; m_j2kDecodeModule = null; m_assetCache = null; m_client = null; }
public bool SendFirstPacket(LLClientView client) { // this means we don't have if (Data == null) { client.SendImageNotFound(m_requestedUUID); m_log.WarnFormat("[TEXTURE]: Got null Data element on a asset {0}.. and the missing image Data property is al", m_requestedUUID); return(true); } // Do we have less then 1 packet's worth of data? else if (m_asset.Data.Length <= cFirstPacketSize) { // Send only 1 packet client.SendImageFirstPart(1, m_requestedUUID, (uint)m_asset.Data.Length, m_asset.Data, 2); m_stopPacket = 0; return(true); } else { byte[] firstImageData = new byte[cFirstPacketSize]; try { Buffer.BlockCopy(m_asset.Data, 0, firstImageData, 0, (int)cFirstPacketSize); client.SendImageFirstPart(TexturePacketCount(), m_requestedUUID, (uint)m_asset.Data.Length, firstImageData, 2); } catch (Exception) { m_log.Error("Texture block copy failed. Possibly out of memory?"); return(true); } } return(false); }
/// <summary> /// Sends packets for this texture to a client until packetsToSend is /// hit or the transfer completes /// </summary> /// <param name="client">Reference to the client that the packets are destined for</param> /// <param name="packetsToSend">Maximum number of packets to send during this call</param> /// <param name="packetsSent">Number of packets sent during this call</param> /// <returns>True if the transfer completes at the current discard level, otherwise false</returns> public bool SendPackets(LLClientView client, int packetsToSend, out int packetsSent) { packetsSent = 0; if (m_currentPacket <= m_stopPacket) { bool sendMore = true; if (!m_sentInfo || (m_currentPacket == 0)) { sendMore = !SendFirstPacket(client); m_sentInfo = true; ++m_currentPacket; ++packetsSent; } if (m_currentPacket < 2) { m_currentPacket = 2; } while (sendMore && packetsSent < packetsToSend && m_currentPacket <= m_stopPacket) { sendMore = SendPacket(client); ++m_currentPacket; ++packetsSent; } } return(m_currentPacket > m_stopPacket); }
/// <summary> /// Sends packets for this texture to a client until packetsToSend is /// hit or the transfer completes /// </summary> /// <param name = "client">Reference to the client that the packets are destined for</param> /// <param name = "packetsToSend">Maximum number of packets to send during this call</param> /// <param name = "packetsSent">Number of packets sent during this call</param> /// <returns>True if the transfer completes at the current discard level, otherwise false</returns> public bool SendPackets(LLClientView client, int packetsToSend, out int packetsSent) { packetsSent = 0; if (m_currentPacket <= m_stopPacket) { bool sendMore = true; if (!m_sentInfo || (m_currentPacket == 0)) { sendMore = !SendFirstPacket(client); m_sentInfo = true; ++m_currentPacket; ++packetsSent; } if (m_currentPacket < 2) { m_currentPacket = 2; } while (sendMore && packetsSent < packetsToSend && m_currentPacket <= m_stopPacket) { sendMore = SendPacket(client); ++m_currentPacket; ++packetsSent; } } return (m_currentPacket > m_stopPacket); }
private bool SendPacket(LLClientView client) { if (client == null || m_asset == null) { return(false); } bool complete = false; int imagePacketSize = ((int)m_currentPacket == (TexturePacketCount())) ? LastPacketSize() : IMAGE_PACKET_SIZE; try { if ((CurrentBytePosition() + IMAGE_PACKET_SIZE) > m_asset.Length) { imagePacketSize = LastPacketSize(); complete = true; if ((CurrentBytePosition() + imagePacketSize) > m_asset.Length) { imagePacketSize = m_asset.Length - CurrentBytePosition(); complete = true; } } /// <summary> /// It is concievable that the client might request packet one /// from a one packet image, which is really packet 0, /// which would leave us with a negative imagePacketSize. /// </summary> if (imagePacketSize > 0) { byte[] imageData = new byte[imagePacketSize]; int currentPosition = CurrentBytePosition(); try { Buffer.BlockCopy(m_asset, currentPosition, imageData, 0, imagePacketSize); } catch (Exception e) { MainConsole.Instance.ErrorFormat( "[J2KIMAGE]: Texture block copy for the first packet failed. textureid={0}, assetlength={1}, currentposition={2}, imagepacketsize={3}, exception={4}", TextureID, m_asset.Length, currentPosition, imagePacketSize, e.Message); return(false); } //Send the packet client.SendImageNextPart((ushort)(m_currentPacket - 1), TextureID, imageData); } return(!complete); } catch (Exception) { return(false); } }
private bool SendPacket(LLClientView client) { bool complete = false; int imagePacketSize = ((int)m_packetNumber == (TexturePacketCount())) ? LastPacketSize() : cImagePacketSize; try { if ((CurrentBytePosition() + cImagePacketSize) > m_asset.Data.Length) { imagePacketSize = LastPacketSize(); complete = true; if ((CurrentBytePosition() + imagePacketSize) > m_asset.Data.Length) { imagePacketSize = m_asset.Data.Length - CurrentBytePosition(); complete = true; } } // It's concievable that the client might request packet one // from a one packet image, which is really packet 0, // which would leave us with a negative imagePacketSize.. if (imagePacketSize > 0) { byte[] imageData = new byte[imagePacketSize]; try { Buffer.BlockCopy(m_asset.Data, CurrentBytePosition(), imageData, 0, imagePacketSize); } catch (Exception e) { m_log.Error("Error copying texture block. Out of memory? imagePacketSize was " + imagePacketSize.ToString() + " on packet " + m_packetNumber.ToString() + " out of " + m_stopPacket.ToString() + ". Exception: " + e.ToString()); return(false); } //Send the packet client.SendImageNextPart((ushort)(m_packetNumber - 1), m_requestedUUID, imageData); } if (complete) { return(false); } else { return(true); } } catch (Exception) { return(false); } }
public LLImageManager(LLClientView client, IAssetCache pAssetCache, IJ2KDecoder pJ2kDecodeModule) { m_client = client; m_assetCache = pAssetCache; /*if (pAssetCache != null) * m_missingImage = pAssetCache.GetAsset(UUID.Parse("5748decc-f629-461c-9a36-a35a221fe21f"), AssetRequestInfo.InternalRequest()); * * if (m_missingImage == null) * m_log.Error("[ClientView] - Couldn't set missing image asset, falling back to missing image packet. This is known to crash the client"); */ m_j2kDecodeModule = pJ2kDecodeModule; }
public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) { m_client = client; m_assetCache = pAssetCache; if (pAssetCache != null && m_missingImage == null) m_missingImage = pAssetCache.Get("5748decc-f629-461c-9a36-a35a221fe21f"); if (m_missingImage == null) MainConsole.Instance.Error( "[ClientView] - Couldn't set missing image asset, falling back to missing image packet. This is known to crash the client"); m_j2kDecodeModule = pJ2kDecodeModule; }
//Constructor public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) { m_imagestore = new Dictionary<UUID,J2KImage>(); m_priorities = new SortedList<double,UUID>(); m_priorityresolver = new Dictionary<int, int>(); m_client = client; m_assetCache = pAssetCache; if (pAssetCache != null) m_missingsubstitute = pAssetCache.Get("5748decc-f629-461c-9a36-a35a221fe21f"); else m_log.Error("[ClientView] - couldn't set missing image, all manner of things will probably break"); m_j2kDecodeModule = pJ2kDecodeModule; }
protected string HandleImageQueuesClear(string[] cmd) { if (cmd.Length != 5) { return("Usage: image queues clear <first-name> <last-name>"); } string firstName = cmd[3]; string lastName = cmd[4]; List <ScenePresence> foundAgents = new List <ScenePresence>(); lock (m_scenes) { foreach (Scene scene in m_scenes.Values) { ScenePresence sp = scene.GetScenePresence(firstName, lastName); if (sp != null) { foundAgents.Add(sp); } } } if (foundAgents.Count == 0) { return(string.Format("No agents found for {0} {1}", firstName, lastName)); } StringBuilder report = new StringBuilder(); foreach (ScenePresence agent in foundAgents) { LLClientView client = agent.ControllingClient as LLClientView; if (client == null) { return("This command is only supported for LLClientView"); } int requestsDeleted = client.ImageManager.ClearImageQueue(); report.AppendFormat( "In region {0} ({1} agent) cleared {2} requests\n", agent.Scene.RegionInfo.RegionName, agent.IsChildAgent ? "child" : "root", requestsDeleted); } return(report.ToString()); }
//Constructor public LLImageManager(LLClientView client, IAssetCache pAssetCache, IJ2KDecoder pJ2kDecodeModule) { m_imagestore = new Dictionary <UUID, J2KImage>(); m_priorities = new SortedList <double, UUID>(); m_priorityresolver = new Dictionary <int, int>(); m_client = client; m_assetCache = pAssetCache; if (pAssetCache != null) { m_missingsubstitute = pAssetCache.GetAsset(UUID.Parse("5748decc-f629-461c-9a36-a35a221fe21f"), true); } else { m_log.Error("[ClientView] - couldn't set missing image, all manner of things will probably break"); } m_j2kDecodeModule = pJ2kDecodeModule; }
public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) { m_client = client; m_assetCache = pAssetCache; if (pAssetCache != null && m_missingImage == null) { //m_missingImage = pAssetCache.Get("5748decc-f629-461c-9a36-a35a221fe21f"); // this is just a blank texture. Not very useful -greythane- m_missingImage = pAssetCache.Get(Constants.MISSING_TEXTURE_ID); } if (m_missingImage == null) { MainConsole.Instance.Error( "[ClientView] - Couldn't set missing image asset, falling back to missing image packet. This is known to crash the client"); } m_j2kDecodeModule = pJ2kDecodeModule; }
protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) { // Create the LLUDPClient LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); IClientAPI existingClient; if (!m_scene.TryGetClient(agentID, out existingClient)) { // Create the LLClientView LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; // Start the IClientAPI client.Start(); } else { m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}", udpClient.AgentID, remoteEndPoint, circuitCode); } }
private bool SendFirstPacket(LLClientView client) { if (client == null) { return(false); } if (m_asset == null) { MainConsole.Instance.Warn("[J2KIMAGE]: Sending ImageNotInDatabase for texture " + TextureID); client.SendImageNotFound(TextureID); return(true); } if (m_asset.Length <= FIRST_PACKET_SIZE) { // We have less then one packet's worth of data client.SendImageFirstPart(1, TextureID, (uint)m_asset.Length, m_asset, 2); m_stopPacket = 0; return(true); } // This is going to be a multi-packet texture download byte[] firstImageData = new byte[FIRST_PACKET_SIZE]; try { Buffer.BlockCopy(m_asset, 0, firstImageData, 0, FIRST_PACKET_SIZE); } catch (Exception) { MainConsole.Instance.ErrorFormat( "[J2KIMAGE]: Texture block copy for the first packet failed. textureid={0}, assetlength={1}", TextureID, m_asset.Length); return(true); } client.SendImageFirstPart(TexturePacketCount(), TextureID, (uint)m_asset.Length, firstImageData, (byte)ImageCodec.J2C); return(false); }
public bool SendPackets(LLClientView client, int maxpack) { if (!m_completedSendAtCurrentDiscardLevel) { if (m_packetNumber <= m_stopPacket) { bool SendMore = true; if (!m_sentinfo || (m_packetNumber == 0)) { if (SendFirstPacket(client)) { SendMore = false; } m_sentinfo = true; m_packetNumber++; } // bool ignoreStop = false; if (m_packetNumber < 2) { m_packetNumber = 2; } int count = 0; while (SendMore && count < maxpack && m_packetNumber <= m_stopPacket) { count++; SendMore = SendPacket(client); m_packetNumber++; } if (m_packetNumber > m_stopPacket) { return(true); } } } return(false); }
protected virtual bool AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AgentCircuitData sessionInfo) { IScenePresence SP; if (!m_scene.TryGetScenePresence(agentID, out SP)) { // Create the LLUDPClient LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); // Create the LLClientView LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; client.DisableFacelights = m_disableFacelights; // Start the IClientAPI m_scene.AddNewClient(client); } else { m_log.DebugFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode ({0}) from {1} at {2} ", circuitCode, agentID, remoteEndPoint); } return(true); }
private bool SendPacket(LLClientView client) { if (client == null || m_asset == null) return false; bool complete = false; int imagePacketSize = ((int) m_currentPacket == (TexturePacketCount())) ? LastPacketSize() : IMAGE_PACKET_SIZE; try { if ((CurrentBytePosition() + IMAGE_PACKET_SIZE) > m_asset.Length) { imagePacketSize = LastPacketSize(); complete = true; if ((CurrentBytePosition() + imagePacketSize) > m_asset.Length) { imagePacketSize = m_asset.Length - CurrentBytePosition(); complete = true; } } // It's concievable that the client might request packet one // from a one packet image, which is really packet 0, // which would leave us with a negative imagePacketSize.. if (imagePacketSize > 0) { byte[] imageData = new byte[imagePacketSize]; int currentPosition = CurrentBytePosition(); try { Buffer.BlockCopy(m_asset, currentPosition, imageData, 0, imagePacketSize); } catch (Exception e) { MainConsole.Instance.ErrorFormat( "[J2KIMAGE]: Texture block copy for the first packet failed. textureid={0}, assetlength={1}, currentposition={2}, imagepacketsize={3}, exception={4}", TextureID, m_asset.Length, currentPosition, imagePacketSize, e.Message); return false; } //Send the packet client.SendImageNextPart((ushort) (m_currentPacket - 1), TextureID, imageData); } return !complete; } catch (Exception) { return false; } }
public virtual bool AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AgentCircuitData sessionInfo) { MainConsole.Instance.Debug("[LLUDPServer] AddClient-" + circuitCode + "-" + agentID + "-" + sessionID + "-" + remoteEndPoint + "-" + sessionInfo); IScenePresence SP; if (!m_scene.TryGetScenePresence(agentID, out SP)) { // Create the LLUDPClient LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); // Create the LLClientView LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; // Start the IClientAPI m_scene.AddNewClient(client, null); m_currentClients.Add(client); } else { MainConsole.Instance.DebugFormat( "[LLUDPSERVER]: Ignoring a repeated UseCircuitCode ({0}) from {1} at {2} ", circuitCode, agentID, remoteEndPoint); } return true; }
private bool SendFirstPacket(LLClientView client) { if (client == null) return false; if (m_asset == null) { MainConsole.Instance.Warn("[J2KIMAGE]: Sending ImageNotInDatabase for texture " + TextureID); client.SendImageNotFound(TextureID); return true; } if (m_asset.Length <= FIRST_PACKET_SIZE) { // We have less then one packet's worth of data client.SendImageFirstPart(1, TextureID, (uint) m_asset.Length, m_asset, 2); m_stopPacket = 0; return true; } // This is going to be a multi-packet texture download byte[] firstImageData = new byte[FIRST_PACKET_SIZE]; try { Buffer.BlockCopy(m_asset, 0, firstImageData, 0, FIRST_PACKET_SIZE); } catch (Exception) { MainConsole.Instance.ErrorFormat( "[J2KIMAGE]: Texture block copy for the first packet failed. textureid={0}, assetlength={1}", TextureID, m_asset.Length); return true; } client.SendImageFirstPart(TexturePacketCount(), TextureID, (uint) m_asset.Length, firstImageData, (byte) ImageCodec.J2C); return false; }
protected void HandleClientKpi(string module, string[] cmd) { s_log.Debug("[CLIENTKPI] Showing Client KPI:"); // Getting Priority Queues Report int columnPadding = 2; int maxNameLength = 18; int maxRegionNameLength = 14; int maxTypeLength = 4; int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding; StringBuilder reportline = new StringBuilder(); bool firstClient = true; lock (m_scenes) { foreach (Scene scene in m_scenes.Values) { scene.ForEachClient( delegate(IClientAPI client) { if (client is LLClientView) { bool isChild = client.SceneAgent.IsChildAgent; string name = client.Name; string regionName = scene.RegionInfo.RegionName; reportline.Append("[PQUEUE] "); reportline.AppendFormat("AgentName:{0},RegionName:{1},isChild:{2},", name, regionName, isChild ? "Cd" : "Rt"); reportline.Append(((LLClientView)client).EntityUpdateQueue.ToString()); s_log.Debug(reportline); reportline.Length = 0; reportline.Append("[QUEUE] "); reportline.AppendFormat("AgentName:{0},RegionName:{1},isChild:{2},", name, regionName, isChild ? "Cd" : "Rt"); if (client is IStatsCollector) { IStatsCollector stats = (IStatsCollector)client; reportline.Append(stats.Report()); } s_log.Debug(reportline); reportline.Length = 0; LLClientView llClient = client as LLClientView; if (firstClient) { reportline.Append("[THROTTLE] SERVER_AGENT_RATES:"); ThrottleRates throttleRates = llClient.UDPServer.ThrottleRates; reportline.AppendFormat( "{0},{1},{2},{3},{4},{5},{6},{7}", (throttleRates.Total * 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); s_log.Debug(reportline); reportline.Length = 0; firstClient = false; } LLUDPClient llUdpClient = llClient.UDPClient; ClientInfo ci = llUdpClient.GetClientInfo(); reportline.Append("[THROTTLE] "); reportline.AppendFormat("AgentName:{0},RegionName:{1},isChild:{2},", name, regionName, isChild ? "Cd" : "Rt"); reportline.AppendFormat( "{0},{1},{2},{3},{4},{5},{6},{7}", (ci.totalThrottle * 8) / 1000, (ci.resendThrottle * 8) / 1000, (ci.landThrottle * 8) / 1000, (ci.windThrottle * 8) / 1000, (ci.cloudThrottle * 8) / 1000, (ci.taskThrottle * 8) / 1000, (ci.textureThrottle * 8) / 1000, (ci.assetThrottle * 8) / 1000); s_log.Debug(reportline); reportline.Length = 0; } }); } } }
protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) { // In priciple there shouldn't be more than one thread here, ever. // But in case that happens, we need to synchronize this piece of code // because it's too important lock (this) { IClientAPI existingClient; if (!m_scene.TryGetClient(agentID, out existingClient)) { // Create the LLUDPClient LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); // Create the LLClientView LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; client.DisableFacelights = m_disableFacelights; // Start the IClientAPI client.Start(); } else { m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}", existingClient.AgentId, remoteEndPoint, circuitCode); } } }
protected virtual bool AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AgentCircuitData sessionInfo) { IScenePresence SP; if (!m_scene.TryGetScenePresence(agentID, out SP)) { // Create the LLUDPClient LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); // Create the LLClientView LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; client.DisableFacelights = m_disableFacelights; // Start the IClientAPI m_scene.AddNewClient(client); m_currentClients.Add (client); } else { m_log.DebugFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode ({0}) from {1} at {2} ", circuitCode, agentID, remoteEndPoint); } return true; }
/// <summary> /// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds). /// </summary> /// <remarks> /// If a connection is active then we will always receive packets even if nothing else is happening, due to /// regular client pings. /// </remarks> /// <param name='client'></param> /// <param name='timeoutTicks'></param> private void DeactivateClientDueToTimeout(LLClientView client, int timeoutTicks) { lock (client.CloseSyncLock) { ClientLogoutsDueToNoReceives++; m_log.WarnFormat( "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2} for {3}ms", client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.Name, timeoutTicks); if (!client.SceneAgent.IsChildAgent) client.Kick("Simulator logged you out due to connection timeout."); } m_scene.CloseAgent(client.AgentId, true); }
private void HandleDropCommand(string module, string[] args) { if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) { return; } if (args.Length != 6) { MainConsole.Instance.Output("Usage: debug lludp drop <in|out> <add|remove> <packet-name>"); return; } string direction = args[3]; string subCommand = args[4]; string packetName = args[5]; if (subCommand == "add") { MainConsole.Instance.Output( "Adding packet {0} to {1} drop list for all connections in {2}", direction, packetName, m_udpServer.Scene.Name); m_udpServer.Scene.ForEachScenePresence( sp => { LLClientView llcv = (LLClientView)sp.ControllingClient; if (direction == "in") { llcv.AddInPacketToDropSet(packetName); } else if (direction == "out") { llcv.AddOutPacketToDropSet(packetName); } } ); } else if (subCommand == "remove") { MainConsole.Instance.Output( "Removing packet {0} from {1} drop list for all connections in {2}", direction, packetName, m_udpServer.Scene.Name); m_udpServer.Scene.ForEachScenePresence( sp => { LLClientView llcv = (LLClientView)sp.ControllingClient; if (direction == "in") { llcv.RemoveInPacketFromDropSet(packetName); } else if (direction == "out") { llcv.RemoveOutPacketFromDropSet(packetName); } } ); } }
/// <summary> /// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds). /// </summary> /// <remarks> /// If a connection is active then we will always receive packets even if nothing else is happening, due to /// regular client pings. /// </remarks> /// <param name='client'></param> private void DeactivateClientDueToTimeout(LLClientView client) { lock (client.CloseSyncLock) { m_log.WarnFormat( "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); if (!client.SceneAgent.IsChildAgent) client.Kick("Simulator logged you out due to connection timeout"); client.CloseWithoutChecks(); } }
private bool SendPacket(LLClientView client) { bool complete = false; int imagePacketSize = ((int)m_packetNumber == (TexturePacketCount())) ? LastPacketSize() : cImagePacketSize; try { if ((CurrentBytePosition() + cImagePacketSize) > m_asset.Data.Length) { imagePacketSize = LastPacketSize(); complete=true; if ((CurrentBytePosition() + imagePacketSize) > m_asset.Data.Length) { imagePacketSize = m_asset.Data.Length - CurrentBytePosition(); complete = true; } } // It's concievable that the client might request packet one // from a one packet image, which is really packet 0, // which would leave us with a negative imagePacketSize.. if (imagePacketSize > 0) { byte[] imageData = new byte[imagePacketSize]; try { Buffer.BlockCopy(m_asset.Data, CurrentBytePosition(), imageData, 0, imagePacketSize); } catch (Exception e) { m_log.Error("Error copying texture block. Out of memory? imagePacketSize was " + imagePacketSize.ToString() + " on packet " + m_packetNumber.ToString() + " out of " + m_stopPacket.ToString() + ". Exception: " + e.ToString()); return false; } //Send the packet client.SendImageNextPart((ushort)(m_packetNumber-1), m_requestedUUID, imageData); } if (complete) { return false; } else { return true; } } catch (Exception) { return false; } }
/// <summary> /// Constructor /// </summary> /// <param name="client">Reference to the client this packet came from</param> /// <param name="packet">Packet data</param> public IncomingPacket(LLClientView client, Packet packet) { Client = client; Packet = packet; }
/// <summary> /// Add a client. /// </summary> /// <param name="circuitCode"></param> /// <param name="agentID"></param> /// <param name="sessionID"></param> /// <param name="remoteEndPoint"></param> /// <param name="sessionInfo"></param> /// <returns>The client if it was added. Null if the client already existed.</returns> protected virtual IClientAPI AddClient( uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) { IClientAPI client = null; // We currently synchronize this code across the whole scene to avoid issues such as // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done // consistently, this lock could probably be removed. lock (this) { if (!m_scene.TryGetClient(agentID, out client)) { LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; client.DebugPacketLevel = DefaultClientPacketDebugLevel; ((LLClientView)client).DisableFacelights = m_disableFacelights; client.Start(); } } return client; }
/// <summary> /// Show client stats data /// </summary> /// <param name="showParams"></param> /// <returns></returns> protected string HandleClientStatsReport(string[] showParams) { // NOTE: This writes to m_log on purpose. We want to store this information // in case we need to analyze it later. // if (showParams.Length <= 4) { m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", "Region", "Name", "Root", "Time", "Reqs/min", "AgentUpdates"); foreach (Scene scene in m_scenes.Values) { scene.ForEachClient( delegate(IClientAPI client) { if (client is LLClientView) { LLClientView llClient = client as LLClientView; ClientInfo cinfo = llClient.UDPClient.GetClientInfo(); int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum(); avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1); string childAgentStatus; if (llClient.SceneAgent != null) { childAgentStatus = llClient.SceneAgent.IsChildAgent ? "N" : "Y"; } else { childAgentStatus = "Off!"; } m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", scene.RegionInfo.RegionName, llClient.Name, childAgentStatus, (DateTime.Now - cinfo.StartedTime).Minutes, avg_reqs, string.Format( "{0} ({1:0.00}%)", llClient.TotalAgentUpdates, cinfo.SyncRequests.ContainsKey("AgentUpdate") ? (float)cinfo.SyncRequests["AgentUpdate"] / llClient.TotalAgentUpdates * 100 : 0)); } }); } return(string.Empty); } string fname = "", lname = ""; if (showParams.Length > 3) { fname = showParams[3]; } if (showParams.Length > 4) { lname = showParams[4]; } foreach (Scene scene in m_scenes.Values) { scene.ForEachClient( delegate(IClientAPI client) { if (client is LLClientView) { LLClientView llClient = client as LLClientView; if (llClient.Name == fname + " " + lname) { ClientInfo cinfo = llClient.GetClientInfo(); AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(llClient.CircuitCode); if (aCircuit == null) // create a dummy one { aCircuit = new AgentCircuitData(); } if (!llClient.SceneAgent.IsChildAgent) { m_log.InfoFormat("[INFO]: {0} # {1} # {2}", llClient.Name, Util.GetViewerName(aCircuit), aCircuit.Id0); } int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum(); avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1); m_log.InfoFormat("[INFO]:"); m_log.InfoFormat("[INFO]: {0} # {1} # Time: {2}min # Avg Reqs/min: {3}", scene.RegionInfo.RegionName, (llClient.SceneAgent.IsChildAgent ? "Child" : "Root"), (DateTime.Now - cinfo.StartedTime).Minutes, avg_reqs); Dictionary <string, int> sortedDict = (from entry in cinfo.AsyncRequests orderby entry.Value descending select entry) .ToDictionary(pair => pair.Key, pair => pair.Value); PrintRequests("TOP ASYNC", sortedDict, cinfo.AsyncRequests.Values.Sum()); sortedDict = (from entry in cinfo.SyncRequests orderby entry.Value descending select entry) .ToDictionary(pair => pair.Key, pair => pair.Value); PrintRequests("TOP SYNC", sortedDict, cinfo.SyncRequests.Values.Sum()); sortedDict = (from entry in cinfo.GenericRequests orderby entry.Value descending select entry) .ToDictionary(pair => pair.Key, pair => pair.Value); PrintRequests("TOP GENERIC", sortedDict, cinfo.GenericRequests.Values.Sum()); } } }); } return(string.Empty); }
/// <summary> /// Generate an image queue report /// </summary> /// <param name="showParams"></param> /// <returns></returns> private string GetImageQueuesReport(string[] showParams) { if (showParams.Length < 5 || showParams.Length > 6) { return("Usage: show image queues <first-name> <last-name> [full]"); } string firstName = showParams[3]; string lastName = showParams[4]; bool showChildAgents = showParams.Length == 6; List <ScenePresence> foundAgents = new List <ScenePresence>(); lock (m_scenes) { foreach (Scene scene in m_scenes.Values) { ScenePresence sp = scene.GetScenePresence(firstName, lastName); if (sp != null && (showChildAgents || !sp.IsChildAgent)) { foundAgents.Add(sp); } } } if (foundAgents.Count == 0) { return(string.Format("No agents found for {0} {1}", firstName, lastName)); } StringBuilder report = new StringBuilder(); foreach (ScenePresence agent in foundAgents) { LLClientView client = agent.ControllingClient as LLClientView; if (client == null) { return("This command is only supported for LLClientView"); } J2KImage[] images = client.ImageManager.GetImages(); report.AppendFormat( "In region {0} ({1} agent)\n", agent.Scene.RegionInfo.RegionName, agent.IsChildAgent ? "child" : "root"); report.AppendFormat("Images in queue: {0}\n", images.Length); if (images.Length > 0) { report.AppendFormat( "{0,-36} {1,-8} {2,-10} {3,-9} {4,-9} {5,-7}\n", "Texture ID", "Last Seq", "Priority", "Start Pkt", "Has Asset", "Decoded"); foreach (J2KImage image in images) { report.AppendFormat( "{0,36} {1,8} {2,10} {3,10} {4,9} {5,7}\n", image.TextureID, image.LastSequence, image.Priority, image.StartPacket, image.HasAsset, image.IsDecoded); } } } return(report.ToString()); }
public bool SendPackets(LLClientView client, int maxpack) { if (!m_completedSendAtCurrentDiscardLevel) { if (m_packetNumber <= m_stopPacket) { bool SendMore = true; if (!m_sentinfo || (m_packetNumber == 0)) { if (SendFirstPacket(client)) { SendMore = false; } m_sentinfo = true; m_packetNumber++; } // bool ignoreStop = false; if (m_packetNumber < 2) { m_packetNumber = 2; } int count = 0; while (SendMore && count < maxpack && m_packetNumber <= m_stopPacket) { count++; SendMore = SendPacket(client); m_packetNumber++; } if (m_packetNumber > m_stopPacket) { return true; } } } return false; }
protected virtual bool AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) { // Create the LLUDPClient LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); IClientAPI existingClient; //Check to make sure we arn't handling two or more circuit codes from the client if we are lagging badly. // The block below this (TryGetClient) works as well, but if it gets locked up before the client is added to the scene, it will break // So we do this check here as well. lock (m_handlingCircuitCodes) { if (m_handlingCircuitCodes.Contains(agentID)) return false; m_handlingCircuitCodes.Add(agentID); } if (!m_scene.TryGetClient(agentID, out existingClient)) { // Create the LLClientView LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; client.DisableFacelights = m_disableFacelights; // Start the IClientAPI client.Start(); //Remove it from the check m_handlingCircuitCodes.Remove(agentID); return true; } else { m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}", udpClient.AgentID, remoteEndPoint, circuitCode); } //Remove it from the check m_handlingCircuitCodes.Remove(agentID); return false; }
protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) { // Create the LLUDPClient LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); IClientAPI existingClient; if (!m_scene.TryGetClient(agentID, out existingClient)) { // Create the LLClientView LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; client.DisableFacelights = m_disableFacelights; // Start the IClientAPI client.Start(); } else { m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}", udpClient.AgentID, remoteEndPoint, circuitCode); } }
/// <summary> /// Show throttle data /// </summary> /// <param name="showParams"></param> /// <returns></returns> protected string GetThrottlesReport(string[] showParams) { bool showChildren = false; if (showParams.Length > 2 && showParams[2] == "full") { showChildren = true; } 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,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}\n", "Total", "Resend", "Land", "Wind", "Cloud", "Task", "Texture", "Asset"); report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); report.AppendFormat( "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", "kb/s", "kb/s", "kb/s", "kb/s", "kb/s", "kb/s", "kb/s", "kb/s"); report.AppendLine(); bool firstClient = true; lock (m_scenes) { foreach (Scene scene in m_scenes.Values) { scene.ForEachClient( delegate(IClientAPI client) { if (client is LLClientView) { LLClientView llClient = client as LLClientView; if (firstClient) { report.AppendLine(GetServerThrottlesReport(llClient.UDPServer)); firstClient = false; } bool isChild = scene.PresenceChildStatus(client.AgentId); if (isChild && !showChildren) { return; } string name = client.Name; string regionName = scene.RegionInfo.RegionName; LLUDPClient llUdpClient = llClient.UDPClient; ClientInfo ci = llUdpClient.GetClientInfo(); report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding)); report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); report.AppendFormat( "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", (ci.totalThrottle * 8) / 1000, (ci.resendThrottle * 8) / 1000, (ci.landThrottle * 8) / 1000, (ci.windThrottle * 8) / 1000, (ci.cloudThrottle * 8) / 1000, (ci.taskThrottle * 8) / 1000, (ci.textureThrottle * 8) / 1000, (ci.assetThrottle * 8) / 1000); report.AppendLine(); } }); } } return(report.ToString()); }
private bool AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint) { UUID agentID = useCircuitCode.CircuitCode.ID; UUID sessionID = useCircuitCode.CircuitCode.SessionID; uint circuitCode = useCircuitCode.CircuitCode.Code; try { m_log.InfoFormat( "[LLUDPSERVER]: UCC Received for client {0} circuit code {1}", useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code); LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, agentID, sessionID, circuitCode); m_scene.ConnectionManager.TryAttachUdpCircuit(client); client.Start(); return true; } catch (OpenSim.Region.Framework.Connection.AttachUdpCircuitException e) { if (e.CircuitAlreadyExisted) { m_log.WarnFormat("[LLUDPSERVER]: Ignoring duplicate UDP connection request. {0}", e.Message); //if the circuit matches, we can ACK the UCC since the client should be //able to communicate with the current circuit if (e.ExistingCircuitMatched) { return true; } else { return false; } } else { m_log.ErrorFormat("[LLUDPSERVER]: Unable to start new connection: {0}", e); return false; } } }
/// <summary> /// Show throttle data /// </summary> /// <param name="showParams"></param> /// <returns></returns> 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; 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,8} {1,8} {2,7} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7}\n", "Max", "Target", "Actual", "Resend", "Land", "Wind", "Cloud", "Task", "Texture", "Asset"); report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); report.AppendFormat( "{0,8} {1,8} {2,7} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7}\n", "kb/s", "kb/s", "kb/s", "kb/s", "kb/s", "kb/s", "kb/s", "kb/s", "kb/s", "kb/s"); report.AppendLine(); lock (m_scenes) { foreach (Scene scene in m_scenes.Values) { scene.ForEachClient( delegate(IClientAPI client) { if (client is LLClientView) { LLClientView llClient = client as LLClientView; bool isChild = client.SceneAgent.IsChildAgent; if (isChild && !showChildren) { return; } string name = client.Name; if (pname != "" && name != pname) { return; } string regionName = scene.RegionInfo.RegionName; LLUDPClient llUdpClient = llClient.UDPClient; ClientInfo ci = llUdpClient.GetClientInfo(); report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding)); report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); report.AppendFormat( "{0,8} {1,8} {2,7} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7}\n", ci.maxThrottle > 0 ? ((ci.maxThrottle * 8) / 1000).ToString() : "-", llUdpClient.FlowThrottle.AdaptiveEnabled ? ((ci.targetThrottle * 8) / 1000).ToString() : (llUdpClient.FlowThrottle.TotalDripRequest * 8 / 1000).ToString(), (ci.totalThrottle * 8) / 1000, (ci.resendThrottle * 8) / 1000, (ci.landThrottle * 8) / 1000, (ci.windThrottle * 8) / 1000, (ci.cloudThrottle * 8) / 1000, (ci.taskThrottle * 8) / 1000, (ci.textureThrottle * 8) / 1000, (ci.assetThrottle * 8) / 1000); } }); } } return(report.ToString()); }
public void HandleUnacked(LLClientView client) { LLUDPClient udpClient = client.UDPClient; if (!udpClient.IsConnected) return; // Disconnect an agent if no packets are received for some time int timeoutTicks = m_ackTimeout; // Allow more slack if the client is "paused" eg file upload dialogue is open // Some sort of limit is needed in case the client crashes, loses its network connection // or some other disaster prevents it from sendung the AgentResume if (udpClient.IsPaused) timeoutTicks = m_pausedAckTimeout; if (client.IsActive && (Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks) { // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even // though it's set later on by LLClientView.Close() client.IsActive = false; // Fire this out on a different thread so that we don't hold up outgoing packet processing for // everybody else if this is being called due to an ack timeout. // This is the same as processing as the async process of a logout request. Util.FireAndForget(o => DeactivateClientDueToTimeout(client, timeoutTicks)); return; } // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO); if (expiredPackets != null) { //m_log.Debug("[LLUDPSERVER]: Handling " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); // Exponential backoff of the retransmission timeout udpClient.BackoffRTO(); for (int i = 0; i < expiredPackets.Count; ++i) expiredPackets[i].UnackedMethod(expiredPackets[i]); } }
/// <summary> /// Add a client. /// </summary> /// <param name="circuitCode"></param> /// <param name="agentID"></param> /// <param name="sessionID"></param> /// <param name="remoteEndPoint"></param> /// <param name="sessionInfo"></param> /// <returns>The client if it was added. Null if the client already existed.</returns> protected virtual IClientAPI AddClient( uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) { IClientAPI client = null; // In priciple there shouldn't be more than one thread here, ever. // But in case that happens, we need to synchronize this piece of code // because it's too important lock (this) { if (!m_scene.TryGetClient(agentID, out client)) { LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; ((LLClientView)client).DisableFacelights = m_disableFacelights; client.Start(); } } return client; }
/// <summary> /// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds). /// </summary> /// <remarks> /// If a connection is active then we will always receive packets even if nothing else is happening, due to /// regular client pings. /// </remarks> /// <param name='client'></param> /// <param name='timeoutTicks'></param> private void DeactivateClientDueToTimeout(LLClientView client, int timeoutTicks) { lock (client.CloseSyncLock) { ClientLogoutsDueToNoReceives++; m_log.WarnFormat( "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name); if (!client.SceneAgent.IsChildAgent) client.Kick("Simulator logged you out due to connection timeout."); } m_scene.IncomingCloseAgent(client.AgentId, true); }
public bool SendFirstPacket(LLClientView client) { // this means we don't have if (Data == null) { client.SendImageNotFound(m_requestedUUID); m_log.WarnFormat("[TEXTURE]: Got null Data element on a asset {0}.. and the missing image Data property is al", m_requestedUUID); return true; } // Do we have less then 1 packet's worth of data? else if (m_asset.Data.Length <= cFirstPacketSize) { // Send only 1 packet client.SendImageFirstPart(1, m_requestedUUID, (uint)m_asset.Data.Length, m_asset.Data, 2); m_stopPacket = 0; return true; } else { byte[] firstImageData = new byte[cFirstPacketSize]; try { Buffer.BlockCopy(m_asset.Data, 0, firstImageData, 0, (int)cFirstPacketSize); client.SendImageFirstPart(TexturePacketCount(), m_requestedUUID, (uint)m_asset.Data.Length, firstImageData, 2); } catch (Exception) { m_log.Error("Texture block copy failed. Possibly out of memory?"); return true; } } return false; }