300 lines
9.1 KiB
C#
300 lines
9.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
using BestHTTP.Extensions;
|
|
using BestHTTP.PlatformSupport.FileSystem;
|
|
|
|
namespace BestHTTP
|
|
{
|
|
public 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);
|
|
VariableSizedBufferPool.Release(bytes);
|
|
}
|
|
|
|
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 (System.IO.Stream fs = HTTPManager.IOService.CreateFileStream(this.CurrentRequest.CurrentUri.LocalPath, FileStreamModes.Open))
|
|
//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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |