From 0b6f8a02a7d0927031bf812429770d6ecc5f483a Mon Sep 17 00:00:00 2001 From: jhurliman Date: Wed, 7 Mar 2007 05:09:18 +0000 Subject: * Updating libsecondlife.dll to the latest version with a working LayerData function * Reformatting some source files * Adding a try/catch sanity check around a phoning home check to osgrid.org * Updating the MSVC project file * Converted LayerData generation to use the functions built in to libsecondlife * Removing unused BitPack.cs and TerrainDecoder.cs files * Added a basic terrain generator (hills algorithm) --- src/OpenSimClient.cs | 889 +++++++++++++++++++++++++++------------------------ 1 file changed, 469 insertions(+), 420 deletions(-) (limited to 'src/OpenSimClient.cs') diff --git a/src/OpenSimClient.cs b/src/OpenSimClient.cs index 655ebfe..497df00 100644 --- a/src/OpenSimClient.cs +++ b/src/OpenSimClient.cs @@ -37,425 +37,474 @@ using System.Timers; namespace OpenSim { - /// - /// Handles new client connections - /// Constructor takes a single Packet and authenticates everything - /// - public class OpenSimClient { - - public LLUUID AgentID; - public LLUUID SessionID; - public uint CircuitCode; - public world.Avatar ClientAvatar; - private UseCircuitCodePacket cirpack; - private Thread ClientThread; - public EndPoint userEP; - private BlockingQueue PacketQueue; - private BlockingQueue AssetRequests; - private Dictionary PendingAcks = new Dictionary(); - private Dictionary NeedAck = new Dictionary(); - private System.Timers.Timer AckTimer; - private uint Sequence = 0; - private object SequenceLock = new object(); - private const int MAX_APPENDED_ACKS = 10; - private const int RESEND_TIMEOUT = 4000; - private const int MAX_SEQUENCE = 0xFFFFFF; - private Queue Inbox; - - public void ack_pack(Packet Pack) { - //libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket(); - //ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; - //ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); - //ack_it.Packets[0].ID = Pack.Header.ID; - //ack_it.Header.Reliable = false; - - //OutPacket(ack_it); - - if (Pack.Header.Reliable) { - lock (PendingAcks) { - uint sequence = (uint)Pack.Header.Sequence; - if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; } - } - } - } - - public void AssetLoader() { - if(OpenSim_Main.cfg.sandbox==false) { - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Starting new thread"); - TransferRequestPacket reqPacket = AssetRequests.Dequeue(); - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Got a request, processing it"); - LLUUID AssetID = new LLUUID(reqPacket.TransferInfo.Params, 0); - WebRequest AssetLoad = WebRequest.Create(OpenSim_Main.cfg.AssetURL + "getasset/" + OpenSim_Main.cfg.AssetSendKey + "/" + AssetID + "/data"); - WebResponse AssetResponse = AssetLoad.GetResponse(); - byte[] idata = new byte[(int)AssetResponse.ContentLength]; - BinaryReader br = new BinaryReader(AssetResponse.GetResponseStream()); - idata = br.ReadBytes((int)AssetResponse.ContentLength); - br.Close(); - - TransferInfoPacket Transfer = new TransferInfoPacket(); - Transfer.TransferInfo.ChannelType = 2; - Transfer.TransferInfo.Status = 0; - Transfer.TransferInfo.TargetType = 0; - Transfer.TransferInfo.Params = reqPacket.TransferInfo.Params; - Transfer.TransferInfo.Size = (int)AssetResponse.ContentLength; - Transfer.TransferInfo.TransferID = reqPacket.TransferInfo.TransferID; - - OutPacket(Transfer); - - TransferPacketPacket TransferPacket = new TransferPacketPacket(); - TransferPacket.TransferData.Packet = 0; - TransferPacket.TransferData.ChannelType = 2; - TransferPacket.TransferData.TransferID=reqPacket.TransferInfo.TransferID; - - if(AssetResponse.ContentLength>1000) { - byte[] chunk = new byte[1000]; - Array.Copy(idata,chunk,1000); - TransferPacket.TransferData.Data = chunk; - TransferPacket.TransferData.Status = 0; - OutPacket(TransferPacket); - - TransferPacket = new TransferPacketPacket(); - TransferPacket.TransferData.Packet = 1; - TransferPacket.TransferData.ChannelType = 2; - TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID; - byte[] chunk1 = new byte[(idata.Length-1000)]; - Array.Copy(idata, 1000, chunk1, 0, chunk1.Length); - TransferPacket.TransferData.Data = chunk1; - TransferPacket.TransferData.Status = 1; - OutPacket(TransferPacket); - } else { - TransferPacket.TransferData.Status = 1; - TransferPacket.TransferData.Data = idata; - OutPacket(TransferPacket); - } - AssetResponse.Close(); - } - } - - public void Logout() { - // TODO - kill any AssetLoaders - ClientThread.Abort(); - } - - public void ProcessInPacket(Packet Pack) { - ack_pack(Pack); - switch(Pack.Type) { - case PacketType.CompleteAgentMovement: - ClientAvatar.CompleteMovement(OpenSim_Main.local_world); - ClientAvatar.SendInitialPosition(); - break; - case PacketType.RegionHandshakeReply: - OpenSim_Main.local_world.SendLayerData(this); - break; - case PacketType.AgentWearablesRequest: - ClientAvatar.SendInitialAppearance(); - break; - case PacketType.TransferRequest: - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request"); - // We put transfer requests into a big queue and then spawn a thread for each new one - TransferRequestPacket transfer = (TransferRequestPacket)Pack; - AssetRequests.Enqueue(transfer); - Thread AssetLoaderThread = new Thread(new ThreadStart(AssetLoader)); - AssetLoaderThread.Start(); - break; - case PacketType.LogoutRequest: - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got a logout request"); - lock(OpenSim_Main.local_world.Entities) { - OpenSim_Main.local_world.Entities.Remove(this.AgentID); - } - - if(OpenSim_Main.cfg.sandbox==false) { - WebRequest DeleteSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + this.AgentID.ToString() + this.CircuitCode.ToString() + "/delete"); - WebResponse GridResponse = DeleteSession.GetResponse(); - StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); - String grTest = sr.ReadLine(); - sr.Close(); - GridResponse.Close(); - OpenSim_Main.localcons.WriteLine("DEBUG: " + grTest); - } - this.ClientThread.Abort(); - break; - case PacketType.AgentUpdate: - ClientAvatar.HandleAgentUpdate((AgentUpdatePacket)Pack); - break; - case PacketType.ChatFromViewer: - ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; - if(Helpers.FieldToString(inchatpack.ChatData.Message)=="") break; - - System.Text.Encoding _enc = System.Text.Encoding.ASCII; - libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket(); - reply.ChatData.Audible = 1; - reply.ChatData.Message = inchatpack.ChatData.Message; - reply.ChatData.ChatType = 1; - reply.ChatData.SourceType = 1; - reply.ChatData.Position = this.ClientAvatar.position; - reply.ChatData.FromName = _enc.GetBytes(this.ClientAvatar.firstname + " " + this.ClientAvatar.lastname + "\0"); - reply.ChatData.OwnerID = this.AgentID; - reply.ChatData.SourceID = this.AgentID; - - - - foreach(OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values) { - client.OutPacket(reply); - } - break; - } - } - - private void ResendUnacked() - { - int now = Environment.TickCount; - - lock (NeedAck) - { - foreach (Packet packet in NeedAck.Values) - { - if (now - packet.TickCount > RESEND_TIMEOUT) - { - - packet.Header.Resent = true; - OutPacket(packet); - } - } - } - } - - private void SendAcks() - { - lock (PendingAcks) - { - if (PendingAcks.Count > 0) - { - if (PendingAcks.Count > 250) - { - return; - } - - - - int i = 0; - PacketAckPacket acks = new PacketAckPacket(); - acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; - - foreach (uint ack in PendingAcks.Values) - { - acks.Packets[i] = new PacketAckPacket.PacketsBlock(); - acks.Packets[i].ID = ack; - i++; - } - - acks.Header.Reliable = false; - OutPacket(acks); - - PendingAcks.Clear(); - } - } - } - - private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea) - { - SendAcks(); - ResendUnacked(); - } - - public void ProcessOutPacket(Packet Pack) { - - // Keep track of when this packet was sent out - Pack.TickCount = Environment.TickCount; - - if (!Pack.Header.Resent) - { - // Set the sequence number - lock (SequenceLock) - { - if (Sequence >= MAX_SEQUENCE) - Sequence = 1; - else - Sequence++; - Pack.Header.Sequence = Sequence; - } - - if (Pack.Header.Reliable) //DIRTY HACK - { - lock (NeedAck) - { - if (!NeedAck.ContainsKey(Pack.Header.Sequence)) - { - NeedAck.Add(Pack.Header.Sequence, Pack); - } - else - { - // Client.Log("Attempted to add a duplicate sequence number (" + - // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " + - // packet.Type.ToString(), Helpers.LogLevel.Warning); - } - } - - // Don't append ACKs to resent packets, in case that's what was causing the - // delivery to fail - if (!Pack.Header.Resent) - { - // Append any ACKs that need to be sent out to this packet - lock (PendingAcks) - { - if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS && - Pack.Type != PacketType.PacketAck && - Pack.Type != PacketType.LogoutRequest) - { - Pack.Header.AckList = new uint[PendingAcks.Count]; - int i = 0; - - foreach (uint ack in PendingAcks.Values) - { - Pack.Header.AckList[i] = ack; - i++; - } - - PendingAcks.Clear(); - Pack.Header.AppendedAcks = true; - } - } - } - } - } - - - byte[] ZeroOutBuffer = new byte[4096]; - byte[] sendbuffer; - sendbuffer = Pack.ToBytes(); - - try { - if (Pack.Header.Zerocoded) { - int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); - OpenSim_Main.Server.SendTo(ZeroOutBuffer, packetsize, SocketFlags.None,userEP); - } else { - OpenSim_Main.Server.SendTo(sendbuffer, sendbuffer.Length, SocketFlags.None,userEP); - } - } catch (Exception) { - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread"); - ClientThread.Abort(); - } - - } - - public void InPacket(Packet NewPack) { - // Handle appended ACKs - if (NewPack.Header.AppendedAcks) - { - lock (NeedAck) - { - foreach (uint ack in NewPack.Header.AckList) - { - OpenSim_Main.localcons.WriteLine("Got appended ack: "+ack); - NeedAck.Remove(ack); - } - } - } - - // Handle PacketAck packets - if (NewPack.Type == PacketType.PacketAck) - { - PacketAckPacket ackPacket = (PacketAckPacket)NewPack; - - lock (NeedAck) - { - foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) - { - NeedAck.Remove(block.ID); - } - } - } else if( ( NewPack.Type == PacketType.StartPingCheck ) ) { - //reply to pingcheck - libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack; - libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket(); - endPing.PingID.PingID = startPing.PingID.PingID; - OutPacket(endPing); - } - else - { - QueItem item = new QueItem(); - item.Packet = NewPack; - item.Incoming = true; - this.PacketQueue.Enqueue(item); - } - - } - - public void OutPacket(Packet NewPack) { - QueItem item = new QueItem(); - item.Packet = NewPack; - item.Incoming = false; - this.PacketQueue.Enqueue(item); - } - - public OpenSimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack) { - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request"); - cirpack = initialcirpack; - userEP = remoteEP; - PacketQueue = new BlockingQueue(); - AssetRequests = new BlockingQueue(); - AckTimer = new System.Timers.Timer(500); - AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); - AckTimer.Start(); - - ClientThread = new Thread(new ThreadStart(AuthUser)); - ClientThread.IsBackground = true; - ClientThread.Start(); - } - - private void ClientLoop() { - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ClientLoop() - Entered loop"); - while(true) { - QueItem nextPacket = PacketQueue.Dequeue(); - if(nextPacket.Incoming) - { - //is a incoming packet - ProcessInPacket(nextPacket.Packet); - } - else - { - //is a out going packet - ProcessOutPacket(nextPacket.Packet); - } - } - } - - private void InitNewClient() { - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world"); - OpenSim_Main.local_world.AddViewerAgent(this); - world.Entity tempent=OpenSim_Main.local_world.Entities[this.AgentID]; - this.ClientAvatar=(world.Avatar)tempent; - } - - private void AuthUser() { - if(OpenSim_Main.cfg.sandbox==false) { - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Authenticating new user request with grid"); - WebRequest CheckSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + cirpack.CircuitCode.ID.ToString() + "/" + cirpack.CircuitCode.Code.ToString() + "/exists"); - OpenSim_Main.localcons.WriteLine(OpenSim_Main.cfg.GridURL); - WebResponse GridResponse = CheckSession.GetResponse(); - StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); - String grTest = sr.ReadLine(); - sr.Close(); - GridResponse.Close(); - if(String.IsNullOrEmpty(grTest) || grTest.Equals("1")) { // YAY! Valid login - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString()); - this.AgentID=cirpack.CircuitCode.ID; - this.SessionID=cirpack.CircuitCode.SessionID; - this.CircuitCode=cirpack.CircuitCode.Code; - InitNewClient(); - ClientLoop(); - } else { // Invalid - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString()); - ClientThread.Abort(); - } - } else { - this.AgentID=cirpack.CircuitCode.ID; - this.SessionID=cirpack.CircuitCode.SessionID; - this.CircuitCode=cirpack.CircuitCode.Code; - InitNewClient(); - ClientLoop(); - } - } - } + /// + /// Handles new client connections + /// Constructor takes a single Packet and authenticates everything + /// + public class OpenSimClient + { + + public LLUUID AgentID; + public LLUUID SessionID; + public uint CircuitCode; + public world.Avatar ClientAvatar; + private UseCircuitCodePacket cirpack; + private Thread ClientThread; + public EndPoint userEP; + private BlockingQueue PacketQueue; + private BlockingQueue AssetRequests; + private Dictionary PendingAcks = new Dictionary(); + private Dictionary NeedAck = new Dictionary(); + private System.Timers.Timer AckTimer; + private uint Sequence = 0; + private object SequenceLock = new object(); + private const int MAX_APPENDED_ACKS = 10; + private const int RESEND_TIMEOUT = 4000; + private const int MAX_SEQUENCE = 0xFFFFFF; + //private Queue Inbox; + + public void ack_pack(Packet Pack) + { + //libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket(); + //ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; + //ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); + //ack_it.Packets[0].ID = Pack.Header.ID; + //ack_it.Header.Reliable = false; + + //OutPacket(ack_it); + + if (Pack.Header.Reliable) + { + lock (PendingAcks) + { + uint sequence = (uint)Pack.Header.Sequence; + if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; } + } + } + } + + public void AssetLoader() + { + if (OpenSim_Main.cfg.sandbox == false) + { + WebResponse AssetResponse; + byte[] idata; + + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Starting new thread"); + TransferRequestPacket reqPacket = AssetRequests.Dequeue(); + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Got a request, processing it"); + LLUUID AssetID = new LLUUID(reqPacket.TransferInfo.Params, 0); + + try + { + WebRequest AssetLoad = WebRequest.Create(OpenSim_Main.cfg.AssetURL + "getasset/" + OpenSim_Main.cfg.AssetSendKey + "/" + AssetID + "/data"); + AssetResponse = AssetLoad.GetResponse(); + idata = new byte[(int)AssetResponse.ContentLength]; + BinaryReader br = new BinaryReader(AssetResponse.GetResponseStream()); + idata = br.ReadBytes((int)AssetResponse.ContentLength); + br.Close(); + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + return; + } + + TransferInfoPacket Transfer = new TransferInfoPacket(); + Transfer.TransferInfo.ChannelType = 2; + Transfer.TransferInfo.Status = 0; + Transfer.TransferInfo.TargetType = 0; + Transfer.TransferInfo.Params = reqPacket.TransferInfo.Params; + Transfer.TransferInfo.Size = (int)AssetResponse.ContentLength; + Transfer.TransferInfo.TransferID = reqPacket.TransferInfo.TransferID; + + OutPacket(Transfer); + + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = 0; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID; + + if (AssetResponse.ContentLength > 1000) + { + byte[] chunk = new byte[1000]; + Array.Copy(idata, chunk, 1000); + TransferPacket.TransferData.Data = chunk; + TransferPacket.TransferData.Status = 0; + OutPacket(TransferPacket); + + TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = 1; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID; + byte[] chunk1 = new byte[(idata.Length - 1000)]; + Array.Copy(idata, 1000, chunk1, 0, chunk1.Length); + TransferPacket.TransferData.Data = chunk1; + TransferPacket.TransferData.Status = 1; + OutPacket(TransferPacket); + } + else + { + TransferPacket.TransferData.Status = 1; + TransferPacket.TransferData.Data = idata; + OutPacket(TransferPacket); + } + AssetResponse.Close(); + } + } + + public void Logout() + { + // TODO - kill any AssetLoaders + ClientThread.Abort(); + } + + public void ProcessInPacket(Packet Pack) + { + ack_pack(Pack); + switch (Pack.Type) + { + case PacketType.CompleteAgentMovement: + ClientAvatar.CompleteMovement(OpenSim_Main.local_world); + ClientAvatar.SendInitialPosition(); + break; + case PacketType.RegionHandshakeReply: + OpenSim_Main.local_world.SendLayerData(this); + break; + case PacketType.AgentWearablesRequest: + ClientAvatar.SendInitialAppearance(); + break; + case PacketType.TransferRequest: + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request"); + // We put transfer requests into a big queue and then spawn a thread for each new one + TransferRequestPacket transfer = (TransferRequestPacket)Pack; + AssetRequests.Enqueue(transfer); + Thread AssetLoaderThread = new Thread(new ThreadStart(AssetLoader)); + AssetLoaderThread.Start(); + break; + case PacketType.LogoutRequest: + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got a logout request"); + lock (OpenSim_Main.local_world.Entities) + { + OpenSim_Main.local_world.Entities.Remove(this.AgentID); + } + + if (OpenSim_Main.cfg.sandbox == false) + { + WebRequest DeleteSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + this.AgentID.ToString() + this.CircuitCode.ToString() + "/delete"); + WebResponse GridResponse = DeleteSession.GetResponse(); + StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); + String grTest = sr.ReadLine(); + sr.Close(); + GridResponse.Close(); + OpenSim_Main.localcons.WriteLine("DEBUG: " + grTest); + } + this.ClientThread.Abort(); + break; + case PacketType.AgentUpdate: + ClientAvatar.HandleAgentUpdate((AgentUpdatePacket)Pack); + break; + case PacketType.ChatFromViewer: + ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; + if (Helpers.FieldToString(inchatpack.ChatData.Message) == "") break; + + System.Text.Encoding _enc = System.Text.Encoding.ASCII; + libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket(); + reply.ChatData.Audible = 1; + reply.ChatData.Message = inchatpack.ChatData.Message; + reply.ChatData.ChatType = 1; + reply.ChatData.SourceType = 1; + reply.ChatData.Position = this.ClientAvatar.position; + reply.ChatData.FromName = _enc.GetBytes(this.ClientAvatar.firstname + " " + this.ClientAvatar.lastname + "\0"); + reply.ChatData.OwnerID = this.AgentID; + reply.ChatData.SourceID = this.AgentID; + + + + foreach (OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values) + { + client.OutPacket(reply); + } + break; + } + } + + private void ResendUnacked() + { + int now = Environment.TickCount; + + lock (NeedAck) + { + foreach (Packet packet in NeedAck.Values) + { + if (now - packet.TickCount > RESEND_TIMEOUT) + { + + packet.Header.Resent = true; + OutPacket(packet); + } + } + } + } + + private void SendAcks() + { + lock (PendingAcks) + { + if (PendingAcks.Count > 0) + { + if (PendingAcks.Count > 250) + { + return; + } + + + + int i = 0; + PacketAckPacket acks = new PacketAckPacket(); + acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; + + foreach (uint ack in PendingAcks.Values) + { + acks.Packets[i] = new PacketAckPacket.PacketsBlock(); + acks.Packets[i].ID = ack; + i++; + } + + acks.Header.Reliable = false; + OutPacket(acks); + + PendingAcks.Clear(); + } + } + } + + private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea) + { + SendAcks(); + ResendUnacked(); + } + + public void ProcessOutPacket(Packet Pack) + { + + // Keep track of when this packet was sent out + Pack.TickCount = Environment.TickCount; + + if (!Pack.Header.Resent) + { + // Set the sequence number + lock (SequenceLock) + { + if (Sequence >= MAX_SEQUENCE) + Sequence = 1; + else + Sequence++; + Pack.Header.Sequence = Sequence; + } + + if (Pack.Header.Reliable) //DIRTY HACK + { + lock (NeedAck) + { + if (!NeedAck.ContainsKey(Pack.Header.Sequence)) + { + NeedAck.Add(Pack.Header.Sequence, Pack); + } + else + { + // Client.Log("Attempted to add a duplicate sequence number (" + + // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " + + // packet.Type.ToString(), Helpers.LogLevel.Warning); + } + } + + // Don't append ACKs to resent packets, in case that's what was causing the + // delivery to fail + if (!Pack.Header.Resent) + { + // Append any ACKs that need to be sent out to this packet + lock (PendingAcks) + { + if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS && + Pack.Type != PacketType.PacketAck && + Pack.Type != PacketType.LogoutRequest) + { + Pack.Header.AckList = new uint[PendingAcks.Count]; + int i = 0; + + foreach (uint ack in PendingAcks.Values) + { + Pack.Header.AckList[i] = ack; + i++; + } + + PendingAcks.Clear(); + Pack.Header.AppendedAcks = true; + } + } + } + } + } + + + byte[] ZeroOutBuffer = new byte[4096]; + byte[] sendbuffer; + sendbuffer = Pack.ToBytes(); + + try + { + if (Pack.Header.Zerocoded) + { + int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); + OpenSim_Main.Server.SendTo(ZeroOutBuffer, packetsize, SocketFlags.None, userEP); + } + else + { + OpenSim_Main.Server.SendTo(sendbuffer, sendbuffer.Length, SocketFlags.None, userEP); + } + } + catch (Exception) + { + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread"); + ClientThread.Abort(); + } + + } + + public void InPacket(Packet NewPack) + { + // Handle appended ACKs + if (NewPack.Header.AppendedAcks) + { + lock (NeedAck) + { + foreach (uint ack in NewPack.Header.AckList) + { + OpenSim_Main.localcons.WriteLine("Got appended ack: " + ack); + NeedAck.Remove(ack); + } + } + } + + // Handle PacketAck packets + if (NewPack.Type == PacketType.PacketAck) + { + PacketAckPacket ackPacket = (PacketAckPacket)NewPack; + + lock (NeedAck) + { + foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) + { + NeedAck.Remove(block.ID); + } + } + } + else if ((NewPack.Type == PacketType.StartPingCheck)) + { + //reply to pingcheck + libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack; + libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket(); + endPing.PingID.PingID = startPing.PingID.PingID; + OutPacket(endPing); + } + else + { + QueItem item = new QueItem(); + item.Packet = NewPack; + item.Incoming = true; + this.PacketQueue.Enqueue(item); + } + + } + + public void OutPacket(Packet NewPack) + { + QueItem item = new QueItem(); + item.Packet = NewPack; + item.Incoming = false; + this.PacketQueue.Enqueue(item); + } + + public OpenSimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack) + { + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request"); + cirpack = initialcirpack; + userEP = remoteEP; + PacketQueue = new BlockingQueue(); + AssetRequests = new BlockingQueue(); + AckTimer = new System.Timers.Timer(500); + AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); + AckTimer.Start(); + + ClientThread = new Thread(new ThreadStart(AuthUser)); + ClientThread.IsBackground = true; + ClientThread.Start(); + } + + private void ClientLoop() + { + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ClientLoop() - Entered loop"); + while (true) + { + QueItem nextPacket = PacketQueue.Dequeue(); + if (nextPacket.Incoming) + { + //is a incoming packet + ProcessInPacket(nextPacket.Packet); + } + else + { + //is a out going packet + ProcessOutPacket(nextPacket.Packet); + } + } + } + + private void InitNewClient() + { + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world"); + OpenSim_Main.local_world.AddViewerAgent(this); + world.Entity tempent = OpenSim_Main.local_world.Entities[this.AgentID]; + this.ClientAvatar = (world.Avatar)tempent; + } + + private void AuthUser() + { + if (OpenSim_Main.cfg.sandbox == false) + { + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Authenticating new user request with grid"); + WebRequest CheckSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + cirpack.CircuitCode.ID.ToString() + "/" + cirpack.CircuitCode.Code.ToString() + "/exists"); + OpenSim_Main.localcons.WriteLine(OpenSim_Main.cfg.GridURL); + WebResponse GridResponse = CheckSession.GetResponse(); + StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); + String grTest = sr.ReadLine(); + sr.Close(); + GridResponse.Close(); + if (String.IsNullOrEmpty(grTest) || grTest.Equals("1")) + { // YAY! Valid login + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString()); + this.AgentID = cirpack.CircuitCode.ID; + this.SessionID = cirpack.CircuitCode.SessionID; + this.CircuitCode = cirpack.CircuitCode.Code; + InitNewClient(); + ClientLoop(); + } + else + { // Invalid + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString()); + ClientThread.Abort(); + } + } + else + { + this.AgentID = cirpack.CircuitCode.ID; + this.SessionID = cirpack.CircuitCode.SessionID; + this.CircuitCode = cirpack.CircuitCode.Code; + InitNewClient(); + ClientLoop(); + } + } + } } -- cgit v1.1