Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

tor integration

  • Loading branch information...
commit c16bc346084d825bfe55583d3ef6817aaf343610 1 parent a55dfbc
@mtigas mtigas authored
View
52 OnionBrowser/OnionBrowser.xcodeproj/project.pbxproj
@@ -13,6 +13,11 @@
696EBD8214F7877900B81BC9 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 696EBD8014F7877900B81BC9 /* InfoPlist.strings */; };
696EBD8414F7877900B81BC9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 696EBD8314F7877900B81BC9 /* main.m */; };
696EBD8814F7877900B81BC9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 696EBD8714F7877900B81BC9 /* AppDelegate.m */; };
+ 696F9EAB14F8D5A900BC5FDC /* TorWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 696F9EA914F8D51300BC5FDC /* TorWrapper.m */; };
+ 696F9EAE14F8D6ED00BC5FDC /* tor_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 696F9EAD14F8D6ED00BC5FDC /* tor_main.c */; };
+ 696F9EB014F8DA6900BC5FDC /* torrc in Resources */ = {isa = PBXBuildFile; fileRef = 696F9EAF14F8DA6900BC5FDC /* torrc */; };
+ 696F9EB414F8DD6D00BC5FDC /* ULINetSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 696F9EB314F8DD6D00BC5FDC /* ULINetSocket.m */; };
+ 696F9EB614F8E21200BC5FDC /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696F9EB514F8E21200BC5FDC /* CFNetwork.framework */; };
69847C4714F788E100288277 /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 69847C3C14F788E100288277 /* libcrypto.a */; };
69847C4814F788E100288277 /* libevent_core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 69847C3D14F788E100288277 /* libevent_core.a */; };
69847C4914F788E100288277 /* libevent_extra.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 69847C3E14F788E100288277 /* libevent_extra.a */; };
@@ -38,6 +43,13 @@
696EBD8514F7877900B81BC9 /* OnionBrowser-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OnionBrowser-Prefix.pch"; sourceTree = "<group>"; };
696EBD8614F7877900B81BC9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
696EBD8714F7877900B81BC9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+ 696F9EA814F8D51300BC5FDC /* TorWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TorWrapper.h; sourceTree = "<group>"; };
+ 696F9EA914F8D51300BC5FDC /* TorWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TorWrapper.m; sourceTree = "<group>"; };
+ 696F9EAD14F8D6ED00BC5FDC /* tor_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tor_main.c; sourceTree = "<group>"; };
+ 696F9EAF14F8DA6900BC5FDC /* torrc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = torrc; sourceTree = "<group>"; };
+ 696F9EB214F8DD6D00BC5FDC /* ULINetSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ULINetSocket.h; sourceTree = "<group>"; };
+ 696F9EB314F8DD6D00BC5FDC /* ULINetSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ULINetSocket.m; sourceTree = "<group>"; };
+ 696F9EB514F8E21200BC5FDC /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
69847C3C14F788E100288277 /* libcrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcrypto.a; path = ../dependencies/lib/libcrypto.a; sourceTree = "<group>"; };
69847C3D14F788E100288277 /* libevent_core.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libevent_core.a; path = ../dependencies/lib/libevent_core.a; sourceTree = "<group>"; };
69847C3E14F788E100288277 /* libevent_extra.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libevent_extra.a; path = ../dependencies/lib/libevent_extra.a; sourceTree = "<group>"; };
@@ -60,6 +72,7 @@
696EBD7814F7877900B81BC9 /* UIKit.framework in Frameworks */,
696EBD7A14F7877900B81BC9 /* Foundation.framework in Frameworks */,
696EBD7C14F7877900B81BC9 /* CoreGraphics.framework in Frameworks */,
+ 696F9EB614F8E21200BC5FDC /* CFNetwork.framework in Frameworks */,
69847C5414F788E900288277 /* libz.dylib in Frameworks */,
69847C4714F788E100288277 /* libcrypto.a in Frameworks */,
69847C4814F788E100288277 /* libevent_core.a in Frameworks */,
@@ -81,6 +94,8 @@
696EBD6814F7877900B81BC9 = {
isa = PBXGroup;
children = (
+ 696F9EB114F8DD5300BC5FDC /* ThirdParty */,
+ 69BB0A4C14F8D31800E7E909 /* Tor */,
696EBD7D14F7877900B81BC9 /* OnionBrowser */,
696EBD7614F7877900B81BC9 /* Frameworks */,
696EBD7414F7877900B81BC9 /* Products */,
@@ -103,6 +118,7 @@
696EBD7714F7877900B81BC9 /* UIKit.framework */,
696EBD7914F7877900B81BC9 /* Foundation.framework */,
696EBD7B14F7877900B81BC9 /* CoreGraphics.framework */,
+ 696F9EB514F8E21200BC5FDC /* CFNetwork.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -128,6 +144,15 @@
name = "Supporting Files";
sourceTree = "<group>";
};
+ 696F9EB114F8DD5300BC5FDC /* ThirdParty */ = {
+ isa = PBXGroup;
+ children = (
+ 696F9EB214F8DD6D00BC5FDC /* ULINetSocket.h */,
+ 696F9EB314F8DD6D00BC5FDC /* ULINetSocket.m */,
+ );
+ name = ThirdParty;
+ sourceTree = "<group>";
+ };
69847C5514F788F600288277 /* Dependencies */ = {
isa = PBXGroup;
children = (
@@ -146,6 +171,17 @@
name = Dependencies;
sourceTree = "<group>";
};
+ 69BB0A4C14F8D31800E7E909 /* Tor */ = {
+ isa = PBXGroup;
+ children = (
+ 696F9EA814F8D51300BC5FDC /* TorWrapper.h */,
+ 696F9EA914F8D51300BC5FDC /* TorWrapper.m */,
+ 696F9EAD14F8D6ED00BC5FDC /* tor_main.c */,
+ 696F9EAF14F8DA6900BC5FDC /* torrc */,
+ );
+ name = Tor;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -197,6 +233,7 @@
buildActionMask = 2147483647;
files = (
696EBD8214F7877900B81BC9 /* InfoPlist.strings in Resources */,
+ 696F9EB014F8DA6900BC5FDC /* torrc in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -208,7 +245,10 @@
buildActionMask = 2147483647;
files = (
696EBD8414F7877900B81BC9 /* main.m in Sources */,
+ 696F9EAB14F8D5A900BC5FDC /* TorWrapper.m in Sources */,
696EBD8814F7877900B81BC9 /* AppDelegate.m in Sources */,
+ 696F9EAE14F8D6ED00BC5FDC /* tor_main.c in Sources */,
+ 696F9EB414F8DD6D00BC5FDC /* ULINetSocket.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -245,7 +285,11 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- HEADER_SEARCH_PATHS = ../dependencies/include;
+ HEADER_SEARCH_PATHS = (
+ ../dependencies/include,
+ ../dependencies/include/common,
+ ../dependencies/include/or,
+ );
IPHONEOS_DEPLOYMENT_TARGET = 5.1;
LIBRARY_SEARCH_PATHS = ../dependencies/lib;
SDKROOT = iphoneos;
@@ -265,7 +309,11 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- HEADER_SEARCH_PATHS = ../dependencies/include;
+ HEADER_SEARCH_PATHS = (
+ ../dependencies/include,
+ ../dependencies/include/common,
+ ../dependencies/include/or,
+ );
IPHONEOS_DEPLOYMENT_TARGET = 5.1;
LIBRARY_SEARCH_PATHS = ../dependencies/lib;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
View
12 OnionBrowser/OnionBrowser/AppDelegate.h
@@ -6,9 +6,21 @@
//
#import <UIKit/UIKit.h>
+#import "TorWrapper.h"
+#import "ULINetSocket.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate>
+@property (nonatomic, retain) TorWrapper *torThread;
+
@property (strong, nonatomic) UIWindow *window;
+@property (nonatomic, retain) NSTimer *torCheckLoopTimer;
+@property (nonatomic, retain) ULINetSocket *mSocket;
+
+- (void)checkTor;
+
+- (void)activateTorCheckLoop;
+- (void)disableTorCheckLoop;
+
@end
View
102 OnionBrowser/OnionBrowser/AppDelegate.m
@@ -10,7 +10,9 @@
@implementation AppDelegate
-@synthesize window = _window;
+@synthesize window = _window, torThread = _torThread,
+ torCheckLoopTimer = _torCheckLoopTimer,
+ mSocket = _mSocket;
- (void)dealloc
{
@@ -20,12 +22,15 @@ - (void)dealloc
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
+ self.torThread = [[TorWrapper alloc] init];
+ [self.torThread start];
+
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
- /* Test */
+ /*
// Test A
unsigned char *inStrg = (unsigned char*)[@"" cStringUsingEncoding:NSASCIIStringEncoding];
unsigned long lngth = 0;
@@ -117,14 +122,72 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
NSLog(@"should be: 07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6");
NSLog(@"");
NSLog(@"View https://en.wikipedia.org/wiki/SHA-2 for more info");
-
+ */
+
+ [NSTimer scheduledTimerWithTimeInterval:4.0f
+ target:self
+ selector:@selector(activateTorCheckLoop)
+ userInfo:nil
+ repeats:NO];
+
return YES;
}
+- (void)checkTor {
+ // Send a simple HTTP 1.0 header to the server and hopefully we won't be rejected
+ [_mSocket writeString:@"getinfo circuit-status\n\r" encoding:NSUTF8StringEncoding];
+
+}
+
+- (void)netsocketDisconnected:(ULINetSocket*)inNetSocket {
+ NSLog( @"GET Example: Disconnected" );
+ NSLog(@"%@", [_mSocket readString:NSUTF8StringEncoding]);
+}
+
+- (void)netsocket:(ULINetSocket*)inNetSocket dataAvailable:(unsigned)inAmount {
+ NSLog( @"GET Example: Data available (%u)", inAmount );
+ NSLog(@"%@", [_mSocket readString:NSUTF8StringEncoding]);
+}
+
+- (void)netsocketDataSent:(ULINetSocket*)inNetSocket {
+ //NSLog( @"GET Example: Data sent" );
+}
+
+#pragma mark -
+
+- (void)activateTorCheckLoop {
+ NSLog(@"Starting to check loop");
+ [ULINetSocket ignoreBrokenPipes];
+ // Create a new ULINetSocket connected to the host. Since ULINetSocket is asynchronous, the socket is not
+ // connected to the host until the delegate method is called.
+ _mSocket = [[ULINetSocket netsocketConnectedToHost:@"127.0.0.1" port:60602] retain];
+
+ // Schedule the ULINetSocket on the current runloop
+ [_mSocket scheduleOnCurrentRunLoop];
+
+ // Set the ULINetSocket's delegate to ourself
+ [_mSocket setDelegate:self];
+
+ [_mSocket writeString:@"authenticate\n\r" encoding:NSUTF8StringEncoding];
+ [_mSocket writeString:@"setevents circ\n\r" encoding:NSUTF8StringEncoding];
+
+ _torCheckLoopTimer = [NSTimer scheduledTimerWithTimeInterval:4.0f
+ target:self
+ selector:@selector(checkTor)
+ userInfo:nil
+ repeats:YES];
+
+}
+- (void)disableTorCheckLoop {
+ [_torCheckLoopTimer invalidate];
+
+}
+
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+ [self disableTorCheckLoop];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
@@ -141,11 +204,44 @@ - (void)applicationWillEnterForeground:(UIApplication *)application
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+ [self activateTorCheckLoop];
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+ [self activateTorCheckLoop];
+ [self.torThread halt_tor];
+}
+
+
+/*
+- (void) gameLoop {
+ while (running)
+ {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [self renderFrame];
+ [pool release];
+ }
+}
+
+- (void) startLoop
+{
+ running = YES;
+#ifdef THREADED_ANIMATION
+ [NSThread detachNewThreadSelector:@selector(gameLoop)
+ toTarget:self withObject:nil];
+#else
+ timer = [NSTimer scheduledTimerWithTimeInterval:1.0f/60
+ target:self selector:@selector(renderFrame) userInfo:nil repeats:YES];
+#endif
+}
+
+- (void) stopLoop
+{
+ [timer invalidate];
+ running = NO;
}
+*/
@end
View
28 OnionBrowser/TorWrapper.h
@@ -0,0 +1,28 @@
+//
+// TorWrapper.h
+// wut
+//
+// Created by Mike Tigas on 2/22/12.
+// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#include "or/or.h"
+#include "or/main.h"
+#include <pthread.h>
+
+#define TOR_IS_RUNNING 0
+#define TOR_IS_STOPPING 1
+#define TOR_IS_STOPPED 2
+
+
+@interface TorWrapper : NSThread {
+ NSUInteger status;
+}
+
+@property (atomic) NSUInteger status;
+
+- (void)halt_tor;
+- (void)kill_tor;
+
+@end
View
140 OnionBrowser/TorWrapper.m
@@ -0,0 +1,140 @@
+//
+// TorWrapper.m
+// wut
+//
+// Created by Mike Tigas on 2/22/12.
+// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#import "TorWrapper.h"
+
+@implementation TorWrapper
+
+@synthesize status;
+
+-(void)main {
+ self.status = TOR_IS_RUNNING;
+
+ NSLog(@"Starting tor...");
+ /*
+ NSFileManager *filemgr;
+ NSArray *dirPaths;
+ dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
+ NSUserDomainMask, YES);
+
+ NSString *docsDir;
+ NSString *torDir;
+ NSString *tmpDir = NSTemporaryDirectory();
+
+ docsDir = [dirPaths objectAtIndex:0];
+ torDir = [docsDir stringByAppendingPathComponent:@"tor"];
+
+ NSLog(@"%@", docsDir);
+ NSLog(@"%@", torDir);
+
+ NSDictionary *fileperms = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInteger:0x777]
+ forKey:NSFilePosixPermissions];
+
+ if ([filemgr isWritableFileAtPath:docsDir] == YES) {
+ NSLog(@"is writable");
+ } else {
+ NSLog(@"NOT writable");
+ }
+ if ([filemgr setAttributes:fileperms ofItemAtPath:docsDir error:nil] == NO) {
+ NSLog(@"docsdir perms?");
+ }
+ NSDictionary *f = [filemgr attributesOfItemAtPath:docsDir error:nil];
+ NSLog(@"%@", f);
+
+ if ([filemgr createDirectoryAtPath:torDir withIntermediateDirectories:YES attributes:nil error: NULL] == NO)
+ {
+ NSLog (@"failed to create tor dir");
+ }
+ if ([filemgr setAttributes:fileperms ofItemAtPath:torDir error:nil] == NO) {
+ NSLog(@"torDir perms?");
+ }
+
+ NSArray *filelist;
+ int count;
+ int i;
+
+ NSLog(@"%@", torDir);
+ filemgr =[NSFileManager defaultManager];
+ filelist = [filemgr contentsOfDirectoryAtPath:torDir error:NULL];
+ count = [filelist count];
+
+ for (i = 0; i < count; i++)
+ NSLog(@"%@", [filelist objectAtIndex: i]);
+
+ NSString *base_torrc = [[NSBundle mainBundle] pathForResource:@"torrc" ofType:nil];
+ NSString *user_torrc = [torDir stringByAppendingPathComponent:@"torrc"];
+
+ filemgr = [NSFileManager defaultManager];
+
+ if ([filemgr removeItemAtPath: user_torrc error: NULL] == YES) {
+ }
+
+ if ([filemgr fileExistsAtPath: user_torrc ] == YES) {
+ //NSLog (@"user torrc exists");
+ } else {
+ NSLog (@"creating user torrc from default");
+ if ([filemgr copyItemAtPath: base_torrc toPath: user_torrc error: NULL] == YES) {
+ //NSLog (@"Copy successful");
+ } else {
+ NSLog (@"Copy failed");
+ }
+ }
+
+ char *arg_0 = "tor";
+ char *arg_1 = "DataDirectory";
+ char *arg_2 = (char*)[[torDir dataUsingEncoding:NSUTF8StringEncoding] bytes];
+ char *arg_3 = "-f";
+ char *arg_4 = (char*)[[user_torrc dataUsingEncoding:NSUTF8StringEncoding] bytes];
+ */
+
+ NSString *tmpDir = NSTemporaryDirectory();
+ NSString *base_torrc = [[NSBundle mainBundle] pathForResource:@"torrc" ofType:nil];
+ const char *arg_0 = "tor";
+ const char *arg_1 = "DataDirectory";
+ const char *arg_2 = [tmpDir cStringUsingEncoding:NSUTF8StringEncoding];
+ const char *arg_3 = "-f";
+ const char *arg_4 = [base_torrc cStringUsingEncoding:NSUTF8StringEncoding];
+
+ const char* argv[] = {arg_0, arg_1, arg_2, arg_3, arg_4, NULL};
+ tor_main(5, argv);
+}
+-(void)halt_tor {
+ if (self.status == TOR_IS_RUNNING) {
+ NSLog(@"Halting tor...");
+ self.status = TOR_IS_STOPPING;
+ [self cancel];
+ raise(SIGINT);
+ self.status = TOR_IS_STOPPED;
+ }
+}
+-(void)kill_tor {
+ if (self.status == TOR_IS_RUNNING) {
+ NSLog(@"Halting tor...");
+ self.status = TOR_IS_STOPPING;
+ [self cancel];
+ raise(SIGTERM);
+ self.status = TOR_IS_STOPPED;
+ }
+}
+
+/** Do whatever cleanup is necessary before shutting Tor down. */
+void fake_tor_cleanup(void) {
+ NSLog(@"fake tor cleanup");
+#ifdef USE_DMALLOC
+ dmalloc_log_stats();
+#endif
+ tor_free_all(1);
+ crypto_global_cleanup();
+#ifdef USE_DMALLOC
+ dmalloc_log_unfreed();
+ dmalloc_shutdown();
+#endif
+}
+
+
+@end
View
242 OnionBrowser/ULINetSocket.h
@@ -0,0 +1,242 @@
+//
+// ULINetSocket.h
+// Version 0.9
+//
+// Copyright (c) 2001 Dustin Mierau.
+// With modifications by Uli Kusterer.
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+
+/*!
+ @header ULINetSocket.h
+ An Objective-C class to simplify asynchronous networking.
+ */
+
+#import <Foundation/Foundation.h>
+#import <netinet/in.h>
+
+@interface ULINetSocket : NSObject
+{
+ CFSocketRef mCFSocketRef;
+ CFRunLoopSourceRef mCFSocketRunLoopSourceRef;
+ id mDelegate;
+ NSTimer* mConnectionTimer;
+ BOOL mSocketConnected;
+ BOOL mSocketListening;
+ NSMutableData* mOutgoingBuffer;
+ NSMutableData* mIncomingBuffer;
+}
+
+/*! @methodgroup Creation */
+
+/*! Creates, opens and schedules a new socket. */
++(ULINetSocket*) netsocket;
++(ULINetSocket*) netsocketListeningOnRandomPort;
+
+/*! Creates a new open socket listening for connections on the specified port.
+ @param inPort the port the socket will listen for connection on. */
++(ULINetSocket*) netsocketListeningOnPort: (UInt16)inPort;
+
+/*! Creates a new open socket connecting to the specified host on the specified port.
+ @param inHostname the name of the host the socket will attempt to connect to.
+ @param inPort the port number the socket will attempt to connect on. */
++(ULINetSocket*) netsocketConnectedToHost: (NSString*)inHostname port: (UInt16)inPort;
+
+// Delegate (id<ULINetSocketDelegate>)
+-(id) delegate;
+-(void) setDelegate: (id)inDelegate;
+
+/*! @methodgroup Opening and Closing */
+/*! Prepares the socket for activity. This should always be called before attempting to connect to a host or listen for connections.
+ @result YES if preparing the socket was successful, NO otherwise. */
+-(BOOL) open;
+
+/*! Closes the socket. If the socket is connected to a host, this call will disconnect from that host. You will need to call open again after calling close as this call basically kills the socket from performing any more activity. You should always call this method before attempting to connect to another host. */
+-(void) close;
+
+/*! @methodgroup Runloop Scheduling */
+-(BOOL) scheduleOnCurrentRunLoop;
+-(BOOL) scheduleOnRunLoop: (NSRunLoop*)inRunLoop;
+
+/*! @methodgroup Listening */
+-(BOOL) listenOnRandomPort;
+/*! Starts the socket listening for connections on the specified port. This method will limit pending connections to 5.
+ @result YES if the socket is successfully put into a listening state, NO otherwise.
+ @param inPort is the port the socket will listen for connections on. */
+-(BOOL) listenOnPort: (UInt16)inPort;
+
+/*! Starts the socket listening for connections on the specified port, limiting pending connection count to the specified amount.
+ @result YES if the socket is successfully put into a listening state, NO otherwise.
+ @param inPort the port the socket will listen for connections on.
+ @param inMaxPendingConnections the maximum number of pending connections that should be allowed before connections start being refused. */
+-(BOOL) listenOnPort: (UInt16)inPort maxPendingConnections: (int)inMaxPendingConnections;
+
+/*! Starts the socket listening for connections on the specified path. This method will limit pending connections to the specified amount.
+ @result YES if the socket is successfully put into a listening state, NO otherwise.
+ @param path is the name of the socket.
+ @param inMaxPendingConnections the maximum number of pending connections that should be allowed before connections start being refused. */
+-(BOOL) listenOnLocalSocketPath: (NSString *)path maxPendingConnections: (int)inMaxPendingConnections;
+
+/*! @methodgroup Connecting */
+/*! Attempts to connect the socket to the specified host on the specified port.
+ @result YES if the socket is successfully put into a connecting state, NO otherwise.
+ @param inHostname the name of the host the socket will attempt to connect to.
+ @param inPort the port number the socket will attempt to connect on. */
+-(BOOL) connectToHost: (NSString*)inHostname port: (UInt16)inPort;
+
+/*! Attempts to connect the socket to the specified host on the specified port. If a positive timeout value is specified the socket will timeout if the connection process takes longer, which is in seconds.
+ @result YES if the socket is successfully put into a connecting state, NO otherwise.
+ @param inHostname the name of the host the socket will attempt to connect to.
+ @param inPort the port number the socket will attempt to connect on.
+ @param inTimeout the amount of time the socket has to establish a connection. */
+-(BOOL) connectToHost: (NSString*)inHostname port: (UInt16)inPort timeout: (NSTimeInterval)inTimeout;
+
+/*! Attempts to connect the socket on the specified path.
+ @result YES if the socket is successfully put into a connecting state, NO otherwise.
+ @param path the path of the socket. */
+-(BOOL) connectToLocalSocketPath: (NSString *)path;
+
+/*! @methodgroup Peeking */
+/*! Allows you to look at the data NetSocket has ready for reading without actually advancing the current read position. Returns all of the available data that is ready for reading. */
+-(NSData*) peekData;
+
+/*! @methodgroup Reading */
+/*! Attempts to read the amount of data specified from the socket, placing it into the specified memory buffer.
+ @result the amount of data (in bytes) actually placed in the buffer, this will never be greater than the specified amount.
+ @param inBuffer the memory buffer read data will be placed into.
+ @param inAmount the desired number of bytes to read. */
+-(unsigned) read: (void*)inBuffer amount: (unsigned)inAmount;
+
+/*! Reads all the available data from the socket. That data that is read is appended to the specified mutable data object.
+ @result the amount of data read in bytes.
+ @param inData the mutable data object to which the read data will be appended. */
+-(unsigned) readOntoData: (NSMutableData*)inData;
+
+/*! Attempts to read the amount of data specified from the socket. The data that is read is appended to the specified mutable data object.
+ @result the amount of data (in bytes) actually placed onto the mutable data object, this value will never be greater than the specified amount.
+ @param inData the mutable data object in which the read data will be appended to.
+ @param inAmount the number of bytes to read. */
+-(unsigned) readOntoData: (NSMutableData*)inData amount: (unsigned)inAmount;
+
+/*! Attempts to read the amount of data specified from the socket. The data that is read is converted to a string using the specified string encoding and then appended to the specified mutable string object.
+ @result the amount of data actually read, this value will never be greater than the specified amount.
+ @param inString the mutable string object in which the read data will be appended to.
+ @param inEncoding the string encoding to use when converting the data intoto a string.
+ @param inAmount the number of bytes to read. */
+-(unsigned) readOntoString: (NSMutableString*)inString encoding: (NSStringEncoding)inEncoding amount: (unsigned)inAmount;
+
+/*! Reads all of the available data from the socket.
+ @result the read data in a new data object. */
+-(NSData*) readData;
+
+/*! Attempts to read the amount of data specified (in bytes) from the socket.
+ @result a new data object containing the read data. You can determine how much was actually read from the socket by checking the length of the data object.
+ @param inAmount the number of bytes to read. */
+-(NSData*) readData: (unsigned)inAmount;
+
+/*! Reads all of the available data from the socket. Returns the read data as a new string object using the specified string encoding.
+ @param inEncoding is the string encoding to use when converting the data into a string. */
+-(NSString*) readString: (NSStringEncoding)inEncoding;
+
+/*! Attempts to read the number of bytes specified from the socket.
+ @result the read data as a new string object using the specified string encoding. You can determine how much was actually read from the socket by checking the length of the string object.
+ @param inEncoding the string encoding to use when converting the data into a string.
+ @param inAmount the number of bytes to read. */
+-(NSString*) readString: (NSStringEncoding)inEncoding amount: (unsigned)inAmount;
+
+/*! @methodgroup Writing */
+/*! Attempts to write the specified amount of bytes onto the socket. In most cases this will be instant, but if you are sending a large amount of data, the data will be copied and sent progressively onto the socket.
+ @param inBytes the memory buffer to write onto the socket.
+ @param inLength the size of the memory buffer in bytes. */
+-(void) write: (const void*)inBytes length: (unsigned)inLength;
+
+/*! Attempts to write the specified data object onto the socket. In most cases this will be instant, but if you are sending a large amount of data, the data will be copied and sent progressively onto the socket.
+ @param inData the data object to write onto the socket. */
+-(void) writeData: (NSData*)inData;
+
+/*! Attempts to write the specified string object onto the socket using the specified encoding to convert the string into data form. In most cases sending this data will be instant, but if you are sending a large amount of data, the data will be copied and sent progressively onto the socket.
+ @param inString the string object to write onto the socket.
+ @param inEncoding the string encoding to use converting the string into data form. */
+-(void) writeString: (NSString*)inString encoding: (NSStringEncoding)inEncoding;
+
+// Properties
+/*! Returns the address the socket is connected to as a string object. */
+-(NSString*) remoteHost;
+
+/*! Returns the port the socket is connected on. */
+-(UInt16) remotePort;
+-(NSString*) localHost;
+-(UInt16) localPort;
+-(BOOL) isConnected;
+-(BOOL) isListening;
+-(unsigned) incomingBufferLength;
+-(unsigned) outgoingBufferLength;
+
+-(CFSocketNativeHandle) nativeSocketHandle;
+
+/*! Returns the underlying CFSocket object. It's probably not a good idea to play with this, but what the hell eh? */
+-(CFSocketRef) cfsocketRef;
+
+// Convenience methods
++(void) ignoreBrokenPipes;
+
+/*! A utility method for turning an address structure into a human-readable dotted IP string.
+ @param inAddress the BSD address structure to be converted. */
++(NSString*) stringWithSocketAddress: (struct in_addr*)inAddress;
+
+@end
+
+#pragma mark -
+
+/*! @methodgroup Delegate methods */
+
+@protocol ULINetSocketDelegate
+@optional
+
+/*! Called when the specified socket has established a connection with the host.
+ @param inNetSocket the notifying socket. */
+-(void) netsocketConnected: (ULINetSocket*)inNetSocket;
+
+/*! Called when the socket could not connect during the specified time interval. The socket is closed automatically, you will need to open it again to use it.
+ @param inNetSocket the notifying socket.
+ @param inTimeout the alloted timeout (in seconds). */
+-(void) netsocket: (ULINetSocket*)inNetSocket connectionTimedOut: (NSTimeInterval)inTimeout;
+
+/*! Called when the specified socket has lost its connection with the host.
+ @param inNetSocket the notifying socket. */
+-(void) netsocketDisconnected: (ULINetSocket*)inNetSocket;
+
+/*! Called when a listening socket has accepted a new connection. A newly created NetSocket is created based on this new connecting client.
+ You need to schedule the given connection on a runloop to be able to use it.
+ @param inNetSocket the notifying socket (The listening socket).
+ @param inNewNetSocket the newly connected socket, abuse it. */
+-(void) netsocket: (ULINetSocket*)inNetSocket connectionAccepted: (ULINetSocket*)inNewNetSocket;
+
+/*! Called when the socket has more data available of the specified amount.
+ @param inNetSocket the notifying socket.
+ @param inAmount the number of bytes of new data available on the socket. */
+-(void) netsocket: (ULINetSocket*)inNetSocket dataAvailable: (unsigned)inAmount;
+
+/*! Called when all of the data has been sent onto the socket.
+ @param inNetSocket the notifying socket. */
+-(void) netsocketDataSent: (ULINetSocket*)inNetSocket;
+
+@end
View
1,226 OnionBrowser/ULINetSocket.m
@@ -0,0 +1,1226 @@
+//
+// ULINetSocket.m
+// Version 0.9
+//
+// Copyright (c) 2001 Dustin Mierau.
+// With modifications by Uli Kusterer.
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+
+#import "ULINetSocket.h"
+#import <arpa/inet.h>
+#import <sys/socket.h>
+#import <sys/un.h>
+#import <sys/time.h>
+#import <sys/ioctl.h>
+#import <fcntl.h>
+#import <netdb.h>
+#import <unistd.h>
+
+static void _cfsocketCallback( CFSocketRef inCFSocketRef, CFSocketCallBackType inType, CFDataRef inAddress, const void* inData, void* inContext );
+
+#pragma mark -
+
+@interface ULINetSocket ( ULIPrivateMethods )
+- (id)initWithNativeSocket:(int)inNativeSocket;
+- (void)unscheduleFromRunLoop;;
+- (void)_cfsocketCreateForNative:(CFSocketNativeHandle)inNativeSocket;
+- (BOOL)_cfsocketCreated;
+- (void)_cfsocketConnected;
+- (void)_cfsocketDisconnected;
+- (void)_cfsocketNewConnection;
+- (void)_cfsocketDataAvailable;
+- (void)_cfsocketWritable;
+- (void)_socketConnectionTimedOut:(NSTimer*)inTimer;
+- (ULINetSocket*)_socketAcceptConnection;
+- (void)_socketReadData;
+- (void)_socketWriteData;
+- (BOOL)_socketIsWritable;
+- (int)_socketReadableByteCount;
+- (void)_scheduleConnectionTimeoutTimer:(NSTimeInterval)inTimeout;
+- (void)_unscheduleConnectionTimeoutTimer;
+@end
+
+#pragma mark -
+
+@implementation ULINetSocket
+
+- (id)init
+{
+ if( ![super init] )
+ return nil;
+
+ // Initialize some values
+ mCFSocketRef = NULL;
+ mCFSocketRunLoopSourceRef = NULL;
+ mDelegate = nil;
+ mConnectionTimer = nil;
+ mSocketConnected = NO;
+ mSocketListening = NO;
+ mOutgoingBuffer = nil;
+ mIncomingBuffer = [[NSMutableData alloc] init];
+
+ return self;
+}
+
+- (id)initWithNativeSocket:(int)inNativeSocket
+{
+ if( ![self init] )
+ return nil;
+
+ // Create CFSocketRef based on specified native socket
+ [self _cfsocketCreateForNative:inNativeSocket];
+
+ // If creation of the CFSocketRef failed, we return nothing and cleanup
+ if( ![self _cfsocketCreated] )
+ {
+ [super dealloc];
+ return nil;
+ }
+
+ // Remember that we are a connected socket
+ mSocketConnected = YES;
+
+ return self;
+}
+
+- (void)dealloc
+{
+ // We don't want the delegate receiving anymore messages from us
+ mDelegate = nil;
+
+ // Unschedule connection timeout timer
+ [self _unscheduleConnectionTimeoutTimer];
+
+ // Unschedule socket from runloop
+ [self unscheduleFromRunLoop];
+
+ // Close socket if it is still open
+ [self close];
+
+ // Reset some values
+ mSocketConnected = NO;
+ mSocketListening = NO;
+
+ // Release our incoming buffer
+ [mIncomingBuffer release];
+ mIncomingBuffer = nil;
+
+ [super dealloc];
+}
+
+#pragma mark -
+
++ (ULINetSocket*)netsocket
+{
+ ULINetSocket* netsocket;
+ BOOL success = NO;
+
+ // Allocate new ULINetSocket
+ netsocket = [[[ULINetSocket alloc] init] autorelease];
+
+ // Attempt to open the socket and schedule it on the current runloop
+ if( [netsocket open] )
+ if( [netsocket scheduleOnCurrentRunLoop] )
+ success = YES;
+
+ // Return the new ULINetSocket if creation was successful
+ return ( success ? netsocket : nil );
+}
+
++ (ULINetSocket*)netsocketListeningOnRandomPort
+{
+ // Return a new netsocket listening on a random open port
+ return [self netsocketListeningOnPort:0];
+}
+
++ (ULINetSocket*)netsocketListeningOnPort:(UInt16)inPort
+{
+ ULINetSocket* netsocket;
+ BOOL success = NO;
+
+ // Create a new ULINetSocket
+ netsocket = [self netsocket];
+
+ // Set the ULINetSocket to listen on the specified port
+ if( [netsocket listenOnPort:inPort] )
+ success = YES;
+
+ // Return the new ULINetSocket if everything went alright
+ return ( success ? netsocket : nil );
+}
+
++ (ULINetSocket*)netsocketConnectedToHost:(NSString*)inHostname port:(UInt16)inPort
+{
+ ULINetSocket* netsocket;
+ BOOL success = NO;
+
+ // Create a new ULINetSocket
+ netsocket = [self netsocket];
+
+ // Attempt to connect to the specified host on the specified port
+ if( [netsocket connectToHost:inHostname port:inPort] )
+ success = YES;
+
+ // Return the new ULINetSocket if everything went alright
+ return ( success ? netsocket : nil );
+}
+
+#pragma mark -
+
+- (id)delegate
+{
+ return mDelegate;
+}
+
+- (void)setDelegate:(id)inDelegate
+{
+ // Set the delegate to the specified delegate
+ mDelegate = inDelegate;
+}
+
+#pragma mark -
+
+- (BOOL)open
+{
+ // If the CFSocketRef has not been allocated, try and do so now
+ if( ![self _cfsocketCreated] )
+ {
+ int nativeSocket;
+
+ // Create native socket
+ nativeSocket = socket( AF_INET, SOCK_STREAM, 0 );
+ if( nativeSocket < 0 )
+ return NO;
+
+ // Create CFSocketRef based on new native socket
+ [self _cfsocketCreateForNative:nativeSocket];
+ }
+
+ // Return whether or not the CFSocket was successfully created
+ return [self _cfsocketCreated];
+}
+
+- (void)close
+{
+ CFSocketNativeHandle nativeSocket;
+
+ // Unschedule from runloop
+ [self unscheduleFromRunLoop];
+
+ // If the CFSocket was created, destroy it
+ if( [self _cfsocketCreated] )
+ {
+ // Get native socket descriptor
+ nativeSocket = [self nativeSocketHandle];
+
+ // Close socket descriptor
+ if( nativeSocket > -1 )
+ close( nativeSocket );
+
+ // Invalidate the CFSocketRef
+ CFSocketInvalidate( mCFSocketRef );
+
+ // Release the CFSocketRef and reset our reference to it
+ CFRelease( mCFSocketRef );
+ mCFSocketRef = NULL;
+ }
+
+ // Remember that we are no longer connected
+ mSocketConnected = NO;
+
+ // Remember that we are no longer listening
+ mSocketListening = NO;
+
+ // Release outgoing buffer
+ [mOutgoingBuffer release];
+ mOutgoingBuffer = nil;
+}
+
+#pragma mark -
+
+- (BOOL)scheduleOnCurrentRunLoop
+{
+ return [self scheduleOnRunLoop:[NSRunLoop currentRunLoop]];
+}
+
+- (BOOL)scheduleOnRunLoop:(NSRunLoop*)inRunLoop
+{
+ CFRunLoopRef runloop;
+
+ // If our CFSocketRef has not been created or we have already been scheduled in a runloop, return
+ if( ![self _cfsocketCreated] || mCFSocketRunLoopSourceRef )
+ return NO;
+
+ // Remove ourselves from any other runloop we might be apart of
+ [self unscheduleFromRunLoop];
+
+ // Get specified CFRunLoop
+ runloop = [inRunLoop getCFRunLoop];
+ if( !runloop )
+ return NO;
+
+ // Create a CFRunLoopSource for our CFSocketRef
+ mCFSocketRunLoopSourceRef = CFSocketCreateRunLoopSource( kCFAllocatorDefault, mCFSocketRef, 0 );
+ if( !mCFSocketRunLoopSourceRef )
+ return NO;
+
+ // Finally schedule our runloop source with the specified CFRunLoop
+ CFRunLoopAddSource( runloop, mCFSocketRunLoopSourceRef, kCFRunLoopDefaultMode );
+
+ return YES;
+}
+
+- (void)unscheduleFromRunLoop
+{
+ // If our CFSocketRef has not been created than it probably hasn't been scheduled yet
+ if( ![self _cfsocketCreated] || mCFSocketRunLoopSourceRef == NULL )
+ return;
+
+ // If the runloop source is not valid, return
+ if( !CFRunLoopSourceIsValid( mCFSocketRunLoopSourceRef ) )
+ return;
+
+ // Invalidate and release the runloop source
+ CFRunLoopSourceInvalidate( mCFSocketRunLoopSourceRef );
+ CFRelease( mCFSocketRunLoopSourceRef );
+
+ // Reset our reference to the runloop source
+ mCFSocketRunLoopSourceRef = NULL;
+}
+
+#pragma mark -
+
+- (BOOL)listenOnRandomPort
+{
+ return [self listenOnPort:0 maxPendingConnections:5];
+}
+
+- (BOOL)listenOnPort:(UInt16)inPort
+{
+ return [self listenOnPort:inPort maxPendingConnections:5];
+}
+
+- (BOOL)listenOnPort:(UInt16)inPort maxPendingConnections:(int)inMaxPendingConnections
+{
+ CFSocketNativeHandle nativeSocket;
+ struct sockaddr_in socketAddress;
+ int socketOptionFlag;
+ int result;
+
+ // If the CFSocket was never created, is connected to another host or is already listening, we cannot use it
+ if( ![self _cfsocketCreated] || [self isConnected] || [self isListening] )
+ return NO;
+
+ // Get native socket descriptor
+ nativeSocket = [self nativeSocketHandle];
+ if( nativeSocket < 0 )
+ return NO;
+
+ // Set this socket option so we can reuse the address immediately
+ socketOptionFlag = 1;
+ result = setsockopt( nativeSocket, SOL_SOCKET, SO_REUSEADDR, &socketOptionFlag, sizeof( socketOptionFlag ) );
+ if( result < 0 )
+ return NO;
+
+ // Setup socket address
+ bzero( &socketAddress, sizeof( socketAddress ) );
+ socketAddress.sin_family = PF_INET;
+ socketAddress.sin_addr.s_addr = htonl( INADDR_ANY );
+ socketAddress.sin_port = htons( inPort );
+
+ // Bind socket to the specified port
+ result = bind( nativeSocket, (struct sockaddr*)&socketAddress, sizeof( socketAddress ) );
+ if( result < 0 )
+ return NO;
+
+ // Start the socket listening on the specified port
+ result = listen( nativeSocket, inMaxPendingConnections );
+ if( result < 0 )
+ return NO;
+
+ // Note that we are actually listening now
+ mSocketListening = YES;
+
+ return YES;
+}
+
+-(BOOL)listenOnLocalSocketPath: (NSString *)path maxPendingConnections:(int)inMaxPendingConnections
+{
+ CFSocketNativeHandle nativeSocket;
+ struct sockaddr_un socketAddress;
+ int result;
+
+ if (![self _cfsocketCreated]) {
+ int sock = socket( PF_LOCAL, SOCK_STREAM, 0 );
+ [self _cfsocketCreateForNative: sock];
+ }
+
+ // If the CFSocket was never created, is connected to another host or is already listening, we cannot use it
+ if( ![self _cfsocketCreated] || [self isConnected] || [self isListening] )
+ return NO;
+
+ // Get native socket descriptor
+ nativeSocket = [self nativeSocketHandle];
+ if( nativeSocket < 0 )
+ return NO;
+
+ // Setup socket address
+ bzero( &socketAddress, sizeof( socketAddress ) );
+ [path getCString: socketAddress.sun_path maxLength: sizeof( socketAddress.sun_path ) encoding: NSASCIIStringEncoding];
+ socketAddress.sun_family = AF_LOCAL;
+
+ unlink ([path cStringUsingEncoding: NSASCIIStringEncoding ]);
+
+ // Bind socket to the specified port
+ result = bind( nativeSocket, (struct sockaddr*)&socketAddress, sizeof( socketAddress ) );
+ if( result < 0 )
+ return NO;
+
+ // Start the socket listening on the specified port
+ result = listen( nativeSocket, inMaxPendingConnections );
+ if( result < 0 )
+ return NO;
+
+ // Note that we are actually listening now
+ mSocketListening = YES;
+
+ return YES;
+}
+
+#pragma mark -
+
+- (BOOL)connectToHost:(NSString*)inHostname port:(UInt16)inPort
+{
+ return [self connectToHost:inHostname port:inPort timeout:-1.0];
+}
+
+- (BOOL)connectToHost:(NSString*)inHostname port:(UInt16)inPort timeout:(NSTimeInterval)inTimeout
+{
+ struct hostent* socketHost;
+ struct sockaddr_in socketAddress;
+ NSData* socketAddressData;
+ CFSocketError socketError;
+
+ // If the CFSocket was never created, is connected to another host or is already listening, we cannot use it
+ if( ![self _cfsocketCreated] || [self isConnected] || [self isListening] )
+ return NO;
+
+ // Get host information
+ socketHost = gethostbyname( [inHostname cStringUsingEncoding: NSASCIIStringEncoding] );
+ if( !socketHost )
+ return NO;
+
+ // Setup socket address
+ bzero( &socketAddress, sizeof( socketAddress ) );
+ bcopy( (char*)socketHost->h_addr, (char*)&socketAddress.sin_addr, socketHost->h_length );
+ socketAddress.sin_family = PF_INET;
+ socketAddress.sin_port = htons( inPort );
+
+ // Enclose socket address in an NSData object
+ socketAddressData = [NSData dataWithBytes:(void*)&socketAddress length:sizeof( socketAddress )];
+
+ // Attempt to connect our CFSocketRef to the specified host
+ socketError = CFSocketConnectToAddress( mCFSocketRef, (CFDataRef)socketAddressData, -1.0 );
+ if( socketError != kCFSocketSuccess )
+ return NO;
+
+ // Schedule our timeout timer if the timeout is greater than zero
+ if( inTimeout >= 0.0 )
+ [self _scheduleConnectionTimeoutTimer:inTimeout];
+
+ // Remove any data left in our outgoing buffer
+ [mIncomingBuffer setLength:0];
+
+ return YES;
+}
+
+-(BOOL)connectToLocalSocketPath: (NSString *)path
+{
+ struct sockaddr_un socketAddress;
+ NSData* socketAddressData;
+ CFSocketError socketError;
+
+ if (![self _cfsocketCreated]) {
+ int sock = socket( PF_LOCAL, SOCK_STREAM, 0 );
+ [self _cfsocketCreateForNative: sock];
+ }
+
+ // If the CFSocket was never created, is connected to another host or is already listening, we cannot use it
+ if( ![self _cfsocketCreated] || [self isConnected] || [self isListening] )
+ return NO;
+
+ // Setup socket address
+ bzero( &socketAddress, sizeof( socketAddress ) );
+ [path getCString: socketAddress.sun_path maxLength: sizeof( socketAddress.sun_path ) encoding: NSASCIIStringEncoding];
+ socketAddress.sun_family = AF_LOCAL;
+
+ // Enclose socket address in an NSData object
+ socketAddressData = [NSData dataWithBytes:(void*)&socketAddress length:sizeof( socketAddress )];
+
+ // Attempt to connect our CFSocketRef to the specified host
+ socketError = CFSocketConnectToAddress( mCFSocketRef, (CFDataRef)socketAddressData, -1.0 );
+ if( socketError != kCFSocketSuccess )
+ return NO;
+
+ // Remove any data left in our outgoing buffer
+ [mIncomingBuffer setLength:0];
+
+ return YES;
+}
+
+#pragma mark -
+
+- (NSData*)peekData
+{
+ return mIncomingBuffer;
+}
+
+#pragma mark -
+
+- (unsigned)read:(void*)inBuffer amount:(unsigned)inAmount
+{
+ unsigned amountToRead;
+
+ // If there is no data to read, simply return
+ if( [mIncomingBuffer length] == 0 )
+ return 0;
+
+ // Determine how much to actually read
+ amountToRead = MIN( inAmount, [mIncomingBuffer length] );
+
+ // Read bytes from our incoming buffer
+ [mIncomingBuffer getBytes:inBuffer length:amountToRead];
+ [mIncomingBuffer replaceBytesInRange:NSMakeRange( 0, amountToRead ) withBytes:NULL length:0];
+
+ return amountToRead;
+}
+
+- (unsigned)readOntoData:(NSMutableData*)inData
+{
+ unsigned amountRead;
+
+ // If there is no data to read, simply return
+ if( [mIncomingBuffer length] == 0 )
+ return 0;
+
+ // Remember the length of our incoming buffer
+ amountRead = [mIncomingBuffer length];
+
+ // Read bytes from our incoming buffer
+ [inData appendData:mIncomingBuffer];
+
+ // Empty out our incoming buffer as we have read it all
+ [mIncomingBuffer setLength:0];
+
+ return amountRead;
+}
+
+- (unsigned)readOntoData:(NSMutableData*)inData amount:(unsigned)inAmount
+{
+ unsigned amountToRead;
+
+ // If there is no data to read, simply return
+ if( [mIncomingBuffer length] == 0 )
+ return 0;
+
+ // Determine how much to actually read
+ amountToRead = MIN( inAmount, [mIncomingBuffer length] );
+
+ // Read bytes from our incoming buffer
+ [inData appendBytes:[mIncomingBuffer bytes] length:amountToRead];
+ [mIncomingBuffer replaceBytesInRange:NSMakeRange( 0, amountToRead ) withBytes:NULL length:0];
+
+ return amountToRead;
+}
+
+- (unsigned)readOntoString:(NSMutableString*)inString encoding:(NSStringEncoding)inEncoding amount:(unsigned)inAmount
+{
+ NSData* readData;
+ NSString* readString;
+ unsigned amountToRead;
+
+ // If there is no data to read, simply return
+ if( [mIncomingBuffer length] == 0 )
+ return 0;
+
+ // Determine how much to actually read
+ amountToRead = MIN( inAmount, [mIncomingBuffer length] );
+
+ // Reference our incoming buffer, we cut down some overhead when the requested amount is the same length as our incoming buffer
+ if( amountToRead == [mIncomingBuffer length] )
+ readData = mIncomingBuffer;
+ else
+ readData = [[NSData alloc] initWithBytesNoCopy:(void*)[mIncomingBuffer bytes] length:amountToRead freeWhenDone:NO];
+
+ // If for some reason we could not create the data object, return
+ if( !readData )
+ return 0;
+
+ // Create an NSString from the read data using the specified string encoding
+ readString = [[NSString alloc] initWithData:readData encoding:inEncoding];
+ if( readString )
+ {
+ // Read bytes from our incoming buffer
+ [mIncomingBuffer replaceBytesInRange:NSMakeRange( 0, amountToRead ) withBytes:NULL length:0];
+
+ // Append created string
+ [inString appendString:readString];
+
+ // Release the NSString we created
+ [readString release];
+ }
+
+ // Release our buffer if it is not our incoming data buffer
+ if( readData != mIncomingBuffer )
+ [readData release];
+
+ return amountToRead;
+}
+
+- (NSData*)readData
+{
+ NSData* readData;
+
+ // If there is no data to read, simply return
+ if( [mIncomingBuffer length] == 0 )
+ return nil;
+
+ // Create new data object with contents of our incoming buffer
+ readData = [NSData dataWithData:mIncomingBuffer];
+ if( !readData )
+ return nil;
+
+ // Size our incoming data buffer as we have now read it all
+ [mIncomingBuffer setLength:0];
+
+ return readData;
+}
+
+- (NSData*)readData:(unsigned)inAmount
+{
+ NSData* readData;
+ unsigned amountToRead;
+
+ // If there is no data to read, simply return
+ if( [mIncomingBuffer length] == 0 )
+ return nil;
+
+ // Determine how much to actually read
+ amountToRead = MIN( inAmount, [mIncomingBuffer length] );
+
+ // Read bytes from our incoming buffer
+ readData = [NSData dataWithBytes:[mIncomingBuffer bytes] length:amountToRead];
+ if( !readData )
+ return nil;
+
+ // Read bytes from our incoming buffer
+ [mIncomingBuffer replaceBytesInRange:NSMakeRange( 0, amountToRead ) withBytes:NULL length:0];
+
+ return readData;
+}
+
+- (NSString*)readString:(NSStringEncoding)inEncoding
+{
+ NSString* readString;
+
+ // If there is no data to read, simply return
+ if( [mIncomingBuffer length] == 0 )
+ return nil;
+
+ // Read bytes from our incoming buffer
+ readString = [[[NSString alloc] initWithData:mIncomingBuffer encoding:inEncoding] autorelease];
+ if( !readString )
+ return nil;
+
+ // Size our incoming data buffer as we have now read it all
+ [mIncomingBuffer setLength:0];
+
+ return readString;
+}
+
+- (NSString*)readString:(NSStringEncoding)inEncoding amount:(unsigned)inAmount
+{
+ NSString* readString;
+ NSData* readData;
+ unsigned amountToRead;
+
+ // If there is no data to read, simply return
+ if( [mIncomingBuffer length] == 0 )
+ return nil;
+
+ // Determine how much to actually read
+ amountToRead = MIN( inAmount, [mIncomingBuffer length] );
+
+ // Reference our incoming buffer, we cut down some overhead when the requested amount is the same length as our incoming buffer
+ if( amountToRead == [mIncomingBuffer length] )
+ readData = mIncomingBuffer;
+ else
+ readData = [[NSData alloc] initWithBytesNoCopy:(void*)[mIncomingBuffer bytes] length:amountToRead freeWhenDone:NO];
+
+ // If for some reason we could not create the data object, return
+ if( !readData )
+ return nil;
+
+ // Create a new NSString from the read bytes using the specified encoding
+ readString = [[[NSString alloc] initWithData:readData encoding:inEncoding] autorelease];
+ if( readString )
+ {
+ // Read bytes from our incoming buffer
+ [mIncomingBuffer replaceBytesInRange:NSMakeRange( 0, amountToRead ) withBytes:NULL length:0];
+ }
+
+ // Release our buffer if it is not our incoming data buffer
+ if( readData != mIncomingBuffer )
+ [readData release];
+
+ return readString;
+}
+
+#pragma mark -
+
+- (void)write:(const void*)inBytes length:(unsigned)inLength
+{
+ // Return if there are no bytes to write
+ if( inLength == 0 )
+ return;
+
+ // If the socket is not connected, simply return
+ if( ![self isConnected] )
+ return;
+
+ // Create outgoing buffer if needed
+ if( !mOutgoingBuffer )
+ mOutgoingBuffer = [[NSMutableData alloc] initWithCapacity:inLength];
+
+ // Append specified bytes to our outgoing buffer
+ [mOutgoingBuffer appendBytes:inBytes length:inLength];
+
+ // Attempt to write the data to the socket
+ [self _socketWriteData];
+}
+
+- (void)writeData:(NSData*)inData
+{
+ [self write:[inData bytes] length:[inData length]];
+}
+
+- (void)writeString:(NSString*)inString encoding:(NSStringEncoding)inEncoding
+{
+ [self writeData:[inString dataUsingEncoding:inEncoding]];
+}
+
+#pragma mark -
+
+-(NSString*) remoteHost
+{
+ CFSocketNativeHandle nativeSocket;
+ struct sockaddr_in address;
+ socklen_t addressLength = sizeof( address );
+
+ // Get the native socket
+ nativeSocket = [self nativeSocketHandle];
+ if( nativeSocket < 0 )
+ return nil;
+
+ // Get peer name information
+ if( getpeername( nativeSocket, (struct sockaddr*)&address, &addressLength ) < 0 )
+ return nil;
+
+ // Return string representation of the remote hostname
+ return [ULINetSocket stringWithSocketAddress:&address.sin_addr];
+}
+
+-(UInt16) remotePort
+{
+ CFSocketNativeHandle nativeSocket;
+ struct sockaddr_in address;
+ socklen_t addressLength = sizeof( address );
+
+ // Get the native socket
+ nativeSocket = [self nativeSocketHandle];
+ if( nativeSocket < 0 )
+ return 0;
+
+ // Get peer name information
+ if( getpeername( nativeSocket, (struct sockaddr*)&address, &addressLength ) < 0 )
+ return 0;
+
+ // Return remote port
+ return ntohs( address.sin_port );
+}
+
+-(NSString*) localHost
+{
+ CFSocketNativeHandle nativeSocket;
+ struct sockaddr_in address;
+ socklen_t addressLength = sizeof( address );
+
+ // Get the native socket
+ nativeSocket = [self nativeSocketHandle];
+ if( nativeSocket < 0 )
+ return nil;
+
+ // Get socket name information
+ if( getsockname( nativeSocket, (struct sockaddr*)&address, &addressLength ) < 0 )
+ return nil;
+
+ // Return string representation of the local hostname
+ return [ULINetSocket stringWithSocketAddress:&address.sin_addr];
+}
+
+- (UInt16)localPort
+{
+ CFSocketNativeHandle nativeSocket;
+ struct sockaddr_in address;
+ socklen_t addressLength = sizeof( address );
+
+ // Get the native socket
+ nativeSocket = [self nativeSocketHandle];
+ if( nativeSocket < 0 )
+ return 0;
+
+ // Get socket name information
+ if( getsockname( nativeSocket, (struct sockaddr*)&address, &addressLength ) < 0 )
+ return 0;
+
+ // Return local port
+ return ntohs( address.sin_port );
+}
+
+- (BOOL)isConnected
+{
+ return mSocketConnected;
+}
+
+- (BOOL)isListening
+{
+ return mSocketListening;
+}
+
+- (unsigned)incomingBufferLength
+{
+ return [mIncomingBuffer length];
+}
+
+- (unsigned)outgoingBufferLength
+{
+ return [mOutgoingBuffer length];
+}
+
+- (CFSocketNativeHandle)nativeSocketHandle
+{
+ // If the CFSocketRef was never created, return an invalid handle
+ if( ![self _cfsocketCreated] )
+ return -1;
+
+ // Return a valid native socket handle
+ return CFSocketGetNative( mCFSocketRef );
+}
+
+- (CFSocketRef)cfsocketRef
+{
+ return mCFSocketRef;
+}
+
+#pragma mark -
+
++ (void)ignoreBrokenPipes
+{
+ // Ignore the broken pipe signal
+ signal( SIGPIPE, SIG_IGN );
+}
+
++(NSString*) stringWithSocketAddress: (struct in_addr*)inAddress
+{
+ return [NSString stringWithCString: inet_ntoa( *inAddress ) encoding: NSASCIIStringEncoding];
+}
+
+#pragma mark -
+
+- (void)_cfsocketCreateForNative:(CFSocketNativeHandle)inNativeSocket
+{
+ CFSocketContext socketContext;
+ CFOptionFlags socketCallbacks;
+ CFOptionFlags socketOptions;
+ int socketFlags;
+ BOOL success = NO;
+
+ // Create socket context
+ bzero( &socketContext, sizeof( socketContext ) );
+ socketContext.info = self;
+
+ // Set socket callbacks
+ socketCallbacks = kCFSocketConnectCallBack + kCFSocketReadCallBack + kCFSocketWriteCallBack;
+
+ // Get the sockets flags
+ socketFlags = fcntl( inNativeSocket, F_GETFL, 0 );
+ if( socketFlags >= 0 )
+ {
+ // Put the socket into non-blocking mode
+ if( fcntl( inNativeSocket, F_SETFL, socketFlags | O_NONBLOCK ) >= 0 )
+ {
+ // Create CFSocketRef based on native socket, if it is created...success!
+ mCFSocketRef = CFSocketCreateWithNative( kCFAllocatorDefault, inNativeSocket, socketCallbacks, &_cfsocketCallback, &socketContext );
+ if( mCFSocketRef )
+ success = YES;
+ }
+ }
+
+ if( !success )
+ {
+ close( inNativeSocket );
+ return;
+ }
+
+ // Set socket options
+ socketOptions = kCFSocketAutomaticallyReenableReadCallBack;
+ CFSocketSetSocketFlags( mCFSocketRef, socketOptions );
+}
+
+- (BOOL)_cfsocketCreated
+{
+ return ( mCFSocketRef != NULL );
+}
+
+- (void)_cfsocketConnected
+{
+ // Unschedule connection timeout timer and release it if it's still running
+ [self _unscheduleConnectionTimeoutTimer];
+
+ // Remember that we are now connected
+ mSocketConnected = YES;
+
+ // Notify our delegate that the socket has connected successfully
+ if( [mDelegate respondsToSelector:@selector( netsocketConnected: )] )
+ [mDelegate netsocketConnected:self];
+
+ // Attempt to write any data that has already been added to our outgoing buffer
+ [self _socketWriteData];
+}
+
+- (void)_cfsocketDisconnected
+{
+ // Close socket
+ [self close];
+
+ // Notify our delegate that the socket has been disconnected
+ if( [mDelegate respondsToSelector:@selector( netsocketDisconnected: )] )
+ [mDelegate netsocketDisconnected:self];
+}
+
+- (void)_cfsocketNewConnection
+{
+ ULINetSocket* netsocket;
+
+ // Accept all pending connections
+ while(( netsocket = [self _socketAcceptConnection] ))
+ {
+ // Notify our delegate that a new connection has been accepted
+ if( [mDelegate respondsToSelector:@selector( netsocket:connectionAccepted: )] )
+ [mDelegate netsocket:self connectionAccepted:netsocket];
+ }
+}
+
+- (void)_cfsocketDataAvailable
+{
+ unsigned oldIncomingBufferLength;
+
+ // Store the old incoming buffer length
+ oldIncomingBufferLength = [mIncomingBuffer length];
+
+ // Read in available data
+ [self _socketReadData];
+
+ // Return if there was no data added to our incoming data buffer
+ if( [mIncomingBuffer length] <= oldIncomingBufferLength )
+ return;
+
+ // Notify our delegate that new data is now available
+ if( [mDelegate respondsToSelector:@selector( netsocket:dataAvailable: )] )
+ [mDelegate netsocket:self dataAvailable:[mIncomingBuffer length]];
+}
+
+- (void)_cfsocketWritable
+{
+ // Attempt to write more data to the socket
+ [self _socketWriteData];
+}
+
+#pragma mark -
+
+- (void)_socketConnectionTimedOut:(NSTimer*)inTimer
+{
+ NSTimeInterval timeInterval;
+
+ // Store the timers time interval
+ timeInterval = [mConnectionTimer timeInterval];
+
+ // Unschedule the timeout timer and release it
+ [self _unscheduleConnectionTimeoutTimer];
+
+ // Notify our delegate that our attempt to connect to the specified remote host failed
+ if( [mDelegate respondsToSelector:@selector( netsocket:connectionTimedOut: )] )
+ [mDelegate netsocket:self connectionTimedOut:timeInterval];
+}
+
+-(ULINetSocket*) _socketAcceptConnection
+{
+ CFSocketNativeHandle nativeSocket;
+ struct sockaddr_in socketAddress;
+ ULINetSocket* netsocket;
+ socklen_t socketAddressSize;
+ int socketDescriptor;
+
+ // Get the native socket
+ nativeSocket = [self nativeSocketHandle];
+ if( nativeSocket < 0 )
+ return nil;
+
+ // Accept pending connection
+ socketAddressSize = sizeof( socketAddress );
+ socketDescriptor = accept( nativeSocket, (struct sockaddr*)&socketAddress, &socketAddressSize );
+ if( socketDescriptor < 0 )
+ return nil;
+
+ // Create a new ULINetSocket object based on the accepted connection
+ netsocket = [[[ULINetSocket alloc] initWithNativeSocket:socketDescriptor] autorelease];
+
+ // If creating the ULINetSocket object failed, let's close the connection and never speak of this to anyone
+ if( !netsocket )
+ close( socketDescriptor );
+
+ // Return ULINetSocket based on accepted connection
+ return netsocket;
+}
+
+- (void)_socketReadData
+{
+ CFSocketNativeHandle nativeSocket;
+ void* readBuffer;
+ int amountAvailable;
+ int amountRead;
+
+ // Determine how many bytes are available on the socket to read
+ amountAvailable = [self _socketReadableByteCount];
+ if( amountAvailable < 0 )
+ return;
+
+ // Get the native socket
+ nativeSocket = [self nativeSocketHandle];
+ if( nativeSocket < 0 )
+ return;
+
+ // Create read buffer
+ readBuffer = malloc( ( amountAvailable == 0 ) ? 1 : amountAvailable );
+ if( !readBuffer )
+ return;
+
+ // Attempt to read the available data
+ amountRead = read( nativeSocket, readBuffer, ( amountAvailable == 0 ) ? 1 : amountAvailable );
+ if( amountRead > 0 )
+ {
+ // Append data to our incoming buffer
+ [mIncomingBuffer appendBytes:readBuffer length:amountRead];
+ }
+ else
+ if( amountRead == 0 )
+ {
+ // We have been disconnected
+ [self _cfsocketDisconnected];
+ }
+ else
+ if( amountRead < 0 )
+ {
+ if( errno != EAGAIN )
+ [self _cfsocketDisconnected];
+ }
+
+ // Free our read buffer
+ free( readBuffer );
+}
+
+- (void)_socketWriteData
+{
+ CFSocketNativeHandle nativeSocket;
+ int amountSent;
+
+ // Return if our CFSocketRef has not been created, the outgoing buffer has no data in it or we are simply not connected
+ if( ![self _cfsocketCreated] || [mOutgoingBuffer length] == 0 || ![self isConnected] )
+ return;
+
+ // Get the native socket
+ nativeSocket = [self nativeSocketHandle];
+ if( nativeSocket < 0 )
+ return;
+
+ // Send all we can
+ amountSent = write( nativeSocket, [mOutgoingBuffer bytes], [mOutgoingBuffer length] );
+ if( amountSent == [mOutgoingBuffer length] )
+ {
+ // We managed to write the entire outgoing buffer to the socket
+ // Disable the write callback for now since we know we are writable
+ CFSocketDisableCallBacks( mCFSocketRef, kCFSocketWriteCallBack );
+ }
+ else
+ if( amountSent >= 0 )
+ {
+ // We managed to write some of our buffer to the socket
+ // Enable the write callback on our CFSocketRef so we know when the socket is writable again
+ if( [self isConnected] )
+ CFSocketEnableCallBacks( mCFSocketRef, kCFSocketWriteCallBack );
+ }
+ else
+ if( errno == EWOULDBLOCK )
+ {
+ // No data has actually been written here
+ amountSent = 0;
+
+ // Enable the write callback on our CFSocketRef so we know when the socket is writable again
+ CFSocketEnableCallBacks( mCFSocketRef, kCFSocketWriteCallBack );
+ }
+ else
+ {
+ // Disable the write callback
+ CFSocketDisableCallBacks( mCFSocketRef, kCFSocketWriteCallBack );
+
+ // Note that we have been disconnected
+ [self _cfsocketDisconnected];
+ return;
+ }
+
+ // Remove the data we managed to write to the socket
+ [mOutgoingBuffer replaceBytesInRange:NSMakeRange( 0, amountSent ) withBytes:NULL length:0];
+
+ // If our outgoing buffer is empty, notify our delegate
+ if( [mOutgoingBuffer length] == 0 )
+ if( [mDelegate respondsToSelector:@selector( netsocketDataSent: )] )
+ [mDelegate netsocketDataSent:self];
+}
+
+- (BOOL)_socketIsWritable
+{
+ CFSocketNativeHandle nativeSocket;
+ struct timeval timeout;
+ fd_set writableSet;
+ int socketCount;
+
+ // Get the native socket
+ nativeSocket = [self nativeSocketHandle];
+ if( nativeSocket < 0 )
+ return NO;
+
+ // Create a socket descriptor set to check against
+ FD_ZERO( &writableSet );
+ FD_SET( nativeSocket, &writableSet );
+
+ // Create a timeout so select does not block
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ // Check socket descriptor for data
+ socketCount = select( nativeSocket + 1, NULL, &writableSet, NULL, &timeout );
+ if( socketCount < 0 )
+ return NO;
+
+ return ( socketCount == 1 );
+}
+
+- (int)_socketReadableByteCount
+{
+ CFSocketNativeHandle nativeHandle;
+ int bytesAvailable;
+
+ // Get native socket
+ nativeHandle = [self nativeSocketHandle];
+ if( nativeHandle < 0 )
+ return 0;
+
+ // Determine how many bytes are available on the socket
+ if( ioctl( nativeHandle, FIONREAD, &bytesAvailable ) == -1 )
+ {
+ if( errno == EINVAL )
+ bytesAvailable = -1;
+ else
+ bytesAvailable = 0;
+ }
+
+ return bytesAvailable;
+}
+
+#pragma mark -
+
+- (void)_scheduleConnectionTimeoutTimer:(NSTimeInterval)inTimeout
+{
+ // Schedule our timeout timer
+ mConnectionTimer = [[NSTimer scheduledTimerWithTimeInterval:inTimeout target:self selector:@selector( _socketConnectionTimedOut: ) userInfo:nil repeats:NO] retain];
+}
+
+- (void)_unscheduleConnectionTimeoutTimer
+{
+ // Remove timer from its runloop
+ [mConnectionTimer invalidate];
+
+ // Release the timer and reset our reference to it
+ [mConnectionTimer release];
+ mConnectionTimer = nil;
+}
+
+@end
+
+#pragma mark -
+
+void
+_cfsocketCallback( CFSocketRef inCFSocketRef, CFSocketCallBackType inType, CFDataRef inAddress, const void* inData, void* inContext )
+{
+ ULINetSocket* netsocket;
+
+ netsocket = (ULINetSocket*)inContext;
+ if( !netsocket )
+ return;
+
+ switch( inType )
+ {
+ case kCFSocketConnectCallBack:
+ // Notify ULINetSocket that we connected successfully
+ [netsocket _cfsocketConnected];
+ break;
+
+ case kCFSocketReadCallBack:
+ {
+ // If the CFSocketRef is in a listening state, we have a new connection. If not, data is available on the socket.
+ if( [netsocket isListening] )
+ [netsocket _cfsocketNewConnection];
+ else
+ [netsocket _cfsocketDataAvailable];
+ }
+ break;
+
+ case kCFSocketWriteCallBack:
+ // Notify the ULINetSocket object that its CFSocketRef is writable again
+ [netsocket _cfsocketWritable];
+ break;
+
+ default:
+ // Unknow CFSocketCallBackType
+ break;
+ }
+}
View
39 OnionBrowser/tor_main.c
@@ -0,0 +1,39 @@
+/* Pull a copy of this here (but disable main()) so that we pull in
+ * `tor_git_revision` properly and compile correctly. (libor.a and libtor.a
+ * don't include this since this source is just for the final tor executable
+ * binary.)
+ */
+
+/* Copyright 2001-2004 Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/** String describing which Tor subversion repository version the source was
+ * built from. This string is generated by a bit of shell kludging int
+ * src/or/Makefile.am, and is usually right.
+ */
+const char tor_git_revision[] =
+#ifndef _MSC_VER
+#include "micro-revision.i"
+#endif
+ "";
+
+/**
+ * \file tor_main.c
+ * \brief Stub module containing a main() function. Allows unit
+ * test binary to link against main.c.
+ **/
+
+int tor_main(int argc, char *argv[]);
+
+/** We keep main() in a separate file so that our unit tests can use
+ * functions from main.c)
+ */
+/*
+ int
+main(int argc, char *argv[])
+{
+ return tor_main(argc, argv);
+}
+*/
View
54 OnionBrowser/torrc
@@ -0,0 +1,54 @@
+# https://www.torproject.org/docs/tor-manual.html
+
+ClientOnly 1
+ExitPolicy reject *:*
+
+AvoidDiskWrites 1
+HardwareAccel 1
+
+SocksPort 60601
+SocksListenAddress 127.0.0.1
+ControlPort 60602
+#ControlListenAddress 0.0.0.0:60602
+#DNSPort 60603
+
+#HashedControlPassword 16:0764FD5DDFD27204601BCC70E63BA9CED1480E621433CC92D3FC5EF185
+
+ConnLimit 100
+
+UseEntryGuards 1
+TunnelDirConns 1
+PreferTunneledDirConns 1
+
+NumEntryGuards 6 #default 3
+
+# debug, info, notice, warn, err
+SafeLogging relay
+Log warn stderr
+
+TestSocks 0
+WarnUnsafeSocks 0 #default 1 (we don't care on iOS)
+
+#ClientTransportPlugin obfs2 exec /usr/local/bin/obfsproxy --managed
+
+#UseBridges 1
+#Bridge 184.73.4.26:443 C64AB14DAEA1B2C25007688A71ADE22B1B8837D5
+#Bridge 97.89.36.202:443
+#Bridge 77.87.241.77:9001
+#Bridge 83.160.85.122:9001
+#Bridge 68.169.35.103:443
+#Bridge 107.22.155.157:443
+#Bridge 31.31.78.22:9001
+#Bridge obfs2 38.229.33.18:42401
+#Bridge obfs2 85.17.20.242:61264
+#Bridge obfs2 85.214.131.213:1051
+#Bridge obfs2 86.59.30.35:45605
+#Bridge obfs2 91.208.34.7:5353
+#Bridge obfs2 109.105.109.163:53999
+#Bridge obfs2 109.163.233.195:1051
+#Bridge obfs2 128.31.0.34:1051
+#Bridge obfs2 131.215.158.1:29936
+#Bridge obfs2 173.254.192.38:1051
+#Bridge obfs2 188.40.20.215:32982
+#Bridge obfs2 212.112.242.160:49259
+#Bridge obfs2 213.108.105.129:36609
View
1  build-tor.sh
@@ -133,6 +133,7 @@ do
cp orconfig.h "${INTERDIR}/${PLATFORM}${SDKVERSION}-${ARCH}.sdk/include/"
find src/common -name "*.h" -exec cp {} "${INTERDIR}/${PLATFORM}${SDKVERSION}-${ARCH}.sdk/include/common/" \;
find src/or -name "*.h" -exec cp {} "${INTERDIR}/${PLATFORM}${SDKVERSION}-${ARCH}.sdk/include/or/" \;
+ find src/or -name "*.i" -exec cp {} "${INTERDIR}/${PLATFORM}${SDKVERSION}-${ARCH}.sdk/include/or/" \;
find src/tools -name "*.h" -exec cp {} "${INTERDIR}/${PLATFORM}${SDKVERSION}-${ARCH}.sdk/include/tools/" \;
make clean
done

2 comments on commit c16bc34

@ioerror

Why are you setting "NumEntryGuards 6" - that will make your users stand out, no?

@mtigas
Owner

@ioerror Early in the lifetime of the app I'd fiddled with the torrc settings a bit for performance reasons. The current version of the torrc no longer does this.

(Sorry for belated reply, was on an extended vacation between the late September and this past weekend.)

Please sign in to comment.
Something went wrong with that request. Please try again.