2 // ManagedDownloader.cs: The managed implementation that uses System.Net
3 // to provide services to the Downloader class.
6 // Miguel de Icaza (miguel@novell.com)
8 // Copyright 2007 Novell, Inc.
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System
.Threading
;
32 using System
.Collections
;
33 using System
.Runtime
.InteropServices
;
37 namespace Moonlight
.Gtk
{
39 internal class ManagedDownloader
{
41 static Hashtable downloaders
= new Hashtable ();
43 // The pointer to the agclr downloader object
46 // Where we track the download
47 delegate void DownloadDelegate ();
51 AutoResetEvent auto_reset
;
52 DownloadDelegate down
;
53 IAsyncResult async_result
;
54 volatile bool downloading
= true;
57 // Either request is non-null, or fname is non-null.
58 // This is merely an optimization: for fname, instead of going
59 // through FileWebRequest threads and the gtk main loop, we just
60 // emit the ready signal as soon as we can.
62 WebRequest request
= null;
65 Mono
.TickCallHandler tick_call
;
67 ManagedDownloader (IntPtr native
)
74 // we can't call event_object_get_surface (or other stuff) if the download has been aborted
78 IntPtr time_manager
= NativeMethods
.surface_get_time_manager (NativeMethods
.event_object_get_surface (downloader
));
79 // Special case: local file, just notify that we are done
82 if (File
.Exists (fname
)) {
83 NativeMethods
.time_manager_add_tick_call (time_manager
, tick_call
= delegate (IntPtr data
) {
87 NativeMethods
.downloader_notify_finished (downloader
, fname
);
91 NativeMethods
.time_manager_add_tick_call (time_manager
, tick_call
= delegate (IntPtr data
) {
95 NativeMethods
.downloader_notify_failed (downloader
, String
.Format ("File `{0}' not found", fname
));
103 throw new Exception ("This Downloader has not been configured yet, call Open");
109 using (WebResponse r
= request
.GetResponse ()){
110 NativeMethods
.time_manager_add_tick_call (time_manager
, tick_call
= delegate (IntPtr data
) {
113 NativeMethods
.downloader_notify_size (downloader
, r
.ContentLength
);
117 auto_reset
.WaitOne ();
119 using (Stream rstream
= r
.GetResponseStream ()){
120 buffer
= new byte [32*1024];
125 count
= rstream
.Read (buffer
, 0, buffer
.Length
);
131 NativeMethods
.time_manager_add_tick_call (time_manager
, tick_call
= delegate (IntPtr data
) {
136 fixed (byte *buf
= &buffer
[0]) {
137 NativeMethods
.downloader_write (downloader
, (IntPtr
)buf
, offset
, count
);
142 auto_reset
.WaitOne ();
147 NativeMethods
.time_manager_add_tick_call (time_manager
, tick_call
= delegate (IntPtr data
) {
151 NativeMethods
.downloader_notify_finished (downloader
, null);
154 } catch (Exception e
){
155 Console
.Error
.WriteLine ("There was an error {0}", e
);
156 NativeMethods
.downloader_notify_failed (downloader
, e
.Message
);
161 // Initiates the download
166 // Need to use a separate thread
168 auto_reset
= new AutoResetEvent (false);
169 down
= new DownloadDelegate (Download
);
171 async_result
= down
.BeginInvoke (new AsyncCallback (DownloadDone
), null);
174 public static void Send (IntPtr state
)
176 ManagedDownloader m
= (ManagedDownloader
) downloaders
[state
];
183 void DownloadDone (IAsyncResult async_result
)
185 down
.EndInvoke (async_result
);
186 this.async_result
= null;
189 void Open (string verb
, string uri
)
191 if (verb
!= "GET" && verb
.ToUpper () != "GET"){
192 Console
.WriteLine ("Do not know what to do with verb {0}", verb
);
197 if (uri
.StartsWith ("file://"))
198 fname
= uri
.Substring (7);
199 if (uri
.StartsWith ("/"))
203 request
= WebRequest
.Create (uri
);
204 } catch (UriFormatException
){
205 fname
= Path
.GetFullPath (uri
);
208 } catch (Exception e
){
209 Console
.WriteLine ("An error happened with the given url {0}", e
);
210 // Do something with this
212 if (request
== null && fname
== null){
213 Console
.WriteLine ("An error happened with the given url, the result was null");
218 public static IntPtr
CreateDownloader (IntPtr native
)
220 ManagedDownloader m
= new ManagedDownloader (native
);
222 downloaders
[(IntPtr
) key
] = m
;
227 public static void DestroyDownloader (IntPtr state
)
229 ManagedDownloader m
= (ManagedDownloader
) downloaders
[state
];
233 downloaders
[state
] = null;
235 m
.downloading
= false;
238 public static void Open (IntPtr state
, string verb
, string uri
, bool custom_header_support
, bool disable_cache
)
240 ManagedDownloader m
= (ManagedDownloader
) downloaders
[state
];
247 public static void Abort (IntPtr state
)
249 ManagedDownloader m
= (ManagedDownloader
) downloaders
[state
];
253 m
.downloading
= false;
256 public static void Header (IntPtr state
, string header
, string value)
258 ManagedDownloader m
= (ManagedDownloader
) downloaders
[state
];
262 m
.request
.Headers
[header
] = value;
265 public static void Body (IntPtr state
, IntPtr body
, int length
)
267 ManagedDownloader m
= (ManagedDownloader
) downloaders
[state
];
271 Stream stream
= m
.request
.GetRequestStream ();
273 byte[] buffer
= new byte[length
];
275 Marshal
.Copy (body
, buffer
, 0, length
);
276 stream
.Write (buffer
, 0, length
);
279 public static IntPtr
CreateWebRequest (string method
, string uri
, IntPtr context
)
281 throw new NotImplementedException ();
284 public static string GetResponseText (string part
, IntPtr state
)
286 ManagedDownloader m
= (ManagedDownloader
) downloaders
[state
];
290 // Ask toshok what he wants here.