KTVHCDataNetworkSource.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. //
  2. // KTVHCDataNetworkSource.m
  3. // KTVHTTPCache
  4. //
  5. // Created by Single on 2017/8/11.
  6. // Copyright © 2017年 Single. All rights reserved.
  7. //
  8. #import "KTVHCDataNetworkSource.h"
  9. #import "KTVHCDataUnitPool.h"
  10. #import "KTVHCDataCallback.h"
  11. #import "KTVHCPathTool.h"
  12. #import "KTVHCDownload.h"
  13. #import "KTVHCError.h"
  14. #import "KTVHCLog.h"
  15. @interface KTVHCDataNetworkSource () <NSLocking, KTVHCDownloadDelegate>
  16. @property (nonatomic, strong) NSLock *coreLock;
  17. @property (nonatomic, strong) NSFileHandle *readingHandle;
  18. @property (nonatomic, strong) NSFileHandle *writingHandle;
  19. @property (nonatomic, strong) KTVHCDataUnitItem *unitItem;
  20. @property (nonatomic, strong) NSURLSessionTask *downlaodTask;
  21. @property (nonatomic) long long downloadLength;
  22. @property (nonatomic) BOOL downloadCalledComplete;
  23. @property (nonatomic) BOOL callHasAvailableData;
  24. @property (nonatomic) BOOL calledPrepare;
  25. @end
  26. @implementation KTVHCDataNetworkSource
  27. @synthesize error = _error;
  28. @synthesize range = _range;
  29. @synthesize closed = _closed;
  30. @synthesize prepared = _prepared;
  31. @synthesize finished = _finished;
  32. @synthesize readedLength = _readedLength;
  33. - (instancetype)initWithRequest:(KTVHCDataRequest *)reqeust
  34. {
  35. if (self = [super init])
  36. {
  37. KTVHCLogAlloc(self);
  38. self->_request = reqeust;
  39. self->_range = reqeust.range;
  40. self.coreLock = [[NSLock alloc] init];
  41. KTVHCLogDataNetworkSource(@"%p, Create network source\nrequest : %@\nrange : %@", self, self.request, KTVHCStringFromRange(self.range));
  42. }
  43. return self;
  44. }
  45. - (void)dealloc
  46. {
  47. KTVHCLogDealloc(self);
  48. KTVHCLogDataNetworkSource(@"%p, Destory network source\nError : %@\ndownloadLength : %lld\nreadedLength : %lld", self, self.error, self.downloadLength, self.readedLength);
  49. }
  50. - (void)prepare
  51. {
  52. [self lock];
  53. if (self.isClosed) {
  54. [self unlock];
  55. return;
  56. }
  57. if (self.calledPrepare) {
  58. [self unlock];
  59. return;
  60. }
  61. self->_calledPrepare = YES;
  62. KTVHCLogDataNetworkSource(@"%p, Call prepare", self);
  63. self.downlaodTask = [[KTVHCDownload download] downloadWithRequest:self.request delegate:self];
  64. [self unlock];
  65. }
  66. - (void)close
  67. {
  68. [self lock];
  69. if (self.isClosed) {
  70. [self unlock];
  71. return;
  72. }
  73. self->_closed = YES;
  74. KTVHCLogDataNetworkSource(@"%p, Call close", self);
  75. if (!self.downloadCalledComplete) {
  76. KTVHCLogDataNetworkSource(@"%p, Cancel download task", self);
  77. [self.downlaodTask cancel];
  78. self.downlaodTask = nil;
  79. }
  80. [self destoryReadingHandle];
  81. [self destoryWritingHandle];
  82. [self unlock];
  83. }
  84. - (NSData *)readDataOfLength:(NSUInteger)length
  85. {
  86. [self lock];
  87. if (self.isClosed || self.isFinished || self.error) {
  88. [self unlock];
  89. return nil;
  90. }
  91. if (self.readedLength >= self.downloadLength) {
  92. if (self.downloadCalledComplete) {
  93. KTVHCLogDataNetworkSource(@"%p, Read data failed\ndownloadLength : %lld\nreadedLength : %lld", self, self.readedLength, self.downloadLength);
  94. [self destoryReadingHandle];
  95. } else {
  96. KTVHCLogDataNetworkSource(@"%p, Read data wait callback", self);
  97. self.callHasAvailableData = YES;
  98. }
  99. [self unlock];
  100. return nil;
  101. }
  102. NSData *data = nil;
  103. @try {
  104. data = [self.readingHandle readDataOfLength:(NSUInteger)MIN(self.downloadLength - self.readedLength, length)];
  105. self->_readedLength += data.length;
  106. KTVHCLogDataNetworkSource(@"%p, Read data\nLength : %lld\ndownloadLength : %lld\nreadedLength : %lld", self, (long long)data.length, self.readedLength, self.downloadLength);
  107. if (self.readedLength >= self.response.contentLength) {
  108. self->_finished = YES;
  109. KTVHCLogDataNetworkSource(@"%p, Read data did finished", self);
  110. [self destoryReadingHandle];
  111. }
  112. } @catch (NSException *exception) {
  113. KTVHCLogDataFileSource(@"%p, Read exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
  114. NSError *error = [KTVHCError errorForException:exception];
  115. [self callbackForFailed:error];
  116. }
  117. [self unlock];
  118. return data;
  119. }
  120. - (void)setDelegate:(id <KTVHCDataNetworkSourceDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue
  121. {
  122. self->_delegate = delegate;
  123. self->_delegateQueue = delegateQueue;
  124. }
  125. - (void)ktv_download:(KTVHCDownload *)download didCompleteWithError:(NSError *)error
  126. {
  127. [self lock];
  128. self.downloadCalledComplete = YES;
  129. [self destoryWritingHandle];
  130. if (self.isClosed) {
  131. KTVHCLogDataNetworkSource(@"%p, Complete but did closed\nError : %@", self, error);
  132. } else if (self.error) {
  133. KTVHCLogDataNetworkSource(@"%p, Complete but did failed\nself.error : %@\nerror : %@", self, self.error, error);
  134. } else if (error) {
  135. if (error.code != NSURLErrorCancelled) {
  136. [self callbackForFailed:error];
  137. } else {
  138. KTVHCLogDataNetworkSource(@"%p, Complete with cancel\nError : %@", self, error);
  139. }
  140. } else if (self.downloadLength >= self.response.contentLength) {
  141. KTVHCLogDataNetworkSource(@"%p, Complete and finisehed", self);
  142. if ([self.delegate respondsToSelector:@selector(ktv_networkSourceDidFinisheDownload:)]) {
  143. [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
  144. [self.delegate ktv_networkSourceDidFinisheDownload:self];
  145. }];
  146. }
  147. } else {
  148. KTVHCLogDataNetworkSource(@"%p, Complete but not finisehed\ndownloadLength : %lld", self, self.downloadLength);
  149. }
  150. [self unlock];
  151. }
  152. - (void)ktv_download:(KTVHCDownload *)download didReceiveResponse:(KTVHCDataResponse *)response
  153. {
  154. [self lock];
  155. if (self.isClosed || self.error) {
  156. [self unlock];
  157. return;
  158. }
  159. self->_response = response;
  160. NSString *path = [KTVHCPathTool filePathWithURL:self.request.URL offset:self.request.range.start];
  161. self.unitItem = [[KTVHCDataUnitItem alloc] initWithPath:path offset:self.request.range.start];
  162. KTVHCDataUnit *unit = [[KTVHCDataUnitPool pool] unitWithURL:self.request.URL];
  163. [unit insertUnitItem:self.unitItem];
  164. KTVHCLogDataNetworkSource(@"%p, Receive response\nResponse : %@\nUnit : %@\nUnitItem : %@", self, response, unit, self.unitItem);
  165. [unit workingRelease];
  166. self.writingHandle = [NSFileHandle fileHandleForWritingAtPath:self.unitItem.absolutePath];
  167. self.readingHandle = [NSFileHandle fileHandleForReadingAtPath:self.unitItem.absolutePath];
  168. [self callbackForPrepared];
  169. [self unlock];
  170. }
  171. - (void)ktv_download:(KTVHCDownload *)download didReceiveData:(NSData *)data
  172. {
  173. [self lock];
  174. if (self.isClosed || self.error) {
  175. [self unlock];
  176. return;
  177. }
  178. @try {
  179. NSError *error = nil;
  180. if (@available(iOS 13.0, *)) {
  181. [self.writingHandle writeData:data error:&error];
  182. } else {
  183. [self.writingHandle writeData:data];
  184. }
  185. if (error) {
  186. [self callbackForFailed:error];
  187. if (!self.downloadCalledComplete) {
  188. KTVHCLogDataNetworkSource(@"%p, Cancel download task because data could not be written", self);
  189. [self.downlaodTask cancel];
  190. self.downlaodTask = nil;
  191. }
  192. } else {
  193. self.downloadLength += data.length;
  194. [self.unitItem updateLength:self.downloadLength];
  195. KTVHCLogDataNetworkSource(@"%p, Receive data : %lld, %lld, %lld", self, (long long)data.length, self.downloadLength, self.unitItem.length);
  196. [self callbackForHasAvailableData];
  197. }
  198. } @catch (NSException *exception) {
  199. NSError *error = [KTVHCError errorForException:exception];
  200. KTVHCLogDataNetworkSource(@"%p, write exception\nError : %@", self, error);
  201. [self callbackForFailed:error];
  202. if (!self.downloadCalledComplete) {
  203. KTVHCLogDataNetworkSource(@"%p, Cancel download task when write exception", self);
  204. [self.downlaodTask cancel];
  205. self.downlaodTask = nil;
  206. }
  207. }
  208. [self unlock];
  209. }
  210. - (void)destoryReadingHandle
  211. {
  212. if (self.readingHandle) {
  213. @try {
  214. [self.readingHandle closeFile];
  215. } @catch (NSException *exception) {
  216. KTVHCLogDataFileSource(@"%p, Close reading handle exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
  217. }
  218. self.readingHandle = nil;
  219. }
  220. }
  221. - (void)destoryWritingHandle
  222. {
  223. if (self.writingHandle) {
  224. @try {
  225. [self.writingHandle synchronizeFile];
  226. [self.writingHandle closeFile];
  227. } @catch (NSException *exception) {
  228. KTVHCLogDataFileSource(@"%p, Close writing handle exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
  229. }
  230. self.writingHandle = nil;
  231. }
  232. }
  233. - (void)callbackForPrepared
  234. {
  235. if (self.isClosed) {
  236. return;
  237. }
  238. if (self.isPrepared) {
  239. return;
  240. }
  241. self->_prepared = YES;
  242. if ([self.delegate respondsToSelector:@selector(ktv_networkSourceDidPrepare:)]) {
  243. KTVHCLogDataNetworkSource(@"%p, Callback for prepared - Begin", self);
  244. [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
  245. KTVHCLogDataNetworkSource(@"%p, Callback for prepared - End", self);
  246. [self.delegate ktv_networkSourceDidPrepare:self];
  247. }];
  248. }
  249. }
  250. - (void)callbackForHasAvailableData
  251. {
  252. if (self.isClosed) {
  253. return;
  254. }
  255. if (!self.callHasAvailableData) {
  256. return;
  257. }
  258. self.callHasAvailableData = NO;
  259. if ([self.delegate respondsToSelector:@selector(ktv_networkSourceHasAvailableData:)]) {
  260. KTVHCLogDataNetworkSource(@"%p, Callback for has available data - Begin", self);
  261. [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
  262. KTVHCLogDataNetworkSource(@"%p, Callback for has available data - End", self);
  263. [self.delegate ktv_networkSourceHasAvailableData:self];
  264. }];
  265. }
  266. }
  267. - (void)callbackForFailed:(NSError *)error
  268. {
  269. if (self.isClosed || !error || self.error) {
  270. return;
  271. }
  272. self->_error = error;
  273. KTVHCLogDataNetworkSource(@"%p, Callback for failed\nError : %@", self, self.error);
  274. if ([self.delegate respondsToSelector:@selector(ktv_networkSource:didFailWithError:)]) {
  275. [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
  276. [self.delegate ktv_networkSource:self didFailWithError:self.error];
  277. }];
  278. }
  279. }
  280. - (void)lock
  281. {
  282. [self.coreLock lock];
  283. }
  284. - (void)unlock
  285. {
  286. [self.coreLock unlock];
  287. }
  288. @end