diff options
author | Jeff Ames | 2008-05-02 03:34:06 +0000 |
---|---|---|
committer | Jeff Ames | 2008-05-02 03:34:06 +0000 |
commit | 058191e6cc45d546058ba0a0ae18054f7ada3bf6 (patch) | |
tree | af81714bf91d323b0c2084b8ac94fd9ece381ed6 /OpenSim/Framework/Communications/RestClient.cs | |
parent | Minimize binary size and external dependencies in OS X LaunchSLClient.app cre... (diff) | |
download | opensim-SC_OLD-058191e6cc45d546058ba0a0ae18054f7ada3bf6.zip opensim-SC_OLD-058191e6cc45d546058ba0a0ae18054f7ada3bf6.tar.gz opensim-SC_OLD-058191e6cc45d546058ba0a0ae18054f7ada3bf6.tar.bz2 opensim-SC_OLD-058191e6cc45d546058ba0a0ae18054f7ada3bf6.tar.xz |
Update svn properties.
Diffstat (limited to 'OpenSim/Framework/Communications/RestClient.cs')
-rw-r--r-- | OpenSim/Framework/Communications/RestClient.cs | 734 |
1 files changed, 367 insertions, 367 deletions
diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/Communications/RestClient.cs index b0b7b1e..d0ac833 100644 --- a/OpenSim/Framework/Communications/RestClient.cs +++ b/OpenSim/Framework/Communications/RestClient.cs | |||
@@ -1,368 +1,368 @@ | |||
1 | using System; | 1 | using System; |
2 | using System.Collections.Generic; | 2 | using System.Collections.Generic; |
3 | using System.IO; | 3 | using System.IO; |
4 | using System.Net; | 4 | using System.Net; |
5 | using System.Reflection; | 5 | using System.Reflection; |
6 | using System.Text; | 6 | using System.Text; |
7 | using System.Threading; | 7 | using System.Threading; |
8 | using System.Web; | 8 | using System.Web; |
9 | using log4net; | 9 | using log4net; |
10 | 10 | ||
11 | namespace OpenSim.Framework.Communications | 11 | namespace OpenSim.Framework.Communications |
12 | { | 12 | { |
13 | /// <summary> | 13 | /// <summary> |
14 | /// Implementation of a generic REST client | 14 | /// Implementation of a generic REST client |
15 | /// </summary> | 15 | /// </summary> |
16 | /// <remarks> | 16 | /// <remarks> |
17 | /// This class is a generic implementation of a REST (Representational State Transfer) web service. This | 17 | /// This class is a generic implementation of a REST (Representational State Transfer) web service. This |
18 | /// class is designed to execute both synchroneously and asynchroneously. | 18 | /// class is designed to execute both synchroneously and asynchroneously. |
19 | /// | 19 | /// |
20 | /// Internally the implementation works as a two stage asynchroneous web-client. | 20 | /// Internally the implementation works as a two stage asynchroneous web-client. |
21 | /// When the request is initiated, RestClient will query asynchroneously for for a web-response, | 21 | /// When the request is initiated, RestClient will query asynchroneously for for a web-response, |
22 | /// sleeping until the initial response is returned by the server. Once the initial response is retrieved | 22 | /// sleeping until the initial response is returned by the server. Once the initial response is retrieved |
23 | /// the second stage of asynchroneous requests will be triggered, in an attempt to read of the response | 23 | /// the second stage of asynchroneous requests will be triggered, in an attempt to read of the response |
24 | /// object into a memorystream as a sequence of asynchroneous reads. | 24 | /// object into a memorystream as a sequence of asynchroneous reads. |
25 | /// | 25 | /// |
26 | /// The asynchronisity of RestClient is designed to move as much processing into the back-ground, allowing | 26 | /// The asynchronisity of RestClient is designed to move as much processing into the back-ground, allowing |
27 | /// other threads to execute, while it waits for a response from the web-service. RestClient it self, can be | 27 | /// other threads to execute, while it waits for a response from the web-service. RestClient it self, can be |
28 | /// invoked by the caller in either synchroneous mode or asynchroneous mode. | 28 | /// invoked by the caller in either synchroneous mode or asynchroneous mode. |
29 | /// </remarks> | 29 | /// </remarks> |
30 | public class RestClient | 30 | public class RestClient |
31 | { | 31 | { |
32 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 32 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
33 | 33 | ||
34 | private string realuri; | 34 | private string realuri; |
35 | 35 | ||
36 | #region member variables | 36 | #region member variables |
37 | 37 | ||
38 | /// <summary> | 38 | /// <summary> |
39 | /// The base Uri of the web-service e.g. http://www.google.com | 39 | /// The base Uri of the web-service e.g. http://www.google.com |
40 | /// </summary> | 40 | /// </summary> |
41 | private string _url; | 41 | private string _url; |
42 | 42 | ||
43 | /// <summary> | 43 | /// <summary> |
44 | /// Path elements of the query | 44 | /// Path elements of the query |
45 | /// </summary> | 45 | /// </summary> |
46 | private List<string> _pathElements = new List<string>(); | 46 | private List<string> _pathElements = new List<string>(); |
47 | 47 | ||
48 | /// <summary> | 48 | /// <summary> |
49 | /// Parameter elements of the query, e.g. min=34 | 49 | /// Parameter elements of the query, e.g. min=34 |
50 | /// </summary> | 50 | /// </summary> |
51 | private Dictionary<string, string> _parameterElements = new Dictionary<string, string>(); | 51 | private Dictionary<string, string> _parameterElements = new Dictionary<string, string>(); |
52 | 52 | ||
53 | /// <summary> | 53 | /// <summary> |
54 | /// Request method. E.g. GET, POST, PUT or DELETE | 54 | /// Request method. E.g. GET, POST, PUT or DELETE |
55 | /// </summary> | 55 | /// </summary> |
56 | private string _method; | 56 | private string _method; |
57 | 57 | ||
58 | /// <summary> | 58 | /// <summary> |
59 | /// Temporary buffer used to store bytes temporarily as they come in from the server | 59 | /// Temporary buffer used to store bytes temporarily as they come in from the server |
60 | /// </summary> | 60 | /// </summary> |
61 | private byte[] _readbuf; | 61 | private byte[] _readbuf; |
62 | 62 | ||
63 | /// <summary> | 63 | /// <summary> |
64 | /// MemoryStream representing the resultiong resource | 64 | /// MemoryStream representing the resultiong resource |
65 | /// </summary> | 65 | /// </summary> |
66 | private Stream _resource; | 66 | private Stream _resource; |
67 | 67 | ||
68 | /// <summary> | 68 | /// <summary> |
69 | /// WebRequest object, held as a member variable | 69 | /// WebRequest object, held as a member variable |
70 | /// </summary> | 70 | /// </summary> |
71 | private HttpWebRequest _request; | 71 | private HttpWebRequest _request; |
72 | 72 | ||
73 | /// <summary> | 73 | /// <summary> |
74 | /// WebResponse object, held as a member variable, so we can close it | 74 | /// WebResponse object, held as a member variable, so we can close it |
75 | /// </summary> | 75 | /// </summary> |
76 | private HttpWebResponse _response; | 76 | private HttpWebResponse _response; |
77 | 77 | ||
78 | /// <summary> | 78 | /// <summary> |
79 | /// This flag will help block the main synchroneous method, in case we run in synchroneous mode | 79 | /// This flag will help block the main synchroneous method, in case we run in synchroneous mode |
80 | /// </summary> | 80 | /// </summary> |
81 | public static ManualResetEvent _allDone = new ManualResetEvent(false); | 81 | public static ManualResetEvent _allDone = new ManualResetEvent(false); |
82 | 82 | ||
83 | /// <summary> | 83 | /// <summary> |
84 | /// Default time out period | 84 | /// Default time out period |
85 | /// </summary> | 85 | /// </summary> |
86 | private const int DefaultTimeout = 10*1000; // 10 seconds timeout | 86 | private const int DefaultTimeout = 10*1000; // 10 seconds timeout |
87 | 87 | ||
88 | /// <summary> | 88 | /// <summary> |
89 | /// Default Buffer size of a block requested from the web-server | 89 | /// Default Buffer size of a block requested from the web-server |
90 | /// </summary> | 90 | /// </summary> |
91 | private const int BufferSize = 4096; // Read blocks of 4 KB. | 91 | private const int BufferSize = 4096; // Read blocks of 4 KB. |
92 | 92 | ||
93 | 93 | ||
94 | /// <summary> | 94 | /// <summary> |
95 | /// if an exception occours during async processing, we need to save it, so it can be | 95 | /// if an exception occours during async processing, we need to save it, so it can be |
96 | /// rethrown on the primary thread; | 96 | /// rethrown on the primary thread; |
97 | /// </summary> | 97 | /// </summary> |
98 | private Exception _asyncException; | 98 | private Exception _asyncException; |
99 | 99 | ||
100 | #endregion member variables | 100 | #endregion member variables |
101 | 101 | ||
102 | #region constructors | 102 | #region constructors |
103 | 103 | ||
104 | /// <summary> | 104 | /// <summary> |
105 | /// Instantiate a new RestClient | 105 | /// Instantiate a new RestClient |
106 | /// </summary> | 106 | /// </summary> |
107 | /// <param name="url">Web-service to query, e.g. http://osgrid.org:8003</param> | 107 | /// <param name="url">Web-service to query, e.g. http://osgrid.org:8003</param> |
108 | public RestClient(string url) | 108 | public RestClient(string url) |
109 | { | 109 | { |
110 | _url = url; | 110 | _url = url; |
111 | _readbuf = new byte[BufferSize]; | 111 | _readbuf = new byte[BufferSize]; |
112 | _resource = new MemoryStream(); | 112 | _resource = new MemoryStream(); |
113 | _request = null; | 113 | _request = null; |
114 | _response = null; | 114 | _response = null; |
115 | _lock = new object(); | 115 | _lock = new object(); |
116 | } | 116 | } |
117 | 117 | ||
118 | private object _lock; | 118 | private object _lock; |
119 | 119 | ||
120 | #endregion constructors | 120 | #endregion constructors |
121 | 121 | ||
122 | /// <summary> | 122 | /// <summary> |
123 | /// Add a path element to the query, e.g. assets | 123 | /// Add a path element to the query, e.g. assets |
124 | /// </summary> | 124 | /// </summary> |
125 | /// <param name="element">path entry</param> | 125 | /// <param name="element">path entry</param> |
126 | public void AddResourcePath(string element) | 126 | public void AddResourcePath(string element) |
127 | { | 127 | { |
128 | if (isSlashed(element)) | 128 | if (isSlashed(element)) |
129 | _pathElements.Add(element.Substring(0, element.Length - 1)); | 129 | _pathElements.Add(element.Substring(0, element.Length - 1)); |
130 | else | 130 | else |
131 | _pathElements.Add(element); | 131 | _pathElements.Add(element); |
132 | } | 132 | } |
133 | 133 | ||
134 | /// <summary> | 134 | /// <summary> |
135 | /// Add a query parameter to the Url | 135 | /// Add a query parameter to the Url |
136 | /// </summary> | 136 | /// </summary> |
137 | /// <param name="name">Name of the parameter, e.g. min</param> | 137 | /// <param name="name">Name of the parameter, e.g. min</param> |
138 | /// <param name="value">Value of the parameter, e.g. 42</param> | 138 | /// <param name="value">Value of the parameter, e.g. 42</param> |
139 | public void AddQueryParameter(string name, string value) | 139 | public void AddQueryParameter(string name, string value) |
140 | { | 140 | { |
141 | _parameterElements.Add(HttpUtility.UrlEncode(name), HttpUtility.UrlEncode(value)); | 141 | _parameterElements.Add(HttpUtility.UrlEncode(name), HttpUtility.UrlEncode(value)); |
142 | } | 142 | } |
143 | 143 | ||
144 | /// <summary> | 144 | /// <summary> |
145 | /// Add a query parameter to the Url | 145 | /// Add a query parameter to the Url |
146 | /// </summary> | 146 | /// </summary> |
147 | /// <param name="name">Name of the parameter, e.g. min</param> | 147 | /// <param name="name">Name of the parameter, e.g. min</param> |
148 | public void AddQueryParameter(string name) | 148 | public void AddQueryParameter(string name) |
149 | { | 149 | { |
150 | _parameterElements.Add(HttpUtility.UrlEncode(name), null); | 150 | _parameterElements.Add(HttpUtility.UrlEncode(name), null); |
151 | } | 151 | } |
152 | 152 | ||
153 | /// <summary> | 153 | /// <summary> |
154 | /// Web-Request method, e.g. GET, PUT, POST, DELETE | 154 | /// Web-Request method, e.g. GET, PUT, POST, DELETE |
155 | /// </summary> | 155 | /// </summary> |
156 | public string RequestMethod | 156 | public string RequestMethod |
157 | { | 157 | { |
158 | get { return _method; } | 158 | get { return _method; } |
159 | set { _method = value; } | 159 | set { _method = value; } |
160 | } | 160 | } |
161 | 161 | ||
162 | /// <summary> | 162 | /// <summary> |
163 | /// True if string contains a trailing slash '/' | 163 | /// True if string contains a trailing slash '/' |
164 | /// </summary> | 164 | /// </summary> |
165 | /// <param name="s">string to be examined</param> | 165 | /// <param name="s">string to be examined</param> |
166 | /// <returns>true if slash is present</returns> | 166 | /// <returns>true if slash is present</returns> |
167 | private static bool isSlashed(string s) | 167 | private static bool isSlashed(string s) |
168 | { | 168 | { |
169 | return s.Substring(s.Length - 1, 1) == "/"; | 169 | return s.Substring(s.Length - 1, 1) == "/"; |
170 | } | 170 | } |
171 | 171 | ||
172 | /// <summary> | 172 | /// <summary> |
173 | /// Build a Uri based on the initial Url, path elements and parameters | 173 | /// Build a Uri based on the initial Url, path elements and parameters |
174 | /// </summary> | 174 | /// </summary> |
175 | /// <returns>fully constructed Uri</returns> | 175 | /// <returns>fully constructed Uri</returns> |
176 | private Uri buildUri() | 176 | private Uri buildUri() |
177 | { | 177 | { |
178 | StringBuilder sb = new StringBuilder(); | 178 | StringBuilder sb = new StringBuilder(); |
179 | sb.Append(_url); | 179 | sb.Append(_url); |
180 | 180 | ||
181 | foreach (string e in _pathElements) | 181 | foreach (string e in _pathElements) |
182 | { | 182 | { |
183 | sb.Append("/"); | 183 | sb.Append("/"); |
184 | sb.Append(e); | 184 | sb.Append(e); |
185 | } | 185 | } |
186 | 186 | ||
187 | bool firstElement = true; | 187 | bool firstElement = true; |
188 | foreach (KeyValuePair<string, string> kv in _parameterElements) | 188 | foreach (KeyValuePair<string, string> kv in _parameterElements) |
189 | { | 189 | { |
190 | if (firstElement) | 190 | if (firstElement) |
191 | { | 191 | { |
192 | sb.Append("?"); | 192 | sb.Append("?"); |
193 | firstElement = false; | 193 | firstElement = false; |
194 | } | 194 | } |
195 | else | 195 | else |
196 | sb.Append("&"); | 196 | sb.Append("&"); |
197 | 197 | ||
198 | sb.Append(kv.Key); | 198 | sb.Append(kv.Key); |
199 | if (!string.IsNullOrEmpty(kv.Value)) | 199 | if (!string.IsNullOrEmpty(kv.Value)) |
200 | { | 200 | { |
201 | sb.Append("="); | 201 | sb.Append("="); |
202 | sb.Append(kv.Value); | 202 | sb.Append(kv.Value); |
203 | } | 203 | } |
204 | } | 204 | } |
205 | realuri = sb.ToString(); | 205 | realuri = sb.ToString(); |
206 | //m_log.InfoFormat("[REST CLIENT]: RestURL: {0}", realuri); | 206 | //m_log.InfoFormat("[REST CLIENT]: RestURL: {0}", realuri); |
207 | return new Uri(sb.ToString()); | 207 | return new Uri(sb.ToString()); |
208 | } | 208 | } |
209 | 209 | ||
210 | #region Async communications with server | 210 | #region Async communications with server |
211 | 211 | ||
212 | /// <summary> | 212 | /// <summary> |
213 | /// Async method, invoked when a block of data has been received from the service | 213 | /// Async method, invoked when a block of data has been received from the service |
214 | /// </summary> | 214 | /// </summary> |
215 | /// <param name="ar"></param> | 215 | /// <param name="ar"></param> |
216 | private void StreamIsReadyDelegate(IAsyncResult ar) | 216 | private void StreamIsReadyDelegate(IAsyncResult ar) |
217 | { | 217 | { |
218 | try | 218 | try |
219 | { | 219 | { |
220 | Stream s = (Stream) ar.AsyncState; | 220 | Stream s = (Stream) ar.AsyncState; |
221 | int read = s.EndRead(ar); | 221 | int read = s.EndRead(ar); |
222 | 222 | ||
223 | if (read > 0) | 223 | if (read > 0) |
224 | { | 224 | { |
225 | _resource.Write(_readbuf, 0, read); | 225 | _resource.Write(_readbuf, 0, read); |
226 | IAsyncResult asynchronousResult = | 226 | IAsyncResult asynchronousResult = |
227 | s.BeginRead(_readbuf, 0, BufferSize, new AsyncCallback(StreamIsReadyDelegate), s); | 227 | s.BeginRead(_readbuf, 0, BufferSize, new AsyncCallback(StreamIsReadyDelegate), s); |
228 | 228 | ||
229 | // TODO! Implement timeout, without killing the server | 229 | // TODO! Implement timeout, without killing the server |
230 | //ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); | 230 | //ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); |
231 | } | 231 | } |
232 | else | 232 | else |
233 | { | 233 | { |
234 | s.Close(); | 234 | s.Close(); |
235 | _allDone.Set(); | 235 | _allDone.Set(); |
236 | } | 236 | } |
237 | } | 237 | } |
238 | catch (Exception e) | 238 | catch (Exception e) |
239 | { | 239 | { |
240 | _allDone.Set(); | 240 | _allDone.Set(); |
241 | _asyncException = e; | 241 | _asyncException = e; |
242 | } | 242 | } |
243 | } | 243 | } |
244 | 244 | ||
245 | #endregion Async communications with server | 245 | #endregion Async communications with server |
246 | 246 | ||
247 | /// <summary> | 247 | /// <summary> |
248 | /// Perform synchroneous request | 248 | /// Perform synchroneous request |
249 | /// </summary> | 249 | /// </summary> |
250 | public Stream Request() | 250 | public Stream Request() |
251 | { | 251 | { |
252 | lock (_lock) | 252 | lock (_lock) |
253 | { | 253 | { |
254 | _request = (HttpWebRequest) WebRequest.Create(buildUri()); | 254 | _request = (HttpWebRequest) WebRequest.Create(buildUri()); |
255 | _request.KeepAlive = false; | 255 | _request.KeepAlive = false; |
256 | _request.ContentType = "application/xml"; | 256 | _request.ContentType = "application/xml"; |
257 | _request.Timeout = 200000; | 257 | _request.Timeout = 200000; |
258 | _asyncException = null; | 258 | _asyncException = null; |
259 | 259 | ||
260 | // IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); | 260 | // IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); |
261 | _response = (HttpWebResponse) _request.GetResponse(); | 261 | _response = (HttpWebResponse) _request.GetResponse(); |
262 | Stream src = _response.GetResponseStream(); | 262 | Stream src = _response.GetResponseStream(); |
263 | int length = src.Read(_readbuf, 0, BufferSize); | 263 | int length = src.Read(_readbuf, 0, BufferSize); |
264 | while (length > 0) | 264 | while (length > 0) |
265 | { | 265 | { |
266 | _resource.Write(_readbuf, 0, length); | 266 | _resource.Write(_readbuf, 0, length); |
267 | length = src.Read(_readbuf, 0, BufferSize); | 267 | length = src.Read(_readbuf, 0, BufferSize); |
268 | } | 268 | } |
269 | 269 | ||
270 | 270 | ||
271 | // TODO! Implement timeout, without killing the server | 271 | // TODO! Implement timeout, without killing the server |
272 | // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted | 272 | // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted |
273 | //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); | 273 | //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); |
274 | 274 | ||
275 | // _allDone.WaitOne(); | 275 | // _allDone.WaitOne(); |
276 | if (_response != null) | 276 | if (_response != null) |
277 | _response.Close(); | 277 | _response.Close(); |
278 | if (_asyncException != null) | 278 | if (_asyncException != null) |
279 | throw _asyncException; | 279 | throw _asyncException; |
280 | 280 | ||
281 | if (_resource != null) | 281 | if (_resource != null) |
282 | { | 282 | { |
283 | _resource.Flush(); | 283 | _resource.Flush(); |
284 | _resource.Seek(0, SeekOrigin.Begin); | 284 | _resource.Seek(0, SeekOrigin.Begin); |
285 | } | 285 | } |
286 | 286 | ||
287 | return _resource; | 287 | return _resource; |
288 | } | 288 | } |
289 | } | 289 | } |
290 | 290 | ||
291 | public Stream Request(Stream src) | 291 | public Stream Request(Stream src) |
292 | { | 292 | { |
293 | _request = (HttpWebRequest) WebRequest.Create(buildUri()); | 293 | _request = (HttpWebRequest) WebRequest.Create(buildUri()); |
294 | _request.KeepAlive = false; | 294 | _request.KeepAlive = false; |
295 | _request.ContentType = "application/xml"; | 295 | _request.ContentType = "application/xml"; |
296 | _request.Timeout = 900000; | 296 | _request.Timeout = 900000; |
297 | _request.Method = RequestMethod; | 297 | _request.Method = RequestMethod; |
298 | _asyncException = null; | 298 | _asyncException = null; |
299 | _request.ContentLength = src.Length; | 299 | _request.ContentLength = src.Length; |
300 | 300 | ||
301 | m_log.InfoFormat("[REST]: Request Length {0}", _request.ContentLength); | 301 | m_log.InfoFormat("[REST]: Request Length {0}", _request.ContentLength); |
302 | m_log.InfoFormat("[REST]: Sending Web Request {0}", buildUri()); | 302 | m_log.InfoFormat("[REST]: Sending Web Request {0}", buildUri()); |
303 | src.Seek(0, SeekOrigin.Begin); | 303 | src.Seek(0, SeekOrigin.Begin); |
304 | m_log.Info("[REST]: Seek is ok"); | 304 | m_log.Info("[REST]: Seek is ok"); |
305 | Stream dst = _request.GetRequestStream(); | 305 | Stream dst = _request.GetRequestStream(); |
306 | m_log.Info("[REST]: GetRequestStream is ok"); | 306 | m_log.Info("[REST]: GetRequestStream is ok"); |
307 | 307 | ||
308 | byte[] buf = new byte[1024]; | 308 | byte[] buf = new byte[1024]; |
309 | int length = src.Read(buf, 0, 1024); | 309 | int length = src.Read(buf, 0, 1024); |
310 | m_log.Info("[REST]: First Read is ok"); | 310 | m_log.Info("[REST]: First Read is ok"); |
311 | while (length > 0) | 311 | while (length > 0) |
312 | { | 312 | { |
313 | dst.Write(buf, 0, length); | 313 | dst.Write(buf, 0, length); |
314 | length = src.Read(buf, 0, 1024); | 314 | length = src.Read(buf, 0, 1024); |
315 | } | 315 | } |
316 | 316 | ||
317 | _response = (HttpWebResponse) _request.GetResponse(); | 317 | _response = (HttpWebResponse) _request.GetResponse(); |
318 | 318 | ||
319 | // IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); | 319 | // IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); |
320 | 320 | ||
321 | // TODO! Implement timeout, without killing the server | 321 | // TODO! Implement timeout, without killing the server |
322 | // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted | 322 | // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted |
323 | //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); | 323 | //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); |
324 | 324 | ||
325 | return null; | 325 | return null; |
326 | } | 326 | } |
327 | 327 | ||
328 | #region Async Invocation | 328 | #region Async Invocation |
329 | 329 | ||
330 | public IAsyncResult BeginRequest(AsyncCallback callback, object state) | 330 | public IAsyncResult BeginRequest(AsyncCallback callback, object state) |
331 | { | 331 | { |
332 | /// <summary> | 332 | /// <summary> |
333 | /// In case, we are invoked asynchroneously this object will keep track of the state | 333 | /// In case, we are invoked asynchroneously this object will keep track of the state |
334 | /// </summary> | 334 | /// </summary> |
335 | AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state); | 335 | AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state); |
336 | ThreadPool.QueueUserWorkItem(RequestHelper, ar); | 336 | ThreadPool.QueueUserWorkItem(RequestHelper, ar); |
337 | return ar; | 337 | return ar; |
338 | } | 338 | } |
339 | 339 | ||
340 | public Stream EndRequest(IAsyncResult asyncResult) | 340 | public Stream EndRequest(IAsyncResult asyncResult) |
341 | { | 341 | { |
342 | AsyncResult<Stream> ar = (AsyncResult<Stream>) asyncResult; | 342 | AsyncResult<Stream> ar = (AsyncResult<Stream>) asyncResult; |
343 | 343 | ||
344 | // Wait for operation to complete, then return result or | 344 | // Wait for operation to complete, then return result or |
345 | // throw exception | 345 | // throw exception |
346 | return ar.EndInvoke(); | 346 | return ar.EndInvoke(); |
347 | } | 347 | } |
348 | 348 | ||
349 | private void RequestHelper(Object asyncResult) | 349 | private void RequestHelper(Object asyncResult) |
350 | { | 350 | { |
351 | // We know that it's really an AsyncResult<DateTime> object | 351 | // We know that it's really an AsyncResult<DateTime> object |
352 | AsyncResult<Stream> ar = (AsyncResult<Stream>) asyncResult; | 352 | AsyncResult<Stream> ar = (AsyncResult<Stream>) asyncResult; |
353 | try | 353 | try |
354 | { | 354 | { |
355 | // Perform the operation; if sucessful set the result | 355 | // Perform the operation; if sucessful set the result |
356 | Stream s = Request(); | 356 | Stream s = Request(); |
357 | ar.SetAsCompleted(s, false); | 357 | ar.SetAsCompleted(s, false); |
358 | } | 358 | } |
359 | catch (Exception e) | 359 | catch (Exception e) |
360 | { | 360 | { |
361 | // If operation fails, set the exception | 361 | // If operation fails, set the exception |
362 | ar.HandleException(e, false); | 362 | ar.HandleException(e, false); |
363 | } | 363 | } |
364 | } | 364 | } |
365 | 365 | ||
366 | #endregion Async Invocation | 366 | #endregion Async Invocation |
367 | } | 367 | } |
368 | } \ No newline at end of file | 368 | } \ No newline at end of file |