aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs138
1 files changed, 96 insertions, 42 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 7964c50..348615e 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -35,6 +35,7 @@ using log4net;
35using Nini.Config; 35using Nini.Config;
36using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Statistics;
38using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
39using OpenMetaverse; 40using OpenMetaverse;
40 41
@@ -190,31 +191,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
190 } 191 }
191 } 192 }
192 193
193 public void RemoveClient(LLUDPClient udpClient)
194 {
195 IClientAPI client;
196
197 if (m_scene.ClientManager.TryGetClient(udpClient.CircuitCode, out client))
198 RemoveClient(client);
199 else
200 m_log.Warn("[LLUDPSERVER]: Failed to lookup IClientAPI for LLUDPClient " + udpClient.AgentID);
201 }
202
203 public void SetClientPaused(UUID agentID, bool paused)
204 {
205 LLUDPClient client;
206 if (clients.TryGetValue(agentID, out client))
207 {
208 client.IsPaused = paused;
209 }
210 else
211 {
212 m_log.Warn("[LLUDPSERVER]: Attempted to pause/unpause unknown agent " + agentID);
213 }
214 }
215
216 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) 194 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
217 { 195 {
196 // CoarseLocationUpdate packets cannot be split in an automated way
197 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
198 allowSplitting = false;
199
218 if (allowSplitting && packet.HasVariableBlocks) 200 if (allowSplitting && packet.HasVariableBlocks)
219 { 201 {
220 byte[][] datas = packet.ToBytesMultiple(); 202 byte[][] datas = packet.ToBytesMultiple();
@@ -251,6 +233,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
251 233
252 public void SendPacket(LLUDPClient client, Packet packet, ThrottleOutPacketType category, bool allowSplitting) 234 public void SendPacket(LLUDPClient client, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
253 { 235 {
236 // CoarseLocationUpdate packets cannot be split in an automated way
237 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
238 allowSplitting = false;
239
254 if (allowSplitting && packet.HasVariableBlocks) 240 if (allowSplitting && packet.HasVariableBlocks)
255 { 241 {
256 byte[][] datas = packet.ToBytesMultiple(); 242 byte[][] datas = packet.ToBytesMultiple();
@@ -339,6 +325,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
339 } 325 }
340 } 326 }
341 327
328 public void SendPing(LLUDPClient client)
329 {
330 IClientAPI api = client.ClientAPI;
331 if (api != null)
332 api.SendStartPingCheck(client.CurrentPingSequence++);
333 }
334
342 public void ResendUnacked(LLUDPClient client) 335 public void ResendUnacked(LLUDPClient client)
343 { 336 {
344 if (client.NeedAcks.Count > 0) 337 if (client.NeedAcks.Count > 0)
@@ -387,9 +380,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
387 //FIXME: Make 60 an .ini setting 380 //FIXME: Make 60 an .ini setting
388 if (Environment.TickCount - client.TickLastPacketReceived > 1000 * 60) 381 if (Environment.TickCount - client.TickLastPacketReceived > 1000 * 60)
389 { 382 {
390 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + client.RemoteEndPoint); 383 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + client.ClientAPI.Name);
391 384
392 RemoveClient(client); 385 RemoveClient(client.ClientAPI);
393 return; 386 return;
394 } 387 }
395 } 388 }
@@ -590,8 +583,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
590 LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); 583 LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint);
591 clients.Add(agentID, client.RemoteEndPoint, client); 584 clients.Add(agentID, client.RemoteEndPoint, client);
592 585
593 // Create the IClientAPI 586 // Create the LLClientView
594 IClientAPI clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode); 587 LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode);
595 clientApi.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; 588 clientApi.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler;
596 clientApi.OnLogout += LogoutHandler; 589 clientApi.OnLogout += LogoutHandler;
597 clientApi.OnConnectionClosed += RemoveClient; 590 clientApi.OnConnectionClosed += RemoveClient;
@@ -618,23 +611,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
618 611
619 private void IncomingPacketHandler() 612 private void IncomingPacketHandler()
620 { 613 {
621 IncomingPacket incomingPacket = new IncomingPacket(); 614 // Set this culture for the thread that incoming packets are received
622 Packet packet = null; 615 // on to en-US to avoid number parsing issues
623 LLUDPClient client = null; 616 Culture.SetCurrentCulture();
617
618 IncomingPacket incomingPacket = default(IncomingPacket);
624 619
625 while (base.IsRunning) 620 while (base.IsRunning)
626 { 621 {
627 // Reset packet to null for the check below
628 packet = null;
629
630 if (packetInbox.Dequeue(100, ref incomingPacket)) 622 if (packetInbox.Dequeue(100, ref incomingPacket))
631 { 623 Util.FireAndForget(ProcessInPacket, incomingPacket);
632 packet = incomingPacket.Packet;
633 client = incomingPacket.Client;
634
635 if (packet != null && client != null)
636 client.ClientAPI.ProcessInPacket(packet);
637 }
638 } 624 }
639 625
640 if (packetInbox.Count > 0) 626 if (packetInbox.Count > 0)
@@ -642,32 +628,98 @@ namespace OpenSim.Region.ClientStack.LindenUDP
642 packetInbox.Clear(); 628 packetInbox.Clear();
643 } 629 }
644 630
631 private void ProcessInPacket(object state)
632 {
633 IncomingPacket incomingPacket = (IncomingPacket)state;
634 Packet packet = incomingPacket.Packet;
635 LLUDPClient client = incomingPacket.Client;
636
637 if (packet != null && client != null)
638 {
639 try
640 {
641 client.ClientAPI.ProcessInPacket(packet);
642 }
643 catch (ThreadAbortException)
644 {
645 throw;
646 }
647 catch (Exception e)
648 {
649 if (StatsManager.SimExtraStats != null)
650 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
651
652 // Don't let a failure in an individual client thread crash the whole sim.
653 m_log.ErrorFormat("[LLUDPSERVER]: Client thread for {0} {1} crashed. Logging them out", client.ClientAPI.Name, client.AgentID);
654 m_log.Error(e.Message, e);
655
656 try
657 {
658 // Make an attempt to alert the user that their session has crashed
659 AgentAlertMessagePacket alert = client.ClientAPI.BuildAgentAlertPacket(
660 "Unfortunately the session for this client on the server has crashed.\n" +
661 "Any further actions taken will not be processed.\n" +
662 "Please relog", true);
663
664 SendPacket(client, alert, ThrottleOutPacketType.Unknown, false);
665
666 // TODO: There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to
667 // listeners yet, though.
668 client.ClientAPI.SendLogoutPacket();
669 RemoveClient(client.ClientAPI);
670 }
671 catch (ThreadAbortException)
672 {
673 throw;
674 }
675 catch (Exception e2)
676 {
677 m_log.Error("[LLUDPSERVER]: Further exception thrown on forced session logout for " + client.ClientAPI.Name);
678 m_log.Error(e2.Message, e2);
679 }
680 }
681 }
682 }
683
645 private void OutgoingPacketHandler() 684 private void OutgoingPacketHandler()
646 { 685 {
686 // Set this culture for the thread that outgoing packets are sent
687 // on to en-US to avoid number parsing issues
688 Culture.SetCurrentCulture();
689
647 int now = Environment.TickCount; 690 int now = Environment.TickCount;
648 int elapsedMS = 0; 691 int elapsedMS = 0;
649 int elapsed100MS = 0; 692 int elapsed100MS = 0;
693 int elapsed500MS = 0;
650 694
651 while (base.IsRunning) 695 while (base.IsRunning)
652 { 696 {
653 bool resendUnacked = false; 697 bool resendUnacked = false;
654 bool sendAcks = false; 698 bool sendAcks = false;
699 bool sendPings = false;
655 bool packetSent = false; 700 bool packetSent = false;
656 701
657 elapsedMS += Environment.TickCount - now; 702 elapsedMS += Environment.TickCount - now;
658 703
659 // Check for packets that need to be resent every 100ms 704 // Check for pending outgoing resends every 100ms
660 if (elapsedMS >= 100) 705 if (elapsedMS >= 100)
661 { 706 {
662 resendUnacked = true; 707 resendUnacked = true;
663 elapsedMS -= 100; 708 elapsedMS -= 100;
664 ++elapsed100MS; 709 ++elapsed100MS;
665 } 710 }
666 // Check for ACKs that need to be sent out every 500ms 711 // Check for pending outgoing ACKs every 500ms
667 if (elapsed100MS >= 5) 712 if (elapsed100MS >= 5)
668 { 713 {
669 sendAcks = true; 714 sendAcks = true;
670 elapsed100MS = 0; 715 elapsed100MS = 0;
716 ++elapsed500MS;
717 }
718 // Send pings to clients every 2000ms
719 if (elapsed500MS >= 4)
720 {
721 sendPings = true;
722 elapsed500MS = 0;
671 } 723 }
672 724
673 clients.ForEach( 725 clients.ForEach(
@@ -679,6 +731,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
679 ResendUnacked(client); 731 ResendUnacked(client);
680 if (sendAcks) 732 if (sendAcks)
681 SendAcks(client); 733 SendAcks(client);
734 if (sendPings)
735 SendPing(client);
682 } 736 }
683 ); 737 );
684 738