diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs | 167 |
1 files changed, 133 insertions, 34 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs index 9d7b39e..e5783de 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs | |||
@@ -40,18 +40,34 @@ using OpenSim.Region.Environment.Scenes; | |||
40 | 40 | ||
41 | namespace OpenSim.Region.ClientStack.LindenUDP | 41 | namespace OpenSim.Region.ClientStack.LindenUDP |
42 | { | 42 | { |
43 | /// <summary> | ||
44 | /// A work in progress, to contain the SL specific file transfer code that is currently in various region modules | ||
45 | /// This file currently contains multiple classes that need to be split out into their own files. | ||
46 | /// </summary> | ||
43 | public class LLFileTransfer : IClientFileTransfer | 47 | public class LLFileTransfer : IClientFileTransfer |
44 | { | 48 | { |
45 | protected IClientAPI m_clientAPI; | 49 | protected IClientAPI m_clientAPI; |
46 | 50 | ||
47 | /// Dictionary of handlers for uploading files from client | 51 | /// Dictionary of handlers for uploading files from client |
48 | /// TODO: Need to add cleanup code to remove handlers that have completed their upload | 52 | /// TODO: Need to add cleanup code to remove handlers that have completed their upload |
49 | protected Dictionary<ulong, XferHandler> m_handlers; | 53 | protected Dictionary<ulong, XferUploadHandler> m_uploadHandlers; |
50 | protected object m_handlerLock = new object(); | 54 | protected object m_uploadHandlersLock = new object(); |
55 | |||
56 | |||
57 | /// <summary> | ||
58 | /// Dictionary of files to be sent to clients | ||
59 | /// </summary> | ||
60 | protected static Dictionary<string, byte[]> m_files; | ||
61 | |||
62 | /// <summary> | ||
63 | /// Dictionary of Download Transfers in progess | ||
64 | /// </summary> | ||
65 | protected Dictionary<ulong, XferDownloadHandler> m_downloadHandlers = new Dictionary<ulong, XferDownloadHandler>(); | ||
66 | |||
51 | 67 | ||
52 | public LLFileTransfer(IClientAPI clientAPI) | 68 | public LLFileTransfer(IClientAPI clientAPI) |
53 | { | 69 | { |
54 | m_handlers = new Dictionary<ulong, XferHandler>(); | 70 | m_uploadHandlers = new Dictionary<ulong, XferUploadHandler>(); |
55 | m_clientAPI = clientAPI; | 71 | m_clientAPI = clientAPI; |
56 | 72 | ||
57 | m_clientAPI.OnXferReceive += XferReceive; | 73 | m_clientAPI.OnXferReceive += XferReceive; |
@@ -72,10 +88,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
72 | { | 88 | { |
73 | if ((String.IsNullOrEmpty(clientFileName)) || (uploadCompleteCallback == null)) | 89 | if ((String.IsNullOrEmpty(clientFileName)) || (uploadCompleteCallback == null)) |
74 | { | 90 | { |
75 | return false; | 91 | return false; |
76 | } | 92 | } |
77 | 93 | ||
78 | XferHandler uploader = new XferHandler(m_clientAPI, clientFileName); | 94 | XferUploadHandler uploader = new XferUploadHandler(m_clientAPI, clientFileName); |
79 | 95 | ||
80 | return StartUpload(uploader, uploadCompleteCallback, abortCallback); | 96 | return StartUpload(uploader, uploadCompleteCallback, abortCallback); |
81 | } | 97 | } |
@@ -87,12 +103,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
87 | return false; | 103 | return false; |
88 | } | 104 | } |
89 | 105 | ||
90 | XferHandler uploader = new XferHandler(m_clientAPI, fileID); | 106 | XferUploadHandler uploader = new XferUploadHandler(m_clientAPI, fileID); |
91 | 107 | ||
92 | return StartUpload(uploader, uploadCompleteCallback, abortCallback); | 108 | return StartUpload(uploader, uploadCompleteCallback, abortCallback); |
93 | } | 109 | } |
94 | 110 | ||
95 | private bool StartUpload(XferHandler uploader, UploadComplete uploadCompleteCallback, UploadAborted abortCallback) | 111 | private bool StartUpload(XferUploadHandler uploader, UploadComplete uploadCompleteCallback, UploadAborted abortCallback) |
96 | { | 112 | { |
97 | uploader.UploadDone += uploadCompleteCallback; | 113 | uploader.UploadDone += uploadCompleteCallback; |
98 | uploader.UploadDone += RemoveXferHandler; | 114 | uploader.UploadDone += RemoveXferHandler; |
@@ -102,11 +118,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
102 | uploader.UploadAborted += abortCallback; | 118 | uploader.UploadAborted += abortCallback; |
103 | } | 119 | } |
104 | 120 | ||
105 | lock (m_handlerLock) | 121 | lock (m_uploadHandlersLock) |
106 | { | 122 | { |
107 | if (!m_handlers.ContainsKey(uploader.XferID)) | 123 | if (!m_uploadHandlers.ContainsKey(uploader.XferID)) |
108 | { | 124 | { |
109 | m_handlers.Add(uploader.XferID, uploader); | 125 | m_uploadHandlers.Add(uploader.XferID, uploader); |
110 | uploader.RequestStartXfer(m_clientAPI); | 126 | uploader.RequestStartXfer(m_clientAPI); |
111 | return true; | 127 | return true; |
112 | } | 128 | } |
@@ -126,37 +142,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
126 | 142 | ||
127 | protected void AbortXferHandler(IClientAPI remoteClient, ulong xferID) | 143 | protected void AbortXferHandler(IClientAPI remoteClient, ulong xferID) |
128 | { | 144 | { |
129 | lock (m_handlerLock) | 145 | lock (m_uploadHandlersLock) |
130 | { | 146 | { |
131 | if (m_handlers.ContainsKey(xferID)) | 147 | if (m_uploadHandlers.ContainsKey(xferID)) |
132 | { | 148 | { |
133 | m_handlers[xferID].AbortUpload(remoteClient); | 149 | m_uploadHandlers[xferID].AbortUpload(remoteClient); |
134 | m_handlers.Remove(xferID); | 150 | m_uploadHandlers.Remove(xferID); |
135 | } | 151 | } |
136 | } | 152 | } |
137 | } | 153 | } |
138 | 154 | ||
139 | protected void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) | 155 | protected void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) |
140 | { | 156 | { |
141 | lock (m_handlerLock) | 157 | lock (m_uploadHandlersLock) |
142 | { | 158 | { |
143 | if (m_handlers.ContainsKey(xferID)) | 159 | if (m_uploadHandlers.ContainsKey(xferID)) |
144 | { | 160 | { |
145 | m_handlers[xferID].XferReceive(remoteClient, xferID, packetID, data); | 161 | m_uploadHandlers[xferID].XferReceive(remoteClient, xferID, packetID, data); |
146 | } | 162 | } |
147 | } | 163 | } |
148 | } | 164 | } |
149 | 165 | ||
150 | protected void RemoveXferHandler(string filename, UUID fileID, byte[] fileData, IClientAPI remoteClient) | 166 | protected void RemoveXferHandler(string filename, UUID fileID, ulong transferID, byte[] fileData, IClientAPI remoteClient) |
151 | { | 167 | { |
152 | 168 | ||
153 | } | 169 | } |
154 | } | 170 | } |
155 | 171 | ||
156 | public class XferHandler | 172 | public class XferUploadHandler |
157 | { | 173 | { |
158 | private AssetBase m_asset; | 174 | private AssetBase m_asset; |
159 | 175 | ||
160 | public event UploadComplete UploadDone; | 176 | public event UploadComplete UploadDone; |
161 | public event UploadAborted UploadAborted; | 177 | public event UploadAborted UploadAborted; |
162 | 178 | ||
@@ -173,27 +189,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
173 | get { return m_complete; } | 189 | get { return m_complete; } |
174 | } | 190 | } |
175 | 191 | ||
176 | public XferHandler(IClientAPI pRemoteClient, string pClientFilename) | 192 | public XferUploadHandler(IClientAPI pRemoteClient, string pClientFilename) |
177 | { | 193 | { |
194 | Initialise(UUID.Zero, pClientFilename); | ||
195 | } | ||
178 | 196 | ||
179 | m_asset = new AssetBase(); | 197 | public XferUploadHandler(IClientAPI pRemoteClient, UUID fileID) |
180 | m_asset.FullID = UUID.Zero; | 198 | { |
181 | m_asset.Type = type; | 199 | Initialise(fileID, String.Empty); |
182 | m_asset.Data = new byte[0]; | ||
183 | m_asset.Name = pClientFilename; | ||
184 | m_asset.Description = "empty"; | ||
185 | m_asset.Local = true; | ||
186 | m_asset.Temporary = true; | ||
187 | mXferID = Util.GetNextXferID(); | ||
188 | } | 200 | } |
189 | 201 | ||
190 | public XferHandler(IClientAPI pRemoteClient, UUID fileID) | 202 | private void Initialise(UUID fileID, string fileName) |
191 | { | 203 | { |
192 | m_asset = new AssetBase(); | 204 | m_asset = new AssetBase(); |
193 | m_asset.FullID = fileID; | 205 | m_asset.FullID = fileID; |
194 | m_asset.Type = type; | 206 | m_asset.Type = type; |
195 | m_asset.Data = new byte[0]; | 207 | m_asset.Data = new byte[0]; |
196 | m_asset.Name = String.Empty; | 208 | m_asset.Name = fileName; |
197 | m_asset.Description = "empty"; | 209 | m_asset.Description = "empty"; |
198 | m_asset.Local = true; | 210 | m_asset.Local = true; |
199 | m_asset.Temporary = true; | 211 | m_asset.Temporary = true; |
@@ -207,7 +219,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
207 | 219 | ||
208 | public void RequestStartXfer(IClientAPI pRemoteClient) | 220 | public void RequestStartXfer(IClientAPI pRemoteClient) |
209 | { | 221 | { |
210 | if (!String.IsNullOrEmpty(m_asset.Name) ) | 222 | if (!String.IsNullOrEmpty(m_asset.Name)) |
211 | { | 223 | { |
212 | pRemoteClient.SendXferRequest(mXferID, m_asset.Type, m_asset.FullID, 0, Utils.StringToBytes(m_asset.Name)); | 224 | pRemoteClient.SendXferRequest(mXferID, m_asset.Type, m_asset.FullID, 0, Utils.StringToBytes(m_asset.Name)); |
213 | } | 225 | } |
@@ -257,7 +269,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
257 | handlerUploadDone = UploadDone; | 269 | handlerUploadDone = UploadDone; |
258 | if (handlerUploadDone != null) | 270 | if (handlerUploadDone != null) |
259 | { | 271 | { |
260 | handlerUploadDone(m_asset.Name, m_asset.FullID, m_asset.Data, remoteClient); | 272 | handlerUploadDone(m_asset.Name, m_asset.FullID, mXferID, m_asset.Data, remoteClient); |
261 | } | 273 | } |
262 | } | 274 | } |
263 | 275 | ||
@@ -270,4 +282,91 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
270 | } | 282 | } |
271 | } | 283 | } |
272 | } | 284 | } |
285 | |||
286 | public class XferDownloadHandler | ||
287 | { | ||
288 | public IClientAPI Client; | ||
289 | private bool complete; | ||
290 | public byte[] Data = new byte[0]; | ||
291 | public int DataPointer = 0; | ||
292 | public string FileName = String.Empty; | ||
293 | public uint Packet = 0; | ||
294 | public uint Serial = 1; | ||
295 | public ulong XferID = 0; | ||
296 | |||
297 | public XferDownloadHandler(string fileName, byte[] data, ulong xferID, IClientAPI client) | ||
298 | { | ||
299 | FileName = fileName; | ||
300 | Data = data; | ||
301 | XferID = xferID; | ||
302 | Client = client; | ||
303 | } | ||
304 | |||
305 | public XferDownloadHandler() | ||
306 | { | ||
307 | } | ||
308 | |||
309 | /// <summary> | ||
310 | /// Start a transfer | ||
311 | /// </summary> | ||
312 | /// <returns>True if the transfer is complete, false if not</returns> | ||
313 | public bool StartSend() | ||
314 | { | ||
315 | if (Data.Length < 1000) | ||
316 | { | ||
317 | // for now (testing) we only support files under 1000 bytes | ||
318 | byte[] transferData = new byte[Data.Length + 4]; | ||
319 | Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); | ||
320 | Array.Copy(Data, 0, transferData, 4, Data.Length); | ||
321 | Client.SendXferPacket(XferID, 0 + 0x80000000, transferData); | ||
322 | |||
323 | complete = true; | ||
324 | } | ||
325 | else | ||
326 | { | ||
327 | byte[] transferData = new byte[1000 + 4]; | ||
328 | Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); | ||
329 | Array.Copy(Data, 0, transferData, 4, 1000); | ||
330 | Client.SendXferPacket(XferID, 0, transferData); | ||
331 | Packet++; | ||
332 | DataPointer = 1000; | ||
333 | } | ||
334 | |||
335 | return complete; | ||
336 | } | ||
337 | |||
338 | /// <summary> | ||
339 | /// Respond to an ack packet from the client | ||
340 | /// </summary> | ||
341 | /// <param name="packet"></param> | ||
342 | /// <returns>True if the transfer is complete, false otherwise</returns> | ||
343 | public bool AckPacket(uint packet) | ||
344 | { | ||
345 | if (!complete) | ||
346 | { | ||
347 | if ((Data.Length - DataPointer) > 1000) | ||
348 | { | ||
349 | byte[] transferData = new byte[1000]; | ||
350 | Array.Copy(Data, DataPointer, transferData, 0, 1000); | ||
351 | Client.SendXferPacket(XferID, Packet, transferData); | ||
352 | Packet++; | ||
353 | DataPointer += 1000; | ||
354 | } | ||
355 | else | ||
356 | { | ||
357 | byte[] transferData = new byte[Data.Length - DataPointer]; | ||
358 | Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); | ||
359 | uint endPacket = Packet |= (uint)0x80000000; | ||
360 | Client.SendXferPacket(XferID, endPacket, transferData); | ||
361 | Packet++; | ||
362 | DataPointer += (Data.Length - DataPointer); | ||
363 | |||
364 | complete = true; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | return complete; | ||
369 | } | ||
370 | } | ||
371 | |||
273 | } \ No newline at end of file | 372 | } \ No newline at end of file |