up
This commit is contained in:
218
Assets/BestHTTP/Connections/ConnectionBase.cs
Normal file
218
Assets/BestHTTP/Connections/ConnectionBase.cs
Normal file
@@ -0,0 +1,218 @@
|
||||
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
|
||||
Windows.System.Threading.ThreadPool.RunAsync(ThreadFunc);
|
||||
#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
|
||||
}
|
||||
}
|
||||
11
Assets/BestHTTP/Connections/ConnectionBase.cs.meta
Normal file
11
Assets/BestHTTP/Connections/ConnectionBase.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19b89653c6a154828965eb801bae64c7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
311
Assets/BestHTTP/Connections/FileConnection.cs
Normal file
311
Assets/BestHTTP/Connections/FileConnection.cs
Normal file
@@ -0,0 +1,311 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if NETFX_CORE
|
||||
using FileStream = BestHTTP.PlatformSupport.IO.FileStream;
|
||||
using FileMode = BestHTTP.PlatformSupport.IO.FileMode;
|
||||
using FileAccess = BestHTTP.PlatformSupport.IO.FileAccess;
|
||||
|
||||
using Directory = BestHTTP.PlatformSupport.IO.Directory;
|
||||
using File = BestHTTP.PlatformSupport.IO.File;
|
||||
#else
|
||||
using FileStream = System.IO.FileStream;
|
||||
using FileMode = System.IO.FileMode;
|
||||
using FileAccess = System.IO.FileAccess;
|
||||
#endif
|
||||
|
||||
using BestHTTP.Extensions;
|
||||
|
||||
namespace BestHTTP
|
||||
{
|
||||
sealed class StreamList : System.IO.Stream
|
||||
{
|
||||
private System.IO.Stream[] Streams;
|
||||
private int CurrentIdx;
|
||||
|
||||
public StreamList(params System.IO.Stream[] streams)
|
||||
{
|
||||
this.Streams = streams;
|
||||
this.CurrentIdx = 0;
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get {
|
||||
if (CurrentIdx >= Streams.Length)
|
||||
return false;
|
||||
return Streams[CurrentIdx].CanRead;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanSeek { get { return false; } }
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get {
|
||||
if (CurrentIdx >= Streams.Length)
|
||||
return false;
|
||||
return Streams[CurrentIdx].CanWrite;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
if (CurrentIdx >= Streams.Length)
|
||||
return;
|
||||
|
||||
// We have to call the flush to all previous streams, as we may advanced the CurrentIdx
|
||||
for (int i = 0; i <= CurrentIdx; ++i)
|
||||
Streams[i].Flush();
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get {
|
||||
if (CurrentIdx >= Streams.Length)
|
||||
return 0;
|
||||
|
||||
long length = 0;
|
||||
for (int i = 0; i < Streams.Length; ++i)
|
||||
length += Streams[i].Length;
|
||||
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (CurrentIdx >= Streams.Length)
|
||||
return -1;
|
||||
|
||||
int readCount = Streams[CurrentIdx].Read(buffer, offset, count);
|
||||
|
||||
while (readCount < count && CurrentIdx++ < Streams.Length)
|
||||
{
|
||||
readCount += Streams[CurrentIdx].Read(buffer, offset + readCount, count - readCount);
|
||||
}
|
||||
|
||||
return readCount;
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (CurrentIdx >= Streams.Length)
|
||||
return;
|
||||
|
||||
Streams[CurrentIdx].Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
public void Write(string str)
|
||||
{
|
||||
byte[] bytes = str.GetASCIIBytes();
|
||||
|
||||
this.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
for (int i = 0; i < Streams.Length; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
Streams[i].Dispose();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
HTTPManager.Logger.Exception("StreamList", "Dispose", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException("Position get");
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException("Position set");
|
||||
}
|
||||
}
|
||||
|
||||
public override long Seek(long offset, System.IO.SeekOrigin origin)
|
||||
{
|
||||
if (CurrentIdx >= Streams.Length)
|
||||
return 0;
|
||||
|
||||
return Streams[CurrentIdx].Seek(offset, origin);
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException("SetLength");
|
||||
}
|
||||
}
|
||||
|
||||
/*public static class AndroidFileHelper
|
||||
{
|
||||
// AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
|
||||
// AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
|
||||
|
||||
public static Stream GetAPKFileStream(string path)
|
||||
{
|
||||
UnityEngine.AndroidJavaClass up = new UnityEngine.AndroidJavaClass("com.unity3d.player.UnityPlayer");
|
||||
UnityEngine.AndroidJavaObject cActivity = up.GetStatic<UnityEngine.AndroidJavaObject>("currentActivity");
|
||||
|
||||
UnityEngine.AndroidJavaObject assetManager = cActivity.GetStatic<UnityEngine.AndroidJavaObject>("getAssets");
|
||||
|
||||
return new AndroidInputStream(assetManager.Call<UnityEngine.AndroidJavaObject>("open", path));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AndroidInputStream : Stream
|
||||
{
|
||||
private UnityEngine.AndroidJavaObject baseStream;
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public AndroidInputStream(UnityEngine.AndroidJavaObject inputStream)
|
||||
{
|
||||
this.baseStream = inputStream;
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.baseStream.Call<int>("read", buffer, offset, count);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}*/
|
||||
|
||||
internal sealed class FileConnection : ConnectionBase
|
||||
{
|
||||
public FileConnection(string serverAddress)
|
||||
:base(serverAddress)
|
||||
{ }
|
||||
|
||||
internal override void Abort(HTTPConnectionStates newState)
|
||||
{
|
||||
State = newState;
|
||||
|
||||
switch (State)
|
||||
{
|
||||
case HTTPConnectionStates.TimedOut: TimedOutStart = DateTime.UtcNow; break;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override void ThreadFunc(object param)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Step 1 : create a stream with header information
|
||||
// Step 2 : create a stream from the file
|
||||
// Step 3 : create a StreamList
|
||||
// Step 4 : create a HTTPResponse object
|
||||
// Step 5 : call the Receive function of the response object
|
||||
|
||||
using (FileStream fs = new FileStream(this.CurrentRequest.CurrentUri.LocalPath, FileMode.Open, FileAccess.Read))
|
||||
//using (Stream fs = AndroidFileHelper.GetAPKFileStream(this.CurrentRequest.CurrentUri.LocalPath))
|
||||
using (StreamList stream = new StreamList(new System.IO.MemoryStream(), fs))
|
||||
{
|
||||
// This will write to the MemoryStream
|
||||
stream.Write("HTTP/1.1 200 Ok\r\n");
|
||||
stream.Write("Content-Type: application/octet-stream\r\n");
|
||||
stream.Write("Content-Length: " + fs.Length.ToString() + "\r\n");
|
||||
stream.Write("\r\n");
|
||||
|
||||
stream.Seek(0, System.IO.SeekOrigin.Begin);
|
||||
|
||||
base.CurrentRequest.Response = new HTTPResponse(base.CurrentRequest, stream, base.CurrentRequest.UseStreaming, false);
|
||||
|
||||
if (!CurrentRequest.Response.Receive())
|
||||
CurrentRequest.Response = null;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
if (CurrentRequest != null)
|
||||
{
|
||||
// Something gone bad, Response must be null!
|
||||
CurrentRequest.Response = null;
|
||||
|
||||
switch (State)
|
||||
{
|
||||
case HTTPConnectionStates.AbortRequested:
|
||||
CurrentRequest.State = HTTPRequestStates.Aborted;
|
||||
break;
|
||||
case HTTPConnectionStates.TimedOut:
|
||||
CurrentRequest.State = HTTPRequestStates.TimedOut;
|
||||
break;
|
||||
default:
|
||||
CurrentRequest.Exception = ex;
|
||||
CurrentRequest.State = HTTPRequestStates.Error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
State = HTTPConnectionStates.Closed;
|
||||
if (CurrentRequest.State == HTTPRequestStates.Processing)
|
||||
{
|
||||
if (CurrentRequest.Response != null)
|
||||
CurrentRequest.State = HTTPRequestStates.Finished;
|
||||
else
|
||||
CurrentRequest.State = HTTPRequestStates.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/BestHTTP/Connections/FileConnection.cs.meta
Normal file
11
Assets/BestHTTP/Connections/FileConnection.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2da61498eefa84751bf83deb77fc1754
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
395
Assets/BestHTTP/Connections/WebGLConnection.cs
Normal file
395
Assets/BestHTTP/Connections/WebGLConnection.cs
Normal file
@@ -0,0 +1,395 @@
|
||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using BestHTTP.Authentication;
|
||||
|
||||
namespace BestHTTP
|
||||
{
|
||||
delegate void OnWebGLRequestHandlerDelegate(int nativeId, int httpStatus, IntPtr pBuffer, int length, int zero);
|
||||
delegate void OnWebGLBufferDelegate(int nativeId, IntPtr pBuffer, int length);
|
||||
delegate void OnWebGLProgressDelegate(int nativeId, int downloaded, int total);
|
||||
delegate void OnWebGLErrorDelegate(int nativeId, string error);
|
||||
delegate void OnWebGLTimeoutDelegate(int nativeId);
|
||||
delegate void OnWebGLAbortedDelegate(int nativeId);
|
||||
|
||||
internal sealed class WebGLConnection : ConnectionBase
|
||||
{
|
||||
static Dictionary<int, WebGLConnection> Connections = new Dictionary<int, WebGLConnection>(4);
|
||||
|
||||
int NativeId;
|
||||
MemoryStream Stream;
|
||||
|
||||
public WebGLConnection(string serverAddress)
|
||||
: base(serverAddress, false)
|
||||
{
|
||||
XHR_SetLoglevel((byte)HTTPManager.Logger.Level);
|
||||
}
|
||||
|
||||
internal override void Abort(HTTPConnectionStates newState)
|
||||
{
|
||||
State = newState;
|
||||
|
||||
switch (State)
|
||||
{
|
||||
case HTTPConnectionStates.TimedOut: TimedOutStart = DateTime.UtcNow; break;
|
||||
}
|
||||
|
||||
XHR_Abort(this.NativeId);
|
||||
}
|
||||
|
||||
protected override void ThreadFunc(object param /*null*/)
|
||||
{
|
||||
// XmlHttpRequest setup
|
||||
|
||||
this.NativeId = XHR_Create(HTTPRequest.MethodNames[(byte)CurrentRequest.MethodType],
|
||||
CurrentRequest.CurrentUri.OriginalString,
|
||||
CurrentRequest.Credentials != null ? CurrentRequest.Credentials.UserName : null,
|
||||
CurrentRequest.Credentials != null ? CurrentRequest.Credentials.Password : null);
|
||||
Connections.Add(NativeId, this);
|
||||
|
||||
CurrentRequest.EnumerateHeaders((header, values) =>
|
||||
{
|
||||
if (header != "Content-Length")
|
||||
for (int i = 0; i < values.Count; ++i)
|
||||
XHR_SetRequestHeader(NativeId, header, values[i]);
|
||||
}, /*callBeforeSendCallback:*/ true);
|
||||
|
||||
byte[] body = CurrentRequest.GetEntityBody();
|
||||
|
||||
XHR_SetResponseHandler(NativeId, WebGLConnection.OnResponse, WebGLConnection.OnError, WebGLConnection.OnTimeout, WebGLConnection.OnAborted);
|
||||
XHR_SetProgressHandler(NativeId, WebGLConnection.OnDownloadProgress, WebGLConnection.OnUploadProgress);
|
||||
|
||||
XHR_SetTimeout(NativeId, (uint)(CurrentRequest.ConnectTimeout.TotalMilliseconds + CurrentRequest.Timeout.TotalMilliseconds));
|
||||
|
||||
XHR_Send(NativeId, body, body != null ? body.Length : 0);
|
||||
}
|
||||
|
||||
#region Callback Implementations
|
||||
|
||||
void OnResponse(int httpStatus, byte[] buffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
Stream = ms;
|
||||
|
||||
XHR_GetStatusLine(NativeId, OnBufferCallback);
|
||||
XHR_GetResponseHeaders(NativeId, OnBufferCallback);
|
||||
|
||||
if (buffer != null && buffer.Length > 0)
|
||||
ms.Write(buffer, 0, buffer.Length);
|
||||
|
||||
ms.Seek(0L, SeekOrigin.Begin);
|
||||
|
||||
SupportedProtocols protocol = CurrentRequest.ProtocolHandler == SupportedProtocols.Unknown ? HTTPProtocolFactory.GetProtocolFromUri(CurrentRequest.CurrentUri) : CurrentRequest.ProtocolHandler;
|
||||
CurrentRequest.Response = HTTPProtocolFactory.Get(protocol, CurrentRequest, ms, CurrentRequest.UseStreaming, false);
|
||||
|
||||
CurrentRequest.Response.Receive(buffer != null && buffer.Length > 0 ? (int)buffer.Length : -1, true);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
HTTPManager.Logger.Exception(this.NativeId + " WebGLConnection", "OnResponse", e);
|
||||
|
||||
if (CurrentRequest != null)
|
||||
{
|
||||
// Something gone bad, Response must be null!
|
||||
CurrentRequest.Response = null;
|
||||
|
||||
switch (State)
|
||||
{
|
||||
case HTTPConnectionStates.AbortRequested:
|
||||
CurrentRequest.State = HTTPRequestStates.Aborted;
|
||||
break;
|
||||
case HTTPConnectionStates.TimedOut:
|
||||
CurrentRequest.State = HTTPRequestStates.TimedOut;
|
||||
break;
|
||||
default:
|
||||
CurrentRequest.Exception = e;
|
||||
CurrentRequest.State = HTTPRequestStates.Error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Connections.Remove(NativeId);
|
||||
|
||||
Stream = null;
|
||||
|
||||
if (CurrentRequest != null)
|
||||
lock (HTTPManager.Locker)
|
||||
{
|
||||
State = HTTPConnectionStates.Closed;
|
||||
if (CurrentRequest.State == HTTPRequestStates.Processing)
|
||||
{
|
||||
if (CurrentRequest.Response != null)
|
||||
CurrentRequest.State = HTTPRequestStates.Finished;
|
||||
else
|
||||
CurrentRequest.State = HTTPRequestStates.Error;
|
||||
}
|
||||
}
|
||||
|
||||
LastProcessTime = DateTime.UtcNow;
|
||||
|
||||
if (OnConnectionRecycled != null)
|
||||
RecycleNow();
|
||||
|
||||
XHR_Release(NativeId);
|
||||
}
|
||||
}
|
||||
|
||||
void OnBuffer(byte[] buffer)
|
||||
{
|
||||
if (Stream != null)
|
||||
{
|
||||
Stream.Write(buffer, 0, buffer.Length);
|
||||
Stream.Write(new byte[2] { HTTPResponse.CR, HTTPResponse.LF }, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void OnDownloadProgress(int down, int total)
|
||||
{
|
||||
CurrentRequest.Downloaded = down;
|
||||
CurrentRequest.DownloadLength = total;
|
||||
CurrentRequest.DownloadProgressChanged = true;
|
||||
}
|
||||
|
||||
void OnUploadProgress(int up, int total)
|
||||
{
|
||||
CurrentRequest.Uploaded = up;
|
||||
CurrentRequest.UploadLength = total;
|
||||
CurrentRequest.UploadProgressChanged = true;
|
||||
}
|
||||
|
||||
void OnError(string error)
|
||||
{
|
||||
HTTPManager.Logger.Information(this.NativeId + " WebGLConnection - OnError", error);
|
||||
|
||||
Connections.Remove(NativeId);
|
||||
|
||||
Stream = null;
|
||||
|
||||
if (CurrentRequest != null)
|
||||
lock (HTTPManager.Locker)
|
||||
{
|
||||
State = HTTPConnectionStates.Closed;
|
||||
CurrentRequest.State = HTTPRequestStates.Error;
|
||||
CurrentRequest.Exception = new Exception(error);
|
||||
}
|
||||
|
||||
LastProcessTime = DateTime.UtcNow;
|
||||
|
||||
if (OnConnectionRecycled != null)
|
||||
RecycleNow();
|
||||
|
||||
XHR_Release(NativeId);
|
||||
}
|
||||
|
||||
void OnTimeout()
|
||||
{
|
||||
HTTPManager.Logger.Information(this.NativeId + " WebGLConnection - OnResponse", string.Empty);
|
||||
|
||||
Connections.Remove(NativeId);
|
||||
|
||||
Stream = null;
|
||||
|
||||
if (CurrentRequest != null)
|
||||
lock (HTTPManager.Locker)
|
||||
{
|
||||
State = HTTPConnectionStates.Closed;
|
||||
CurrentRequest.State = HTTPRequestStates.TimedOut;
|
||||
}
|
||||
|
||||
LastProcessTime = DateTime.UtcNow;
|
||||
|
||||
if (OnConnectionRecycled != null)
|
||||
RecycleNow();
|
||||
|
||||
XHR_Release(NativeId);
|
||||
}
|
||||
|
||||
void OnAborted()
|
||||
{
|
||||
HTTPManager.Logger.Information(this.NativeId + " WebGLConnection - OnAborted", string.Empty);
|
||||
|
||||
Connections.Remove(NativeId);
|
||||
|
||||
Stream = null;
|
||||
|
||||
if (CurrentRequest != null)
|
||||
lock (HTTPManager.Locker)
|
||||
{
|
||||
State = HTTPConnectionStates.Closed;
|
||||
CurrentRequest.State = HTTPRequestStates.Aborted;
|
||||
}
|
||||
|
||||
LastProcessTime = DateTime.UtcNow;
|
||||
|
||||
if (OnConnectionRecycled != null)
|
||||
RecycleNow();
|
||||
|
||||
XHR_Release(NativeId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region WebGL Static Callbacks
|
||||
|
||||
[AOT.MonoPInvokeCallback(typeof(OnWebGLRequestHandlerDelegate))]
|
||||
static void OnResponse(int nativeId, int httpStatus, IntPtr pBuffer, int length, int err)
|
||||
{
|
||||
HTTPManager.Logger.Information("WebGLConnection - OnResponse", string.Format("{0} {1} {2} {3}", nativeId, httpStatus, length, err));
|
||||
|
||||
WebGLConnection conn = null;
|
||||
if (!Connections.TryGetValue(nativeId, out conn))
|
||||
{
|
||||
HTTPManager.Logger.Error("WebGLConnection - OnResponse", "No WebGL connection found for nativeId: " + nativeId.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[length];
|
||||
|
||||
// Copy data from the 'unmanaged' memory to managed memory. Buffer will be reclaimed by the GC.
|
||||
Marshal.Copy(pBuffer, buffer, 0, length);
|
||||
|
||||
conn.OnResponse(httpStatus, buffer);
|
||||
}
|
||||
|
||||
[AOT.MonoPInvokeCallback(typeof(OnWebGLBufferDelegate))]
|
||||
static void OnBufferCallback(int nativeId, IntPtr pBuffer, int length)
|
||||
{
|
||||
WebGLConnection conn = null;
|
||||
if (!Connections.TryGetValue(nativeId, out conn))
|
||||
{
|
||||
HTTPManager.Logger.Error("WebGLConnection - OnBufferCallback", "No WebGL connection found for nativeId: " + nativeId.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[length];
|
||||
|
||||
// Copy data from the 'unmanaged' memory to managed memory. Buffer will be reclaimed by the GC.
|
||||
Marshal.Copy(pBuffer, buffer, 0, length);
|
||||
|
||||
conn.OnBuffer(buffer);
|
||||
}
|
||||
|
||||
[AOT.MonoPInvokeCallback(typeof(OnWebGLProgressDelegate))]
|
||||
static void OnDownloadProgress(int nativeId, int downloaded, int total)
|
||||
{
|
||||
HTTPManager.Logger.Information(nativeId + " OnDownloadProgress", downloaded.ToString() + " / " + total.ToString());
|
||||
|
||||
WebGLConnection conn = null;
|
||||
if (!Connections.TryGetValue(nativeId, out conn))
|
||||
{
|
||||
HTTPManager.Logger.Error("WebGLConnection - OnDownloadProgress", "No WebGL connection found for nativeId: " + nativeId.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
conn.OnDownloadProgress(downloaded, total);
|
||||
}
|
||||
|
||||
[AOT.MonoPInvokeCallback(typeof(OnWebGLProgressDelegate))]
|
||||
static void OnUploadProgress(int nativeId, int uploaded, int total)
|
||||
{
|
||||
HTTPManager.Logger.Information(nativeId + " OnUploadProgress", uploaded.ToString() + " / " + total.ToString());
|
||||
|
||||
WebGLConnection conn = null;
|
||||
if (!Connections.TryGetValue(nativeId, out conn))
|
||||
{
|
||||
HTTPManager.Logger.Error("WebGLConnection - OnUploadProgress", "No WebGL connection found for nativeId: " + nativeId.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
conn.OnUploadProgress(uploaded, total);
|
||||
}
|
||||
|
||||
[AOT.MonoPInvokeCallback(typeof(OnWebGLErrorDelegate))]
|
||||
static void OnError(int nativeId, string error)
|
||||
{
|
||||
WebGLConnection conn = null;
|
||||
if (!Connections.TryGetValue(nativeId, out conn))
|
||||
{
|
||||
HTTPManager.Logger.Error("WebGLConnection - OnError", "No WebGL connection found for nativeId: " + nativeId.ToString() + " Error: " + error);
|
||||
return;
|
||||
}
|
||||
|
||||
conn.OnError(error);
|
||||
}
|
||||
|
||||
[AOT.MonoPInvokeCallback(typeof(OnWebGLTimeoutDelegate))]
|
||||
static void OnTimeout(int nativeId)
|
||||
{
|
||||
WebGLConnection conn = null;
|
||||
if (!Connections.TryGetValue(nativeId, out conn))
|
||||
{
|
||||
HTTPManager.Logger.Error("WebGLConnection - OnTimeout", "No WebGL connection found for nativeId: " + nativeId.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
conn.OnTimeout();
|
||||
}
|
||||
|
||||
[AOT.MonoPInvokeCallback(typeof(OnWebGLAbortedDelegate))]
|
||||
static void OnAborted(int nativeId)
|
||||
{
|
||||
WebGLConnection conn = null;
|
||||
if (!Connections.TryGetValue(nativeId, out conn))
|
||||
{
|
||||
HTTPManager.Logger.Error("WebGLConnection - OnAborted", "No WebGL connection found for nativeId: " + nativeId.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
conn.OnAborted();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region WebGL Interface
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern int XHR_Create(string method, string url, string userName, string passwd);
|
||||
|
||||
/// <summary>
|
||||
/// Is an unsigned long representing the number of milliseconds a request can take before automatically being terminated. A value of 0 (which is the default) means there is no timeout.
|
||||
/// </summary>
|
||||
[DllImport("__Internal")]
|
||||
private static extern void XHR_SetTimeout(int nativeId, uint timeout);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void XHR_SetRequestHeader(int nativeId, string header, string value);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void XHR_SetResponseHandler(int nativeId, OnWebGLRequestHandlerDelegate onresponse, OnWebGLErrorDelegate onerror, OnWebGLTimeoutDelegate ontimeout, OnWebGLAbortedDelegate onabort);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void XHR_SetProgressHandler(int nativeId, OnWebGLProgressDelegate onDownloadProgress, OnWebGLProgressDelegate onUploadProgress);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void XHR_Send(int nativeId, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = 2)] byte[] body, int length);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void XHR_GetResponseHeaders(int nativeId, OnWebGLBufferDelegate callback);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void XHR_GetStatusLine(int nativeId, OnWebGLBufferDelegate callback);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void XHR_Abort(int nativeId);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void XHR_Release(int nativeId);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void XHR_SetLoglevel(int logLevel);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
11
Assets/BestHTTP/Connections/WebGLConnection.cs.meta
Normal file
11
Assets/BestHTTP/Connections/WebGLConnection.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c888ab88487f84e229e82f41bcda24a8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user