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 { 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); } 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("currentActivity"); public static Stream GetAPKFileStream(string path) { UnityEngine.AndroidJavaClass up = new UnityEngine.AndroidJavaClass("com.unity3d.player.UnityPlayer"); UnityEngine.AndroidJavaObject cActivity = up.GetStatic("currentActivity"); UnityEngine.AndroidJavaObject assetManager = cActivity.GetStatic("getAssets"); return new AndroidInputStream(assetManager.Call("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("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; } } } } }