aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Communications/RestClient.cs
diff options
context:
space:
mode:
authorDavid Walter Seikel2016-11-03 21:44:39 +1000
committerDavid Walter Seikel2016-11-03 21:44:39 +1000
commit134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch)
tree216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Framework/Communications/RestClient.cs
parentMore changing to production grid. Double oops. (diff)
downloadopensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/RestClient.cs (renamed from OpenSim/Framework/Communications/RestClient.cs)314
1 files changed, 276 insertions, 38 deletions
diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/RestClient.cs
index 97b3b60..7080ca5 100644
--- a/OpenSim/Framework/Communications/RestClient.cs
+++ b/OpenSim/Framework/RestClient.cs
@@ -35,7 +35,9 @@ using System.Threading;
35using System.Web; 35using System.Web;
36using log4net; 36using log4net;
37 37
38namespace OpenSim.Framework.Communications 38using OpenSim.Framework.ServiceAuth;
39
40namespace OpenSim.Framework
39{ 41{
40 /// <summary> 42 /// <summary>
41 /// Implementation of a generic REST client 43 /// Implementation of a generic REST client
@@ -54,7 +56,7 @@ namespace OpenSim.Framework.Communications
54 /// other threads to execute, while it waits for a response from the web-service. RestClient itself can be 56 /// other threads to execute, while it waits for a response from the web-service. RestClient itself can be
55 /// invoked by the caller in either synchronous mode or asynchronous modes. 57 /// invoked by the caller in either synchronous mode or asynchronous modes.
56 /// </remarks> 58 /// </remarks>
57 public class RestClient 59 public class RestClient : IDisposable
58 { 60 {
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60 62
@@ -88,7 +90,7 @@ namespace OpenSim.Framework.Communications
88 private byte[] _readbuf; 90 private byte[] _readbuf;
89 91
90 /// <summary> 92 /// <summary>
91 /// MemoryStream representing the resultiong resource 93 /// MemoryStream representing the resulting resource
92 /// </summary> 94 /// </summary>
93 private Stream _resource; 95 private Stream _resource;
94 96
@@ -146,6 +148,33 @@ namespace OpenSim.Framework.Communications
146 148
147 #endregion constructors 149 #endregion constructors
148 150
151
152 #region Dispose
153
154 private bool disposed = false;
155
156 public void Dispose()
157 {
158 Dispose(true);
159 GC.SuppressFinalize(this);
160 }
161
162 protected virtual void Dispose(bool disposing)
163 {
164 if (disposed)
165 return;
166
167 if (disposing)
168 {
169 _resource.Dispose();
170 }
171
172 disposed = true;
173 }
174
175 #endregion Dispose
176
177
149 /// <summary> 178 /// <summary>
150 /// Add a path element to the query, e.g. assets 179 /// Add a path element to the query, e.g. assets
151 /// </summary> 180 /// </summary>
@@ -299,6 +328,14 @@ namespace OpenSim.Framework.Communications
299 /// </summary> 328 /// </summary>
300 public Stream Request() 329 public Stream Request()
301 { 330 {
331 return Request(null);
332 }
333
334 /// <summary>
335 /// Perform a synchronous request
336 /// </summary>
337 public Stream Request(IServiceAuth auth)
338 {
302 lock (_lock) 339 lock (_lock)
303 { 340 {
304 _request = (HttpWebRequest) WebRequest.Create(buildUri()); 341 _request = (HttpWebRequest) WebRequest.Create(buildUri());
@@ -307,44 +344,54 @@ namespace OpenSim.Framework.Communications
307 _request.Timeout = 200000; 344 _request.Timeout = 200000;
308 _request.Method = RequestMethod; 345 _request.Method = RequestMethod;
309 _asyncException = null; 346 _asyncException = null;
347 if (auth != null)
348 auth.AddAuthorization(_request.Headers);
349
350 int reqnum = WebUtil.RequestNumber++;
351 if (WebUtil.DebugLevel >= 3)
352 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} REST {1} to {2}", reqnum, _request.Method, _request.RequestUri);
310 353
311// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); 354// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request);
355
312 try 356 try
313 { 357 {
314 _response = (HttpWebResponse) _request.GetResponse(); 358 using (_response = (HttpWebResponse) _request.GetResponse())
359 {
360 using (Stream src = _response.GetResponseStream())
361 {
362 int length = src.Read(_readbuf, 0, BufferSize);
363 while (length > 0)
364 {
365 _resource.Write(_readbuf, 0, length);
366 length = src.Read(_readbuf, 0, BufferSize);
367 }
368
369 // TODO! Implement timeout, without killing the server
370 // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
371 //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
372
373 // _allDone.WaitOne();
374 }
375 }
315 } 376 }
316 catch (WebException e) 377 catch (WebException e)
317 { 378 {
318 HttpWebResponse errorResponse = e.Response as HttpWebResponse; 379 using (HttpWebResponse errorResponse = e.Response as HttpWebResponse)
319 if (null != errorResponse && HttpStatusCode.NotFound == errorResponse.StatusCode)
320 {
321 m_log.Warn("[REST CLIENT] Resource not found (404)");
322 }
323 else
324 { 380 {
325 m_log.Error("[REST CLIENT] Error fetching resource from server " + _request.Address.ToString()); 381 if (null != errorResponse && HttpStatusCode.NotFound == errorResponse.StatusCode)
326 m_log.Debug(e.ToString()); 382 {
383 // This is often benign. E.g., requesting a missing asset will return 404.
384 m_log.DebugFormat("[REST CLIENT] Resource not found (404): {0}", _request.Address.ToString());
385 }
386 else
387 {
388 m_log.Error(string.Format("[REST CLIENT] Error fetching resource from server: {0} ", _request.Address.ToString()), e);
389 }
327 } 390 }
328 391
329 return null; 392 return null;
330 } 393 }
331 394
332 Stream src = _response.GetResponseStream();
333 int length = src.Read(_readbuf, 0, BufferSize);
334 while (length > 0)
335 {
336 _resource.Write(_readbuf, 0, length);
337 length = src.Read(_readbuf, 0, BufferSize);
338 }
339
340
341 // TODO! Implement timeout, without killing the server
342 // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
343 //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
344
345// _allDone.WaitOne();
346 if (_response != null)
347 _response.Close();
348 if (_asyncException != null) 395 if (_asyncException != null)
349 throw _asyncException; 396 throw _asyncException;
350 397
@@ -354,11 +401,14 @@ namespace OpenSim.Framework.Communications
354 _resource.Seek(0, SeekOrigin.Begin); 401 _resource.Seek(0, SeekOrigin.Begin);
355 } 402 }
356 403
404 if (WebUtil.DebugLevel >= 5)
405 WebUtil.LogResponseDetail(reqnum, _resource);
406
357 return _resource; 407 return _resource;
358 } 408 }
359 } 409 }
360 410
361 public Stream Request(Stream src) 411 public Stream Request(Stream src, IServiceAuth auth)
362 { 412 {
363 _request = (HttpWebRequest) WebRequest.Create(buildUri()); 413 _request = (HttpWebRequest) WebRequest.Create(buildUri());
364 _request.KeepAlive = false; 414 _request.KeepAlive = false;
@@ -367,24 +417,58 @@ namespace OpenSim.Framework.Communications
367 _request.Method = RequestMethod; 417 _request.Method = RequestMethod;
368 _asyncException = null; 418 _asyncException = null;
369 _request.ContentLength = src.Length; 419 _request.ContentLength = src.Length;
420 if (auth != null)
421 auth.AddAuthorization(_request.Headers);
370 422
371 m_log.InfoFormat("[REST]: Request Length {0}", _request.ContentLength);
372 m_log.InfoFormat("[REST]: Sending Web Request {0}", buildUri());
373 src.Seek(0, SeekOrigin.Begin); 423 src.Seek(0, SeekOrigin.Begin);
374 m_log.Info("[REST]: Seek is ok"); 424
425 int reqnum = WebUtil.RequestNumber++;
426 if (WebUtil.DebugLevel >= 3)
427 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} REST {1} to {2}", reqnum, _request.Method, _request.RequestUri);
428 if (WebUtil.DebugLevel >= 5)
429 WebUtil.LogOutgoingDetail(string.Format("SEND {0}: ", reqnum), src);
430
375 Stream dst = _request.GetRequestStream(); 431 Stream dst = _request.GetRequestStream();
376 m_log.Info("[REST]: GetRequestStream is ok");
377 432
378 byte[] buf = new byte[1024]; 433 byte[] buf = new byte[1024];
379 int length = src.Read(buf, 0, 1024); 434 int length = src.Read(buf, 0, 1024);
380 m_log.Info("[REST]: First Read is ok");
381 while (length > 0) 435 while (length > 0)
382 { 436 {
383 dst.Write(buf, 0, length); 437 dst.Write(buf, 0, length);
384 length = src.Read(buf, 0, 1024); 438 length = src.Read(buf, 0, 1024);
385 } 439 }
386 440
387 _response = (HttpWebResponse) _request.GetResponse(); 441 try
442 {
443 _response = (HttpWebResponse)_request.GetResponse();
444 }
445 catch (WebException e)
446 {
447 m_log.WarnFormat("[REST]: Request {0} {1} failed with status {2} and message {3}",
448 RequestMethod, _request.RequestUri, e.Status, e.Message);
449 return null;
450 }
451 catch (Exception e)
452 {
453 m_log.WarnFormat(
454 "[REST]: Request {0} {1} failed with exception {2} {3}",
455 RequestMethod, _request.RequestUri, e.Message, e.StackTrace);
456 return null;
457 }
458
459 if (WebUtil.DebugLevel >= 5)
460 {
461 using (Stream responseStream = _response.GetResponseStream())
462 {
463 using (StreamReader reader = new StreamReader(responseStream))
464 {
465 string responseStr = reader.ReadToEnd();
466 WebUtil.LogResponseDetail(reqnum, responseStr);
467 }
468 }
469 }
470
471 _response.Close();
388 472
389// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); 473// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request);
390 474
@@ -403,7 +487,7 @@ namespace OpenSim.Framework.Communications
403 /// In case, we are invoked asynchroneously this object will keep track of the state 487 /// In case, we are invoked asynchroneously this object will keep track of the state
404 /// </summary> 488 /// </summary>
405 AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state); 489 AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state);
406 Util.FireAndForget(RequestHelper, ar); 490 Util.FireAndForget(RequestHelper, ar, "RestClient.BeginRequest");
407 return ar; 491 return ar;
408 } 492 }
409 493
@@ -423,7 +507,7 @@ namespace OpenSim.Framework.Communications
423 try 507 try
424 { 508 {
425 // Perform the operation; if sucessful set the result 509 // Perform the operation; if sucessful set the result
426 Stream s = Request(); 510 Stream s = Request(null);
427 ar.SetAsCompleted(s, false); 511 ar.SetAsCompleted(s, false);
428 } 512 }
429 catch (Exception e) 513 catch (Exception e)
@@ -435,4 +519,158 @@ namespace OpenSim.Framework.Communications
435 519
436 #endregion Async Invocation 520 #endregion Async Invocation
437 } 521 }
438} 522
523 internal class SimpleAsyncResult : IAsyncResult
524 {
525 private readonly AsyncCallback m_callback;
526
527 /// <summary>
528 /// Is process completed?
529 /// </summary>
530 /// <remarks>Should really be boolean, but VolatileRead has no boolean method</remarks>
531 private byte m_completed;
532
533 /// <summary>
534 /// Did process complete synchronously?
535 /// </summary>
536 /// <remarks>I have a hard time imagining a scenario where this is the case, again, same issue about
537 /// booleans and VolatileRead as m_completed
538 /// </remarks>
539 private byte m_completedSynchronously;
540
541 private readonly object m_asyncState;
542 private ManualResetEvent m_waitHandle;
543 private Exception m_exception;
544
545 internal SimpleAsyncResult(AsyncCallback cb, object state)
546 {
547 m_callback = cb;
548 m_asyncState = state;
549 m_completed = 0;
550 m_completedSynchronously = 1;
551 }
552
553 #region IAsyncResult Members
554
555 public object AsyncState
556 {
557 get { return m_asyncState; }
558 }
559
560 public WaitHandle AsyncWaitHandle
561 {
562 get
563 {
564 if (m_waitHandle == null)
565 {
566 bool done = IsCompleted;
567 ManualResetEvent mre = new ManualResetEvent(done);
568 if (Interlocked.CompareExchange(ref m_waitHandle, mre, null) != null)
569 {
570 mre.Close();
571 }
572 else
573 {
574 if (!done && IsCompleted)
575 {
576 m_waitHandle.Set();
577 }
578 }
579 }
580
581 return m_waitHandle;
582 }
583 }
584
585
586 public bool CompletedSynchronously
587 {
588 get { return Thread.VolatileRead(ref m_completedSynchronously) == 1; }
589 }
590
591
592 public bool IsCompleted
593 {
594 get { return Thread.VolatileRead(ref m_completed) == 1; }
595 }
596
597 #endregion
598
599 #region class Methods
600
601 internal void SetAsCompleted(bool completedSynchronously)
602 {
603 m_completed = 1;
604 if (completedSynchronously)
605 m_completedSynchronously = 1;
606 else
607 m_completedSynchronously = 0;
608
609 SignalCompletion();
610 }
611
612 internal void HandleException(Exception e, bool completedSynchronously)
613 {
614 m_completed = 1;
615 if (completedSynchronously)
616 m_completedSynchronously = 1;
617 else
618 m_completedSynchronously = 0;
619 m_exception = e;
620
621 SignalCompletion();
622 }
623
624 private void SignalCompletion()
625 {
626 if (m_waitHandle != null) m_waitHandle.Set();
627
628 if (m_callback != null) m_callback(this);
629 }
630
631 public void EndInvoke()
632 {
633 // This method assumes that only 1 thread calls EndInvoke
634 if (!IsCompleted)
635 {
636 // If the operation isn't done, wait for it
637 AsyncWaitHandle.WaitOne();
638 AsyncWaitHandle.Close();
639 m_waitHandle.Close();
640 m_waitHandle = null; // Allow early GC
641 }
642
643 // Operation is done: if an exception occured, throw it
644 if (m_exception != null) throw m_exception;
645 }
646
647 #endregion
648 }
649
650 internal class AsyncResult<T> : SimpleAsyncResult
651 {
652 private T m_result = default(T);
653
654 public AsyncResult(AsyncCallback asyncCallback, Object state) :
655 base(asyncCallback, state)
656 {
657 }
658
659 public void SetAsCompleted(T result, bool completedSynchronously)
660 {
661 // Save the asynchronous operation's result
662 m_result = result;
663
664 // Tell the base class that the operation completed
665 // sucessfully (no exception)
666 base.SetAsCompleted(completedSynchronously);
667 }
668
669 public new T EndInvoke()
670 {
671 base.EndInvoke();
672 return m_result;
673 }
674 }
675
676} \ No newline at end of file