diff options
More work on moving Xfer file transfer handling code to the Client stack from the various region modules that it is currently in.
Still not enabled yet.
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Framework/IClientFileTransfer.cs | 2 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs | 167 |
2 files changed, 134 insertions, 35 deletions
diff --git a/OpenSim/Framework/IClientFileTransfer.cs b/OpenSim/Framework/IClientFileTransfer.cs index 832164e..ac5fc2b 100644 --- a/OpenSim/Framework/IClientFileTransfer.cs +++ b/OpenSim/Framework/IClientFileTransfer.cs | |||
@@ -32,7 +32,7 @@ using OpenMetaverse; | |||
32 | 32 | ||
33 | namespace OpenSim.Framework | 33 | namespace OpenSim.Framework |
34 | { | 34 | { |
35 | public delegate void UploadComplete(string filename, UUID fileID, byte[] fileData, IClientAPI remoteClient); | 35 | public delegate void UploadComplete(string filename, UUID fileID, ulong transferID, byte[] fileData, IClientAPI remoteClient); |
36 | public delegate void UploadAborted(string filename, UUID fileID, ulong transferID, IClientAPI remoteClient); | 36 | public delegate void UploadAborted(string filename, UUID fileID, ulong transferID, IClientAPI remoteClient); |
37 | 37 | ||
38 | public interface IClientFileTransfer | 38 | public interface IClientFileTransfer |
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 |