aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/OpenSim.RegionServer/Client
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/OpenSim.RegionServer/Client/ClientView.Grid.cs192
-rw-r--r--OpenSim/OpenSim.RegionServer/Client/ClientView.PacketHandlers.cs196
-rw-r--r--OpenSim/OpenSim.RegionServer/Client/ClientView.ProcessPackets.cs523
-rw-r--r--OpenSim/OpenSim.RegionServer/Client/ClientView.cs461
-rw-r--r--OpenSim/OpenSim.RegionServer/Client/ClientViewBase.cs326
5 files changed, 0 insertions, 1698 deletions
diff --git a/OpenSim/OpenSim.RegionServer/Client/ClientView.Grid.cs b/OpenSim/OpenSim.RegionServer/Client/ClientView.Grid.cs
deleted file mode 100644
index 0bccbc2..0000000
--- a/OpenSim/OpenSim.RegionServer/Client/ClientView.Grid.cs
+++ /dev/null
@@ -1,192 +0,0 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*
27*/
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using libsecondlife;
32using libsecondlife.Packets;
33using Nwc.XmlRpc;
34using System.Net;
35using System.Net.Sockets;
36using System.IO;
37using System.Threading;
38using System.Timers;
39using OpenSim.Framework.Interfaces;
40using OpenSim.Framework.Types;
41using OpenSim.Framework.Inventory;
42using OpenSim.Framework.Utilities;
43using OpenSim.RegionServer.Simulator;
44using OpenSim.RegionServer.Assets;
45using OpenSim.Framework.Console;
46
47namespace OpenSim.RegionServer.Client
48{
49 public partial class ClientView
50 {
51
52 public void EnableNeighbours()
53 {
54 if ((this.m_gridServer.GetName() == "Remote") && (!this.m_child))
55 {
56 Hashtable SimParams;
57 ArrayList SendParams;
58 XmlRpcRequest GridReq;
59 XmlRpcResponse GridResp;
60 List<Packet> enablePackets = new List<Packet>();
61
62 RemoteGridBase gridServer = (RemoteGridBase)this.m_gridServer;
63
64 foreach (Hashtable neighbour in gridServer.neighbours)
65 {
66 try
67 {
68 string neighbourIPStr = (string)neighbour["sim_ip"];
69 System.Net.IPAddress neighbourIP = System.Net.IPAddress.Parse(neighbourIPStr);
70 ushort neighbourPort = (ushort)Convert.ToInt32(neighbour["sim_port"]);
71 string reqUrl = "http://" + neighbourIPStr + ":" + neighbourPort.ToString();
72
73 MainConsole.Instance.Verbose("Requesting " + reqUrl);
74
75 SimParams = new Hashtable();
76 SimParams["session_id"] = this.SessionID.ToString();
77 SimParams["secure_session_id"] = this.SecureSessionID.ToString();
78 SimParams["firstname"] = this.ClientAvatar.firstname;
79 SimParams["lastname"] = this.ClientAvatar.lastname;
80 SimParams["agent_id"] = this.AgentID.ToString();
81 SimParams["circuit_code"] = (Int32)this.CircuitCode;
82 SimParams["child_agent"] = "1";
83 SendParams = new ArrayList();
84 SendParams.Add(SimParams);
85
86 GridReq = new XmlRpcRequest("expect_user", SendParams);
87 GridResp = GridReq.Send(reqUrl, 3000);
88 EnableSimulatorPacket enablesimpacket = new EnableSimulatorPacket();
89 enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock();
90 enablesimpacket.SimulatorInfo.Handle = Helpers.UIntsToLong((uint)(Convert.ToInt32(neighbour["region_locx"]) * 256), (uint)(Convert.ToInt32(neighbour["region_locy"]) * 256));
91
92
93 byte[] byteIP = neighbourIP.GetAddressBytes();
94 enablesimpacket.SimulatorInfo.IP = (uint)byteIP[3] << 24;
95 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[2] << 16;
96 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[1] << 8;
97 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[0];
98 enablesimpacket.SimulatorInfo.Port = neighbourPort;
99 enablePackets.Add(enablesimpacket);
100 }
101 catch
102 {
103 MainConsole.Instance.Notice("Could not connect to neighbour " + neighbour["sim_ip"] + ":" + neighbour["sim_port"] + ", continuing.");
104 }
105 }
106 Thread.Sleep(3000);
107 foreach (Packet enable in enablePackets)
108 {
109 this.OutPacket(enable);
110 }
111 enablePackets.Clear();
112
113 }
114 }
115
116 public void CrossSimBorder(LLVector3 avatarpos)
117 { // VERY VERY BASIC
118
119 LLVector3 newpos = avatarpos;
120 uint neighbourx = this.m_regionData.RegionLocX;
121 uint neighboury = this.m_regionData.RegionLocY;
122
123 if (avatarpos.X < 0)
124 {
125 neighbourx -= 1;
126 newpos.X = 254;
127 }
128 if (avatarpos.X > 255)
129 {
130 neighbourx += 1;
131 newpos.X = 1;
132 }
133 if (avatarpos.Y < 0)
134 {
135 neighboury -= 1;
136 newpos.Y = 254;
137 }
138 if (avatarpos.Y > 255)
139 {
140 neighboury += 1;
141 newpos.Y = 1;
142 }
143 MainConsole.Instance.Notice("SimClient.cs:CrossSimBorder() - Crossing border to neighbouring sim at [" + neighbourx.ToString() + "," + neighboury.ToString() + "]");
144
145 Hashtable SimParams;
146 ArrayList SendParams;
147 XmlRpcRequest GridReq;
148 XmlRpcResponse GridResp;
149 foreach (Hashtable borderingSim in ((RemoteGridBase)m_gridServer).neighbours)
150 {
151 if (((string)borderingSim["region_locx"]).Equals(neighbourx.ToString()) && ((string)borderingSim["region_locy"]).Equals(neighboury.ToString()))
152 {
153 SimParams = new Hashtable();
154 SimParams["firstname"] = this.ClientAvatar.firstname;
155 SimParams["lastname"] = this.ClientAvatar.lastname;
156 SimParams["circuit_code"] = this.CircuitCode.ToString();
157 SimParams["pos_x"] = newpos.X.ToString();
158 SimParams["pos_y"] = newpos.Y.ToString();
159 SimParams["pos_z"] = newpos.Z.ToString();
160 SendParams = new ArrayList();
161 SendParams.Add(SimParams);
162
163 GridReq = new XmlRpcRequest("agent_crossing", SendParams);
164 GridResp = GridReq.Send("http://" + borderingSim["sim_ip"] + ":" + borderingSim["sim_port"], 3000);
165
166 CrossedRegionPacket NewSimPack = new CrossedRegionPacket();
167 NewSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock();
168 NewSimPack.AgentData.AgentID = this.AgentID;
169 NewSimPack.AgentData.SessionID = this.SessionID;
170 NewSimPack.Info = new CrossedRegionPacket.InfoBlock();
171 NewSimPack.Info.Position = newpos;
172 NewSimPack.Info.LookAt = new LLVector3(0.99f, 0.042f, 0); // copied from Avatar.cs - SHOULD BE DYNAMIC!!!!!!!!!!
173 NewSimPack.RegionData = new libsecondlife.Packets.CrossedRegionPacket.RegionDataBlock();
174 NewSimPack.RegionData.RegionHandle = Helpers.UIntsToLong((uint)(Convert.ToInt32(borderingSim["region_locx"]) * 256), (uint)(Convert.ToInt32(borderingSim["region_locy"]) * 256));
175 System.Net.IPAddress neighbourIP = System.Net.IPAddress.Parse((string)borderingSim["sim_ip"]);
176 byte[] byteIP = neighbourIP.GetAddressBytes();
177 NewSimPack.RegionData.SimIP = (uint)byteIP[3] << 24;
178 NewSimPack.RegionData.SimIP += (uint)byteIP[2] << 16;
179 NewSimPack.RegionData.SimIP += (uint)byteIP[1] << 8;
180 NewSimPack.RegionData.SimIP += (uint)byteIP[0];
181 NewSimPack.RegionData.SimPort = (ushort)Convert.ToInt32(borderingSim["sim_port"]);
182 NewSimPack.RegionData.SeedCapability = new byte[0];
183 lock (PacketQueue)
184 {
185 ProcessOutPacket(NewSimPack);
186 DowngradeClient();
187 }
188 }
189 }
190 }
191 }
192}
diff --git a/OpenSim/OpenSim.RegionServer/Client/ClientView.PacketHandlers.cs b/OpenSim/OpenSim.RegionServer/Client/ClientView.PacketHandlers.cs
deleted file mode 100644
index 4af0485..0000000
--- a/OpenSim/OpenSim.RegionServer/Client/ClientView.PacketHandlers.cs
+++ /dev/null
@@ -1,196 +0,0 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*
27*/
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using libsecondlife;
32using libsecondlife.Packets;
33using Nwc.XmlRpc;
34using System.Net;
35using System.Net.Sockets;
36using System.IO;
37using System.Threading;
38using System.Timers;
39using OpenSim.Framework.Interfaces;
40using OpenSim.Framework.Types;
41using OpenSim.Framework.Inventory;
42using OpenSim.Framework.Utilities;
43using OpenSim.RegionServer.Simulator;
44using OpenSim.RegionServer.Assets;
45using OpenSim.Framework.Console;
46
47namespace OpenSim.RegionServer.Client
48{
49 public partial class ClientView
50 {
51 protected virtual void RegisterLocalPacketHandlers()
52 {
53 this.AddLocalPacketHandler(PacketType.LogoutRequest, this.Logout);
54 this.AddLocalPacketHandler(PacketType.AgentCachedTexture, this.AgentTextureCached);
55 this.AddLocalPacketHandler(PacketType.MultipleObjectUpdate, this.MultipleObjUpdate);
56 }
57
58 protected virtual bool Logout(ClientView simClient, Packet packet)
59 {
60 MainConsole.Instance.Notice("OpenSimClient.cs:ProcessInPacket() - Got a logout request");
61 //send reply to let the client logout
62 LogoutReplyPacket logReply = new LogoutReplyPacket();
63 logReply.AgentData.AgentID = this.AgentID;
64 logReply.AgentData.SessionID = this.SessionID;
65 logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
66 logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
67 logReply.InventoryData[0].ItemID = LLUUID.Zero;
68 OutPacket(logReply);
69 //tell all clients to kill our object
70 KillObjectPacket kill = new KillObjectPacket();
71 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
72 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
73 kill.ObjectData[0].ID = this.ClientAvatar.localid;
74 foreach (ClientView client in m_clientThreads.Values)
75 {
76 client.OutPacket(kill);
77 }
78 if (this.m_userServer != null)
79 {
80 this.m_inventoryCache.ClientLeaving(this.AgentID, this.m_userServer);
81 }
82 else
83 {
84 this.m_inventoryCache.ClientLeaving(this.AgentID, null);
85 }
86
87 m_gridServer.LogoutSession(this.SessionID, this.AgentID, this.CircuitCode);
88 /*lock (m_world.Entities)
89 {
90 m_world.Entities.Remove(this.AgentID);
91 }*/
92 m_world.RemoveViewerAgent(this);
93 //need to do other cleaning up here too
94 m_clientThreads.Remove(this.CircuitCode);
95 m_networkServer.RemoveClientCircuit(this.CircuitCode);
96 this.ClientThread.Abort();
97 return true;
98 }
99
100 protected bool AgentTextureCached(ClientView simclient, Packet packet)
101 {
102 AgentCachedTexturePacket chechedtex = (AgentCachedTexturePacket)packet;
103 AgentCachedTextureResponsePacket cachedresp = new AgentCachedTextureResponsePacket();
104 cachedresp.AgentData.AgentID = this.AgentID;
105 cachedresp.AgentData.SessionID = this.SessionID;
106 cachedresp.AgentData.SerialNum = this.cachedtextureserial;
107 this.cachedtextureserial++;
108 cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[chechedtex.WearableData.Length];
109 for (int i = 0; i < chechedtex.WearableData.Length; i++)
110 {
111 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
112 cachedresp.WearableData[i].TextureIndex = chechedtex.WearableData[i].TextureIndex;
113 cachedresp.WearableData[i].TextureID = LLUUID.Zero;
114 cachedresp.WearableData[i].HostName = new byte[0];
115 }
116 this.OutPacket(cachedresp);
117 return true;
118 }
119
120 protected bool MultipleObjUpdate(ClientView simClient, Packet packet)
121 {
122 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
123 for (int i = 0; i < multipleupdate.ObjectData.Length; i++)
124 {
125 if (multipleupdate.ObjectData[i].Type == 9) //change position
126 {
127 libsecondlife.LLVector3 pos = new LLVector3(multipleupdate.ObjectData[i].Data, 0);
128 OnUpdatePrimPosition(multipleupdate.ObjectData[i].ObjectLocalID, pos, this);
129 //should update stored position of the prim
130 }
131 else if (multipleupdate.ObjectData[i].Type == 10)//rotation
132 {
133 libsecondlife.LLQuaternion rot = new LLQuaternion(multipleupdate.ObjectData[i].Data, 0, true);
134 OnUpdatePrimRotation(multipleupdate.ObjectData[i].ObjectLocalID, rot, this);
135 }
136 else if (multipleupdate.ObjectData[i].Type == 13)//scale
137 {
138 libsecondlife.LLVector3 scale = new LLVector3(multipleupdate.ObjectData[i].Data, 12);
139 OnUpdatePrimScale(multipleupdate.ObjectData[i].ObjectLocalID, scale, this);
140 }
141 }
142 return true;
143 }
144
145 public void RequestMapLayer() //should be getting the map layer from the grid server
146 {
147 //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area)
148 MapLayerReplyPacket mapReply = new MapLayerReplyPacket();
149 mapReply.AgentData.AgentID = this.AgentID;
150 mapReply.AgentData.Flags = 0;
151 mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1];
152 mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock();
153 mapReply.LayerData[0].Bottom = this.m_regionData.RegionLocY - 50;
154 mapReply.LayerData[0].Left = this.m_regionData.RegionLocX - 50;
155 mapReply.LayerData[0].Top = this.m_regionData.RegionLocY + 50;
156 mapReply.LayerData[0].Right = this.m_regionData.RegionLocX + 50;
157 mapReply.LayerData[0].ImageID = new LLUUID("00000000-0000-0000-9999-000000000005");
158 this.OutPacket(mapReply);
159 }
160
161 public void RequestMapBlocks(int minX, int minY, int maxX, int maxY)
162 {
163 IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY);
164 int len;
165 if (simMapProfiles == null)
166 len = 0;
167 else
168 len = simMapProfiles.Count;
169
170 int i;
171 int mtu = 24; // Number of regions to send per packet. Will be more precise in future. ( TODO )
172 for (i = 0; i < len; i += mtu)
173 {
174 MapBlockReplyPacket mbReply = new MapBlockReplyPacket();
175 mbReply.AgentData.AgentID = this.AgentID;
176
177 mbReply.Data = new MapBlockReplyPacket.DataBlock[Math.Min(mtu, len - i)];
178 int j;
179 for (j = 0; (j < mtu) && ((i + j) < len); j++)
180 {
181 Hashtable mp = (Hashtable)simMapProfiles[j];
182 mbReply.Data[j] = new MapBlockReplyPacket.DataBlock();
183 mbReply.Data[j].Name = libsecondlife.Helpers.StringToField((string)mp["name"]);
184 mbReply.Data[j].Access = System.Convert.ToByte(mp["access"]);
185 mbReply.Data[j].Agents = System.Convert.ToByte(mp["agents"]);
186 mbReply.Data[j].MapImageID = new LLUUID((string)mp["map-image-id"]);
187 mbReply.Data[j].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]);
188 mbReply.Data[j].WaterHeight = System.Convert.ToByte(mp["water-height"]);
189 mbReply.Data[j].X = System.Convert.ToUInt16(mp["x"]);
190 mbReply.Data[j].Y = System.Convert.ToUInt16(mp["y"]);
191 }
192 this.OutPacket(mbReply);
193 }
194 }
195 }
196}
diff --git a/OpenSim/OpenSim.RegionServer/Client/ClientView.ProcessPackets.cs b/OpenSim/OpenSim.RegionServer/Client/ClientView.ProcessPackets.cs
deleted file mode 100644
index 306bf63..0000000
--- a/OpenSim/OpenSim.RegionServer/Client/ClientView.ProcessPackets.cs
+++ /dev/null
@@ -1,523 +0,0 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*
27*/
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using libsecondlife;
32using libsecondlife.Packets;
33using Nwc.XmlRpc;
34using System.Net;
35using System.Net.Sockets;
36using System.IO;
37using System.Threading;
38using System.Timers;
39using OpenSim.Framework.Interfaces;
40using OpenSim.Framework.Types;
41using OpenSim.Framework.Inventory;
42using OpenSim.Framework.Utilities;
43using OpenSim.RegionServer.Simulator;
44using OpenSim.RegionServer.Assets;
45using OpenSim.Framework.Console;
46
47namespace OpenSim.RegionServer.Client
48{
49 public partial class ClientView
50 {
51 public delegate void GenericCall(ClientView remoteClient);
52 public delegate void GenericCall2();
53 public delegate void GenericCall3(Packet packet); // really don't want to be passing packets in these events, so this is very temporary.
54 public delegate void GenericCall4(Packet packet, ClientView remoteClient);
55 public delegate void UpdateShape(uint localID, ObjectShapePacket.ObjectDataBlock shapeBlock);
56 public delegate void ObjectSelect(uint localID, ClientView remoteClient);
57 public delegate void UpdatePrimFlags(uint localID, Packet packet, ClientView remoteClient);
58 public delegate void UpdatePrimTexture(uint localID, byte[] texture, ClientView remoteClient);
59 public delegate void UpdatePrimVector(uint localID, LLVector3 pos, ClientView remoteClient);
60 public delegate void UpdatePrimRotation(uint localID, LLQuaternion rot, ClientView remoteClient);
61 public delegate void StatusChange(bool status);
62
63
64 public event ChatFromViewer OnChatFromViewer;
65 public event RezObject OnRezObject;
66 public event GenericCall4 OnDeRezObject;
67 public event ModifyTerrain OnModifyTerrain;
68 public event GenericCall OnRegionHandShakeReply;
69 public event GenericCall OnRequestWearables;
70 public event SetAppearance OnSetAppearance;
71 public event GenericCall2 OnCompleteMovementToRegion;
72 public event GenericCall3 OnAgentUpdate;
73 public event StartAnim OnStartAnim;
74 public event GenericCall OnRequestAvatarsData;
75 public event LinkObjects OnLinkObjects;
76 public event GenericCall4 OnAddPrim;
77 public event UpdateShape OnUpdatePrimShape;
78 public event ObjectSelect OnObjectSelect;
79 public event UpdatePrimFlags OnUpdatePrimFlags;
80 public event UpdatePrimTexture OnUpdatePrimTexture;
81 public event UpdatePrimVector OnUpdatePrimPosition;
82 public event UpdatePrimRotation OnUpdatePrimRotation;
83 public event UpdatePrimVector OnUpdatePrimScale;
84 public event StatusChange OnChildAgentStatus;
85
86 public event ParcelPropertiesRequest OnParcelPropertiesRequest;
87 public event ParcelDivideRequest OnParcelDivideRequest;
88 public event ParcelJoinRequest OnParcelJoinRequest;
89 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
90
91 protected override void ProcessInPacket(Packet Pack)
92 {
93 ack_pack(Pack);
94 if (debug)
95 {
96 if (Pack.Type != PacketType.AgentUpdate)
97 {
98 Console.WriteLine("IN: " + Pack.Type.ToString());
99 }
100 }
101
102
103 if (this.ProcessPacketMethod(Pack))
104 {
105 //there is a handler registered that handled this packet type
106 return;
107 }
108 else
109 {
110 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
111
112 switch (Pack.Type)
113 {
114 case PacketType.ViewerEffect:
115 ViewerEffectPacket viewer = (ViewerEffectPacket)Pack;
116 foreach (ClientView client in m_clientThreads.Values)
117 {
118 if (client.AgentID != this.AgentID)
119 {
120 viewer.AgentData.AgentID = client.AgentID;
121 viewer.AgentData.SessionID = client.SessionID;
122 client.OutPacket(viewer);
123 }
124 }
125 break;
126
127 #region New Event System - World/Avatar
128 case PacketType.ChatFromViewer:
129 ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack;
130 if (Util.FieldToString(inchatpack.ChatData.Message) == "")
131 {
132 //empty message so don't bother with it
133 break;
134 }
135 string fromName = ClientAvatar.firstname + " " + ClientAvatar.lastname;
136 byte[] message = inchatpack.ChatData.Message;
137 byte type = inchatpack.ChatData.Type;
138 LLVector3 fromPos = ClientAvatar.Pos;
139 LLUUID fromAgentID = AgentID;
140 this.OnChatFromViewer(message, type, fromPos, fromName, fromAgentID);
141 break;
142 case PacketType.RezObject:
143 RezObjectPacket rezPacket = (RezObjectPacket)Pack;
144 AgentInventory inven = this.m_inventoryCache.GetAgentsInventory(this.AgentID);
145 if (inven != null)
146 {
147 if (inven.InventoryItems.ContainsKey(rezPacket.InventoryData.ItemID))
148 {
149 AssetBase asset = this.m_assetCache.GetAsset(inven.InventoryItems[rezPacket.InventoryData.ItemID].AssetID);
150 if (asset != null)
151 {
152 this.OnRezObject(asset, rezPacket.RezData.RayEnd);
153 this.m_inventoryCache.DeleteInventoryItem(this, rezPacket.InventoryData.ItemID);
154 }
155 }
156 }
157 break;
158 case PacketType.DeRezObject:
159 OnDeRezObject(Pack, this);
160 break;
161 case PacketType.ModifyLand:
162 ModifyLandPacket modify = (ModifyLandPacket)Pack;
163 if (modify.ParcelData.Length > 0)
164 {
165 OnModifyTerrain(modify.ModifyBlock.Action, modify.ParcelData[0].North, modify.ParcelData[0].West);
166 }
167 break;
168 case PacketType.RegionHandshakeReply:
169 OnRegionHandShakeReply(this);
170 break;
171 case PacketType.AgentWearablesRequest:
172 OnRequestWearables(this);
173 OnRequestAvatarsData(this);
174 break;
175 case PacketType.AgentSetAppearance:
176 AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack;
177 OnSetAppearance(appear.ObjectData.TextureEntry, appear.VisualParam);
178 break;
179 case PacketType.CompleteAgentMovement:
180 if (this.m_child) this.UpgradeClient();
181 OnCompleteMovementToRegion();
182 this.EnableNeighbours();
183 break;
184 case PacketType.AgentUpdate:
185 OnAgentUpdate(Pack);
186 break;
187 case PacketType.AgentAnimation:
188 if (!m_child)
189 {
190 AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack;
191 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
192 {
193 if (AgentAni.AnimationList[i].StartAnim)
194 {
195 OnStartAnim(AgentAni.AnimationList[i].AnimID, 1);
196 }
197 }
198 }
199 break;
200
201 #endregion
202
203 #region New Event System - Objects/Prims
204 case PacketType.ObjectLink:
205 ObjectLinkPacket link = (ObjectLinkPacket)Pack;
206 uint parentprimid = 0;
207 List<uint> childrenprims = new List<uint>();
208 if (link.ObjectData.Length > 1)
209 {
210 parentprimid = link.ObjectData[0].ObjectLocalID;
211
212 for (int i = 1; i < link.ObjectData.Length; i++)
213 {
214 childrenprims.Add(link.ObjectData[i].ObjectLocalID);
215 }
216 }
217 OnLinkObjects(parentprimid, childrenprims);
218 break;
219 case PacketType.ObjectAdd:
220 m_world.AddNewPrim((ObjectAddPacket)Pack, this);
221 OnAddPrim(Pack, this);
222 break;
223 case PacketType.ObjectShape:
224 ObjectShapePacket shape = (ObjectShapePacket)Pack;
225 for (int i = 0; i < shape.ObjectData.Length; i++)
226 {
227 OnUpdatePrimShape(shape.ObjectData[i].ObjectLocalID, shape.ObjectData[i]);
228 }
229 break;
230 case PacketType.ObjectSelect:
231 ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack;
232 for (int i = 0; i < incomingselect.ObjectData.Length; i++)
233 {
234 OnObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this);
235 }
236 break;
237 case PacketType.ObjectFlagUpdate:
238 ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack;
239 OnUpdatePrimFlags(flags.AgentData.ObjectLocalID, Pack, this);
240 break;
241 case PacketType.ObjectImage:
242 ObjectImagePacket imagePack = (ObjectImagePacket)Pack;
243 for (int i = 0; i < imagePack.ObjectData.Length; i++)
244 {
245 OnUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, imagePack.ObjectData[i].TextureEntry, this);
246
247 }
248 break;
249 #endregion
250
251 #region Inventory/Asset/Other related packets
252 case PacketType.RequestImage:
253 RequestImagePacket imageRequest = (RequestImagePacket)Pack;
254 for (int i = 0; i < imageRequest.RequestImage.Length; i++)
255 {
256 m_assetCache.AddTextureRequest(this, imageRequest.RequestImage[i].Image);
257 }
258 break;
259 case PacketType.TransferRequest:
260 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
261 m_assetCache.AddAssetRequest(this, transfer);
262 break;
263 case PacketType.AssetUploadRequest:
264 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
265 this.UploadAssets.HandleUploadPacket(request, request.AssetBlock.TransactionID.Combine(this.SecureSessionID));
266 break;
267 case PacketType.RequestXfer:
268 break;
269 case PacketType.SendXferPacket:
270 this.UploadAssets.HandleXferPacket((SendXferPacketPacket)Pack);
271 break;
272 case PacketType.CreateInventoryFolder:
273 CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack;
274 m_inventoryCache.CreateNewInventoryFolder(this, invFolder.FolderData.FolderID, (ushort)invFolder.FolderData.Type, Util.FieldToString(invFolder.FolderData.Name), invFolder.FolderData.ParentID);
275 break;
276 case PacketType.CreateInventoryItem:
277 CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack;
278 if (createItem.InventoryBlock.TransactionID != LLUUID.Zero)
279 {
280 this.UploadAssets.CreateInventoryItem(createItem);
281 }
282 else
283 {
284 this.CreateInventoryItem(createItem);
285 }
286 break;
287 case PacketType.FetchInventory:
288 FetchInventoryPacket FetchInventory = (FetchInventoryPacket)Pack;
289 m_inventoryCache.FetchInventory(this, FetchInventory);
290 break;
291 case PacketType.FetchInventoryDescendents:
292 FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack;
293 m_inventoryCache.FetchInventoryDescendents(this, Fetch);
294 break;
295 case PacketType.UpdateInventoryItem:
296 UpdateInventoryItemPacket update = (UpdateInventoryItemPacket)Pack;
297 for (int i = 0; i < update.InventoryData.Length; i++)
298 {
299 if (update.InventoryData[i].TransactionID != LLUUID.Zero)
300 {
301 AssetBase asset = m_assetCache.GetAsset(update.InventoryData[i].TransactionID.Combine(this.SecureSessionID));
302 if (asset != null)
303 {
304 m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset);
305 }
306 else
307 {
308 asset = this.UploadAssets.AddUploadToAssetCache(update.InventoryData[i].TransactionID);
309 if (asset != null)
310 {
311 m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset);
312 }
313 else
314 {
315
316 }
317 }
318 }
319 else
320 {
321 m_inventoryCache.UpdateInventoryItemDetails(this, update.InventoryData[i].ItemID, update.InventoryData[i]); ;
322 }
323 }
324 break;
325 case PacketType.RequestTaskInventory:
326 RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack;
327 ReplyTaskInventoryPacket replytask = new ReplyTaskInventoryPacket();
328 bool foundent = false;
329 foreach (Entity ent in m_world.Entities.Values)
330 {
331 if (ent.localid == requesttask.InventoryData.LocalID)
332 {
333 replytask.InventoryData.TaskID = ent.uuid;
334 replytask.InventoryData.Serial = 0;
335 replytask.InventoryData.Filename = new byte[0];
336 foundent = true;
337 }
338 }
339 if (foundent)
340 {
341 this.OutPacket(replytask);
342 }
343 break;
344 case PacketType.UpdateTaskInventory:
345 UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack;
346 AgentInventory myinventory = this.m_inventoryCache.GetAgentsInventory(this.AgentID);
347 if (myinventory != null)
348 {
349 if (updatetask.UpdateData.Key == 0)
350 {
351 if (myinventory.InventoryItems[updatetask.InventoryData.ItemID] != null)
352 {
353 if (myinventory.InventoryItems[updatetask.InventoryData.ItemID].Type == 7)
354 {
355 LLUUID noteaid = myinventory.InventoryItems[updatetask.InventoryData.ItemID].AssetID;
356 AssetBase assBase = this.m_assetCache.GetAsset(noteaid);
357 if (assBase != null)
358 {
359 foreach (Entity ent in m_world.Entities.Values)
360 {
361 if (ent.localid == updatetask.UpdateData.LocalID)
362 {
363 if (ent is OpenSim.RegionServer.Simulator.Primitive)
364 {
365 this.m_world.AddScript(ent, Util.FieldToString(assBase.Data));
366 }
367 }
368 }
369 }
370 }
371 }
372 }
373 }
374 break;
375 case PacketType.MapLayerRequest:
376 // This be busted.
377 MapLayerRequestPacket MapRequest = (MapLayerRequestPacket)Pack;
378 this.RequestMapLayer();
379 this.RequestMapBlocks((int)this.m_regionData.RegionLocX - 5, (int)this.m_regionData.RegionLocY - 5, (int)this.m_regionData.RegionLocX + 5, (int)this.m_regionData.RegionLocY + 5);
380 break;
381
382 case PacketType.MapBlockRequest:
383 MapBlockRequestPacket MapBRequest = (MapBlockRequestPacket)Pack;
384 this.RequestMapBlocks(MapBRequest.PositionData.MinX, MapBRequest.PositionData.MinY, MapBRequest.PositionData.MaxX, MapBRequest.PositionData.MaxY);
385 break;
386
387 case PacketType.MapNameRequest:
388 // TODO.
389 break;
390
391 case PacketType.TeleportLandmarkRequest:
392 TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack;
393
394 TeleportStartPacket tpStart = new TeleportStartPacket();
395 tpStart.Info.TeleportFlags = 8; // tp via lm
396 this.OutPacket(tpStart);
397
398 TeleportProgressPacket tpProgress = new TeleportProgressPacket();
399 tpProgress.Info.Message = (new System.Text.ASCIIEncoding()).GetBytes("sending_landmark");
400 tpProgress.Info.TeleportFlags = 8;
401 tpProgress.AgentData.AgentID = tpReq.Info.AgentID;
402 this.OutPacket(tpProgress);
403
404 // Fetch landmark
405 LLUUID lmid = tpReq.Info.LandmarkID;
406 AssetBase lma = this.m_assetCache.GetAsset(lmid);
407 if (lma != null)
408 {
409 AssetLandmark lm = new AssetLandmark(lma);
410
411 if (lm.RegionID == m_regionData.SimUUID)
412 {
413 TeleportLocalPacket tpLocal = new TeleportLocalPacket();
414
415 tpLocal.Info.AgentID = tpReq.Info.AgentID;
416 tpLocal.Info.TeleportFlags = 8; // Teleport via landmark
417 tpLocal.Info.LocationID = 2;
418 tpLocal.Info.Position = lm.Position;
419 OutPacket(tpLocal);
420 }
421 else
422 {
423 TeleportCancelPacket tpCancel = new TeleportCancelPacket();
424 tpCancel.Info.AgentID = tpReq.Info.AgentID;
425 tpCancel.Info.SessionID = tpReq.Info.SessionID;
426 OutPacket(tpCancel);
427 }
428 }
429 else
430 {
431 Console.WriteLine("Cancelling Teleport - fetch asset not yet implemented");
432
433 TeleportCancelPacket tpCancel = new TeleportCancelPacket();
434 tpCancel.Info.AgentID = tpReq.Info.AgentID;
435 tpCancel.Info.SessionID = tpReq.Info.SessionID;
436 OutPacket(tpCancel);
437 }
438 break;
439 case PacketType.TeleportLocationRequest:
440 TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack;
441 Console.WriteLine(tpLocReq.ToString());
442
443 tpStart = new TeleportStartPacket();
444 tpStart.Info.TeleportFlags = 16; // Teleport via location
445 Console.WriteLine(tpStart.ToString());
446 OutPacket(tpStart);
447
448 if (m_regionData.RegionHandle != tpLocReq.Info.RegionHandle)
449 {
450 /* m_gridServer.getRegion(tpLocReq.Info.RegionHandle); */
451 Console.WriteLine("Inter-sim teleport not yet implemented");
452 TeleportCancelPacket tpCancel = new TeleportCancelPacket();
453 tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID;
454 tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID;
455
456 OutPacket(tpCancel);
457 }
458 else
459 {
460 Console.WriteLine("Local teleport");
461 TeleportLocalPacket tpLocal = new TeleportLocalPacket();
462 tpLocal.Info.AgentID = tpLocReq.AgentData.AgentID;
463 tpLocal.Info.TeleportFlags = tpStart.Info.TeleportFlags;
464 tpLocal.Info.LocationID = 2;
465 tpLocal.Info.LookAt = tpLocReq.Info.LookAt;
466 tpLocal.Info.Position = tpLocReq.Info.Position;
467 OutPacket(tpLocal);
468
469 }
470 break;
471 #endregion
472
473 #region Parcel Packets
474 case PacketType.ParcelPropertiesRequest:
475 ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack;
476 OnParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West), (int)Math.Round(propertiesRequest.ParcelData.South), (int)Math.Round(propertiesRequest.ParcelData.East), (int)Math.Round(propertiesRequest.ParcelData.North),propertiesRequest.ParcelData.SequenceID,propertiesRequest.ParcelData.SnapSelection, this);
477 break;
478 case PacketType.ParcelDivide:
479 ParcelDividePacket parcelDivide = (ParcelDividePacket)Pack;
480 OnParcelDivideRequest((int)Math.Round(parcelDivide.ParcelData.West), (int)Math.Round(parcelDivide.ParcelData.South), (int)Math.Round(parcelDivide.ParcelData.East), (int)Math.Round(parcelDivide.ParcelData.North), this);
481 break;
482 case PacketType.ParcelJoin:
483 ParcelJoinPacket parcelJoin = (ParcelJoinPacket)Pack;
484 OnParcelJoinRequest((int)Math.Round(parcelJoin.ParcelData.West), (int)Math.Round(parcelJoin.ParcelData.South), (int)Math.Round(parcelJoin.ParcelData.East), (int)Math.Round(parcelJoin.ParcelData.North), this);
485 break;
486 case PacketType.ParcelPropertiesUpdate:
487 ParcelPropertiesUpdatePacket updatePacket = (ParcelPropertiesUpdatePacket)Pack;
488 OnParcelPropertiesUpdateRequest(updatePacket, this);
489 break;
490 #endregion
491
492 #region Estate Packets
493 case PacketType.EstateOwnerMessage:
494 this.m_world.estateManager.handleEstateOwnerMessage((EstateOwnerMessagePacket)Pack, this);
495 break;
496 #endregion
497 #region unimplemented handlers
498 case PacketType.AgentIsNowWearing:
499 // AgentIsNowWearingPacket wear = (AgentIsNowWearingPacket)Pack;
500 break;
501 case PacketType.ObjectScale:
502 break;
503 case PacketType.MoneyBalanceRequest:
504 //This need to be actually done and not thrown back with fake infos
505 break;
506
507 case PacketType.EstateCovenantRequest:
508 //This should be actually done and not thrown back with fake info
509 EstateCovenantRequestPacket estateCovenantRequest = (EstateCovenantRequestPacket)Pack;
510 EstateCovenantReplyPacket estateCovenantReply = new EstateCovenantReplyPacket();
511 estateCovenantReply.Data.EstateName = libsecondlife.Helpers.StringToField("Leet Estate");
512 estateCovenantReply.Data.EstateOwnerID = LLUUID.Zero;
513 estateCovenantReply.Data.CovenantID = LLUUID.Zero;
514 estateCovenantReply.Data.CovenantTimestamp = (uint)0;
515 this.OutPacket((Packet)estateCovenantReply);
516 MainConsole.Instance.Notice("Sent Temporary Estate packet (they are in leet estate)");
517 break;
518 #endregion
519 }
520 }
521 }
522 }
523}
diff --git a/OpenSim/OpenSim.RegionServer/Client/ClientView.cs b/OpenSim/OpenSim.RegionServer/Client/ClientView.cs
deleted file mode 100644
index 29efcc9..0000000
--- a/OpenSim/OpenSim.RegionServer/Client/ClientView.cs
+++ /dev/null
@@ -1,461 +0,0 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*
27*/
28
29using System;
30using System.Collections;
31using System.Collections.Generic;
32using libsecondlife;
33using libsecondlife.Packets;
34using Nwc.XmlRpc;
35using System.Net;
36using System.Net.Sockets;
37using System.IO;
38using System.Threading;
39using System.Timers;
40using OpenSim.Framework.Interfaces;
41using OpenSim.Framework.Types;
42using OpenSim.Framework.Inventory;
43using OpenSim.Framework.Utilities;
44using OpenSim.RegionServer.Simulator;
45using OpenSim.RegionServer.Assets;
46using OpenSim.Framework.Console;
47
48namespace OpenSim.RegionServer.Client
49{
50 public delegate bool PacketMethod(ClientView simClient, Packet packet);
51
52 /// <summary>
53 /// Handles new client connections
54 /// Constructor takes a single Packet and authenticates everything
55 /// </summary>
56 public partial class ClientView : ClientViewBase, IClientAPI
57 {
58 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
59 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); //local handlers for this instance
60
61 public LLUUID AgentID;
62 public LLUUID SessionID;
63 public LLUUID SecureSessionID = LLUUID.Zero;
64 public bool m_child;
65 public Simulator.Avatar ClientAvatar;
66 private UseCircuitCodePacket cirpack;
67 public Thread ClientThread;
68 public LLVector3 startpos;
69
70 private AgentAssetUpload UploadAssets;
71 private LLUUID newAssetFolder = LLUUID.Zero;
72 private bool debug = false;
73 private World m_world;
74 private Dictionary<uint, ClientView> m_clientThreads;
75 private AssetCache m_assetCache;
76 private IGridServer m_gridServer;
77 private IUserServer m_userServer = null;
78 private InventoryCache m_inventoryCache;
79 public bool m_sandboxMode;
80 private int cachedtextureserial = 0;
81 private RegionInfo m_regionData;
82 protected AuthenticateSessionsBase m_authenticateSessionsHandler;
83
84 public IUserServer UserServer
85 {
86 set
87 {
88 this.m_userServer = value;
89 }
90 }
91
92 public LLVector3 StartPos
93 {
94 get
95 {
96 return startpos;
97 }
98 set
99 {
100 startpos = value;
101 }
102 }
103
104 public ClientView(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, World world, Dictionary<uint, ClientView> clientThreads, AssetCache assetCache, IGridServer gridServer, OpenSimNetworkHandler application, InventoryCache inventoryCache, bool sandboxMode, bool child, RegionInfo regionDat, AuthenticateSessionsBase authenSessions)
105 {
106 m_world = world;
107 m_clientThreads = clientThreads;
108 m_assetCache = assetCache;
109 m_gridServer = gridServer;
110 m_networkServer = application;
111 m_inventoryCache = inventoryCache;
112 m_sandboxMode = sandboxMode;
113 m_child = child;
114 m_regionData = regionDat;
115 m_authenticateSessionsHandler = authenSessions;
116 MainConsole.Instance.Notice("OpenSimClient.cs - Started up new client thread to handle incoming request");
117 cirpack = initialcirpack;
118 userEP = remoteEP;
119
120 if (m_gridServer.GetName() == "Remote")
121 {
122 this.m_child = m_authenticateSessionsHandler.GetAgentChildStatus(initialcirpack.CircuitCode.Code);
123 this.startpos = m_authenticateSessionsHandler.GetPosition(initialcirpack.CircuitCode.Code);
124
125 // Dont rez new users underground
126 float aboveGround = 3.0f; // rez at least 3 meters above ground
127 if (this.startpos.Z < (m_world.Terrain[(int)this.startpos.X, (int)this.startpos.Y] + aboveGround))
128 this.startpos.Z = m_world.Terrain[(int)this.startpos.X, (int)this.startpos.Y] + aboveGround;
129
130 }
131 else
132 {
133 this.startpos = new LLVector3(128, 128, m_world.Terrain[(int)128, (int)128] + 15.0f); // new LLVector3(128.0f, 128.0f, 60f);
134 }
135
136 PacketQueue = new BlockingQueue<QueItem>();
137
138 this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache);
139 AckTimer = new System.Timers.Timer(500);
140 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
141 AckTimer.Start();
142
143 this.RegisterLocalPacketHandlers();
144
145
146
147 ClientThread = new Thread(new ThreadStart(AuthUser));
148 ClientThread.IsBackground = true;
149 ClientThread.Start();
150 }
151
152 # region Client Methods
153 public void UpgradeClient()
154 {
155 MainConsole.Instance.Notice("SimClient.cs:UpgradeClient() - upgrading child to full agent");
156 this.m_child = false;
157 //this.m_world.RemoveViewerAgent(this);
158 if (!this.m_sandboxMode)
159 {
160 this.startpos = m_authenticateSessionsHandler.GetPosition(CircuitCode);
161 m_authenticateSessionsHandler.UpdateAgentChildStatus(CircuitCode, false);
162 }
163 OnChildAgentStatus(this.m_child);
164 //this.InitNewClient();
165 }
166
167 public void DowngradeClient()
168 {
169 MainConsole.Instance.Notice("SimClient.cs:UpgradeClient() - changing full agent to child");
170 this.m_child = true;
171 OnChildAgentStatus(this.m_child);
172 //this.m_world.RemoveViewerAgent(this);
173 //this.m_world.AddViewerAgent(this);
174 }
175
176 public void KillClient()
177 {
178 KillObjectPacket kill = new KillObjectPacket();
179 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
180 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
181 kill.ObjectData[0].ID = this.ClientAvatar.localid;
182 foreach (ClientView client in m_clientThreads.Values)
183 {
184 client.OutPacket(kill);
185 }
186 if (this.m_userServer != null)
187 {
188 this.m_inventoryCache.ClientLeaving(this.AgentID, this.m_userServer);
189 }
190 else
191 {
192 this.m_inventoryCache.ClientLeaving(this.AgentID, null);
193 }
194
195 m_world.RemoveViewerAgent(this);
196
197 m_clientThreads.Remove(this.CircuitCode);
198 m_networkServer.RemoveClientCircuit(this.CircuitCode);
199 this.ClientThread.Abort();
200 }
201 #endregion
202
203 # region Packet Handling
204 public static bool AddPacketHandler(PacketType packetType, PacketMethod handler)
205 {
206 bool result = false;
207 lock (PacketHandlers)
208 {
209 if (!PacketHandlers.ContainsKey(packetType))
210 {
211 PacketHandlers.Add(packetType, handler);
212 result = true;
213 }
214 }
215 return result;
216 }
217
218 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler)
219 {
220 bool result = false;
221 lock (m_packetHandlers)
222 {
223 if (!m_packetHandlers.ContainsKey(packetType))
224 {
225 m_packetHandlers.Add(packetType, handler);
226 result = true;
227 }
228 }
229 return result;
230 }
231
232 protected virtual bool ProcessPacketMethod(Packet packet)
233 {
234 bool result = false;
235 bool found = false;
236 PacketMethod method;
237 if (m_packetHandlers.TryGetValue(packet.Type, out method))
238 {
239 //there is a local handler for this packet type
240 result = method(this, packet);
241 }
242 else
243 {
244 //there is not a local handler so see if there is a Global handler
245 lock (PacketHandlers)
246 {
247 found = PacketHandlers.TryGetValue(packet.Type, out method);
248 }
249 if (found)
250 {
251 result = method(this, packet);
252 }
253 }
254 return result;
255 }
256
257 protected virtual void ClientLoop()
258 {
259 MainConsole.Instance.Notice("OpenSimClient.cs:ClientLoop() - Entered loop");
260 while (true)
261 {
262 QueItem nextPacket = PacketQueue.Dequeue();
263 if (nextPacket.Incoming)
264 {
265 //is a incoming packet
266 ProcessInPacket(nextPacket.Packet);
267 }
268 else
269 {
270 //is a out going packet
271 ProcessOutPacket(nextPacket.Packet);
272 }
273 }
274 }
275 # endregion
276
277 # region Setup
278
279 protected virtual void InitNewClient()
280 {
281 MainConsole.Instance.Notice("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world");
282 this.ClientAvatar = m_world.AddViewerAgent(this);
283 }
284
285 protected virtual void AuthUser()
286 {
287 // AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
288 AuthenticateResponse sessionInfo = this.m_networkServer.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
289 if (!sessionInfo.Authorised)
290 {
291 //session/circuit not authorised
292 OpenSim.Framework.Console.MainConsole.Instance.Notice("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString());
293 ClientThread.Abort();
294 }
295 else
296 {
297 OpenSim.Framework.Console.MainConsole.Instance.Notice("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString());
298 //session is authorised
299 this.AgentID = cirpack.CircuitCode.ID;
300 this.SessionID = cirpack.CircuitCode.SessionID;
301 this.CircuitCode = cirpack.CircuitCode.Code;
302 InitNewClient();
303 this.ClientAvatar.firstname = sessionInfo.LoginInfo.First;
304 this.ClientAvatar.lastname = sessionInfo.LoginInfo.Last;
305 if (sessionInfo.LoginInfo.SecureSession != LLUUID.Zero)
306 {
307 this.SecureSessionID = sessionInfo.LoginInfo.SecureSession;
308 }
309
310 // Create Inventory, currently only works for sandbox mode
311 if (m_sandboxMode)
312 {
313 this.SetupInventory(sessionInfo);
314 }
315
316 //m_world.parcelManager.sendParcelOverlay(this);
317 m_world.estateManager.sendRegionInfoPacket(this);
318
319 ClientLoop();
320 }
321 }
322 # endregion
323
324
325 protected override void KillThread()
326 {
327 this.ClientThread.Abort();
328 }
329
330 #region World/Avatar To Viewer Methods
331
332 public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID)
333 {
334 System.Text.Encoding enc = System.Text.Encoding.ASCII;
335 libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket();
336 reply.ChatData.Audible = 1;
337 reply.ChatData.Message = message;
338 reply.ChatData.ChatType = type;
339 reply.ChatData.SourceType = 1;
340 reply.ChatData.Position = fromPos;
341 reply.ChatData.FromName = enc.GetBytes(fromName + "\0");
342 reply.ChatData.OwnerID = fromAgentID;
343 reply.ChatData.SourceID = fromAgentID;
344
345 this.OutPacket(reply);
346 }
347
348 public void SendAppearance(AvatarWearable[] wearables)
349 {
350 AgentWearablesUpdatePacket aw = new AgentWearablesUpdatePacket();
351 aw.AgentData.AgentID = this.AgentID;
352 aw.AgentData.SerialNum = 0;
353 aw.AgentData.SessionID = this.SessionID;
354
355 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13];
356 AgentWearablesUpdatePacket.WearableDataBlock awb;
357 for (int i = 0; i < wearables.Length; i++)
358 {
359 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
360 awb.WearableType = (byte)i;
361 awb.AssetID = wearables[i].AssetID;
362 awb.ItemID = wearables[i].ItemID;
363 aw.WearableData[i] = awb;
364 }
365
366 this.OutPacket(aw);
367 }
368 #endregion
369
370 #region Inventory Creation
371 private void SetupInventory(AuthenticateResponse sessionInfo)
372 {
373 AgentInventory inventory = null;
374 if (sessionInfo.LoginInfo.InventoryFolder != null)
375 {
376 inventory = this.CreateInventory(sessionInfo.LoginInfo.InventoryFolder);
377 if (sessionInfo.LoginInfo.BaseFolder != null)
378 {
379 if (!inventory.HasFolder(sessionInfo.LoginInfo.BaseFolder))
380 {
381 m_inventoryCache.CreateNewInventoryFolder(this, sessionInfo.LoginInfo.BaseFolder);
382 }
383 this.newAssetFolder = sessionInfo.LoginInfo.BaseFolder;
384 AssetBase[] inventorySet = m_assetCache.CreateNewInventorySet(this.AgentID);
385 if (inventorySet != null)
386 {
387 for (int i = 0; i < inventorySet.Length; i++)
388 {
389 if (inventorySet[i] != null)
390 {
391 m_inventoryCache.AddNewInventoryItem(this, sessionInfo.LoginInfo.BaseFolder, inventorySet[i]);
392 }
393 }
394 }
395 }
396 }
397 }
398 private AgentInventory CreateInventory(LLUUID baseFolder)
399 {
400 AgentInventory inventory = null;
401 if (this.m_userServer != null)
402 {
403 // a user server is set so request the inventory from it
404 MainConsole.Instance.Verbose("getting inventory from user server");
405 inventory = m_inventoryCache.FetchAgentsInventory(this.AgentID, m_userServer);
406 }
407 else
408 {
409 inventory = new AgentInventory();
410 inventory.AgentID = this.AgentID;
411 inventory.CreateRootFolder(this.AgentID, false);
412 m_inventoryCache.AddNewAgentsInventory(inventory);
413 m_inventoryCache.CreateNewInventoryFolder(this, baseFolder);
414 }
415 return inventory;
416 }
417
418 private void CreateInventoryItem(CreateInventoryItemPacket packet)
419 {
420 if (!(packet.InventoryBlock.Type == 3 || packet.InventoryBlock.Type == 7))
421 {
422 MainConsole.Instance.Warn("Attempted to create " + Util.FieldToString(packet.InventoryBlock.Name) + " in inventory. Unsupported type");
423 return;
424 }
425
426 //lets try this out with creating a notecard
427 AssetBase asset = new AssetBase();
428
429 asset.Name = Util.FieldToString(packet.InventoryBlock.Name);
430 asset.Description = Util.FieldToString(packet.InventoryBlock.Description);
431 asset.InvType = packet.InventoryBlock.InvType;
432 asset.Type = packet.InventoryBlock.Type;
433 asset.FullID = LLUUID.Random();
434
435 switch (packet.InventoryBlock.Type)
436 {
437 case 7: // Notecard
438 asset.Data = new byte[0];
439 break;
440
441 case 3: // Landmark
442 String content;
443 content = "Landmark version 2\n";
444 content += "region_id " + m_regionData.SimUUID + "\n";
445 String strPos = String.Format("%.2f %.2f %.2f>",
446 this.ClientAvatar.Pos.X,
447 this.ClientAvatar.Pos.Y,
448 this.ClientAvatar.Pos.Z);
449 content += "local_pos " + strPos + "\n";
450 asset.Data = (new System.Text.ASCIIEncoding()).GetBytes(content);
451 break;
452 default:
453 break;
454 }
455 m_assetCache.AddAsset(asset);
456 m_inventoryCache.AddNewInventoryItem(this, packet.InventoryBlock.FolderID, asset);
457 }
458 #endregion
459
460 }
461}
diff --git a/OpenSim/OpenSim.RegionServer/Client/ClientViewBase.cs b/OpenSim/OpenSim.RegionServer/Client/ClientViewBase.cs
deleted file mode 100644
index 2ff245f..0000000
--- a/OpenSim/OpenSim.RegionServer/Client/ClientViewBase.cs
+++ /dev/null
@@ -1,326 +0,0 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*
27*/
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using libsecondlife;
32using libsecondlife.Packets;
33using System.Net;
34using System.Net.Sockets;
35using System.IO;
36using System.Threading;
37using System.Timers;
38using OpenSim.Framework.Utilities;
39using OpenSim.Framework.Interfaces;
40using OpenSim.Framework.Console;
41
42namespace OpenSim.RegionServer.Client
43{
44 public class ClientViewBase
45 {
46 protected BlockingQueue<QueItem> PacketQueue;
47 protected Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
48 protected Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
49
50 protected System.Timers.Timer AckTimer;
51 protected uint Sequence = 0;
52 protected object SequenceLock = new object();
53 protected const int MAX_APPENDED_ACKS = 10;
54 protected const int RESEND_TIMEOUT = 4000;
55 protected const int MAX_SEQUENCE = 0xFFFFFF;
56
57 public uint CircuitCode;
58 public EndPoint userEP;
59
60 protected OpenSimNetworkHandler m_networkServer;
61
62 public ClientViewBase()
63 {
64
65 }
66
67 protected virtual void ProcessInPacket(Packet Pack)
68 {
69
70 }
71
72 protected virtual void ProcessOutPacket(Packet Pack)
73 {
74 // Keep track of when this packet was sent out
75 Pack.TickCount = Environment.TickCount;
76
77
78 if (!Pack.Header.Resent)
79 {
80 // Set the sequence number
81 lock (SequenceLock)
82 {
83 if (Sequence >= MAX_SEQUENCE)
84 Sequence = 1;
85 else
86 Sequence++;
87 Pack.Header.Sequence = Sequence;
88 }
89
90 if (Pack.Header.Reliable) //DIRTY HACK
91 {
92 lock (NeedAck)
93 {
94 if (!NeedAck.ContainsKey(Pack.Header.Sequence))
95 {
96 try
97 {
98 NeedAck.Add(Pack.Header.Sequence, Pack);
99 }
100 catch (Exception e) // HACKY
101 {
102 e.ToString();
103 // Ignore
104 // Seems to throw a exception here occasionally
105 // of 'duplicate key' despite being locked.
106 // !?!?!?
107 }
108 }
109 else
110 {
111 // Client.Log("Attempted to add a duplicate sequence number (" +
112 // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
113 // packet.Type.ToString(), Helpers.LogLevel.Warning);
114 }
115 }
116
117 // Don't append ACKs to resent packets, in case that's what was causing the
118 // delivery to fail
119 if (!Pack.Header.Resent)
120 {
121 // Append any ACKs that need to be sent out to this packet
122 lock (PendingAcks)
123 {
124 if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS &&
125 Pack.Type != PacketType.PacketAck &&
126 Pack.Type != PacketType.LogoutRequest)
127 {
128 Pack.Header.AckList = new uint[PendingAcks.Count];
129 int i = 0;
130
131 foreach (uint ack in PendingAcks.Values)
132 {
133 Pack.Header.AckList[i] = ack;
134 i++;
135 }
136
137 PendingAcks.Clear();
138 Pack.Header.AppendedAcks = true;
139 }
140 }
141 }
142 }
143 }
144
145 byte[] ZeroOutBuffer = new byte[4096];
146 byte[] sendbuffer;
147 sendbuffer = Pack.ToBytes();
148
149 try
150 {
151 if (Pack.Header.Zerocoded)
152 {
153 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
154 m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, CircuitCode);//userEP);
155 }
156 else
157 {
158 m_networkServer.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, CircuitCode); //userEP);
159 }
160 }
161 catch (Exception)
162 {
163 MainConsole.Instance.Warn("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread");
164 this.KillThread();
165 }
166
167 }
168
169 public virtual void InPacket(Packet NewPack)
170 {
171 // Handle appended ACKs
172 if (NewPack.Header.AppendedAcks)
173 {
174 lock (NeedAck)
175 {
176 foreach (uint ack in NewPack.Header.AckList)
177 {
178 NeedAck.Remove(ack);
179 }
180 }
181 }
182
183 // Handle PacketAck packets
184 if (NewPack.Type == PacketType.PacketAck)
185 {
186 PacketAckPacket ackPacket = (PacketAckPacket)NewPack;
187
188 lock (NeedAck)
189 {
190 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
191 {
192 NeedAck.Remove(block.ID);
193 }
194 }
195 }
196 else if ((NewPack.Type == PacketType.StartPingCheck))
197 {
198 //reply to pingcheck
199 libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack;
200 libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket();
201 endPing.PingID.PingID = startPing.PingID.PingID;
202 OutPacket(endPing);
203 }
204 else
205 {
206 QueItem item = new QueItem();
207 item.Packet = NewPack;
208 item.Incoming = true;
209 this.PacketQueue.Enqueue(item);
210 }
211
212 }
213
214 public virtual void OutPacket(Packet NewPack)
215 {
216 QueItem item = new QueItem();
217 item.Packet = NewPack;
218 item.Incoming = false;
219 this.PacketQueue.Enqueue(item);
220 }
221
222 # region Low Level Packet Methods
223
224 protected void ack_pack(Packet Pack)
225 {
226 if (Pack.Header.Reliable)
227 {
228 libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket();
229 ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
230 ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
231 ack_it.Packets[0].ID = Pack.Header.Sequence;
232 ack_it.Header.Reliable = false;
233
234 OutPacket(ack_it);
235
236 }
237 /*
238 if (Pack.Header.Reliable)
239 {
240 lock (PendingAcks)
241 {
242 uint sequence = (uint)Pack.Header.Sequence;
243 if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; }
244 }
245 }*/
246 }
247
248 protected void ResendUnacked()
249 {
250 int now = Environment.TickCount;
251
252 lock (NeedAck)
253 {
254 foreach (Packet packet in NeedAck.Values)
255 {
256 if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent))
257 {
258 OpenSim.Framework.Console.MainConsole.Instance.Verbose("Resending " + packet.Type.ToString() + " packet, " +
259 (now - packet.TickCount) + "ms have passed");
260
261 packet.Header.Resent = true;
262 OutPacket(packet);
263 }
264 }
265 }
266 }
267
268 protected void SendAcks()
269 {
270 lock (PendingAcks)
271 {
272 if (PendingAcks.Count > 0)
273 {
274 if (PendingAcks.Count > 250)
275 {
276 // FIXME: Handle the odd case where we have too many pending ACKs queued up
277 OpenSim.Framework.Console.MainConsole.Instance.Verbose("Too many ACKs queued up!");
278 return;
279 }
280
281
282 int i = 0;
283 PacketAckPacket acks = new PacketAckPacket();
284 acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count];
285
286 foreach (uint ack in PendingAcks.Values)
287 {
288 acks.Packets[i] = new PacketAckPacket.PacketsBlock();
289 acks.Packets[i].ID = ack;
290 i++;
291 }
292
293 acks.Header.Reliable = false;
294 OutPacket(acks);
295
296 PendingAcks.Clear();
297 }
298 }
299 }
300
301 protected void AckTimer_Elapsed(object sender, ElapsedEventArgs ea)
302 {
303 SendAcks();
304 ResendUnacked();
305 }
306 #endregion
307
308 protected virtual void KillThread()
309 {
310
311 }
312
313 #region Nested Classes
314
315 public class QueItem
316 {
317 public QueItem()
318 {
319 }
320
321 public Packet Packet;
322 public bool Incoming;
323 }
324 #endregion
325 }
326}