github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/PsiphonTunnel.h (about)

     1  //
     2  //  PsiphonTunnel.h
     3  //  PsiphonTunnel
     4  //
     5  
     6  /*
     7   * Copyright (c) 2016, Psiphon Inc.
     8   * All rights reserved.
     9   *
    10   * This program is free software: you can redistribute it and/or modify
    11   * it under the terms of the GNU General Public License as published by
    12   * the Free Software Foundation, either version 3 of the License, or
    13   * (at your option) any later version.
    14   *
    15   * This program is distributed in the hope that it will be useful,
    16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    18   * GNU General Public License for more details.
    19   *
    20   * You should have received a copy of the GNU General Public License
    21   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    22   *
    23   */
    24  
    25  #import "Reachability.h"
    26  #import "DefaultRouteMonitor.h"
    27  #import "ReachabilityProtocol.h"
    28  #import "JailbreakCheck.h"
    29  #import "PsiphonClientPlatform.h"
    30  
    31  //! Project version number for PsiphonTunnel.
    32  FOUNDATION_EXPORT double PsiphonTunnelVersionNumber;
    33  
    34  //! Project version string for PsiphonTunnel.
    35  FOUNDATION_EXPORT const unsigned char PsiphonTunnelVersionString[];
    36  
    37  
    38  /*!
    39   The set of possible connection states the tunnel can be in.
    40   */
    41  typedef NS_ENUM(NSInteger, PsiphonConnectionState)
    42  {
    43      PsiphonConnectionStateDisconnected = 0,
    44      PsiphonConnectionStateConnecting,
    45      PsiphonConnectionStateConnected,
    46      PsiphonConnectionStateWaitingForNetwork
    47  };
    48  
    49  /*!
    50   @protocol PsiphonTunnelLoggerDelegate
    51   Used to communicate diagnostic logs to the application that is using the PsiphonTunnel framework.
    52   */
    53  @protocol PsiphonTunnelLoggerDelegate <NSObject>
    54  
    55  @optional
    56  
    57  /*!
    58   Gets runtime errors info that may be useful for debugging.
    59   @param message  The diagnostic message string.
    60   @param timestamp RFC3339 encoded timestamp.
    61   */
    62  - (void)onDiagnosticMessage:(NSString * _Nonnull)message withTimestamp:(NSString * _Nonnull)timestamp;
    63  
    64  @end
    65  
    66  /*!
    67   @protocol TunneledAppDelegate
    68   Used to communicate with the application that is using the PsiphonTunnel framework,
    69   and retrieve config info from it.
    70  
    71   All delegate methods will be called on a single serial dispatch queue. They will be made asynchronously unless otherwise noted (specifically when calling getPsiphonConfig and getEmbeddedServerEntries).
    72   */
    73  @protocol TunneledAppDelegate <NSObject, PsiphonTunnelLoggerDelegate>
    74  
    75  //
    76  // Required delegate methods
    77  //
    78  @required
    79  
    80  /*!
    81   Called when tunnel is starting to get the library consumer's desired configuration.
    82  
    83   @code
    84   Required fields:
    85   - `PropagationChannelId`
    86   - `SponsorId`
    87   - Remote server list functionality is not strictly required, but absence greatly undermines circumvention ability.
    88     - `RemoteServerListURLs`
    89     - `RemoteServerListSignaturePublicKey`
    90   - Obfuscated server list functionality is also not strictly required, but aids circumvention ability.
    91     - `ObfuscatedServerListRootURLs`
    92     - `RemoteServerListSignaturePublicKey`: This is the same field as above. It is required if either `RemoteServerListURLs` or `ObfuscatedServerListRootURLs` is supplied.
    93  
    94   Optional fields (if you don't need them, don't set them):
    95   - `DataStoreDirectory`: If not set, the library will use a sane location. Override if the client wants to restrict where operational data is kept. If overridden, the directory must already exist and be writable.
    96   - `RemoteServerListDownloadFilename`: If not set, the library will use a sane location. Override if the client wants to restrict where operational data is kept.
    97   - `ObfuscatedServerListDownloadDirectory`: If not set, the library will use a sane location. Override if the client wants to restrict where operational data is kept. If overridden, the directory must already exist and be writable.
    98   - `UpstreamProxyUrl`
    99   - `EmitDiagnosticNotices`
   100   - `EgressRegion`
   101   - `EstablishTunnelTimeoutSeconds`
   102   - Only set if disabling timeouts (for very slow network connections):
   103     - `TunnelConnectTimeoutSeconds`
   104     - `TunnelPortForwardDialTimeoutSeconds`
   105     - `TunnelSshKeepAliveProbeTimeoutSeconds`
   106     - `TunnelSshKeepAlivePeriodicTimeoutSeconds`
   107     - `FetchRemoteServerListTimeoutSeconds`
   108     - `PsiphonApiServerTimeoutSeconds`
   109     - `FetchRoutesTimeoutSeconds`
   110     - `HttpProxyOriginServerTimeoutSeconds`
   111   - Fields which should only be set by Psiphon proper:
   112     - `LocalHttpProxyPort`
   113     - `LocalSocksProxyPort`
   114   @endcode
   115  
   116   @note All other config fields must not be set.
   117  
   118   See the tunnel-core config code for details about the fields.
   119   https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/psiphon/config.go
   120  
   121   @return Either JSON NSString with config that should be used to run the Psiphon tunnel,
   122           or return already parsed JSON as NSDictionary,
   123           or nil on error.
   124   */
   125  - (id _Nullable)getPsiphonConfig;
   126  
   127  //
   128  // Optional delegate methods. Note that some of these are probably necessary for
   129  // for a functioning app to implement, for example `onConnected`.
   130  //
   131  @optional
   132  
   133  /*!
   134   Called when the tunnel is starting to get the initial server entries (typically embedded in the app) that will be used to bootstrap the Psiphon tunnel connection. This value is in a particular format and will be supplied by Psiphon Inc.
   135   If getEmbeddedServerEntriesPath is also implemented, it will take precedence over this method, unless getEmbeddedServerEntriesPath returns NULL or an empty string.
   136   @return  Pre-existing server entries to use when attempting to connect to a server. Must return an empty string if there are no embedded server entries. Must return NULL if there is an error and the tunnel starting should abort.
   137   */
   138  - (NSString * _Nullable)getEmbeddedServerEntries;
   139  
   140  /*!
   141    Called when the tunnel is starting to get the initial server entries (typically embedded in the app) that will be used to bootstrap the Psiphon tunnel connection. This value is in a particular format and will be supplied by Psiphon Inc.
   142    If this method is implemented, it takes precedence over getEmbeddedServerEntries, and getEmbeddedServerEntries will not be called unless this method returns NULL or an empty string.
   143    @return Optional path where embedded server entries file is located. This file should be readable by the library.
   144   */
   145  - (NSString * _Nullable)getEmbeddedServerEntriesPath;
   146  
   147  /*!
   148   Called when the tunnel is in the process of connecting.
   149   */
   150  - (void)onConnecting;
   151  /*!
   152   Called when the tunnel has successfully connected.
   153   */
   154  - (void)onConnected;
   155  
   156  /*!
   157   Called when the tunnel notices that the device has no network connectivity and
   158   begins waiting to regain it. When connecitvity is regained, `onConnecting`
   159   will be called.
   160   */
   161  - (void)onStartedWaitingForNetworkConnectivity;
   162  
   163  /*!
   164   Called when the tunnel's connection state changes.
   165   Note that this will be called _in addition to, but before_ `onConnecting`, etc.
   166   Also note that this will not be called for the initial disconnected state
   167   (since it didn't change from anything).
   168   @param oldState  The previous connection state.
   169   @param newState  The new connection state.
   170   */
   171  - (void)onConnectionStateChangedFrom:(PsiphonConnectionState)oldState to:(PsiphonConnectionState)newState;
   172  
   173  /*!
   174   Called to indicate that tunnel-core is exiting imminently (usually due to
   175   a `stop()` call, but could be due to an unexpected error).
   176   onExiting may be called before or after `stop()` returns.
   177   */
   178  - (void)onExiting;
   179  
   180  /*!
   181  Called when the device's Internet connection state has changed.
   182  This may mean that it had connectivity and now doesn't, or went from Wi-Fi to
   183  WWAN or vice versa or VPN state changed
   184  */
   185  - (void)onInternetReachabilityChanged:(NetworkReachability)currentReachability;
   186  
   187  /*!
   188   Called when tunnel-core determines which server egress regions are available
   189   for use. This can be used for updating the UI which provides the options to
   190   the user.
   191   @param regions  A string array containing the available egress region country codes.
   192   */
   193  - (void)onAvailableEgressRegions:(NSArray * _Nonnull)regions;
   194  
   195  /*!
   196   If the tunnel is started with a fixed SOCKS proxy port, and that port is
   197   already in use, this will be called.
   198   @param port  The port number.
   199   */
   200  - (void)onSocksProxyPortInUse:(NSInteger)port;
   201  /*!
   202   If the tunnel is started with a fixed HTTP proxy port, and that port is
   203   already in use, this will be called.
   204   @param port  The port number.
   205   */
   206  - (void)onHttpProxyPortInUse:(NSInteger)port;
   207  
   208  /*!
   209   Called when tunnel-core determines what port will be used for the local SOCKS proxy.
   210   @param port  The port number.
   211   */
   212  - (void)onListeningSocksProxyPort:(NSInteger)port;
   213  /*!
   214   Called when tunnel-core determines what port will be used for the local HTTP proxy.
   215   @param port  The port number.
   216   */
   217  - (void)onListeningHttpProxyPort:(NSInteger)port;
   218  
   219  /*!
   220   Called when a error occurs when trying to utilize a configured upstream proxy.
   221   @param message  A message giving additional info about the error.
   222   */
   223  - (void)onUpstreamProxyError:(NSString * _Nonnull)message;
   224  
   225  /*!
   226   Called after the handshake with the Psiphon server, with the client region as determined by the server.
   227   @param region  The country code of the client, as determined by the server.
   228   */
   229  - (void)onClientRegion:(NSString * _Nonnull)region;
   230  
   231  /*!
   232   Called after the handshake with the Psiphon server, with the client address as seen by the server.
   233   @param address  The Internet address of the client, IP:port, as seen by the server.
   234   */
   235  - (void)onClientAddress:(NSString * _Nonnull)address;
   236  
   237  /*!
   238   Called to report that split tunnel is on for the given regions.
   239   @param regions  The regions split tunnel is on for.
   240   */
   241  - (void)onSplitTunnelRegions:(NSArray * _Nonnull)regions;
   242  
   243  /*!
   244   Called to indicate that an address has been classified as being within the
   245   split tunnel region and therefore is being access directly rather than tunneled.
   246   Note: `address` should remain private; this notice should be used for alerting
   247   users, not for diagnotics logs.
   248   @param address  The IP or hostname that is not being tunneled.
   249   */
   250  - (void)onUntunneledAddress:(NSString * _Nonnull)address;
   251  
   252  /*!
   253   Called to report how many bytes have been transferred since the last time
   254   this function was called.
   255   By default onBytesTransferred is disabled. Enable it by setting
   256   EmitBytesTransferred to true in the Psiphon config.
   257   @param sent  The number of bytes sent.
   258   @param received  The number of bytes received.
   259   */
   260  - (void)onBytesTransferred:(int64_t)sent :(int64_t)received;
   261  
   262  /*!
   263   Called when tunnel-core discovers a home page associated with this client.
   264   If there are no home pages, it will not be called. May be called more than
   265   once, for multiple home pages.
   266   Note: This is probably only applicable to Psiphon Inc.'s apps.
   267   @param url  The URL of the home page.
   268   */
   269  - (void)onHomepage:(NSString * _Nonnull)url;
   270  
   271  /*!
   272   Called when tunnel-core receives server timetamp in the handshake
   273   @param timestamp  The server timestamp in RFC3339 format.
   274   */
   275  - (void)onServerTimestamp:(NSString * _Nonnull)timestamp;
   276  
   277  /*!
   278   Called when tunnel-core receives an array of active authorization IDs in the handshake
   279   @param authorizations  A string array containing active authorization IDs.
   280   */
   281  - (void)onActiveAuthorizationIDs:(NSArray * _Nonnull)authorizations;
   282  
   283  /*!
   284   Called when tunnel-core receives traffic rate limit information in the handshake
   285   @param upstreamBytesPerSecond  upstream rate limit; 0 for no limit
   286   @param downstreamBytesPerSecond  downstream rate limit; 0 for no limit
   287   */
   288  - (void)onTrafficRateLimits:(int64_t)upstreamBytesPerSecond :(int64_t)downstreamBytesPerSecond;
   289  
   290  /*!
   291   Called when tunnel-core receives an alert from the server.
   292   @param reason The reason for the alert.
   293   @param subject Additional context or classification of the reason; blank for none.
   294   */
   295  - (void)onServerAlert:(NSString * _Nonnull)reason :(NSString * _Nonnull)subject :(NSArray * _Nonnull)actionURLs;
   296  
   297  @end
   298  
   299  /*!
   300   The interface for managing the Psiphon tunnel -- set up, tear down, receive info about.
   301   */
   302  @interface PsiphonTunnel : NSObject
   303  
   304  /*!
   305   Returns an instance of PsiphonTunnel. This is either a new instance or the pre-existing singleton. If an instance already exists, it will be stopped when this function is called.
   306   @param tunneledAppDelegate  The delegate implementation to use for callbacks.
   307   @return  The PsiphonTunnel instance.
   308   */
   309  + (PsiphonTunnel * _Nonnull)newPsiphonTunnel:(id<TunneledAppDelegate> _Nonnull)tunneledAppDelegate;
   310  
   311  /*!
   312  Returns the default data root directory that is used by PsiphonTunnel if DataRootDirectory is not specified in the config returned by
   313  getPsiphonConfig.
   314  @param err Any error encountered while obtaining the default data root directory. If set, the return value should be ignored.
   315  @return  The default data root directory used by PsiphonTunnel.
   316  */
   317  + (NSURL * _Nullable)defaultDataRootDirectoryWithError:(NSError * _Nullable * _Nonnull)err;
   318  
   319  /*!
   320  Returns the path where the homepage notices file will be created.
   321  @note    This file will only be created if UseNoticeFiles is set in the config returned by `getPsiphonConfig`.
   322  @param dataRootDirectory the configured data root directory. If DataRootDirectory is not specified in the config returned by
   323  getPsiphonConfig, then use `defaultDataRootDirectory`.
   324  @return  The file path at which the homepage file will be created.
   325  */
   326  + (NSURL * _Nullable)homepageFilePath:(NSURL * _Nonnull)dataRootDirectory;
   327  
   328  /*!
   329  Returns the path where the notices file will be created. When the file is rotated it will be moved to `oldNoticesFilePath`.
   330  @note    This file will only be created if UseNoticeFiles is set in the config returned by `getPsiphonConfig`.
   331  @param dataRootDirectory the configured data root directory. If DataRootDirectory is not specified in the config returned by
   332  `getPsiphonConfig`, then use `defaultDataRootDirectory`.
   333  @return  The file path at which the notices file will be created.
   334  */
   335  + (NSURL * _Nullable)noticesFilePath:(NSURL * _Nonnull)dataRootDirectory;
   336  
   337  /*!
   338  Returns the path where the rotated notices file will be created.
   339  @note    This file will only be created if UseNoticeFiles is set in the config returned by `getPsiphonConfig`.
   340  @param dataRootDirectory the configured data root directory. If DataRootDirectory is not specified in the config returned by
   341  `getPsiphonConfig`, then use `defaultDataRootDirectory`.
   342  @return  The file path at which the rotated notices file can be found once rotated.
   343  */
   344  + (NSURL * _Nullable)olderNoticesFilePath:(NSURL * _Nonnull)dataRootDirectory;
   345  
   346  /*!
   347   Start connecting the PsiphonTunnel. Returns before connection is complete -- delegate callbacks (such as `onConnected` and `onConnectionStateChanged`) are used to indicate progress and state.
   348   @param ifNeeded  If TRUE, the tunnel will only be started if it's not already connected and healthy. If FALSE, the tunnel will be forced to stop and reconnect.
   349   @return TRUE if the connection start was successful, FALSE otherwise.
   350   */
   351  - (BOOL)start:(BOOL)ifNeeded;
   352  
   353  /*!
   354   Reconnect a previously started PsiphonTunnel with the specified config changes.
   355   reconnectWithConfig has no effect if there is no running PsiphonTunnel.
   356   */
   357  - (void)reconnectWithConfig:(NSString * _Nullable) newSponsorID :(NSArray<NSString *> *_Nullable)newAuthorizations;
   358  
   359  /*!
   360   Force stops the tunnel and reconnects with the current session ID.
   361   Retuns with FALSE immediately if no session ID has already been generated.
   362  
   363   @note On the first connection `start:` method should always be used to generate a
   364   session ID.
   365  
   366   @return TRUE if the connection start was successful, FALSE otherwise.
   367   */
   368  - (BOOL)stopAndReconnectWithCurrentSessionID;
   369  
   370  /*!
   371   Stop the tunnel (regardless of its current connection state).
   372   */
   373  - (void)stop;
   374  
   375  /*!
   376   Returns the current tunnel connection state.
   377   @return  The current connection state.
   378   */
   379  - (PsiphonConnectionState)getConnectionState;
   380  
   381  /*!
   382   Returns the current network reachability status, if Psiphon tunnel is not in a
   383   disconnected state.
   384   @return The current reachability status.
   385   */
   386  - (BOOL)getNetworkReachabilityStatus:(NetworkReachability * _Nonnull)status;
   387  
   388  /*!
   389   Provides the port number of the local SOCKS proxy. Only valid when currently connected (will return 0 otherwise).
   390   @return  The current local SOCKS proxy port number.
   391   */
   392  - (NSInteger)getLocalSocksProxyPort;
   393  
   394  /*!
   395   Provides the port number of the local HTTP proxy. Only valid when currently connected (will return 0 otherwise).
   396   @return  The current local HTTP proxy port number.
   397   */
   398  - (NSInteger)getLocalHttpProxyPort;
   399  
   400  /*!
   401   Only valid in whole device mode. Provides the MTU the packet tunnel requires the device to use.
   402   @return  The MTU size.
   403   */
   404  - (long)getPacketTunnelMTU;
   405  
   406  /*!
   407   Only valid in whole device mode. Provides the DNS resolver IP address that is provided by the packet tunnel to the device.
   408    @return  The IP address of the DNS resolver as a string.
   409   */
   410  - (NSString * _Nonnull)getPacketTunnelDNSResolverIPv4Address;
   411  
   412  /*!
   413   Only valid in whole device mode. Provides the DNS resolver IP address that is provided by the packet tunnel to the device.
   414   @return  The IP address of the DNS resolver as a string.
   415   */
   416  - (NSString * _Nonnull)getPacketTunnelDNSResolverIPv6Address;
   417  
   418  /*!
   419   Provides the tunnel-core build info json as a string. See the tunnel-core build info code for details https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/master/psiphon/common/buildinfo.go.
   420   @return  The build info json as a string.
   421   */
   422  + (NSString * _Nonnull)getBuildInfo;
   423  
   424  #pragma mark - Profiling utitlities
   425  
   426  /*!
   427   Writes Go runtime profile information to a set of files in the specifiec output directory.
   428   @param cpuSampleDurationSeconds determines how to long to wait and sample profiles that require active sampling. When set to 0, these profiles are skipped.
   429   @param blockSampleDurationSeconds determines how to long to wait and sample profiles that require active sampling. When set to 0, these profiles are skipped.
   430   */
   431  - (void)writeRuntimeProfilesTo:(NSString * _Nonnull)outputDirectory withCPUSampleDurationSeconds:(int)cpuSampleDurationSeconds withBlockSampleDurationSeconds:(int)blockSampleDurationSeconds;
   432  
   433   @end
   434  
   435  /*!
   436   @protocol PsiphonTunnelFeedbackDelegate
   437   Used to communicate the outcome of feedback upload operations to the application using the PsiphonTunnel framework.
   438   */
   439  @protocol PsiphonTunnelFeedbackDelegate <NSObject>
   440  
   441  /// Called once the feedback upload has completed.
   442  /// @param err If non-nil, then the upload failed.
   443  - (void)sendFeedbackCompleted:(NSError * _Nullable)err;
   444  
   445  @end
   446  
   447  /*!
   448   The interface for managing the Psiphon tunnel feedback upload operations.
   449   @warning Should not be used in the same process as PsiphonTunnel.
   450   @warning Only a single instance of PsiphonTunnelFeedback should be used at a time. Using multiple instances in parallel, or
   451   concurrently, will result in undefined behavior.
   452   */
   453  @interface PsiphonTunnelFeedback : NSObject
   454  
   455  /*!
   456   Upload a feedback package to Psiphon Inc. The app collects feedback and diagnostics information in a particular format and then calls this
   457   function to upload it for later investigation. This call is asynchronous and returns before the upload completes. The operation has
   458   completed when `sendFeedbackCompleted:` is called on the provided `PsiphonTunnelFeedbackDelegate`.
   459   @param feedbackJson The feedback data to upload.
   460   @param feedbackConfigJson The feedback compatible config. Must be an NSDictionary or NSString. Config must be provided by
   461   Psiphon Inc.
   462   @param uploadPath The path at which to upload the diagnostic data. Must be provided by Psiphon Inc.
   463   @param loggerDelegate Optional delegate which will be called to log informational notices, including warnings. Stored as a weak
   464   reference; the caller is responsible for holding a strong reference.
   465   @param feedbackDelegate Delegate which `sendFeedbackCompleted(error)` is called on once when the operation completes; if
   466   error is non-nil, then the operation failed. Stored as a weak reference; the caller is responsible for holding a strong reference.
   467   @warning Only one active upload is supported at a time. An ongoing upload will be cancelled if this function is called again before it
   468   completes.
   469   @warning An ongoing feedback upload started with `startSendFeedback:` should be stopped with `stopSendFeedback` before the
   470   process exits. This ensures that any underlying resources are cleaned up; failing to do so may result in data store corruption or other
   471   undefined behavior.
   472   @warning `PsiphonTunnel.start:` and `startSendFeedback:`  both make an attempt to migrate persistent files from legacy locations in a
   473   one-time operation. If these functions are called in parallel, then there is a chance that the migration attempts could execute at the same
   474   time and result in non-fatal errors in one, or both, of the migration operations.
   475   */
   476  - (void)startSendFeedback:(NSString * _Nonnull)feedbackJson
   477         feedbackConfigJson:(id _Nonnull)feedbackConfigJson
   478                 uploadPath:(NSString * _Nonnull)uploadPath
   479             loggerDelegate:(id<PsiphonTunnelLoggerDelegate> _Nullable)loggerDelegate
   480           feedbackDelegate:(id<PsiphonTunnelFeedbackDelegate> _Nonnull)feedbackDelegate;
   481  
   482  /*!
   483   Interrupt an in-progress feedback upload operation started with `startSendFeedback:`. This call is synchronous and returns once the
   484   upload has been cancelled.
   485   */
   486  - (void)stopSendFeedback;
   487  
   488  @end