FileConnection.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. using System;
  2. using System.Collections.Generic;
  3. using BestHTTP.Extensions;
  4. using BestHTTP.PlatformSupport.FileSystem;
  5. namespace BestHTTP
  6. {
  7. public sealed class StreamList : System.IO.Stream
  8. {
  9. private System.IO.Stream[] Streams;
  10. private int CurrentIdx;
  11. public StreamList(params System.IO.Stream[] streams)
  12. {
  13. this.Streams = streams;
  14. this.CurrentIdx = 0;
  15. }
  16. public override bool CanRead
  17. {
  18. get {
  19. if (CurrentIdx >= Streams.Length)
  20. return false;
  21. return Streams[CurrentIdx].CanRead;
  22. }
  23. }
  24. public override bool CanSeek { get { return false; } }
  25. public override bool CanWrite
  26. {
  27. get {
  28. if (CurrentIdx >= Streams.Length)
  29. return false;
  30. return Streams[CurrentIdx].CanWrite;
  31. }
  32. }
  33. public override void Flush()
  34. {
  35. if (CurrentIdx >= Streams.Length)
  36. return;
  37. // We have to call the flush to all previous streams, as we may advanced the CurrentIdx
  38. for (int i = 0; i <= CurrentIdx; ++i)
  39. Streams[i].Flush();
  40. }
  41. public override long Length
  42. {
  43. get {
  44. if (CurrentIdx >= Streams.Length)
  45. return 0;
  46. long length = 0;
  47. for (int i = 0; i < Streams.Length; ++i)
  48. length += Streams[i].Length;
  49. return length;
  50. }
  51. }
  52. public override int Read(byte[] buffer, int offset, int count)
  53. {
  54. if (CurrentIdx >= Streams.Length)
  55. return -1;
  56. int readCount = Streams[CurrentIdx].Read(buffer, offset, count);
  57. while (readCount < count && CurrentIdx++ < Streams.Length)
  58. {
  59. readCount += Streams[CurrentIdx].Read(buffer, offset + readCount, count - readCount);
  60. }
  61. return readCount;
  62. }
  63. public override void Write(byte[] buffer, int offset, int count)
  64. {
  65. if (CurrentIdx >= Streams.Length)
  66. return;
  67. Streams[CurrentIdx].Write(buffer, offset, count);
  68. }
  69. public void Write(string str)
  70. {
  71. byte[] bytes = str.GetASCIIBytes();
  72. this.Write(bytes, 0, bytes.Length);
  73. VariableSizedBufferPool.Release(bytes);
  74. }
  75. protected override void Dispose(bool disposing)
  76. {
  77. for (int i = 0; i < Streams.Length; ++i)
  78. {
  79. try
  80. {
  81. Streams[i].Dispose();
  82. }
  83. catch(Exception ex)
  84. {
  85. HTTPManager.Logger.Exception("StreamList", "Dispose", ex);
  86. }
  87. }
  88. }
  89. public override long Position
  90. {
  91. get
  92. {
  93. throw new NotImplementedException("Position get");
  94. }
  95. set
  96. {
  97. throw new NotImplementedException("Position set");
  98. }
  99. }
  100. public override long Seek(long offset, System.IO.SeekOrigin origin)
  101. {
  102. if (CurrentIdx >= Streams.Length)
  103. return 0;
  104. return Streams[CurrentIdx].Seek(offset, origin);
  105. }
  106. public override void SetLength(long value)
  107. {
  108. throw new NotImplementedException("SetLength");
  109. }
  110. }
  111. /*public static class AndroidFileHelper
  112. {
  113. // AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
  114. // AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
  115. public static Stream GetAPKFileStream(string path)
  116. {
  117. UnityEngine.AndroidJavaClass up = new UnityEngine.AndroidJavaClass("com.unity3d.player.UnityPlayer");
  118. UnityEngine.AndroidJavaObject cActivity = up.GetStatic<UnityEngine.AndroidJavaObject>("currentActivity");
  119. UnityEngine.AndroidJavaObject assetManager = cActivity.GetStatic<UnityEngine.AndroidJavaObject>("getAssets");
  120. return new AndroidInputStream(assetManager.Call<UnityEngine.AndroidJavaObject>("open", path));
  121. }
  122. }
  123. public sealed class AndroidInputStream : Stream
  124. {
  125. private UnityEngine.AndroidJavaObject baseStream;
  126. public override bool CanRead
  127. {
  128. get { throw new NotImplementedException(); }
  129. }
  130. public override bool CanSeek
  131. {
  132. get { throw new NotImplementedException(); }
  133. }
  134. public override bool CanWrite
  135. {
  136. get { throw new NotImplementedException(); }
  137. }
  138. public override void Flush()
  139. {
  140. throw new NotImplementedException();
  141. }
  142. public override long Length
  143. {
  144. get { throw new NotImplementedException(); }
  145. }
  146. public override long Position
  147. {
  148. get
  149. {
  150. throw new NotImplementedException();
  151. }
  152. set
  153. {
  154. throw new NotImplementedException();
  155. }
  156. }
  157. public AndroidInputStream(UnityEngine.AndroidJavaObject inputStream)
  158. {
  159. this.baseStream = inputStream;
  160. }
  161. public override int Read(byte[] buffer, int offset, int count)
  162. {
  163. return this.baseStream.Call<int>("read", buffer, offset, count);
  164. }
  165. public override long Seek(long offset, SeekOrigin origin)
  166. {
  167. throw new NotImplementedException();
  168. }
  169. public override void SetLength(long value)
  170. {
  171. throw new NotImplementedException();
  172. }
  173. public override void Write(byte[] buffer, int offset, int count)
  174. {
  175. throw new NotImplementedException();
  176. }
  177. }*/
  178. internal sealed class FileConnection : ConnectionBase
  179. {
  180. public FileConnection(string serverAddress)
  181. :base(serverAddress)
  182. { }
  183. internal override void Abort(HTTPConnectionStates newState)
  184. {
  185. State = newState;
  186. switch (State)
  187. {
  188. case HTTPConnectionStates.TimedOut: TimedOutStart = DateTime.UtcNow; break;
  189. }
  190. throw new NotImplementedException();
  191. }
  192. protected override void ThreadFunc(object param)
  193. {
  194. try
  195. {
  196. // Step 1 : create a stream with header information
  197. // Step 2 : create a stream from the file
  198. // Step 3 : create a StreamList
  199. // Step 4 : create a HTTPResponse object
  200. // Step 5 : call the Receive function of the response object
  201. using (System.IO.Stream fs = HTTPManager.IOService.CreateFileStream(this.CurrentRequest.CurrentUri.LocalPath, FileStreamModes.Open))
  202. //using (Stream fs = AndroidFileHelper.GetAPKFileStream(this.CurrentRequest.CurrentUri.LocalPath))
  203. using (StreamList stream = new StreamList(new System.IO.MemoryStream(), fs))
  204. {
  205. // This will write to the MemoryStream
  206. stream.Write("HTTP/1.1 200 Ok\r\n");
  207. stream.Write("Content-Type: application/octet-stream\r\n");
  208. stream.Write("Content-Length: " + fs.Length.ToString() + "\r\n");
  209. stream.Write("\r\n");
  210. stream.Seek(0, System.IO.SeekOrigin.Begin);
  211. base.CurrentRequest.Response = new HTTPResponse(base.CurrentRequest, stream, base.CurrentRequest.UseStreaming, false);
  212. if (!CurrentRequest.Response.Receive())
  213. CurrentRequest.Response = null;
  214. }
  215. }
  216. catch(Exception ex)
  217. {
  218. if (CurrentRequest != null)
  219. {
  220. // Something gone bad, Response must be null!
  221. CurrentRequest.Response = null;
  222. switch (State)
  223. {
  224. case HTTPConnectionStates.AbortRequested:
  225. CurrentRequest.State = HTTPRequestStates.Aborted;
  226. break;
  227. case HTTPConnectionStates.TimedOut:
  228. CurrentRequest.State = HTTPRequestStates.TimedOut;
  229. break;
  230. default:
  231. CurrentRequest.Exception = ex;
  232. CurrentRequest.State = HTTPRequestStates.Error;
  233. break;
  234. }
  235. }
  236. }
  237. finally
  238. {
  239. State = HTTPConnectionStates.Closed;
  240. if (CurrentRequest.State == HTTPRequestStates.Processing)
  241. {
  242. if (CurrentRequest.Response != null)
  243. CurrentRequest.State = HTTPRequestStates.Finished;
  244. else
  245. CurrentRequest.State = HTTPRequestStates.Error;
  246. }
  247. }
  248. }
  249. }
  250. }