PsiphonTunnelController.m 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. //
  2. // PsiphonMobile.m
  3. // PsiphonMobile
  4. //
  5. // Created by eugene-imac on 2016-08-16.
  6. // Copyright © 2016 Psiphon Inc. All rights reserved.
  7. //
  8. #import <Psi/Psi.h>
  9. #import "PsiphonTunnelController.h"
  10. #import "Reachability.h"
  11. @interface PsiphonTunnelController () <GoPsiPsiphonProvider>
  12. @end
  13. @implementation PsiphonTunnelController
  14. +(PsiphonTunnelController *) sharedInstance {
  15. static PsiphonTunnelController *sharedInstance = nil;
  16. static dispatch_once_t onceToken = 0;
  17. dispatch_once(&onceToken, ^{
  18. sharedInstance = [[self alloc] init];
  19. // Do any other initialisation stuff here
  20. });
  21. return sharedInstance;
  22. }
  23. -(void) startTunnel {
  24. [self stopTunnel];
  25. [[self tunneledAppProtocolDelegate] onDiagnosticMessage:@"starting Psiphon library"];
  26. @try {
  27. NSString *configStr = [[self tunneledAppProtocolDelegate] getPsiphonConfig];
  28. NSError *e = nil;
  29. GoPsiStart(
  30. configStr,
  31. @"",
  32. self,
  33. false, // useDeviceBinder
  34. &e);
  35. }
  36. @catch(NSException *exception) {
  37. [[self tunneledAppProtocolDelegate] onDiagnosticMessage:[NSString stringWithFormat: @"failed to start Psiphon library: %@", exception.reason]];
  38. }
  39. [[self tunneledAppProtocolDelegate] onDiagnosticMessage:@"Psiphon library started"];
  40. }
  41. -(void) stopTunnel {
  42. [[self tunneledAppProtocolDelegate] onDiagnosticMessage: @"stopping Psiphon library"];
  43. GoPsiStop();
  44. [[self tunneledAppProtocolDelegate] onDiagnosticMessage: @"Psiphon library stop"];
  45. }
  46. #pragma mark - GoPsiphonProvider protocol implementation
  47. - (NSString*)getPrimaryDnsServer {
  48. return @"8.8.8.8";
  49. }
  50. - (NSString*)getSecondaryDnsServer {
  51. return @"8.8.4.4";
  52. }
  53. - (BOOL)bindToDevice:(long)fileDescriptor error:(NSError**)error {
  54. return TRUE;
  55. }
  56. - (NSString*)getDnsServer {
  57. //This method is used only in VPN mode
  58. return @"";
  59. }
  60. - (long)hasNetworkConnectivity {
  61. Reachability *reachability = [Reachability reachabilityForInternetConnection];
  62. NetworkStatus netstat = [reachability currentReachabilityStatus];
  63. return (int) netstat != NotReachable;
  64. }
  65. - (void)notice:(NSString*)noticeJSON {
  66. NSData *noticeData = [noticeJSON dataUsingEncoding:NSUTF8StringEncoding];
  67. NSError *error = nil;
  68. BOOL diagnostic = TRUE;
  69. NSDictionary *notice = [NSJSONSerialization JSONObjectWithData:noticeData options:kNilOptions error:&error];
  70. if(error) {
  71. // TODO: handle JSON error
  72. }
  73. else {
  74. NSString *noticeType = [notice valueForKey:@"noticeType"];
  75. if ([noticeType isEqualToString:@"Tunnels"]) {
  76. NSInteger count = [[[notice valueForKey: @"data"] valueForKey:@"count"] integerValue];
  77. if (count > 0) {
  78. [self.tunneledAppProtocolDelegate onConnected];
  79. } else {
  80. [self.tunneledAppProtocolDelegate onConnecting];
  81. }
  82. } else if ([noticeType isEqualToString:@"AvailableEgressRegions"]) {
  83. NSArray *regions = [[notice valueForKey: @"data"] valueForKey:@"regions"];
  84. [self.tunneledAppProtocolDelegate onAvailableEgressRegions:regions];
  85. } else if ([noticeType isEqualToString:@"SocksProxyPortInUse"]) {
  86. NSInteger port = [(NSNumber*)[[notice valueForKey: @"data"] valueForKey:@"port"] integerValue];
  87. [self.tunneledAppProtocolDelegate onSocksProxyPortInUse:port];
  88. } else if ([noticeType isEqualToString:@"HttpProxyPortInUse"]) {
  89. NSInteger port = [(NSNumber*)[[notice valueForKey: @"data"] valueForKey:@"port"] integerValue];
  90. [self.tunneledAppProtocolDelegate onHttpProxyPortInUse:port];
  91. } else if ([noticeType isEqualToString:@"ListeningSocksProxyPort"]) {
  92. NSInteger port = [(NSNumber*)[[notice valueForKey: @"data"] valueForKey:@"port"] integerValue];
  93. [self.tunneledAppProtocolDelegate onListeningSocksProxyPort:port];
  94. } else if ([noticeType isEqualToString:@"ListeningHttpProxyPort"]) {
  95. NSInteger port = [(NSNumber*)[[notice valueForKey: @"data"] valueForKey:@"port"] integerValue];
  96. [self.tunneledAppProtocolDelegate onListeningHttpProxyPort:port];
  97. } else if ([noticeType isEqualToString:@"UpstreamProxyError"]) {
  98. [self.tunneledAppProtocolDelegate onUpstreamProxyError:[[notice valueForKey: @"data"] valueForKey:@"message"]];
  99. } else if ([noticeType isEqualToString:@"ClientUpgradeDownloaded"]) {
  100. [self.tunneledAppProtocolDelegate onClientUpgradeDownloaded:[[notice valueForKey: @"data"] valueForKey:@"filename"]];
  101. } else if ([noticeType isEqualToString:@"Homepage"]) {
  102. [self.tunneledAppProtocolDelegate onHomepage:[[notice valueForKey: @"data"] valueForKey:@"url"]];
  103. } else if ([noticeType isEqualToString:@"ClientRegion"]) {
  104. [self.tunneledAppProtocolDelegate onClientRegion:[[notice valueForKey: @"data"] valueForKey:@"region"]];
  105. } else if ([noticeType isEqualToString:@"UntunneledAddress"]) {
  106. [self.tunneledAppProtocolDelegate onUntunneledAddress :[[notice valueForKey: @"data"] valueForKey:@"address"]];
  107. } else if ([noticeType isEqualToString:@"BytesTransferred"]) {
  108. diagnostic = FALSE;
  109. NSDictionary *bytes = [notice valueForKey: @"data"];
  110. [self.tunneledAppProtocolDelegate onBytesTransferred:[bytes[@"received"] longValue]:[bytes[@"sent"] longValue]];
  111. }
  112. if (diagnostic) {
  113. NSData *diagnosticData = [NSJSONSerialization dataWithJSONObject:[notice valueForKey: @"data"] options:kNilOptions error:&error];
  114. if (error == nil){
  115. NSString *diagnosticStr = [[NSString alloc] initWithData:diagnosticData encoding:NSUTF8StringEncoding];
  116. NSString *diagnosticMessage = [NSString stringWithFormat:@"%@: %@", noticeType, diagnosticStr];
  117. [self. tunneledAppProtocolDelegate onDiagnosticMessage : diagnosticMessage];
  118. }
  119. }
  120. }
  121. }
  122. @end
  123. @implementation Psi
  124. + (void)sendFeedback:(NSString*)configJson diagnostics: (NSString*)diagnosticsJson b64EncodedPublicKey: (NSString*) b64EncodedPublicKey uploadServer: (NSString*)uploadServer uploadPath: (NSString*) uploadPath uploadServerHeaders: (NSString*)uploadServerHeaders {
  125. GoPsiSendFeedback(configJson, diagnosticsJson, b64EncodedPublicKey, uploadServer, uploadPath, uploadServerHeaders);
  126. }
  127. @end