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