aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Agent/TextureSender
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Agent/TextureSender')
-rw-r--r--OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs220
1 files changed, 220 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs
new file mode 100644
index 0000000..37b0652
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs
@@ -0,0 +1,220 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.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.Reflection;
30using libsecondlife.Packets;
31using log4net;
32using OpenSim.Framework;
33using OpenSim.Region.Environment.Interfaces;
34
35namespace OpenSim.Region.Environment.Modules.Agent.TextureSender
36{
37 /// <summary>
38 /// A TextureSender handles the process of receiving a texture requested by the client from the
39 /// AssetCache, and then sending that texture back to the client.
40 /// </summary>
41 public class TextureSender : ITextureSender
42 {
43 private static readonly ILog m_log
44 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 /// <summary>
47 /// Records the number of times texture send has been called.
48 /// </summary>
49 public int counter = 0;
50
51 /// <summary>
52 /// Holds the texture asset to send.
53 /// </summary>
54 private AssetBase m_asset;
55
56 //public LLUUID assetID { get { return m_asset.FullID; } }
57
58 /// <summary>
59 /// This is actually the number of extra packets required to send the texture data! We always assume
60 /// at least one is required.
61 /// </summary>
62 private int NumPackets = 0;
63
64 /// <summary>
65 /// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts
66 /// at the 600th byte (0th indexed).
67 /// </summary>
68 private int PacketCounter = 0;
69
70 // See ITextureSender
71 public bool Cancel
72 {
73 get { return false; }
74 set { m_cancel = value; }
75 }
76
77 private bool m_cancel = false;
78
79 // See ITextureSender
80 public bool Sending
81 {
82 get { return false; }
83 set { m_sending = value; }
84 }
85
86 private bool m_sending = false;
87
88 public bool ImageLoaded = false;
89
90 private IClientAPI RequestUser;
91
92 private int RequestedDiscardLevel = -1;
93 private uint StartPacketNumber = 0;
94
95 public TextureSender(IClientAPI client, int discardLevel, uint packetNumber)
96 {
97 RequestUser = client;
98 RequestedDiscardLevel = discardLevel;
99 StartPacketNumber = packetNumber;
100 }
101
102 /// <summary>
103 /// Load up the texture data to send.
104 /// </summary>
105 /// <param name="asset">
106 /// A <see cref="AssetBase"/>
107 /// </param>
108 public void TextureReceived(AssetBase asset)
109 {
110 m_asset = asset;
111 NumPackets = CalculateNumPackets(asset.Data.Length);
112 PacketCounter = (int) StartPacketNumber;
113 ImageLoaded = true;
114 }
115
116 // See ITextureSender
117 public void UpdateRequest(int discardLevel, uint packetNumber)
118 {
119 RequestedDiscardLevel = discardLevel;
120 StartPacketNumber = packetNumber;
121 PacketCounter = (int) StartPacketNumber;
122 }
123
124 // See ITextureSender
125 public bool SendTexturePacket()
126 {
127 //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID);
128
129 SendPacket();
130 counter++;
131 if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) ||
132 ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1)))))
133 {
134 return true;
135 }
136 return false;
137 }
138
139 /// <summary>
140 /// Sends a texture packet to the client.
141 /// </summary>
142 private void SendPacket()
143 {
144 if (PacketCounter <= NumPackets)
145 {
146 if (PacketCounter == 0)
147 {
148 if (NumPackets == 0)
149 {
150 ImageDataPacket im = new ImageDataPacket();
151 im.Header.Reliable = false;
152 im.ImageID.Packets = 1;
153 im.ImageID.ID = m_asset.FullID;
154 im.ImageID.Size = (uint) m_asset.Data.Length;
155 im.ImageData.Data = m_asset.Data;
156 im.ImageID.Codec = 2;
157 RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
158 PacketCounter++;
159 }
160 else
161 {
162 ImageDataPacket im = new ImageDataPacket();
163 im.Header.Reliable = false;
164 im.ImageID.Packets = (ushort) (NumPackets);
165 im.ImageID.ID = m_asset.FullID;
166 im.ImageID.Size = (uint) m_asset.Data.Length;
167 im.ImageData.Data = new byte[600];
168 Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600);
169 im.ImageID.Codec = 2;
170 RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
171 PacketCounter++;
172 }
173 }
174 else
175 {
176 ImagePacketPacket im = new ImagePacketPacket();
177 im.Header.Reliable = false;
178 im.ImageID.Packet = (ushort) (PacketCounter);
179 im.ImageID.ID = m_asset.FullID;
180 int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1));
181 if (size > 1000) size = 1000;
182 im.ImageData.Data = new byte[size];
183 try
184 {
185 Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size);
186 }
187 catch (ArgumentOutOfRangeException)
188 {
189 m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" +
190 m_asset.FullID.ToString() );
191 return;
192 }
193 RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
194 PacketCounter++;
195 }
196 }
197 }
198
199 /// <summary>
200 /// Calculate the number of packets that will be required to send the texture loaded into this sender
201 /// This is actually the number of 1000 byte packets not including an initial 600 byte packet...
202 /// </summary>
203 /// <param name="length"></param>
204 /// <returns></returns>
205 private int CalculateNumPackets(int length)
206 {
207 int numPackets = 0;
208
209 if (length > 600)
210 {
211 //over 600 bytes so split up file
212 int restData = (length - 600);
213 int restPackets = ((restData + 999)/1000);
214 numPackets = restPackets;
215 }
216
217 return numPackets;
218 }
219 }
220} \ No newline at end of file