QNConnectChecker.m 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // QNConnectChecker.m
  3. // QiniuSDK_Mac
  4. //
  5. // Created by yangsen on 2021/1/8.
  6. // Copyright © 2021 Qiniu. All rights reserved.
  7. //
  8. #import "QNDefine.h"
  9. #import "QNLogUtil.h"
  10. #import "QNConfiguration.h"
  11. #import "QNSingleFlight.h"
  12. #import "QNConnectChecker.h"
  13. #import "QNUploadSystemClient.h"
  14. @interface QNConnectChecker()
  15. @end
  16. @implementation QNConnectChecker
  17. + (QNSingleFlight *)singleFlight {
  18. static QNSingleFlight *singleFlight = nil;
  19. static dispatch_once_t onceToken;
  20. dispatch_once(&onceToken, ^{
  21. singleFlight = [[QNSingleFlight alloc] init];
  22. });
  23. return singleFlight;
  24. }
  25. + (BOOL)check {
  26. __block BOOL isConnected = false;
  27. dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  28. [self check:^(BOOL isConnectedP) {
  29. isConnected = isConnectedP;
  30. dispatch_semaphore_signal(semaphore);
  31. }];
  32. dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
  33. return isConnected;
  34. }
  35. + (void)check:(void (^)(BOOL isConnected))complete {
  36. QNSingleFlight *singleFlight = [self singleFlight];
  37. kQNWeakSelf;
  38. [singleFlight perform:@"connect_check" action:^(QNSingleFlightComplete _Nonnull singleFlightComplete) {
  39. kQNStrongSelf;
  40. [self checkAllHosts:^(BOOL isConnected) {
  41. singleFlightComplete(@(isConnected), nil);
  42. }];
  43. } complete:^(id _Nullable value, NSError * _Nullable error) {
  44. if (complete) {
  45. complete([(NSNumber *)value boolValue]);
  46. }
  47. }];
  48. }
  49. + (void)checkAllHosts:(void (^)(BOOL isConnected))complete {
  50. __block int completeCount = 0;
  51. __block BOOL isCompleted = false;
  52. __block BOOL isConnected = false;
  53. kQNWeakSelf;
  54. NSArray *allHosts = [kQNGlobalConfiguration.connectCheckURLStrings copy];
  55. for (NSString *host in allHosts) {
  56. [self checkHost:host complete:^(BOOL isHostConnected) {
  57. kQNStrongSelf;
  58. @synchronized (self) {
  59. completeCount += 1;
  60. }
  61. if (isHostConnected) {
  62. isConnected = YES;
  63. }
  64. if (isHostConnected || completeCount == allHosts.count) {
  65. @synchronized (self) {
  66. if (isCompleted) {
  67. QNLogInfo(@"== check all hosts has completed totalCount:%d completeCount:%d", allHosts.count, completeCount);
  68. return;
  69. } else {
  70. QNLogInfo(@"== check all hosts completed totalCount:%d completeCount:%d", allHosts.count, completeCount);
  71. isCompleted = true;
  72. }
  73. }
  74. complete(isConnected);
  75. } else {
  76. QNLogInfo(@"== check all hosts not completed totalCount:%d completeCount:%d", allHosts.count, completeCount);
  77. }
  78. }];
  79. }
  80. }
  81. + (void)checkHost:(NSString *)host complete:(void (^)(BOOL isConnected))complete {
  82. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  83. request.URL = [NSURL URLWithString:host];
  84. request.HTTPMethod = @"HEAD";
  85. request.timeoutInterval = kQNGlobalConfiguration.connectCheckTimeout;
  86. QNUploadSystemClient *client = [[QNUploadSystemClient alloc] init];
  87. [client request:request connectionProxy:nil progress:nil complete:^(NSURLResponse * response, QNUploadSingleRequestMetrics * metrics, NSData * _Nullable data, NSError * error) {
  88. if (response && [(NSHTTPURLResponse *)response statusCode] > 99) {
  89. QNLogInfo(@"== checkHost:%@ result: true", host);
  90. complete(true);
  91. } else {
  92. QNLogInfo(@"== checkHost:%@ result: false", host);
  93. complete(false);
  94. }
  95. }];
  96. }
  97. @end