123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- using System;
- using System.Threading;
- #if NETFX_CORE
- using System.Threading.Tasks;
- //Disable CD4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
- #pragma warning disable 4014
- //Disable warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
- #pragma warning disable 1998
- #endif
- namespace BestHTTP
- {
- internal delegate void HTTPConnectionRecycledDelegate(ConnectionBase conn);
- internal abstract class ConnectionBase : IDisposable
- {
- #region Public Properties
- /// <summary>
- /// The address of the server that this connection is bound to.
- /// </summary>
- public string ServerAddress { get; protected set; }
- /// <summary>
- /// The state of this connection.
- /// </summary>
- public HTTPConnectionStates State { get; protected set; }
- /// <summary>
- /// It's true if this connection is available to process a HTTPRequest.
- /// </summary>
- public bool IsFree { get { return State == HTTPConnectionStates.Initial || State == HTTPConnectionStates.Free; } }
- /// <summary>
- /// Returns true if it's an active connection.
- /// </summary>
- public bool IsActive { get { return State > HTTPConnectionStates.Initial && State < HTTPConnectionStates.Free; } }
- /// <summary>
- /// If the State is HTTPConnectionStates.Processing, then it holds a HTTPRequest instance. Otherwise it's null.
- /// </summary>
- public HTTPRequest CurrentRequest { get; protected set; }
- public virtual bool IsRemovable { get { return IsFree && (DateTime.UtcNow - LastProcessTime) > HTTPManager.MaxConnectionIdleTime; } }
- /// <summary>
- /// When we start to process the current request. It's set after the connection is established.
- /// </summary>
- public DateTime StartTime { get; protected set; }
- /// <summary>
- /// When this connection timed out.
- /// </summary>
- public DateTime TimedOutStart { get; protected set; }
- #if !BESTHTTP_DISABLE_PROXY
- protected HTTPProxy Proxy { get; set; }
- public bool HasProxy { get { return Proxy != null; } }
- #endif
- public Uri LastProcessedUri { get; protected set; }
- #endregion
- #region Protected Fields
- protected DateTime LastProcessTime;
- protected HTTPConnectionRecycledDelegate OnConnectionRecycled = null;
- #endregion
- #region Privates
- private bool IsThreaded;
- #endregion
- public ConnectionBase(string serverAddress)
- :this(serverAddress, true)
- {}
- public ConnectionBase(string serverAddress, bool threaded)
- {
- this.ServerAddress = serverAddress;
- this.State = HTTPConnectionStates.Initial;
- this.LastProcessTime = DateTime.UtcNow;
- this.IsThreaded = threaded;
- }
- internal abstract void Abort(HTTPConnectionStates hTTPConnectionStates);
- internal void Process(HTTPRequest request)
- {
- if (State == HTTPConnectionStates.Processing)
- throw new Exception("Connection already processing a request!");
- StartTime = DateTime.MaxValue;
- State = HTTPConnectionStates.Processing;
- CurrentRequest = request;
- if (IsThreaded)
- {
- #if NETFX_CORE
- #pragma warning disable 4014
- Windows.System.Threading.ThreadPool.RunAsync(ThreadFunc);
- #pragma warning restore 4014
- #else
- ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunc));
- //new Thread(ThreadFunc)
- // .Start();
- #endif
- }
- else
- ThreadFunc(null);
- }
- protected virtual
- #if NETFX_CORE
- async
- #endif
- void ThreadFunc(object param)
- {
- }
- internal void HandleProgressCallback()
- {
- if (CurrentRequest.OnProgress != null && CurrentRequest.DownloadProgressChanged)
- {
- try
- {
- CurrentRequest.OnProgress(CurrentRequest, CurrentRequest.Downloaded, CurrentRequest.DownloadLength);
- }
- catch (Exception ex)
- {
- HTTPManager.Logger.Exception("ConnectionBase", "HandleProgressCallback - OnProgress", ex);
- }
- CurrentRequest.DownloadProgressChanged = false;
- }
- if (CurrentRequest.OnUploadProgress != null && CurrentRequest.UploadProgressChanged)
- {
- try
- {
- CurrentRequest.OnUploadProgress(CurrentRequest, CurrentRequest.Uploaded, CurrentRequest.UploadLength);
- }
- catch (Exception ex)
- {
- HTTPManager.Logger.Exception("ConnectionBase", "HandleProgressCallback - OnUploadProgress", ex);
- }
- CurrentRequest.UploadProgressChanged = false;
- }
- }
- internal void HandleCallback()
- {
- try
- {
- HandleProgressCallback();
- if (State == HTTPConnectionStates.Upgraded)
- {
- if (CurrentRequest != null && CurrentRequest.Response != null && CurrentRequest.Response.IsUpgraded)
- CurrentRequest.UpgradeCallback();
- State = HTTPConnectionStates.WaitForProtocolShutdown;
- }
- else
- CurrentRequest.CallCallback();
- }
- catch (Exception ex)
- {
- HTTPManager.Logger.Exception("ConnectionBase", "HandleCallback", ex);
- }
- }
- internal void Recycle(HTTPConnectionRecycledDelegate onConnectionRecycled)
- {
- OnConnectionRecycled = onConnectionRecycled;
- if (!(State > HTTPConnectionStates.Initial && State < HTTPConnectionStates.WaitForProtocolShutdown) || State == HTTPConnectionStates.Redirected)
- RecycleNow();
- }
- protected void RecycleNow()
- {
- if (State == HTTPConnectionStates.TimedOut ||
- State == HTTPConnectionStates.Closed)
- LastProcessTime = DateTime.MinValue;
- State = HTTPConnectionStates.Free;
- CurrentRequest = null;
- if (OnConnectionRecycled != null)
- {
- OnConnectionRecycled(this);
- OnConnectionRecycled = null;
- }
- }
- #region Dispose Pattern
- protected bool IsDisposed { get; private set; }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- protected virtual void Dispose(bool disposing)
- {
- IsDisposed = true;
- }
- #endregion
- }
- }
|