├── Resources ├── Images │ ├── Icon.png │ ├── Default.png │ ├── Icon-72.png │ ├── Icon@2x.png │ ├── Default@2x.png │ ├── Icon-Small.png │ ├── iTunesArtwork │ ├── Icon-Small-50.png │ └── Icon-Small@2x.png ├── Strings │ ├── en.lproj │ │ └── Localizable.strings │ ├── es.lproj │ │ └── Localizable.strings │ └── fr.lproj │ │ └── Localizable.strings ├── Entitlements.entitlements └── NIBs │ ├── MainWindow.xib │ └── BWRootController.xib ├── .gitignore ├── bluewoki_Prefix.pch ├── Classes ├── Helpers │ ├── BWProtocol.h │ ├── BWProtocol.m │ ├── BWBluetoothConnection.h │ ├── BWWifiConnection.h │ ├── BWPeerProxyDelegate.h │ ├── BWPeerServiceDelegate.h │ ├── BWMessageObject.h │ ├── BWMessageBroker.h │ ├── BWMessageBrokerDelegate.h │ ├── BWConnectionDelegate.h │ ├── BWPeerBrowser.h │ ├── BWPeerService.h │ ├── BWPeerProxy.h │ ├── BWMessageObject.m │ ├── BWConnection.h │ ├── BWConnection.m │ ├── BWPeerBrowser.m │ ├── BWPeerProxy.m │ ├── BWPeerService.m │ ├── BWBluetoothConnection.m │ ├── BWMessageBroker.m │ └── BWWifiConnection.m ├── AppDelegate │ ├── BWAppDelegate.h │ └── BWAppDelegate.m └── Controllers │ ├── BWBrowserController.h │ ├── BWBrowserControllerDelegate.h │ ├── BWRootController.h │ ├── BWBrowserController.m │ └── BWRootController.m ├── main.m ├── LICENSE.txt ├── README.markdown ├── bluewoki-Info.plist ├── bluewoki.xcodeproj └── project.pbxproj └── Externals └── AsyncSocket └── AsyncSocket.h /Resources/Images/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Images/Icon.png -------------------------------------------------------------------------------- /Resources/Images/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Images/Default.png -------------------------------------------------------------------------------- /Resources/Images/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Images/Icon-72.png -------------------------------------------------------------------------------- /Resources/Images/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Images/Icon@2x.png -------------------------------------------------------------------------------- /Resources/Images/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Images/Default@2x.png -------------------------------------------------------------------------------- /Resources/Images/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Images/Icon-Small.png -------------------------------------------------------------------------------- /Resources/Images/iTunesArtwork: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Images/iTunesArtwork -------------------------------------------------------------------------------- /Resources/Images/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Images/Icon-Small-50.png -------------------------------------------------------------------------------- /Resources/Images/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Images/Icon-Small@2x.png -------------------------------------------------------------------------------- /Resources/Strings/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Strings/en.lproj/Localizable.strings -------------------------------------------------------------------------------- /Resources/Strings/es.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Strings/es.lproj/Localizable.strings -------------------------------------------------------------------------------- /Resources/Strings/fr.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/bluewoki/HEAD/Resources/Strings/fr.lproj/Localizable.strings -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Documentation 2 | build 3 | *.pbxuser 4 | *.mode2v3 5 | *.mode1v3 6 | .DS_Store 7 | 8 | *.perspectivev3 9 | xcuserdata 10 | project.xcworkspace 11 | 12 | -------------------------------------------------------------------------------- /bluewoki_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'bluewoki' target in the 'bluewoki' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /Classes/Helpers/BWProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWProtocol.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | extern NSString * const BLUEWOKI_PROTOCOL_NAME; 10 | -------------------------------------------------------------------------------- /Classes/Helpers/BWProtocol.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWProtocol.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWProtocol.h" 10 | 11 | NSString * const BLUEWOKI_PROTOCOL_NAME = @"_bluewoki._tcp."; 12 | -------------------------------------------------------------------------------- /Classes/Helpers/BWBluetoothConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWBluetoothConnection.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 9/14/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWConnection.h" 10 | 11 | @interface BWBluetoothConnection : BWConnection 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Resources/Entitlements.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | get-task-allow 6 | 7 | application-identifier 8 | 2DCEUWWNKF.com.akosma.bluewoki 9 | 10 | 11 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 6/29/09. 6 | // Copyright akosma software 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) { 12 | 13 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | [pool release]; 16 | return retVal; 17 | } 18 | -------------------------------------------------------------------------------- /Classes/Helpers/BWWifiConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWWifiConnection.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 9/14/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWConnection.h" 10 | #import "BWPeerServiceDelegate.h" 11 | #import "BWPeerProxyDelegate.h" 12 | 13 | @interface BWWifiConnection : BWConnection 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/Helpers/BWPeerProxyDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWPeerProxyDelegate.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class BWPeerProxy; 12 | 13 | @protocol BWPeerProxyDelegate 14 | 15 | @optional 16 | 17 | - (void)proxyDidConnect:(BWPeerProxy *)proxy; 18 | - (void)proxyDidDisconnect:(BWPeerProxy *)proxy; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Classes/Helpers/BWPeerServiceDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWPeerServiceDelegate.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class BWPeerService; 13 | 14 | @protocol BWPeerServiceDelegate 15 | 16 | @optional 17 | - (void)peerService:(BWPeerService *)service didReceiveCallRequestFromPeer:(NSString *)peerID; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/AppDelegate/BWAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWAppDelegate.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 6/29/09. 6 | // Copyright akosma software 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class BWRootController; 12 | 13 | @interface BWAppDelegate : NSObject 14 | 15 | @property (nonatomic, retain) IBOutlet UIWindow *window; 16 | @property (nonatomic, retain) IBOutlet BWRootController *controller; 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /Classes/Controllers/BWBrowserController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWBrowserController.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BWBrowserControllerDelegate.h" 11 | 12 | @class BWPeerBrowser; 13 | 14 | @interface BWBrowserController : UITableViewController 15 | 16 | @property (nonatomic, retain) BWPeerBrowser *browser; 17 | @property (nonatomic, assign) id delegate; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/Controllers/BWBrowserControllerDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWBrowserControllerDelegate.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class BWBrowserController; 12 | @class BWPeerProxy; 13 | 14 | 15 | @protocol BWBrowserControllerDelegate 16 | 17 | @optional 18 | - (void)peersBrowserController:(BWBrowserController *)controller didSelectPeer:(BWPeerProxy *)peer; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Classes/Helpers/BWMessageObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWMessageObject.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | typedef enum { 13 | BWMessageKindNone = 0, 14 | BWMessageKindVoiceCallRequest = 1, 15 | BWMessageKindVoiceCallRequestDenied = 2 16 | } BWMessageKind; 17 | 18 | @interface BWMessageObject : NSObject 19 | 20 | @property (nonatomic) BWMessageKind kind; 21 | @property (nonatomic, retain) NSData *body; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/Helpers/BWMessageBroker.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWMessageBroker.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BWMessageBrokerDelegate.h" 11 | 12 | @class AsyncSocket; 13 | @class BWMessageObject; 14 | 15 | @interface BWMessageBroker : NSObject 16 | 17 | @property (nonatomic, assign) id delegate; 18 | 19 | - (id)initWithAsyncSocket:(AsyncSocket *)socket; 20 | - (void)sendMessage:(BWMessageObject *)newMessage; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Classes/Helpers/BWMessageBrokerDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWMessageBrokerDelegate.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class BWMessageBroker; 12 | @class BWMessageObject; 13 | 14 | @protocol BWMessageBrokerDelegate 15 | 16 | @optional 17 | 18 | - (void)messageBroker:(BWMessageBroker *)server didSendMessage:(BWMessageObject *)message; 19 | 20 | - (void)messageBroker:(BWMessageBroker *)server didReceiveMessage:(BWMessageObject *)message; 21 | 22 | - (void)messageBrokerDidDisconnectUnexpectedly:(BWMessageBroker *)server; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/AppDelegate/BWAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWAppDelegate.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 6/29/09. 6 | // Copyright akosma software 2009. All rights reserved. 7 | // 8 | 9 | #import "BWAppDelegate.h" 10 | #import "BWRootController.h" 11 | 12 | @implementation BWAppDelegate 13 | 14 | @synthesize window = _window; 15 | @synthesize controller = _controller; 16 | 17 | - (void)applicationDidFinishLaunching:(UIApplication *)application 18 | { 19 | self.window.rootViewController = self.controller; 20 | [self.window makeKeyAndVisible]; 21 | } 22 | 23 | - (void)dealloc 24 | { 25 | [_window release]; 26 | [_controller release]; 27 | [super dealloc]; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Classes/Helpers/BWConnectionDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWConnectionDelegate.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 9/14/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class BWConnection; 12 | 13 | 14 | @protocol BWConnectionDelegate 15 | 16 | @optional 17 | 18 | - (void)connection:(BWConnection *)connection didFailWithError:(NSError *)error; 19 | - (void)connectionIsConnecting:(BWConnection *)connection; 20 | - (void)connectionDidConnect:(BWConnection *)connection; 21 | - (void)connectionDidDisconnect:(BWConnection *)connection; 22 | - (void)connectionDidReceiveCall:(BWConnection *)connection; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/Helpers/BWPeerBrowser.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWPeerBrowser.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString * const PeerBrowserDidChangeCountNotification; 12 | 13 | @class BWPeerProxy; 14 | 15 | @interface BWPeerBrowser : NSObject 16 | 17 | @property (nonatomic, retain) NSMutableArray *peerArray; 18 | @property (nonatomic, retain) NSNetServiceBrowser *peerBrowser; 19 | 20 | - (void)startSearchingForPeers; 21 | - (void)stopSearchingForPeers; 22 | - (NSInteger)connectedPeersCount; 23 | - (BWPeerProxy *)peerAtIndex:(NSUInteger)index; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Classes/Helpers/BWPeerService.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWPeerService.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BWMessageBrokerDelegate.h" 11 | #import "BWPeerServiceDelegate.h" 12 | 13 | @class BWMessageBroker; 14 | 15 | 16 | @interface BWPeerService : NSObject 18 | 19 | @property (nonatomic, retain) NSNetService *netService; 20 | @property (nonatomic, retain) BWMessageBroker *messageBroker; 21 | @property (nonatomic, getter = isConnected) BOOL connected; 22 | @property (nonatomic, assign) id delegate; 23 | 24 | - (void)startService; 25 | - (void)stopService; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Classes/Controllers/BWRootController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWRootController.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import "BWConnectionDelegate.h" 14 | 15 | @interface BWRootController : UIViewController 18 | 19 | @property (nonatomic, retain) IBOutlet UILabel *statusLabel; 20 | @property (nonatomic, retain) IBOutlet UIButton *connectButton; 21 | 22 | - (IBAction)showConnectionKinds:(id)sender; 23 | - (IBAction)openWebsite:(id)sender; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Classes/Helpers/BWPeerProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWPeerProxy.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "BWMessageBrokerDelegate.h" 12 | #import "BWPeerProxyDelegate.h" 13 | 14 | @interface BWPeerProxy : NSObject 16 | 17 | @property (nonatomic, getter = isConnected) BOOL connected; 18 | @property (nonatomic, assign) id delegate; 19 | @property (nonatomic, readonly) NSString *serviceName; 20 | 21 | + (id)proxyWithService:(NSNetService *)service; 22 | - (id)initWithService:(NSNetService *)service; 23 | - (void)connect; 24 | - (void)sendVoiceCallRequestWithPeerID:(NSString *)peerID; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/Helpers/BWMessageObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWMessageObject.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWMessageObject.h" 10 | 11 | 12 | @implementation BWMessageObject 13 | 14 | @synthesize kind = _kind; 15 | @synthesize body = _body; 16 | 17 | - (id)init 18 | { 19 | self = [super init]; 20 | if (self) 21 | { 22 | _kind = BWMessageKindNone; 23 | } 24 | return self; 25 | } 26 | 27 | - (id)initWithCoder:(NSCoder *)coder 28 | { 29 | self = [super init]; 30 | if (self) 31 | { 32 | _kind = (BWMessageKind)[coder decodeIntForKey:@"kind"]; 33 | _body = [[coder decodeObjectForKey:@"body"] retain]; 34 | } 35 | return self; 36 | } 37 | 38 | - (void)encodeWithCoder:(NSCoder *)coder 39 | { 40 | [coder encodeInt:self.kind forKey:@"kind"]; 41 | [coder encodeObject:self.body forKey:@"body"]; 42 | } 43 | 44 | - (void)dealloc 45 | { 46 | [_body release]; 47 | _body = nil; 48 | 49 | [super dealloc]; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Classes/Helpers/BWConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // BWConnection.h 3 | // bluewoki 4 | // 5 | // Created by Adrian on 9/14/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "BWConnectionDelegate.h" 12 | #import "BWBrowserControllerDelegate.h" 13 | 14 | @interface BWConnection : NSObject 18 | 19 | @property (nonatomic, assign) id delegate; 20 | @property (nonatomic, copy) NSString *remotePeerID; 21 | @property (nonatomic, getter = isConnected) BOOL connected; 22 | @property (nonatomic, readonly) NSString *otherPeerName; 23 | @property (nonatomic, retain) GKSession *chatSession; 24 | 25 | + (id)connection; 26 | 27 | - (void)connect; 28 | - (void)disconnect; 29 | - (void)answerIncomingCall; 30 | - (void)denyIncomingCall; 31 | - (GKSession *)createChatSession; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009, Adrian Kosmaczewski / akosma software 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | Neither the name of Adrian Kosmaczewski or akosma software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | bluewoki 2 | ======== 3 | 4 | bluewoki is a simple walkie-talkie over Bluetooth and wifi for devices 5 | running iOS 4.0+. It allows iPhone and iPod Touch devices to connect to 6 | each other via Bluetooth or a wifi network to exchange vocal messages. 7 | When using Bluetooth, the devices must be close enough to each other so 8 | that they can connect. 9 | 10 | The application is [available at the App Store][1]. 11 | 12 | The source code is released under a liberal BSD license. The project 13 | uses and includes the [AsyncSocket library][2], which is in the public 14 | domain. 15 | 16 | Xcode 4.1 is required to open the project. 17 | 18 | FAQ 19 | --- 20 | 21 | ### Why charging for open source software? 22 | 23 | This question has already been raised in the case of [Tux Raider World 24 | Challenge][3] and I will simply quote one of its FAQ entries: 25 | 26 | > Tux Rider is an Open Source software that complies to the GPLv2. Hence 27 | > the source code is made available to all clients. Yet, the GPLv2 28 | > doesn't says that the author cannot be rewarded for his work. In fact, 29 | > there is a widely spread misunderstanding that says that Open Source 30 | > equals free of charge. The free software foundation clearly explains: 31 | > “Free software is a matter of liberty, not price. To understand the 32 | > concept, you should think of free as in free speech, not as in free 33 | > beer.” — The Free Software Definition (GNU - FSF) 34 | 35 | ### Any other comment? 36 | 37 | Read this [amazing article by Zed Shaw][4]. I completely agree with his 38 | views on licensing. 39 | 40 | [1]:http://itunes.com/apps/bluewoki 41 | [2]:http://code.google.com/p/cocoaasyncsocket/ 42 | [3]:http://barlow-server.com/tuxriderworldchallenge/ 43 | [4]:http://zedshaw.com/blog/2009-07-13.html 44 | 45 | -------------------------------------------------------------------------------- /bluewoki-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleDocumentTypes 10 | 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleIconFile 14 | 15 | CFBundleIconFiles 16 | 17 | Icon.png 18 | Icon-72.png 19 | Icon-Small-50.png 20 | Icon-Small.png 21 | Icon-Small@2x.png 22 | Icon@2x.png 23 | 24 | CFBundleIdentifier 25 | com.akosma.bluewoki 26 | CFBundleInfoDictionaryVersion 27 | 6.0 28 | CFBundleName 29 | ${PRODUCT_NAME} 30 | CFBundlePackageType 31 | APPL 32 | CFBundleSignature 33 | ???? 34 | CFBundleURLTypes 35 | 36 | CFBundleVersion 37 | 2.0 38 | LSRequiresIPhoneOS 39 | 40 | NSMainNibFile 41 | MainWindow 42 | UIBackgroundModes 43 | 44 | audio 45 | voip 46 | 47 | UIPrerenderedIcon 48 | 49 | UIStatusBarStyle 50 | UIStatusBarStyleBlackOpaque 51 | UISupportedInterfaceOrientations 52 | 53 | UIInterfaceOrientationPortrait 54 | 55 | UTExportedTypeDeclarations 56 | 57 | UTImportedTypeDeclarations 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Classes/Helpers/BWConnection.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWConnection.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 9/14/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWConnection.h" 10 | 11 | @implementation BWConnection 12 | 13 | @synthesize delegate = _delegate; 14 | @synthesize remotePeerID = _otherPeerID; 15 | @synthesize chatSession = _chatSession; 16 | @synthesize connected = _connected; 17 | @dynamic otherPeerName; 18 | 19 | + (id)connection 20 | { 21 | return [[[[self class] alloc] init] autorelease]; 22 | } 23 | 24 | - (void)dealloc 25 | { 26 | [_chatSession release]; 27 | [_otherPeerID release]; 28 | [super dealloc]; 29 | } 30 | 31 | #pragma mark - Public methods 32 | 33 | - (NSString *)otherPeerName 34 | { 35 | return [self.chatSession displayNameForPeer:self.remotePeerID]; 36 | } 37 | 38 | - (void)connect 39 | { 40 | // Overridden by subclasses 41 | } 42 | 43 | - (void)disconnect 44 | { 45 | // Overridden by subclasses 46 | } 47 | 48 | - (void)answerIncomingCall 49 | { 50 | // Overridden by subclasses 51 | } 52 | 53 | - (void)denyIncomingCall 54 | { 55 | // Overridden by subclasses 56 | } 57 | 58 | - (GKSession *)createChatSession 59 | { 60 | NSString *sessionId = @"bluewoki"; 61 | NSString *name = [[UIDevice currentDevice] name]; 62 | GKSession* session = [[[GKSession alloc] initWithSessionID:sessionId 63 | displayName:name 64 | sessionMode:GKSessionModePeer] autorelease]; 65 | return session; 66 | } 67 | 68 | #pragma mark - GKVoiceChatClient methods 69 | 70 | - (NSString *)participantID 71 | { 72 | return self.chatSession.peerID; 73 | } 74 | 75 | - (void)voiceChatService:(GKVoiceChatService *)voiceChatService 76 | sendData:(NSData *)data 77 | toParticipantID:(NSString *)participantID 78 | { 79 | [self.chatSession sendData:data 80 | toPeers:[NSArray arrayWithObject:participantID] 81 | withDataMode:GKSendDataReliable 82 | error:nil]; 83 | } 84 | 85 | - (void)receiveData:(NSData *)data 86 | fromPeer:(NSString *)peer 87 | inSession:(GKSession *)session 88 | context:(void *)context; 89 | { 90 | [[GKVoiceChatService defaultVoiceChatService] receivedData:data 91 | fromParticipantID:peer]; 92 | } 93 | 94 | - (void)voiceChatService:(GKVoiceChatService *)voiceChatService 95 | didStopWithParticipantID:(NSString *)participantID 96 | error:(NSError *)error 97 | { 98 | self.connected = NO; 99 | if ([self.delegate respondsToSelector:@selector(connectionDidDisconnect:)]) 100 | { 101 | [self.delegate connectionDidDisconnect:self]; 102 | } 103 | } 104 | 105 | - (void)voiceChatService:(GKVoiceChatService *)voiceChatService 106 | didStartWithParticipantID:(NSString *)participantID 107 | { 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /Classes/Helpers/BWPeerBrowser.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWPeerBrowser.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWPeerBrowser.h" 10 | #import "BWProtocol.h" 11 | #import "BWPeerProxy.h" 12 | 13 | NSString * const PeerBrowserDidChangeCountNotification = @"PeerBrowserDidChangeCountNotification"; 14 | 15 | 16 | @implementation BWPeerBrowser 17 | 18 | @synthesize peerArray = _peerArray; 19 | @synthesize peerBrowser = _peerBrowser; 20 | 21 | - (id)init 22 | { 23 | self = [super init]; 24 | if (self) 25 | { 26 | _peerArray = [[NSMutableArray alloc] init]; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)dealloc 32 | { 33 | [self stopSearchingForPeers]; 34 | 35 | [_peerArray release]; 36 | 37 | [super dealloc]; 38 | } 39 | 40 | #pragma mark - Public methods 41 | 42 | - (NSInteger)connectedPeersCount 43 | { 44 | return [self.peerArray count]; 45 | } 46 | 47 | - (void)startSearchingForPeers 48 | { 49 | self.peerBrowser = [[[NSNetServiceBrowser alloc] init] autorelease]; 50 | [self.peerBrowser setDelegate:self]; 51 | [self.peerBrowser searchForServicesOfType:BLUEWOKI_PROTOCOL_NAME 52 | inDomain:@""]; 53 | } 54 | 55 | - (void)stopSearchingForPeers 56 | { 57 | [self.peerBrowser stop]; 58 | self.peerBrowser = nil; 59 | [self.peerArray removeAllObjects]; 60 | [[NSNotificationCenter defaultCenter] postNotificationName:PeerBrowserDidChangeCountNotification 61 | object:self]; 62 | } 63 | 64 | - (BWPeerProxy *)peerAtIndex:(NSUInteger)index 65 | { 66 | return [self.peerArray objectAtIndex:index]; 67 | } 68 | 69 | #pragma mark - NSNetServiceBrowser delegate methods 70 | 71 | - (void)netServiceBrowser:(NSNetServiceBrowser *)browser 72 | didFindService:(NSNetService *)service 73 | moreComing:(BOOL)more 74 | { 75 | if (!more) 76 | { 77 | if (![[service name] isEqualToString:[UIDevice currentDevice].name]) 78 | { 79 | BWPeerProxy *peer = [BWPeerProxy proxyWithService:service]; 80 | [self.peerArray addObject:peer]; 81 | 82 | [[NSNotificationCenter defaultCenter] postNotificationName:PeerBrowserDidChangeCountNotification 83 | object:self]; 84 | } 85 | } 86 | } 87 | 88 | - (void)netServiceBrowser:(NSNetServiceBrowser *)browser 89 | didRemoveService:(NSNetService *)service 90 | moreComing:(BOOL)more 91 | { 92 | if (!more) 93 | { 94 | BWPeerProxy *peerToRemove = nil; 95 | for (BWPeerProxy *proxy in self.peerArray) 96 | { 97 | if ([proxy.serviceName isEqualToString:[service name]]) 98 | { 99 | peerToRemove = proxy; 100 | } 101 | } 102 | 103 | if (peerToRemove != nil) 104 | { 105 | [self.peerArray removeObject:peerToRemove]; 106 | } 107 | 108 | [[NSNotificationCenter defaultCenter] postNotificationName:PeerBrowserDidChangeCountNotification 109 | object:self]; 110 | } 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /Classes/Helpers/BWPeerProxy.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWPeerProxy.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWPeerProxy.h" 10 | #import "BWProtocol.h" 11 | #import "BWMessageBroker.h" 12 | #import "AsyncSocket.h" 13 | #import "BWMessageObject.h" 14 | 15 | @interface BWPeerProxy () 16 | 17 | @property (nonatomic, retain) NSNetService *netService; 18 | @property (nonatomic, retain) NSNetService *service; 19 | @property (nonatomic, retain) AsyncSocket *socket; 20 | @property (nonatomic, retain) BWMessageBroker *messageBroker; 21 | 22 | @end 23 | 24 | 25 | @implementation BWPeerProxy 26 | 27 | @synthesize netService = _netService; 28 | @synthesize messageBroker = _messageBroker; 29 | @synthesize service = _service; 30 | @synthesize connected = _connected; 31 | @synthesize socket = _socket; 32 | @synthesize delegate = _delegate; 33 | @dynamic serviceName; 34 | 35 | + (id)proxyWithService:(NSNetService *)service 36 | { 37 | return [[[[self class] alloc] initWithService:service] autorelease]; 38 | } 39 | 40 | - (id)initWithService:(NSNetService *)service 41 | { 42 | self = [super init]; 43 | if (self) 44 | { 45 | _connected = NO; 46 | 47 | _service = [service retain]; 48 | [_service setDelegate:self]; 49 | } 50 | return self; 51 | } 52 | 53 | - (void)dealloc 54 | { 55 | [_messageBroker release]; 56 | [_service release]; 57 | [_socket release]; 58 | 59 | _delegate = nil; 60 | 61 | [super dealloc]; 62 | } 63 | 64 | #pragma mark - Public methods 65 | 66 | - (NSString *)serviceName 67 | { 68 | return [self.service name]; 69 | } 70 | 71 | - (void)connect 72 | { 73 | [self.service resolveWithTimeout:0]; 74 | } 75 | 76 | - (void)sendVoiceCallRequestWithPeerID:(NSString *)peerID 77 | { 78 | BWMessageObject *newMessage = [[[BWMessageObject alloc] init] autorelease]; 79 | newMessage.kind = BWMessageKindVoiceCallRequest; 80 | newMessage.body = [peerID dataUsingEncoding:NSUTF8StringEncoding]; 81 | [self.messageBroker sendMessage:newMessage]; 82 | } 83 | 84 | #pragma mark - NSNetServiceDelegate methods 85 | 86 | - (void)netServiceDidResolveAddress:(NSNetService *)service 87 | { 88 | self.socket = [[[AsyncSocket alloc] init] autorelease]; 89 | [self.socket setDelegate:self]; 90 | [self.socket connectToAddress:service.addresses.lastObject error:nil]; 91 | } 92 | 93 | - (void)netService:(NSNetService *)service didNotResolve:(NSDictionary *)errorDict 94 | { 95 | NSLog(@"Could not resolve: %@", errorDict); 96 | } 97 | 98 | #pragma mark - Socket Callbacks 99 | 100 | -(void)onSocketDidDisconnect:(AsyncSocket *)sock 101 | { 102 | self.socket = nil; 103 | self.messageBroker = nil; 104 | self.connected = NO; 105 | 106 | if ([self.delegate performSelector:@selector(proxyDidDisconnect:)]) 107 | { 108 | [self.delegate proxyDidDisconnect:self]; 109 | } 110 | } 111 | 112 | -(BOOL)onSocketWillConnect:(AsyncSocket *)sock 113 | { 114 | if (self.messageBroker == nil) 115 | { 116 | [sock retain]; 117 | return YES; 118 | } 119 | return NO; 120 | } 121 | 122 | -(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port 123 | { 124 | self.messageBroker = [[[BWMessageBroker alloc] initWithAsyncSocket:sock] autorelease]; 125 | [sock release]; 126 | self.messageBroker.delegate = self; 127 | self.connected = YES; 128 | 129 | if ([self.delegate performSelector:@selector(proxyDidConnect:)]) 130 | { 131 | [self.delegate proxyDidConnect:self]; 132 | } 133 | } 134 | 135 | #pragma mark - MessageBroker Delegate Methods 136 | 137 | - (void)messageBroker:(BWMessageBroker *)server didReceiveMessage:(BWMessageObject *)message 138 | { 139 | switch (message.kind) 140 | { 141 | default: 142 | break; 143 | } 144 | } 145 | 146 | @end 147 | -------------------------------------------------------------------------------- /Classes/Helpers/BWPeerService.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWPeerService.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWPeerService.h" 10 | #import "BWProtocol.h" 11 | #import "BWMessageBroker.h" 12 | #import "AsyncSocket.h" 13 | #import "BWMessageObject.h" 14 | 15 | 16 | @interface BWPeerService () 17 | 18 | @property (readwrite, retain) AsyncSocket *listeningSocket; 19 | @property (readwrite, retain) AsyncSocket *connectionSocket; 20 | 21 | @end 22 | 23 | 24 | @implementation BWPeerService 25 | 26 | @synthesize messageBroker = _messageBroker; 27 | @synthesize listeningSocket = _listeningSocket; 28 | @synthesize connectionSocket = _connectionSocket; 29 | @synthesize netService = _netService; 30 | @synthesize connected = _connected; 31 | @synthesize delegate = _delegate; 32 | 33 | - (void)dealloc 34 | { 35 | [self stopService]; 36 | [_messageBroker release]; 37 | _delegate = nil; 38 | 39 | [super dealloc]; 40 | } 41 | 42 | #pragma mark - Public methods 43 | 44 | -(void)startService 45 | { 46 | NSError *error; 47 | self.listeningSocket = [[[AsyncSocket alloc] init] autorelease]; 48 | [self.listeningSocket setDelegate:self]; 49 | if (![self.listeningSocket acceptOnPort:0 error:&error]) 50 | { 51 | NSLog(@"Failed to create listening socket"); 52 | return; 53 | } 54 | 55 | self.netService = [[[NSNetService alloc] initWithDomain:@"" 56 | type:BLUEWOKI_PROTOCOL_NAME 57 | name:[UIDevice currentDevice].name 58 | port:self.listeningSocket.localPort] autorelease]; 59 | self.netService.delegate = self; 60 | [self.netService publish]; 61 | } 62 | 63 | -(void)stopService 64 | { 65 | self.listeningSocket = nil; 66 | self.connectionSocket = nil; 67 | self.messageBroker.delegate = nil; 68 | self.messageBroker = nil; 69 | 70 | [self.netService stop]; 71 | self.netService = nil; 72 | } 73 | 74 | #pragma mark - Socket Callbacks 75 | 76 | - (BOOL)onSocketWillConnect:(AsyncSocket *)sock 77 | { 78 | if (self.connectionSocket == nil) 79 | { 80 | self.connectionSocket = sock; 81 | return YES; 82 | } 83 | return NO; 84 | } 85 | 86 | - (void)onSocketDidDisconnect:(AsyncSocket *)sock 87 | { 88 | if (sock == self.connectionSocket) 89 | { 90 | self.connectionSocket = nil; 91 | self.messageBroker = nil; 92 | self.connected = NO; 93 | } 94 | } 95 | 96 | - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port 97 | { 98 | self.messageBroker = [[[BWMessageBroker alloc] initWithAsyncSocket:sock] autorelease]; 99 | self.messageBroker.delegate = self; 100 | self.connected = YES; 101 | } 102 | 103 | #pragma mark - Net Service Delegate Methods 104 | 105 | - (void)netService:(NSNetService *)aNetService didNotPublish:(NSDictionary *)dict 106 | { 107 | NSLog(@"Failed to publish: %@", dict); 108 | } 109 | 110 | #pragma mark - MessageBroker Delegate Methods 111 | 112 | - (void)messageBroker:(BWMessageBroker *)server didReceiveMessage:(BWMessageObject *)message 113 | { 114 | switch (message.kind) 115 | { 116 | case BWMessageKindVoiceCallRequest: 117 | { 118 | NSString *peerID = [[[NSString alloc] initWithData:message.body 119 | encoding:NSUTF8StringEncoding] autorelease]; 120 | if ([self.delegate respondsToSelector:@selector(peerService:didReceiveCallRequestFromPeer:)]) 121 | { 122 | [self.delegate peerService:self didReceiveCallRequestFromPeer:peerID]; 123 | } 124 | break; 125 | } 126 | 127 | default: 128 | break; 129 | } 130 | } 131 | 132 | @end 133 | -------------------------------------------------------------------------------- /Classes/Controllers/BWBrowserController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWBrowserController.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWBrowserController.h" 10 | #import "BWPeerBrowser.h" 11 | #import "BWPeerProxy.h" 12 | 13 | @interface BWBrowserController () 14 | 15 | @property (nonatomic, retain) UIBarButtonItem *cancelItem; 16 | 17 | @end 18 | 19 | 20 | @implementation BWBrowserController 21 | 22 | @synthesize browser = _browser; 23 | @synthesize cancelItem = _cancelItem; 24 | @synthesize delegate = _delegate; 25 | 26 | - (id)init 27 | { 28 | self = [super initWithStyle:UITableViewStyleGrouped]; 29 | if (self) 30 | { 31 | } 32 | return self; 33 | } 34 | 35 | - (void)dealloc 36 | { 37 | [_browser release]; 38 | [_cancelItem release]; 39 | _delegate = nil; 40 | [super dealloc]; 41 | } 42 | 43 | - (void)didReceiveMemoryWarning 44 | { 45 | [super didReceiveMemoryWarning]; 46 | } 47 | 48 | #pragma mark - View lifecycle 49 | 50 | - (void)viewDidLoad 51 | { 52 | [super viewDidLoad]; 53 | 54 | // This makes sure that the remote devices available are updated live 55 | [[NSNotificationCenter defaultCenter] addObserver:self.tableView 56 | selector:@selector(reloadData) 57 | name:PeerBrowserDidChangeCountNotification 58 | object:nil]; 59 | 60 | self.cancelItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel 61 | target:self 62 | action:@selector(cancel:)] autorelease]; 63 | self.navigationItem.rightBarButtonItem = self.cancelItem; 64 | self.navigationController.navigationBar.barStyle = UIBarStyleBlack; 65 | self.title = @"bluewoki online"; 66 | self.tableView.backgroundColor = [UIColor darkGrayColor]; 67 | self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 68 | } 69 | 70 | - (void)cancel:(id)sender 71 | { 72 | [self.browser stopSearchingForPeers]; 73 | self.delegate = nil; 74 | [self dismissModalViewControllerAnimated:YES]; 75 | } 76 | 77 | - (void)viewDidUnload 78 | { 79 | [super viewDidUnload]; 80 | } 81 | 82 | - (void)viewWillAppear:(BOOL)animated 83 | { 84 | [super viewWillAppear:animated]; 85 | self.browser = [[[BWPeerBrowser alloc] init] autorelease]; 86 | [self.browser startSearchingForPeers]; 87 | } 88 | 89 | - (void)viewWillDisappear:(BOOL)animated 90 | { 91 | [super viewWillDisappear:animated]; 92 | [self.browser stopSearchingForPeers]; 93 | self.browser = nil; 94 | } 95 | 96 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 97 | { 98 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 99 | } 100 | 101 | #pragma mark - Table view data source 102 | 103 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 104 | { 105 | return 1; 106 | } 107 | 108 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 109 | { 110 | return [self.browser connectedPeersCount]; 111 | } 112 | 113 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 114 | { 115 | static NSString *CellIdentifier = @"Cell"; 116 | 117 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 118 | if (cell == nil) 119 | { 120 | cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 121 | reuseIdentifier:CellIdentifier] autorelease]; 122 | } 123 | 124 | BWPeerProxy *peer = [self.browser peerAtIndex:indexPath.row]; 125 | cell.textLabel.text = peer.serviceName; 126 | 127 | return cell; 128 | } 129 | 130 | #pragma mark - Table view delegate 131 | 132 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 133 | { 134 | BWPeerProxy *peer = [self.browser peerAtIndex:indexPath.row]; 135 | if ([self.delegate respondsToSelector:@selector(peersBrowserController:didSelectPeer:)]) 136 | { 137 | [self.delegate peersBrowserController:self didSelectPeer:peer]; 138 | } 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /Classes/Helpers/BWBluetoothConnection.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWBluetoothConnection.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 9/14/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWBluetoothConnection.h" 10 | 11 | @interface BWBluetoothConnection () 12 | 13 | @property (nonatomic, retain) GKPeerPickerController *pickerController; 14 | 15 | @end 16 | 17 | 18 | @implementation BWBluetoothConnection 19 | 20 | @synthesize pickerController = _pickerController; 21 | 22 | - (void)dealloc 23 | { 24 | [_pickerController release]; 25 | [super dealloc]; 26 | } 27 | 28 | #pragma mark - Public methods 29 | 30 | - (void)connect 31 | { 32 | [GKVoiceChatService defaultVoiceChatService].client = self; 33 | self.connected = NO; 34 | 35 | self.pickerController = [[[GKPeerPickerController alloc] init] autorelease]; 36 | self.pickerController.delegate = self; 37 | self.pickerController.connectionTypesMask = GKPeerPickerConnectionTypeNearby; 38 | [self.pickerController show]; 39 | } 40 | 41 | - (void)disconnect 42 | { 43 | [[GKVoiceChatService defaultVoiceChatService] stopVoiceChatWithParticipantID:self.remotePeerID]; 44 | [GKVoiceChatService defaultVoiceChatService].client = nil; 45 | 46 | [self.chatSession disconnectFromAllPeers]; 47 | self.chatSession.delegate = nil; 48 | self.chatSession = nil; 49 | self.connected = NO; 50 | self.remotePeerID = nil; 51 | } 52 | 53 | #pragma mark - GKPeerPickerControllerDelegate methods 54 | 55 | - (void)peerPickerController:(GKPeerPickerController *)picker 56 | didConnectPeer:(NSString *)peerID 57 | toSession:(GKSession *)session 58 | { 59 | if (picker == self.pickerController) 60 | { 61 | self.remotePeerID = peerID; 62 | self.chatSession = session; 63 | self.chatSession.delegate = self; 64 | [self.chatSession setDataReceiveHandler:self withContext:nil]; 65 | 66 | self.pickerController.delegate = nil; 67 | [self.pickerController dismiss]; 68 | self.pickerController = nil; 69 | 70 | [[GKVoiceChatService defaultVoiceChatService] startVoiceChatWithParticipantID:self.remotePeerID 71 | error:nil]; 72 | 73 | self.connected = YES; 74 | if ([self.delegate respondsToSelector:@selector(connectionDidConnect:)]) 75 | { 76 | [self.delegate connectionDidConnect:self]; 77 | } 78 | } 79 | } 80 | 81 | - (GKSession *)peerPickerController:(GKPeerPickerController *)picker 82 | sessionForConnectionType:(GKPeerPickerConnectionType)type 83 | { 84 | return [self createChatSession]; 85 | } 86 | 87 | - (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker 88 | { 89 | if (picker == self.pickerController) 90 | { 91 | self.connected = NO; 92 | } 93 | } 94 | 95 | #pragma mark - GKSessionDelegate methods 96 | 97 | - (void)session:(GKSession *)session 98 | peer:(NSString *)peerID 99 | didChangeState:(GKPeerConnectionState)state 100 | { 101 | if (session == self.chatSession) 102 | { 103 | switch (state) 104 | { 105 | case GKPeerStateAvailable: 106 | break; 107 | 108 | case GKPeerStateUnavailable: 109 | break; 110 | 111 | case GKPeerStateConnected: 112 | break; 113 | 114 | case GKPeerStateDisconnected: 115 | { 116 | self.connected = NO; 117 | if ([self.delegate respondsToSelector:@selector(connectionDidDisconnect:)]) 118 | { 119 | [self.delegate connectionDidDisconnect:self]; 120 | } 121 | break; 122 | } 123 | 124 | case GKPeerStateConnecting: 125 | { 126 | if ([self.delegate respondsToSelector:@selector(connectionIsConnecting:)]) 127 | { 128 | [self.delegate connectionIsConnecting:self]; 129 | } 130 | break; 131 | } 132 | 133 | default: 134 | break; 135 | } 136 | } 137 | } 138 | 139 | - (void)session:(GKSession *)session 140 | connectionWithPeerFailed:(NSString *)peerID 141 | withError:(NSError *)error 142 | { 143 | if (session == self.chatSession) 144 | { 145 | self.connected = NO; 146 | if ([self.delegate respondsToSelector:@selector(connection:didFailWithError:)]) 147 | { 148 | [self.delegate connection:self didFailWithError:error]; 149 | } 150 | } 151 | } 152 | 153 | @end 154 | -------------------------------------------------------------------------------- /Classes/Helpers/BWMessageBroker.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWMessageBroker.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWMessageBroker.h" 10 | #import "AsyncSocket.h" 11 | #import "BWMessageObject.h" 12 | 13 | static const unsigned int MESSAGE_HEADER_SIZE = sizeof(UInt64); 14 | static const float SOCKET_TIMEOUT = -1.0; 15 | 16 | @interface BWMessageBroker () 17 | 18 | @property (nonatomic, retain) AsyncSocket *socket; 19 | @property (nonatomic) BOOL connectionLostUnexpectedly; 20 | @property (nonatomic, retain) NSMutableArray *messageQueue; 21 | @property (nonatomic, getter = isPaused) BOOL paused; 22 | 23 | @end 24 | 25 | 26 | @implementation BWMessageBroker 27 | 28 | @synthesize delegate = _delegate; 29 | @synthesize socket = _socket; 30 | @synthesize connectionLostUnexpectedly = _connectionLostUnexpectedly; 31 | @synthesize messageQueue = _messageQueue; 32 | @synthesize paused = _paused; 33 | 34 | -(id)initWithAsyncSocket:(AsyncSocket *)newSocket 35 | { 36 | self = [super init]; 37 | if (self) 38 | { 39 | _socket = [newSocket retain]; 40 | [_socket setDelegate:self]; 41 | _messageQueue = [[NSMutableArray alloc] init]; 42 | [_socket readDataToLength:MESSAGE_HEADER_SIZE 43 | withTimeout:SOCKET_TIMEOUT 44 | tag:0]; 45 | } 46 | return self; 47 | } 48 | 49 | - (void)dealloc 50 | { 51 | _delegate = nil; 52 | 53 | [_socket setDelegate:nil]; 54 | if ([_socket isConnected]) 55 | { 56 | [_socket disconnect]; 57 | } 58 | [_socket release]; 59 | _socket = nil; 60 | 61 | [_messageQueue release]; 62 | _messageQueue = nil; 63 | 64 | [super dealloc]; 65 | } 66 | 67 | #pragma mark - Public methods 68 | 69 | -(void)sendMessage:(BWMessageObject *)message 70 | { 71 | [self.messageQueue addObject:message]; 72 | NSData *messageData = [NSKeyedArchiver archivedDataWithRootObject:message]; 73 | 74 | UInt64 header[1]; 75 | header[0] = [messageData length]; 76 | header[0] = CFSwapInt64HostToLittle(header[0]); 77 | 78 | NSData *headerData = [NSData dataWithBytes:header 79 | length:MESSAGE_HEADER_SIZE]; 80 | [self.socket writeData:headerData 81 | withTimeout:SOCKET_TIMEOUT 82 | tag:(long)0]; 83 | 84 | [self.socket writeData:messageData 85 | withTimeout:SOCKET_TIMEOUT 86 | tag:(long)1]; 87 | } 88 | 89 | #pragma mark - AsyncSocket delegate methods 90 | 91 | - (void)onSocketDidDisconnect:(AsyncSocket *)sock 92 | { 93 | if (self.connectionLostUnexpectedly) 94 | { 95 | if ([self.delegate respondsToSelector:@selector(messageBroker:didDisconnectUnexpectedly:)]) 96 | { 97 | [self.delegate messageBrokerDidDisconnectUnexpectedly:self]; 98 | } 99 | } 100 | } 101 | 102 | - (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err 103 | { 104 | self.connectionLostUnexpectedly = YES; 105 | } 106 | 107 | - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 108 | { 109 | switch (tag) 110 | { 111 | case 0: 112 | { 113 | // Header 114 | UInt64 header = *((UInt64*)[data bytes]); 115 | header = CFSwapInt64LittleToHost(header); // Convert from little endian to native 116 | [self.socket readDataToLength:(CFIndex)header 117 | withTimeout:SOCKET_TIMEOUT 118 | tag:(long)1]; 119 | break; 120 | } 121 | 122 | case 1: 123 | { 124 | // Message body. Pass to delegate 125 | if ([self.delegate respondsToSelector:@selector(messageBroker:didReceiveMessage:)] ) 126 | { 127 | BWMessageObject *message = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 128 | [self.delegate messageBroker:self didReceiveMessage:message]; 129 | } 130 | 131 | // Begin listening for next message 132 | if (!self.isPaused) 133 | { 134 | [self.socket readDataToLength:MESSAGE_HEADER_SIZE 135 | withTimeout:SOCKET_TIMEOUT 136 | tag:(long)0]; 137 | } 138 | break; 139 | } 140 | 141 | default: 142 | { 143 | NSLog(@"Unknown tag in read of socket data %d", (int)tag); 144 | break; 145 | } 146 | } 147 | } 148 | 149 | - (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag 150 | { 151 | if (tag == 1) 152 | { 153 | // If the message is now complete, remove from queue, and tell the delegate 154 | BWMessageObject *message = [[[self.messageQueue objectAtIndex:0] retain] autorelease]; 155 | [self.messageQueue removeObjectAtIndex:0]; 156 | if ([self.delegate respondsToSelector:@selector(messageBroker:didSendMessage:)]) 157 | { 158 | [self.delegate messageBroker:self didSendMessage:message]; 159 | } 160 | } 161 | } 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /Classes/Helpers/BWWifiConnection.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWWifiConnection.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 9/14/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWWifiConnection.h" 10 | #import "BWPeerService.h" 11 | #import "BWPeerProxy.h" 12 | 13 | @interface BWWifiConnection () 14 | 15 | @property (nonatomic, retain) BWPeerService *service; 16 | @property (nonatomic, retain) BWPeerProxy *peerProxy; 17 | 18 | @end 19 | 20 | 21 | @implementation BWWifiConnection 22 | 23 | @synthesize service = _service; 24 | @synthesize peerProxy = _peerProxy; 25 | 26 | - (void)dealloc 27 | { 28 | _service.delegate = nil; 29 | [_service release]; 30 | [_peerProxy release]; 31 | [super dealloc]; 32 | } 33 | 34 | #pragma mark - Public methods 35 | 36 | - (void)connect 37 | { 38 | [GKVoiceChatService defaultVoiceChatService].client = self; 39 | self.connected = NO; 40 | 41 | self.chatSession = [self createChatSession]; 42 | self.chatSession.delegate = self; 43 | self.chatSession.available = YES; 44 | [self.chatSession setDataReceiveHandler:self withContext:nil]; 45 | 46 | self.service = [[[BWPeerService alloc] init] autorelease]; 47 | self.service.delegate = self; 48 | [self.service startService]; 49 | } 50 | 51 | - (void)disconnect 52 | { 53 | [[GKVoiceChatService defaultVoiceChatService] stopVoiceChatWithParticipantID:self.remotePeerID]; 54 | [GKVoiceChatService defaultVoiceChatService].client = nil; 55 | 56 | [self.chatSession disconnectFromAllPeers]; 57 | self.chatSession.delegate = nil; 58 | self.chatSession = nil; 59 | self.connected = NO; 60 | self.remotePeerID = nil; 61 | 62 | self.service.delegate = nil; 63 | [self.service stopService]; 64 | } 65 | 66 | - (void)answerIncomingCall 67 | { 68 | [self.chatSession connectToPeer:self.remotePeerID 69 | withTimeout:60]; 70 | } 71 | 72 | - (void)denyIncomingCall 73 | { 74 | self.chatSession.available = NO; 75 | } 76 | 77 | #pragma mark - GKSessionDelegate methods 78 | 79 | - (void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID 80 | { 81 | if (session == self.chatSession) 82 | { 83 | // This method is only called in the device that receives a call 84 | [self.chatSession acceptConnectionFromPeer:peerID 85 | error:nil]; 86 | } 87 | } 88 | 89 | - (void)session:(GKSession *)session 90 | peer:(NSString *)peerID 91 | didChangeState:(GKPeerConnectionState)state 92 | { 93 | if (session == self.chatSession) 94 | { 95 | switch (state) 96 | { 97 | case GKPeerStateAvailable: 98 | break; 99 | 100 | case GKPeerStateUnavailable: 101 | { 102 | self.connected = NO; 103 | if ([self.delegate respondsToSelector:@selector(connectionDidDisconnect:)]) 104 | { 105 | [self.delegate connectionDidDisconnect:self]; 106 | } 107 | break; 108 | } 109 | 110 | case GKPeerStateConnected: 111 | { 112 | self.connected = YES; 113 | 114 | // The PeerID changes during the process... we have to get it again here 115 | // otherwise the display of the remote device name is wrong! 116 | self.remotePeerID = peerID; 117 | [[GKVoiceChatService defaultVoiceChatService] startVoiceChatWithParticipantID:peerID 118 | error:nil]; 119 | 120 | if ([self.delegate respondsToSelector:@selector(connectionDidConnect:)]) 121 | { 122 | [self.delegate connectionDidConnect:self]; 123 | } 124 | break; 125 | } 126 | 127 | case GKPeerStateDisconnected: 128 | { 129 | self.connected = NO; 130 | if ([self.delegate respondsToSelector:@selector(connectionDidDisconnect:)]) 131 | { 132 | [self.delegate connectionDidDisconnect:self]; 133 | } 134 | break; 135 | } 136 | 137 | case GKPeerStateConnecting: 138 | { 139 | break; 140 | } 141 | 142 | default: 143 | break; 144 | } 145 | } 146 | } 147 | 148 | - (void)session:(GKSession *)session 149 | connectionWithPeerFailed:(NSString *)peerID 150 | withError:(NSError *)error 151 | { 152 | if (session == self.chatSession) 153 | { 154 | self.connected = NO; 155 | if ([self.delegate respondsToSelector:@selector(connectionDidDisconnect:)]) 156 | { 157 | [self.delegate connectionDidDisconnect:self]; 158 | } 159 | } 160 | } 161 | 162 | #pragma mark - BWPeerServiceDelegate methods 163 | 164 | - (void)peerService:(BWPeerService *)service didReceiveCallRequestFromPeer:(NSString *)peerID 165 | { 166 | if (service == self.service) 167 | { 168 | // Called when another device is calling this one. 169 | if ([self.delegate respondsToSelector:@selector(connectionIsConnecting:)]) 170 | { 171 | [self.delegate connectionIsConnecting:self]; 172 | } 173 | 174 | self.remotePeerID = peerID; 175 | if ([self.delegate respondsToSelector:@selector(connectionDidReceiveCall:)]) 176 | { 177 | [self.delegate connectionDidReceiveCall:self]; 178 | } 179 | } 180 | } 181 | 182 | #pragma mark - BWBrowserControllerDelegate methods 183 | 184 | - (void)peersBrowserController:(BWBrowserController *)controller didSelectPeer:(BWPeerProxy *)peer 185 | { 186 | self.peerProxy = peer; 187 | self.peerProxy.delegate = self; 188 | 189 | // Upon success, the method proxyDidConnect: below will be called 190 | [self.peerProxy connect]; 191 | 192 | if ([self.delegate respondsToSelector:@selector(connectionIsConnecting:)]) 193 | { 194 | [self.delegate connectionIsConnecting:self]; 195 | } 196 | } 197 | 198 | #pragma mark - BWPeerProxyDelegate methods 199 | 200 | - (void)proxyDidConnect:(BWPeerProxy *)proxy 201 | { 202 | if (proxy == self.peerProxy) 203 | { 204 | // Called when the current device has an open socket with 205 | // the remote device selected by the current user. 206 | [self.peerProxy sendVoiceCallRequestWithPeerID:self.chatSession.peerID]; 207 | } 208 | } 209 | 210 | @end 211 | -------------------------------------------------------------------------------- /Classes/Controllers/BWRootController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BWRootController.m 3 | // bluewoki 4 | // 5 | // Created by Adrian on 5/21/11. 6 | // Copyright 2011 akosma software. All rights reserved. 7 | // 8 | 9 | #import "BWRootController.h" 10 | #import "BWBrowserController.h" 11 | #import "BWBluetoothConnection.h" 12 | #import "BWWifiConnection.h" 13 | 14 | @interface BWRootController () 15 | 16 | @property (nonatomic, retain) BWConnection *connection; 17 | @property (nonatomic, retain) UINavigationController *navController; 18 | @property (nonatomic, retain) BWBrowserController *peersBrowserController; 19 | 20 | - (void)closeConnectionWithMessage:(NSString *)message; 21 | 22 | @end 23 | 24 | 25 | @implementation BWRootController 26 | 27 | @synthesize statusLabel = _statusLabel; 28 | @synthesize connectButton = _connectButton; 29 | @synthesize navController = _navController; 30 | @synthesize connection = _connection; 31 | @synthesize peersBrowserController = _peersBrowserController; 32 | 33 | - (void)dealloc 34 | { 35 | [_connection release]; 36 | [_navController release]; 37 | [_peersBrowserController release]; 38 | [super dealloc]; 39 | } 40 | 41 | - (void)didReceiveMemoryWarning 42 | { 43 | [super didReceiveMemoryWarning]; 44 | } 45 | 46 | #pragma mark - View lifecycle 47 | 48 | - (void)viewDidLoad 49 | { 50 | [super viewDidLoad]; 51 | 52 | NSError *myErr; 53 | AVAudioSession *audioSession = [AVAudioSession sharedInstance]; 54 | [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&myErr]; 55 | [audioSession setActive:YES 56 | error:&myErr]; 57 | 58 | // Routing default audio to external speaker 59 | AudioSessionInitialize(NULL, NULL, NULL, NULL); 60 | UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; 61 | AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, 62 | sizeof(audioRouteOverride), 63 | &audioRouteOverride); 64 | AudioSessionSetActive(true); 65 | 66 | self.statusLabel.text = NSLocalizedString(@"ready", @"Used when the application starts and after the peer disconnects"); 67 | [self.connectButton setTitle:NSLocalizedString(@"connect", @"Shown on the connect button") 68 | forState:UIControlStateNormal]; 69 | } 70 | 71 | - (void)viewDidUnload 72 | { 73 | [super viewDidUnload]; 74 | } 75 | 76 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 77 | { 78 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 79 | } 80 | 81 | #pragma mark - IBAction methods 82 | 83 | - (IBAction)showConnectionKinds:(id)sender 84 | { 85 | if (self.connection.isConnected) 86 | { 87 | [self closeConnectionWithMessage:NSLocalizedString(@"disconnected", @"Shown when the other user disconnects")]; 88 | self.navController = nil; 89 | self.connection = nil; 90 | } 91 | else 92 | { 93 | // Create a peer picker to select Bluetooth vs. Wifi connection 94 | GKPeerPickerController *pickerController = [[[GKPeerPickerController alloc] init] autorelease]; 95 | pickerController.delegate = self; 96 | pickerController.connectionTypesMask = GKPeerPickerConnectionTypeNearby 97 | | GKPeerPickerConnectionTypeOnline; 98 | [pickerController show]; 99 | } 100 | } 101 | 102 | - (IBAction)openWebsite:(id)sender 103 | { 104 | NSURL *url = [NSURL URLWithString:@"http://bluewoki.com/"]; 105 | [[UIApplication sharedApplication] openURL:url]; 106 | } 107 | 108 | #pragma mark - GKPeerPickerControllerDelegate methods 109 | 110 | - (void)peerPickerController:(GKPeerPickerController *)picker 111 | didSelectConnectionType:(GKPeerPickerConnectionType)type 112 | { 113 | [picker dismiss]; 114 | switch (type) 115 | { 116 | case GKPeerPickerConnectionTypeOnline: 117 | { 118 | self.connection = [BWWifiConnection connection]; 119 | 120 | if (self.navController == nil) 121 | { 122 | self.peersBrowserController = [[[BWBrowserController alloc] init] autorelease]; 123 | self.navController = [[[UINavigationController alloc] initWithRootViewController:self.peersBrowserController] autorelease]; 124 | } 125 | self.peersBrowserController.delegate = self.connection; 126 | 127 | [self presentModalViewController:self.navController animated:YES]; 128 | break; 129 | } 130 | 131 | case GKPeerPickerConnectionTypeNearby: 132 | { 133 | self.connection = [BWBluetoothConnection connection]; 134 | break; 135 | } 136 | 137 | default: 138 | break; 139 | } 140 | self.connection.delegate = self; 141 | [self.connection connect]; 142 | } 143 | 144 | #pragma mark - BWConnectionDelegate methods 145 | 146 | - (void)connection:(BWConnection *)connection didFailWithError:(NSError *)error 147 | { 148 | [self closeConnectionWithMessage:NSLocalizedString(@"error", @"Shown when the connection generated an error")]; 149 | } 150 | 151 | - (void)connectionIsConnecting:(BWConnection *)connection 152 | { 153 | if (self.navController != nil) 154 | { 155 | self.peersBrowserController.delegate = nil; 156 | [self.navController dismissModalViewControllerAnimated:YES]; 157 | } 158 | self.statusLabel.text = NSLocalizedString(@"connecting", @"Shown while the connection is negotiated"); 159 | } 160 | 161 | - (void)connectionDidConnect:(BWConnection *)connection 162 | { 163 | self.statusLabel.text = [NSString stringWithFormat:NSLocalizedString(@"connected with", @"Shows who we're talking to"), 164 | self.connection.otherPeerName]; 165 | [UIApplication sharedApplication].idleTimerDisabled = YES; 166 | [UIDevice currentDevice].proximityMonitoringEnabled = YES; 167 | [self.connectButton setTitle:NSLocalizedString(@"disconnect", @"Shown on the disconnect button") 168 | forState:UIControlStateNormal]; 169 | } 170 | 171 | - (void)connectionDidDisconnect:(BWConnection *)connection 172 | { 173 | [self closeConnectionWithMessage:NSLocalizedString(@"peer disconnected", @"Shown when the other user disconnects")]; 174 | } 175 | 176 | - (void)connectionDidReceiveCall:(BWConnection *)connection 177 | { 178 | NSString *titleTemplate = NSLocalizedString(@"call title", @"Title of the incoming call dialog box"); 179 | NSString *messageTemplate = NSLocalizedString(@"message received", @"Shown when a call is received (wifi only)"); 180 | NSString *message = [NSString stringWithFormat:messageTemplate, self.connection.otherPeerName]; 181 | NSString *titleText = [NSString stringWithFormat:titleTemplate, self.connection.otherPeerName]; 182 | NSString *yes = NSLocalizedString(@"yes", @"The word 'yes'"); 183 | NSString *no = NSLocalizedString(@"no", @"The word 'no'"); 184 | UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:titleText 185 | message:message 186 | delegate:self 187 | cancelButtonTitle:no 188 | otherButtonTitles:yes, nil] autorelease]; 189 | [alert show]; 190 | } 191 | 192 | #pragma mark - UIAlertView methods 193 | 194 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 195 | { 196 | if (buttonIndex == 1) 197 | { 198 | [self.connection answerIncomingCall]; 199 | } 200 | else 201 | { 202 | [self.connection denyIncomingCall]; 203 | [self closeConnectionWithMessage:NSLocalizedString(@"disconnected", @"Shown when the other user disconnects")]; 204 | } 205 | } 206 | 207 | #pragma mark - Private methods 208 | 209 | - (void)closeConnectionWithMessage:(NSString *)message 210 | { 211 | [self.connection disconnect]; 212 | [UIApplication sharedApplication].idleTimerDisabled = NO; 213 | [UIDevice currentDevice].proximityMonitoringEnabled = NO; 214 | self.statusLabel.text = message; 215 | [self.connectButton setTitle:NSLocalizedString(@"connect", @"Shown on the connect button") 216 | forState:UIControlStateNormal]; 217 | [self performSelector:@selector(resetInterface) 218 | withObject:nil 219 | afterDelay:3]; 220 | } 221 | 222 | - (void)resetInterface 223 | { 224 | self.statusLabel.text = NSLocalizedString(@"ready", @"Used when the application starts and after the peer disconnects"); 225 | } 226 | 227 | @end 228 | -------------------------------------------------------------------------------- /Resources/NIBs/MainWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 768 5 | 11B26 6 | 907 7 | 1138 8 | 566.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 141 12 | 13 | 14 | YES 15 | 16 | 17 | YES 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | YES 22 | 23 | YES 24 | 25 | 26 | YES 27 | 28 | 29 | 30 | YES 31 | 32 | IBFilesOwner 33 | IBCocoaTouchFramework 34 | 35 | 36 | IBFirstResponder 37 | IBCocoaTouchFramework 38 | 39 | 40 | IBCocoaTouchFramework 41 | 42 | 43 | 44 | 292 45 | {320, 480} 46 | 47 | 1 48 | MCAwIDAAA 49 | 50 | NO 51 | 52 | 2 53 | 54 | IBCocoaTouchFramework 55 | 56 | 57 | 58 | 59 | 1 60 | 61 | IBCocoaTouchFramework 62 | NO 63 | 64 | 65 | 66 | 67 | YES 68 | 69 | 70 | delegate 71 | 72 | 73 | 74 | 4 75 | 76 | 77 | 78 | window 79 | 80 | 81 | 82 | 15 83 | 84 | 85 | 86 | controller 87 | 88 | 89 | 90 | 31 91 | 92 | 93 | 94 | 95 | YES 96 | 97 | 0 98 | 99 | 100 | 101 | 102 | 103 | -1 104 | 105 | 106 | File's Owner 107 | 108 | 109 | 3 110 | 111 | 112 | bluewoki App Delegate 113 | 114 | 115 | -2 116 | 117 | 118 | 119 | 120 | 12 121 | 122 | 123 | YES 124 | 125 | 126 | 127 | 128 | 30 129 | 130 | 131 | 132 | 133 | 134 | 135 | YES 136 | 137 | YES 138 | -1.CustomClassName 139 | -2.CustomClassName 140 | 12.IBEditorWindowLastContentRect 141 | 12.IBPluginDependency 142 | 3.CustomClassName 143 | 3.IBPluginDependency 144 | 30.CustomClassName 145 | 30.IBPluginDependency 146 | 147 | 148 | YES 149 | UIApplication 150 | UIResponder 151 | {{422, 346}, {320, 480}} 152 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 153 | BWAppDelegate 154 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 155 | BWRootController 156 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 157 | 158 | 159 | 160 | YES 161 | 162 | 163 | YES 164 | 165 | 166 | 167 | 168 | YES 169 | 170 | 171 | YES 172 | 173 | 174 | 175 | 31 176 | 177 | 178 | 179 | YES 180 | 181 | BWAppDelegate 182 | NSObject 183 | 184 | YES 185 | 186 | YES 187 | controller 188 | window 189 | 190 | 191 | YES 192 | BWRootController 193 | UIWindow 194 | 195 | 196 | 197 | YES 198 | 199 | YES 200 | controller 201 | window 202 | 203 | 204 | YES 205 | 206 | controller 207 | BWRootController 208 | 209 | 210 | window 211 | UIWindow 212 | 213 | 214 | 215 | 216 | IBUserSource 217 | 218 | 219 | 220 | 221 | BWRootController 222 | UIViewController 223 | 224 | YES 225 | 226 | YES 227 | openWebsite: 228 | showPeers: 229 | 230 | 231 | YES 232 | id 233 | id 234 | 235 | 236 | 237 | YES 238 | 239 | YES 240 | openWebsite: 241 | showPeers: 242 | 243 | 244 | YES 245 | 246 | openWebsite: 247 | id 248 | 249 | 250 | showPeers: 251 | id 252 | 253 | 254 | 255 | 256 | YES 257 | 258 | YES 259 | connectButton 260 | statusLabel 261 | 262 | 263 | YES 264 | UIButton 265 | UILabel 266 | 267 | 268 | 269 | YES 270 | 271 | YES 272 | connectButton 273 | statusLabel 274 | 275 | 276 | YES 277 | 278 | connectButton 279 | UIButton 280 | 281 | 282 | statusLabel 283 | UILabel 284 | 285 | 286 | 287 | 288 | IBUserSource 289 | 290 | 291 | 292 | 293 | 294 | 0 295 | IBCocoaTouchFramework 296 | 297 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 298 | 299 | 300 | 301 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 302 | 303 | 304 | YES 305 | 306 | 3 307 | 141 308 | 309 | 310 | -------------------------------------------------------------------------------- /Resources/NIBs/BWRootController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1056 5 | 11B26 6 | 907 7 | 1138 8 | 566.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 141 12 | 13 | 14 | YES 15 | 16 | 17 | YES 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | YES 22 | 23 | YES 24 | 25 | 26 | YES 27 | 28 | 29 | 30 | YES 31 | 32 | IBFilesOwner 33 | IBCocoaTouchFramework 34 | 35 | 36 | IBFirstResponder 37 | IBCocoaTouchFramework 38 | 39 | 40 | 41 | 274 42 | 43 | YES 44 | 45 | 46 | 256 47 | {320, 460} 48 | 49 | NO 50 | YES 51 | 4 52 | YES 53 | IBCocoaTouchFramework 54 | 55 | NSImage 56 | Default.png 57 | 58 | 59 | 60 | 61 | 292 62 | {{138, 154}, {143, 78}} 63 | 64 | NO 65 | NO 66 | IBCocoaTouchFramework 67 | 0 68 | 0 69 | 70 | Helvetica-Bold 71 | 18 72 | 16 73 | 74 | 75 | 3 76 | MQA 77 | 78 | 79 | 1 80 | MC4yMjI4MjYwNjM2IDAuMjIyODI2MDYzNiAwLjIyMjgyNjA2MzYAA 81 | 82 | 83 | 3 84 | MC41AA 85 | 86 | 87 | 88 | 89 | 292 90 | {{20, 20}, {280, 50}} 91 | 92 | NO 93 | NO 94 | IBCocoaTouchFramework 95 | 0 96 | 0 97 | 98 | Helvetica-Bold 99 | 15 100 | 16 101 | 102 | 103 | 104 | 1 105 | MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA 106 | 107 | 108 | 109 | 110 | 111 | 292 112 | {{49, 85}, {221, 52}} 113 | 114 | NO 115 | YES 116 | NO 117 | IBCocoaTouchFramework 118 | initializing 119 | 120 | Helvetica-Bold 121 | 24 122 | 16 123 | 124 | 125 | 1 126 | MCAwIDAAA 127 | 128 | 129 | 1 130 | NO 131 | 10 132 | 2 133 | 1 134 | 135 | 136 | {{0, 20}, {320, 460}} 137 | 138 | 3 139 | MAA 140 | 141 | 142 | IBCocoaTouchFramework 143 | 144 | 145 | 146 | 147 | YES 148 | 149 | 150 | view 151 | 152 | 153 | 154 | 3 155 | 156 | 157 | 158 | connectButton 159 | 160 | 161 | 162 | 8 163 | 164 | 165 | 166 | statusLabel 167 | 168 | 169 | 170 | 9 171 | 172 | 173 | 174 | openWebsite: 175 | 176 | 177 | 7 178 | 179 | 11 180 | 181 | 182 | 183 | showConnectionKinds: 184 | 185 | 186 | 7 187 | 188 | 12 189 | 190 | 191 | 192 | 193 | YES 194 | 195 | 0 196 | 197 | 198 | 199 | 200 | 201 | 1 202 | 203 | 204 | YES 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | -1 214 | 215 | 216 | File's Owner 217 | 218 | 219 | -2 220 | 221 | 222 | 223 | 224 | 4 225 | 226 | 227 | 228 | 229 | 5 230 | 231 | 232 | 233 | 234 | 6 235 | 236 | 237 | 238 | 239 | 7 240 | 241 | 242 | 243 | 244 | 245 | 246 | YES 247 | 248 | YES 249 | -1.CustomClassName 250 | -2.CustomClassName 251 | 1.IBEditorWindowLastContentRect 252 | 1.IBPluginDependency 253 | 5.IBPluginDependency 254 | 6.IBPluginDependency 255 | 7.IBPluginDependency 256 | 257 | 258 | YES 259 | BWRootController 260 | UIResponder 261 | {{556, 412}, {320, 480}} 262 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 263 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 264 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 265 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 266 | 267 | 268 | 269 | YES 270 | 271 | 272 | YES 273 | 274 | 275 | 276 | 277 | YES 278 | 279 | 280 | YES 281 | 282 | 283 | 284 | 12 285 | 286 | 287 | 288 | YES 289 | 290 | BWRootController 291 | UIViewController 292 | 293 | YES 294 | 295 | YES 296 | openWebsite: 297 | showConnectionKinds: 298 | 299 | 300 | YES 301 | id 302 | id 303 | 304 | 305 | 306 | YES 307 | 308 | YES 309 | openWebsite: 310 | showConnectionKinds: 311 | 312 | 313 | YES 314 | 315 | openWebsite: 316 | id 317 | 318 | 319 | showConnectionKinds: 320 | id 321 | 322 | 323 | 324 | 325 | YES 326 | 327 | YES 328 | connectButton 329 | statusLabel 330 | 331 | 332 | YES 333 | UIButton 334 | UILabel 335 | 336 | 337 | 338 | YES 339 | 340 | YES 341 | connectButton 342 | statusLabel 343 | 344 | 345 | YES 346 | 347 | connectButton 348 | UIButton 349 | 350 | 351 | statusLabel 352 | UILabel 353 | 354 | 355 | 356 | 357 | IBUserSource 358 | 359 | 360 | 361 | 362 | 363 | 0 364 | IBCocoaTouchFramework 365 | 366 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 367 | 368 | 369 | YES 370 | 371 | 3 372 | 373 | Default.png 374 | {320, 460} 375 | 376 | 141 377 | 378 | 379 | -------------------------------------------------------------------------------- /bluewoki.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 11 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 12 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 13 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; 14 | 3A57D1051420939E002E5F5D /* BWBluetoothConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A57D1041420939E002E5F5D /* BWBluetoothConnection.m */; }; 15 | 3A57D109142098BC002E5F5D /* BWConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A57D108142098BC002E5F5D /* BWConnection.m */; }; 16 | 3A57D10C1420A06E002E5F5D /* BWWifiConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A57D10B1420A06E002E5F5D /* BWWifiConnection.m */; }; 17 | 3A5C41D313881C0A008FB231 /* BWRootController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3A5C41D213881C0A008FB231 /* BWRootController.xib */; }; 18 | 3A5FBAEC0FF8B03B0060478C /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A5FBAEB0FF8B03B0060478C /* AudioToolbox.framework */; }; 19 | 3A5FBAEE0FF8B0400060478C /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A5FBAED0FF8B0400060478C /* AVFoundation.framework */; }; 20 | 3A5FBAF00FF8B0480060478C /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A5FBAEF0FF8B0480060478C /* GameKit.framework */; }; 21 | 3A5FBAF80FF8B0D50060478C /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A5FBAF60FF8B0D50060478C /* Default.png */; }; 22 | 3A5FBAF90FF8B0D50060478C /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A5FBAF70FF8B0D50060478C /* Icon.png */; }; 23 | 3A61C07314208C3100FEA33D /* Entitlements.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 3A61C07214208C3100FEA33D /* Entitlements.entitlements */; }; 24 | 3A891AA513881F8000804131 /* BWAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A891A9B13881F8000804131 /* BWAppDelegate.m */; }; 25 | 3A891AA613881F8000804131 /* BWRootController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A891A9E13881F8000804131 /* BWRootController.m */; }; 26 | 3A891AA713881F8000804131 /* BWMessageObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A891AA113881F8000804131 /* BWMessageObject.m */; }; 27 | 3A891AA813881F8000804131 /* BWMessageBroker.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A891AA313881F8000804131 /* BWMessageBroker.m */; }; 28 | 3A891AAD13881FAE00804131 /* AsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A891AAC13881FAE00804131 /* AsyncSocket.m */; }; 29 | 3A891AAF13881FDD00804131 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A891AAE13881FDD00804131 /* CFNetwork.framework */; }; 30 | 3A891AB21388224000804131 /* BWPeerProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A891AB11388224000804131 /* BWPeerProxy.m */; }; 31 | 3A891ABD138823D000804131 /* BWProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A891ABC138823D000804131 /* BWProtocol.m */; }; 32 | 3A891AC21388280000804131 /* BWPeerService.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A891AC11388280000804131 /* BWPeerService.m */; }; 33 | 3A891AC513882A2700804131 /* BWPeerBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A891AC413882A2700804131 /* BWPeerBrowser.m */; }; 34 | 3A891AC81388316F00804131 /* BWBrowserController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A891AC71388316F00804131 /* BWBrowserController.m */; }; 35 | 3AD05E44142083FF00D4971C /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3AD05E43142083FF00D4971C /* Default@2x.png */; }; 36 | 3AD05E4B1420869700D4971C /* Icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 3AD05E451420869700D4971C /* Icon-72.png */; }; 37 | 3AD05E4C1420869700D4971C /* Icon-Small-50.png in Resources */ = {isa = PBXBuildFile; fileRef = 3AD05E461420869700D4971C /* Icon-Small-50.png */; }; 38 | 3AD05E4D1420869700D4971C /* Icon-Small.png in Resources */ = {isa = PBXBuildFile; fileRef = 3AD05E471420869700D4971C /* Icon-Small.png */; }; 39 | 3AD05E4E1420869700D4971C /* Icon-Small@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3AD05E481420869700D4971C /* Icon-Small@2x.png */; }; 40 | 3AD05E4F1420869700D4971C /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3AD05E491420869700D4971C /* Icon@2x.png */; }; 41 | 3AD05E501420869700D4971C /* iTunesArtwork in Resources */ = {isa = PBXBuildFile; fileRef = 3AD05E4A1420869700D4971C /* iTunesArtwork */; }; 42 | 3AF6C9450FF8B7F000312D0A /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3AF6C9440FF8B7F000312D0A /* MainWindow.xib */; }; 43 | 3AF6F7490FF8DEA50083EA15 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3AF6F7450FF8DEA50083EA15 /* Localizable.strings */; }; 44 | /* End PBXBuildFile section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 48 | 1D6058910D05DD3D006BFB54 /* bluewoki.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = bluewoki.app; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 50 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 51 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 52 | 32CA4F630368D1EE00C91783 /* bluewoki_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bluewoki_Prefix.pch; sourceTree = ""; }; 53 | 3A57D1031420939E002E5F5D /* BWBluetoothConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWBluetoothConnection.h; sourceTree = ""; }; 54 | 3A57D1041420939E002E5F5D /* BWBluetoothConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWBluetoothConnection.m; sourceTree = ""; }; 55 | 3A57D10614209438002E5F5D /* BWConnectionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWConnectionDelegate.h; sourceTree = ""; }; 56 | 3A57D107142098BC002E5F5D /* BWConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWConnection.h; sourceTree = ""; }; 57 | 3A57D108142098BC002E5F5D /* BWConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWConnection.m; sourceTree = ""; }; 58 | 3A57D10A1420A06E002E5F5D /* BWWifiConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWWifiConnection.h; sourceTree = ""; }; 59 | 3A57D10B1420A06E002E5F5D /* BWWifiConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWWifiConnection.m; sourceTree = ""; }; 60 | 3A5C41D213881C0A008FB231 /* BWRootController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BWRootController.xib; sourceTree = ""; }; 61 | 3A5FBAEB0FF8B03B0060478C /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 62 | 3A5FBAED0FF8B0400060478C /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; 63 | 3A5FBAEF0FF8B0480060478C /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; }; 64 | 3A5FBAF60FF8B0D50060478C /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 65 | 3A5FBAF70FF8B0D50060478C /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; }; 66 | 3A61C07214208C3100FEA33D /* Entitlements.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Entitlements.entitlements; sourceTree = ""; }; 67 | 3A7C55F813883E7600D29272 /* BWBrowserControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWBrowserControllerDelegate.h; sourceTree = ""; }; 68 | 3A7C56011388561200D29272 /* BWPeerServiceDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWPeerServiceDelegate.h; sourceTree = ""; }; 69 | 3A891A9A13881F8000804131 /* BWAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWAppDelegate.h; sourceTree = ""; }; 70 | 3A891A9B13881F8000804131 /* BWAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWAppDelegate.m; sourceTree = ""; }; 71 | 3A891A9D13881F8000804131 /* BWRootController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWRootController.h; sourceTree = ""; }; 72 | 3A891A9E13881F8000804131 /* BWRootController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWRootController.m; sourceTree = ""; }; 73 | 3A891AA013881F8000804131 /* BWMessageObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWMessageObject.h; sourceTree = ""; }; 74 | 3A891AA113881F8000804131 /* BWMessageObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWMessageObject.m; sourceTree = ""; }; 75 | 3A891AA213881F8000804131 /* BWMessageBroker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWMessageBroker.h; sourceTree = ""; }; 76 | 3A891AA313881F8000804131 /* BWMessageBroker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWMessageBroker.m; sourceTree = ""; }; 77 | 3A891AA413881F8000804131 /* BWMessageBrokerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWMessageBrokerDelegate.h; sourceTree = ""; }; 78 | 3A891AAB13881FAE00804131 /* AsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncSocket.h; sourceTree = ""; }; 79 | 3A891AAC13881FAE00804131 /* AsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AsyncSocket.m; sourceTree = ""; }; 80 | 3A891AAE13881FDD00804131 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 81 | 3A891AB01388224000804131 /* BWPeerProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWPeerProxy.h; sourceTree = ""; }; 82 | 3A891AB11388224000804131 /* BWPeerProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWPeerProxy.m; sourceTree = ""; }; 83 | 3A891ABB138823CF00804131 /* BWProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWProtocol.h; sourceTree = ""; }; 84 | 3A891ABC138823D000804131 /* BWProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWProtocol.m; sourceTree = ""; }; 85 | 3A891ABF138825D900804131 /* BWPeerProxyDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWPeerProxyDelegate.h; sourceTree = ""; }; 86 | 3A891AC0138827FF00804131 /* BWPeerService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWPeerService.h; sourceTree = ""; }; 87 | 3A891AC11388280000804131 /* BWPeerService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWPeerService.m; sourceTree = ""; }; 88 | 3A891AC313882A2700804131 /* BWPeerBrowser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWPeerBrowser.h; sourceTree = ""; }; 89 | 3A891AC413882A2700804131 /* BWPeerBrowser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWPeerBrowser.m; sourceTree = ""; }; 90 | 3A891AC61388316F00804131 /* BWBrowserController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWBrowserController.h; sourceTree = ""; }; 91 | 3A891AC71388316F00804131 /* BWBrowserController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWBrowserController.m; sourceTree = ""; }; 92 | 3AD05E43142083FF00D4971C /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 93 | 3AD05E451420869700D4971C /* Icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72.png"; sourceTree = ""; }; 94 | 3AD05E461420869700D4971C /* Icon-Small-50.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-50.png"; sourceTree = ""; }; 95 | 3AD05E471420869700D4971C /* Icon-Small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small.png"; sourceTree = ""; }; 96 | 3AD05E481420869700D4971C /* Icon-Small@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small@2x.png"; sourceTree = ""; }; 97 | 3AD05E491420869700D4971C /* Icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon@2x.png"; sourceTree = ""; }; 98 | 3AD05E4A1420869700D4971C /* iTunesArtwork */ = {isa = PBXFileReference; lastKnownFileType = file; path = iTunesArtwork; sourceTree = ""; }; 99 | 3AF6C9440FF8B7F000312D0A /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 100 | 3AF6F7460FF8DEA50083EA15 /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 101 | 3AF6F7470FF8DEA50083EA15 /* es */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; 102 | 3AF6F7480FF8DEA50083EA15 /* fr */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; 103 | 8D1107310486CEB800E47090 /* bluewoki-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "bluewoki-Info.plist"; path = "../bluewoki-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; 104 | /* End PBXFileReference section */ 105 | 106 | /* Begin PBXFrameworksBuildPhase section */ 107 | 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { 108 | isa = PBXFrameworksBuildPhase; 109 | buildActionMask = 2147483647; 110 | files = ( 111 | 3A891AAF13881FDD00804131 /* CFNetwork.framework in Frameworks */, 112 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 113 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 114 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, 115 | 3A5FBAEC0FF8B03B0060478C /* AudioToolbox.framework in Frameworks */, 116 | 3A5FBAEE0FF8B0400060478C /* AVFoundation.framework in Frameworks */, 117 | 3A5FBAF00FF8B0480060478C /* GameKit.framework in Frameworks */, 118 | ); 119 | runOnlyForDeploymentPostprocessing = 0; 120 | }; 121 | /* End PBXFrameworksBuildPhase section */ 122 | 123 | /* Begin PBXGroup section */ 124 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 1D6058910D05DD3D006BFB54 /* bluewoki.app */, 128 | ); 129 | name = Products; 130 | sourceTree = ""; 131 | }; 132 | 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 3A891AA913881FAE00804131 /* Externals */, 136 | 3A891A9813881F8000804131 /* Classes */, 137 | 3A22AD4C0FF8ACC100E867BE /* Resources */, 138 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 139 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 140 | 19C28FACFE9D520D11CA2CBB /* Products */, 141 | ); 142 | name = CustomTemplate; 143 | sourceTree = ""; 144 | }; 145 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 32CA4F630368D1EE00C91783 /* bluewoki_Prefix.pch */, 149 | 29B97316FDCFA39411CA2CEA /* main.m */, 150 | ); 151 | name = "Other Sources"; 152 | sourceTree = ""; 153 | }; 154 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 3A891AAE13881FDD00804131 /* CFNetwork.framework */, 158 | 3A5FBAEB0FF8B03B0060478C /* AudioToolbox.framework */, 159 | 3A5FBAED0FF8B0400060478C /* AVFoundation.framework */, 160 | 3A5FBAEF0FF8B0480060478C /* GameKit.framework */, 161 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 162 | 1D30AB110D05D00D00671497 /* Foundation.framework */, 163 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */, 164 | ); 165 | name = Frameworks; 166 | sourceTree = ""; 167 | }; 168 | 3A22AD4C0FF8ACC100E867BE /* Resources */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | 3AF6F7440FF8DEA50083EA15 /* Strings */, 172 | 3AF6C9430FF8B7F000312D0A /* NIBs */, 173 | 3A5FBAF50FF8B0D50060478C /* Images */, 174 | 8D1107310486CEB800E47090 /* bluewoki-Info.plist */, 175 | 3A61C07214208C3100FEA33D /* Entitlements.entitlements */, 176 | ); 177 | path = Resources; 178 | sourceTree = ""; 179 | }; 180 | 3A5FBAF50FF8B0D50060478C /* Images */ = { 181 | isa = PBXGroup; 182 | children = ( 183 | 3A5FBAF70FF8B0D50060478C /* Icon.png */, 184 | 3AD05E451420869700D4971C /* Icon-72.png */, 185 | 3AD05E461420869700D4971C /* Icon-Small-50.png */, 186 | 3AD05E471420869700D4971C /* Icon-Small.png */, 187 | 3AD05E481420869700D4971C /* Icon-Small@2x.png */, 188 | 3AD05E491420869700D4971C /* Icon@2x.png */, 189 | 3AD05E4A1420869700D4971C /* iTunesArtwork */, 190 | 3AD05E43142083FF00D4971C /* Default@2x.png */, 191 | 3A5FBAF60FF8B0D50060478C /* Default.png */, 192 | ); 193 | path = Images; 194 | sourceTree = ""; 195 | }; 196 | 3A891A9813881F8000804131 /* Classes */ = { 197 | isa = PBXGroup; 198 | children = ( 199 | 3A891A9913881F8000804131 /* AppDelegate */, 200 | 3A891A9C13881F8000804131 /* Controllers */, 201 | 3A891A9F13881F8000804131 /* Helpers */, 202 | ); 203 | path = Classes; 204 | sourceTree = ""; 205 | }; 206 | 3A891A9913881F8000804131 /* AppDelegate */ = { 207 | isa = PBXGroup; 208 | children = ( 209 | 3A891A9A13881F8000804131 /* BWAppDelegate.h */, 210 | 3A891A9B13881F8000804131 /* BWAppDelegate.m */, 211 | ); 212 | path = AppDelegate; 213 | sourceTree = ""; 214 | }; 215 | 3A891A9C13881F8000804131 /* Controllers */ = { 216 | isa = PBXGroup; 217 | children = ( 218 | 3A891A9D13881F8000804131 /* BWRootController.h */, 219 | 3A891A9E13881F8000804131 /* BWRootController.m */, 220 | 3A891AC61388316F00804131 /* BWBrowserController.h */, 221 | 3A891AC71388316F00804131 /* BWBrowserController.m */, 222 | 3A7C55F813883E7600D29272 /* BWBrowserControllerDelegate.h */, 223 | ); 224 | path = Controllers; 225 | sourceTree = ""; 226 | }; 227 | 3A891A9F13881F8000804131 /* Helpers */ = { 228 | isa = PBXGroup; 229 | children = ( 230 | 3A891AA013881F8000804131 /* BWMessageObject.h */, 231 | 3A891AA113881F8000804131 /* BWMessageObject.m */, 232 | 3A891AA213881F8000804131 /* BWMessageBroker.h */, 233 | 3A891AA313881F8000804131 /* BWMessageBroker.m */, 234 | 3A891AA413881F8000804131 /* BWMessageBrokerDelegate.h */, 235 | 3A891AB01388224000804131 /* BWPeerProxy.h */, 236 | 3A891AB11388224000804131 /* BWPeerProxy.m */, 237 | 3A891ABF138825D900804131 /* BWPeerProxyDelegate.h */, 238 | 3A891ABB138823CF00804131 /* BWProtocol.h */, 239 | 3A891ABC138823D000804131 /* BWProtocol.m */, 240 | 3A891AC0138827FF00804131 /* BWPeerService.h */, 241 | 3A891AC11388280000804131 /* BWPeerService.m */, 242 | 3A7C56011388561200D29272 /* BWPeerServiceDelegate.h */, 243 | 3A891AC313882A2700804131 /* BWPeerBrowser.h */, 244 | 3A891AC413882A2700804131 /* BWPeerBrowser.m */, 245 | 3A57D107142098BC002E5F5D /* BWConnection.h */, 246 | 3A57D108142098BC002E5F5D /* BWConnection.m */, 247 | 3A57D10614209438002E5F5D /* BWConnectionDelegate.h */, 248 | 3A57D1031420939E002E5F5D /* BWBluetoothConnection.h */, 249 | 3A57D1041420939E002E5F5D /* BWBluetoothConnection.m */, 250 | 3A57D10A1420A06E002E5F5D /* BWWifiConnection.h */, 251 | 3A57D10B1420A06E002E5F5D /* BWWifiConnection.m */, 252 | ); 253 | path = Helpers; 254 | sourceTree = ""; 255 | }; 256 | 3A891AA913881FAE00804131 /* Externals */ = { 257 | isa = PBXGroup; 258 | children = ( 259 | 3A891AAA13881FAE00804131 /* AsyncSocket */, 260 | ); 261 | path = Externals; 262 | sourceTree = ""; 263 | }; 264 | 3A891AAA13881FAE00804131 /* AsyncSocket */ = { 265 | isa = PBXGroup; 266 | children = ( 267 | 3A891AAB13881FAE00804131 /* AsyncSocket.h */, 268 | 3A891AAC13881FAE00804131 /* AsyncSocket.m */, 269 | ); 270 | path = AsyncSocket; 271 | sourceTree = ""; 272 | }; 273 | 3AF6C9430FF8B7F000312D0A /* NIBs */ = { 274 | isa = PBXGroup; 275 | children = ( 276 | 3AF6C9440FF8B7F000312D0A /* MainWindow.xib */, 277 | 3A5C41D213881C0A008FB231 /* BWRootController.xib */, 278 | ); 279 | path = NIBs; 280 | sourceTree = ""; 281 | }; 282 | 3AF6F7440FF8DEA50083EA15 /* Strings */ = { 283 | isa = PBXGroup; 284 | children = ( 285 | 3AF6F7450FF8DEA50083EA15 /* Localizable.strings */, 286 | ); 287 | path = Strings; 288 | sourceTree = ""; 289 | }; 290 | /* End PBXGroup section */ 291 | 292 | /* Begin PBXNativeTarget section */ 293 | 1D6058900D05DD3D006BFB54 /* bluewoki */ = { 294 | isa = PBXNativeTarget; 295 | buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "bluewoki" */; 296 | buildPhases = ( 297 | 1D60588D0D05DD3D006BFB54 /* Resources */, 298 | 1D60588E0D05DD3D006BFB54 /* Sources */, 299 | 1D60588F0D05DD3D006BFB54 /* Frameworks */, 300 | ); 301 | buildRules = ( 302 | ); 303 | dependencies = ( 304 | ); 305 | name = bluewoki; 306 | productName = bluewoki; 307 | productReference = 1D6058910D05DD3D006BFB54 /* bluewoki.app */; 308 | productType = "com.apple.product-type.application"; 309 | }; 310 | /* End PBXNativeTarget section */ 311 | 312 | /* Begin PBXProject section */ 313 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 314 | isa = PBXProject; 315 | attributes = { 316 | LastUpgradeCheck = 0420; 317 | }; 318 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "bluewoki" */; 319 | compatibilityVersion = "Xcode 3.2"; 320 | developmentRegion = English; 321 | hasScannedForEncodings = 1; 322 | knownRegions = ( 323 | English, 324 | Japanese, 325 | French, 326 | German, 327 | fr, 328 | Spanish, 329 | en, 330 | es, 331 | ); 332 | mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; 333 | projectDirPath = ""; 334 | projectRoot = ""; 335 | targets = ( 336 | 1D6058900D05DD3D006BFB54 /* bluewoki */, 337 | ); 338 | }; 339 | /* End PBXProject section */ 340 | 341 | /* Begin PBXResourcesBuildPhase section */ 342 | 1D60588D0D05DD3D006BFB54 /* Resources */ = { 343 | isa = PBXResourcesBuildPhase; 344 | buildActionMask = 2147483647; 345 | files = ( 346 | 3A5FBAF80FF8B0D50060478C /* Default.png in Resources */, 347 | 3A5FBAF90FF8B0D50060478C /* Icon.png in Resources */, 348 | 3AF6C9450FF8B7F000312D0A /* MainWindow.xib in Resources */, 349 | 3AF6F7490FF8DEA50083EA15 /* Localizable.strings in Resources */, 350 | 3A5C41D313881C0A008FB231 /* BWRootController.xib in Resources */, 351 | 3AD05E44142083FF00D4971C /* Default@2x.png in Resources */, 352 | 3AD05E4B1420869700D4971C /* Icon-72.png in Resources */, 353 | 3AD05E4C1420869700D4971C /* Icon-Small-50.png in Resources */, 354 | 3AD05E4D1420869700D4971C /* Icon-Small.png in Resources */, 355 | 3AD05E4E1420869700D4971C /* Icon-Small@2x.png in Resources */, 356 | 3AD05E4F1420869700D4971C /* Icon@2x.png in Resources */, 357 | 3AD05E501420869700D4971C /* iTunesArtwork in Resources */, 358 | 3A61C07314208C3100FEA33D /* Entitlements.entitlements in Resources */, 359 | ); 360 | runOnlyForDeploymentPostprocessing = 0; 361 | }; 362 | /* End PBXResourcesBuildPhase section */ 363 | 364 | /* Begin PBXSourcesBuildPhase section */ 365 | 1D60588E0D05DD3D006BFB54 /* Sources */ = { 366 | isa = PBXSourcesBuildPhase; 367 | buildActionMask = 2147483647; 368 | files = ( 369 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 370 | 3A891AA513881F8000804131 /* BWAppDelegate.m in Sources */, 371 | 3A891AA613881F8000804131 /* BWRootController.m in Sources */, 372 | 3A891AA713881F8000804131 /* BWMessageObject.m in Sources */, 373 | 3A891AA813881F8000804131 /* BWMessageBroker.m in Sources */, 374 | 3A891AAD13881FAE00804131 /* AsyncSocket.m in Sources */, 375 | 3A891AB21388224000804131 /* BWPeerProxy.m in Sources */, 376 | 3A891ABD138823D000804131 /* BWProtocol.m in Sources */, 377 | 3A891AC21388280000804131 /* BWPeerService.m in Sources */, 378 | 3A891AC513882A2700804131 /* BWPeerBrowser.m in Sources */, 379 | 3A891AC81388316F00804131 /* BWBrowserController.m in Sources */, 380 | 3A57D1051420939E002E5F5D /* BWBluetoothConnection.m in Sources */, 381 | 3A57D109142098BC002E5F5D /* BWConnection.m in Sources */, 382 | 3A57D10C1420A06E002E5F5D /* BWWifiConnection.m in Sources */, 383 | ); 384 | runOnlyForDeploymentPostprocessing = 0; 385 | }; 386 | /* End PBXSourcesBuildPhase section */ 387 | 388 | /* Begin PBXVariantGroup section */ 389 | 3AF6F7450FF8DEA50083EA15 /* Localizable.strings */ = { 390 | isa = PBXVariantGroup; 391 | children = ( 392 | 3AF6F7460FF8DEA50083EA15 /* en */, 393 | 3AF6F7470FF8DEA50083EA15 /* es */, 394 | 3AF6F7480FF8DEA50083EA15 /* fr */, 395 | ); 396 | name = Localizable.strings; 397 | sourceTree = ""; 398 | }; 399 | /* End PBXVariantGroup section */ 400 | 401 | /* Begin XCBuildConfiguration section */ 402 | 1D6058940D05DD3E006BFB54 /* Debug */ = { 403 | isa = XCBuildConfiguration; 404 | buildSettings = { 405 | ALWAYS_SEARCH_USER_PATHS = NO; 406 | COPY_PHASE_STRIP = NO; 407 | GCC_DYNAMIC_NO_PIC = NO; 408 | GCC_OPTIMIZATION_LEVEL = 0; 409 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 410 | GCC_PREFIX_HEADER = bluewoki_Prefix.pch; 411 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 412 | INFOPLIST_FILE = "bluewoki-Info.plist"; 413 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; 414 | PRODUCT_NAME = bluewoki; 415 | }; 416 | name = Debug; 417 | }; 418 | 1D6058950D05DD3E006BFB54 /* Release */ = { 419 | isa = XCBuildConfiguration; 420 | buildSettings = { 421 | ALWAYS_SEARCH_USER_PATHS = NO; 422 | CODE_SIGN_ENTITLEMENTS = Resources/Entitlements.entitlements; 423 | COPY_PHASE_STRIP = YES; 424 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 425 | GCC_PREFIX_HEADER = bluewoki_Prefix.pch; 426 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 427 | INFOPLIST_FILE = "bluewoki-Info.plist"; 428 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; 429 | PRODUCT_NAME = bluewoki; 430 | }; 431 | name = Release; 432 | }; 433 | C01FCF4F08A954540054247B /* Debug */ = { 434 | isa = XCBuildConfiguration; 435 | buildSettings = { 436 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 437 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 438 | GCC_C_LANGUAGE_STANDARD = c99; 439 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 440 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 441 | GCC_WARN_UNUSED_VARIABLE = YES; 442 | RUN_CLANG_STATIC_ANALYZER = YES; 443 | SDKROOT = iphoneos; 444 | }; 445 | name = Debug; 446 | }; 447 | C01FCF5008A954540054247B /* Release */ = { 448 | isa = XCBuildConfiguration; 449 | buildSettings = { 450 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 451 | CODE_SIGN_ENTITLEMENTS = Resources/Entitlements.entitlements; 452 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; 453 | GCC_C_LANGUAGE_STANDARD = c99; 454 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 455 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 456 | GCC_WARN_UNUSED_VARIABLE = YES; 457 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 458 | RUN_CLANG_STATIC_ANALYZER = YES; 459 | SDKROOT = iphoneos; 460 | }; 461 | name = Release; 462 | }; 463 | /* End XCBuildConfiguration section */ 464 | 465 | /* Begin XCConfigurationList section */ 466 | 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "bluewoki" */ = { 467 | isa = XCConfigurationList; 468 | buildConfigurations = ( 469 | 1D6058940D05DD3E006BFB54 /* Debug */, 470 | 1D6058950D05DD3E006BFB54 /* Release */, 471 | ); 472 | defaultConfigurationIsVisible = 0; 473 | defaultConfigurationName = Release; 474 | }; 475 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "bluewoki" */ = { 476 | isa = XCConfigurationList; 477 | buildConfigurations = ( 478 | C01FCF4F08A954540054247B /* Debug */, 479 | C01FCF5008A954540054247B /* Release */, 480 | ); 481 | defaultConfigurationIsVisible = 0; 482 | defaultConfigurationName = Release; 483 | }; 484 | /* End XCConfigurationList section */ 485 | }; 486 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 487 | } 488 | -------------------------------------------------------------------------------- /Externals/AsyncSocket/AsyncSocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // AsyncSocket.h 3 | // 4 | // This class is in the public domain. 5 | // Originally created by Dustin Voss on Wed Jan 29 2003. 6 | // Updated and maintained by Deusty Designs and the Mac development community. 7 | // 8 | // http://code.google.com/p/cocoaasyncsocket/ 9 | // 10 | 11 | #import 12 | 13 | @class AsyncSocket; 14 | @class AsyncReadPacket; 15 | @class AsyncWritePacket; 16 | 17 | extern NSString *const AsyncSocketException; 18 | extern NSString *const AsyncSocketErrorDomain; 19 | 20 | enum AsyncSocketError 21 | { 22 | AsyncSocketCFSocketError = kCFSocketError, // From CFSocketError enum. 23 | AsyncSocketNoError = 0, // Never used. 24 | AsyncSocketCanceledError, // onSocketWillConnect: returned NO. 25 | AsyncSocketConnectTimeoutError, 26 | AsyncSocketReadMaxedOutError, // Reached set maxLength without completing 27 | AsyncSocketReadTimeoutError, 28 | AsyncSocketWriteTimeoutError 29 | }; 30 | typedef enum AsyncSocketError AsyncSocketError; 31 | 32 | @protocol AsyncSocketDelegate 33 | @optional 34 | 35 | /** 36 | * In the event of an error, the socket is closed. 37 | * You may call "unreadData" during this call-back to get the last bit of data off the socket. 38 | * When connecting, this delegate method may be called 39 | * before"onSocket:didAcceptNewSocket:" or "onSocket:didConnectToHost:". 40 | **/ 41 | - (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err; 42 | 43 | /** 44 | * Called when a socket disconnects with or without error. If you want to release a socket after it disconnects, 45 | * do so here. It is not safe to do that during "onSocket:willDisconnectWithError:". 46 | * 47 | * If you call the disconnect method, and the socket wasn't already disconnected, 48 | * this delegate method will be called before the disconnect method returns. 49 | **/ 50 | - (void)onSocketDidDisconnect:(AsyncSocket *)sock; 51 | 52 | /** 53 | * Called when a socket accepts a connection. Another socket is spawned to handle it. The new socket will have 54 | * the same delegate and will call "onSocket:didConnectToHost:port:". 55 | **/ 56 | - (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket; 57 | 58 | /** 59 | * Called when a new socket is spawned to handle a connection. This method should return the run-loop of the 60 | * thread on which the new socket and its delegate should operate. If omitted, [NSRunLoop currentRunLoop] is used. 61 | **/ 62 | - (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket; 63 | 64 | /** 65 | * Called when a socket is about to connect. This method should return YES to continue, or NO to abort. 66 | * If aborted, will result in AsyncSocketCanceledError. 67 | * 68 | * If the connectToHost:onPort:error: method was called, the delegate will be able to access and configure the 69 | * CFReadStream and CFWriteStream as desired prior to connection. 70 | * 71 | * If the connectToAddress:error: method was called, the delegate will be able to access and configure the 72 | * CFSocket and CFSocketNativeHandle (BSD socket) as desired prior to connection. You will be able to access and 73 | * configure the CFReadStream and CFWriteStream in the onSocket:didConnectToHost:port: method. 74 | **/ 75 | - (BOOL)onSocketWillConnect:(AsyncSocket *)sock; 76 | 77 | /** 78 | * Called when a socket connects and is ready for reading and writing. 79 | * The host parameter will be an IP address, not a DNS name. 80 | **/ 81 | - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port; 82 | 83 | /** 84 | * Called when a socket has completed reading the requested data into memory. 85 | * Not called if there is an error. 86 | **/ 87 | - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag; 88 | 89 | /** 90 | * Called when a socket has read in data, but has not yet completed the read. 91 | * This would occur if using readToData: or readToLength: methods. 92 | * It may be used to for things such as updating progress bars. 93 | **/ 94 | - (void)onSocket:(AsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 95 | 96 | /** 97 | * Called when a socket has completed writing the requested data. Not called if there is an error. 98 | **/ 99 | - (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag; 100 | 101 | /** 102 | * Called when a socket has written some data, but has not yet completed the entire write. 103 | * It may be used to for things such as updating progress bars. 104 | **/ 105 | - (void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 106 | 107 | /** 108 | * Called if a read operation has reached its timeout without completing. 109 | * This method allows you to optionally extend the timeout. 110 | * If you return a positive time interval (> 0) the read's timeout will be extended by the given amount. 111 | * If you don't implement this method, or return a non-positive time interval (<= 0) the read will timeout as usual. 112 | * 113 | * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. 114 | * The length parameter is the number of bytes that have been read so far for the read operation. 115 | * 116 | * Note that this method may be called multiple times for a single read if you return positive numbers. 117 | **/ 118 | - (NSTimeInterval)onSocket:(AsyncSocket *)sock 119 | shouldTimeoutReadWithTag:(long)tag 120 | elapsed:(NSTimeInterval)elapsed 121 | bytesDone:(NSUInteger)length; 122 | 123 | /** 124 | * Called if a write operation has reached its timeout without completing. 125 | * This method allows you to optionally extend the timeout. 126 | * If you return a positive time interval (> 0) the write's timeout will be extended by the given amount. 127 | * If you don't implement this method, or return a non-positive time interval (<= 0) the write will timeout as usual. 128 | * 129 | * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. 130 | * The length parameter is the number of bytes that have been written so far for the write operation. 131 | * 132 | * Note that this method may be called multiple times for a single write if you return positive numbers. 133 | **/ 134 | - (NSTimeInterval)onSocket:(AsyncSocket *)sock 135 | shouldTimeoutWriteWithTag:(long)tag 136 | elapsed:(NSTimeInterval)elapsed 137 | bytesDone:(NSUInteger)length; 138 | 139 | /** 140 | * Called after the socket has successfully completed SSL/TLS negotiation. 141 | * This method is not called unless you use the provided startTLS method. 142 | * 143 | * If a SSL/TLS negotiation fails (invalid certificate, etc) then the socket will immediately close, 144 | * and the onSocket:willDisconnectWithError: delegate method will be called with the specific SSL error code. 145 | **/ 146 | - (void)onSocketDidSecure:(AsyncSocket *)sock; 147 | 148 | @end 149 | 150 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 151 | #pragma mark - 152 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 153 | 154 | @interface AsyncSocket : NSObject 155 | { 156 | CFSocketNativeHandle theNativeSocket4; 157 | CFSocketNativeHandle theNativeSocket6; 158 | 159 | CFSocketRef theSocket4; // IPv4 accept or connect socket 160 | CFSocketRef theSocket6; // IPv6 accept or connect socket 161 | 162 | CFReadStreamRef theReadStream; 163 | CFWriteStreamRef theWriteStream; 164 | 165 | CFRunLoopSourceRef theSource4; // For theSocket4 166 | CFRunLoopSourceRef theSource6; // For theSocket6 167 | CFRunLoopRef theRunLoop; 168 | CFSocketContext theContext; 169 | NSArray *theRunLoopModes; 170 | 171 | NSTimer *theConnectTimer; 172 | 173 | NSMutableArray *theReadQueue; 174 | AsyncReadPacket *theCurrentRead; 175 | NSTimer *theReadTimer; 176 | NSMutableData *partialReadBuffer; 177 | 178 | NSMutableArray *theWriteQueue; 179 | AsyncWritePacket *theCurrentWrite; 180 | NSTimer *theWriteTimer; 181 | 182 | id theDelegate; 183 | UInt16 theFlags; 184 | 185 | long theUserData; 186 | } 187 | 188 | - (id)init; 189 | - (id)initWithDelegate:(id)delegate; 190 | - (id)initWithDelegate:(id)delegate userData:(long)userData; 191 | 192 | /* String representation is long but has no "\n". */ 193 | - (NSString *)description; 194 | 195 | /** 196 | * Use "canSafelySetDelegate" to see if there is any pending business (reads and writes) with the current delegate 197 | * before changing it. It is, of course, safe to change the delegate before connecting or accepting connections. 198 | **/ 199 | - (id)delegate; 200 | - (BOOL)canSafelySetDelegate; 201 | - (void)setDelegate:(id)delegate; 202 | 203 | /* User data can be a long, or an id or void * cast to a long. */ 204 | - (long)userData; 205 | - (void)setUserData:(long)userData; 206 | 207 | /* Don't use these to read or write. And don't close them either! */ 208 | - (CFSocketRef)getCFSocket; 209 | - (CFReadStreamRef)getCFReadStream; 210 | - (CFWriteStreamRef)getCFWriteStream; 211 | 212 | // Once one of the accept or connect methods are called, the AsyncSocket instance is locked in 213 | // and the other accept/connect methods can't be called without disconnecting the socket first. 214 | // If the attempt fails or times out, these methods either return NO or 215 | // call "onSocket:willDisconnectWithError:" and "onSockedDidDisconnect:". 216 | 217 | // When an incoming connection is accepted, AsyncSocket invokes several delegate methods. 218 | // These methods are (in chronological order): 219 | // 1. onSocket:didAcceptNewSocket: 220 | // 2. onSocket:wantsRunLoopForNewSocket: 221 | // 3. onSocketWillConnect: 222 | // 223 | // Your server code will need to retain the accepted socket (if you want to accept it). 224 | // The best place to do this is probably in the onSocket:didAcceptNewSocket: method. 225 | // 226 | // After the read and write streams have been setup for the newly accepted socket, 227 | // the onSocket:didConnectToHost:port: method will be called on the proper run loop. 228 | // 229 | // Multithreading Note: If you're going to be moving the newly accepted socket to another run 230 | // loop by implementing onSocket:wantsRunLoopForNewSocket:, then you should wait until the 231 | // onSocket:didConnectToHost:port: method before calling read, write, or startTLS methods. 232 | // Otherwise read/write events are scheduled on the incorrect runloop, and chaos may ensue. 233 | 234 | /** 235 | * Tells the socket to begin listening and accepting connections on the given port. 236 | * When a connection comes in, the AsyncSocket instance will call the various delegate methods (see above). 237 | * The socket will listen on all available interfaces (e.g. wifi, ethernet, etc) 238 | **/ 239 | - (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr; 240 | 241 | /** 242 | * This method is the same as acceptOnPort:error: with the additional option 243 | * of specifying which interface to listen on. So, for example, if you were writing code for a server that 244 | * has multiple IP addresses, you could specify which address you wanted to listen on. Or you could use it 245 | * to specify that the socket should only accept connections over ethernet, and not other interfaces such as wifi. 246 | * You may also use the special strings "localhost" or "loopback" to specify that 247 | * the socket only accept connections from the local machine. 248 | * 249 | * To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method. 250 | **/ 251 | - (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr; 252 | 253 | /** 254 | * Connects to the given host and port. 255 | * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2") 256 | **/ 257 | - (BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr; 258 | 259 | /** 260 | * This method is the same as connectToHost:onPort:error: with an additional timeout option. 261 | * To not time out use a negative time interval, or simply use the connectToHost:onPort:error: method. 262 | **/ 263 | - (BOOL)connectToHost:(NSString *)hostname 264 | onPort:(UInt16)port 265 | withTimeout:(NSTimeInterval)timeout 266 | error:(NSError **)errPtr; 267 | 268 | /** 269 | * Connects to the given address, specified as a sockaddr structure wrapped in a NSData object. 270 | * For example, a NSData object returned from NSNetservice's addresses method. 271 | * 272 | * If you have an existing struct sockaddr you can convert it to a NSData object like so: 273 | * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; 274 | * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; 275 | **/ 276 | - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; 277 | 278 | /** 279 | * This method is the same as connectToAddress:error: with an additional timeout option. 280 | * To not time out use a negative time interval, or simply use the connectToAddress:error: method. 281 | **/ 282 | - (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr; 283 | 284 | - (BOOL)connectToAddress:(NSData *)remoteAddr 285 | viaInterfaceAddress:(NSData *)interfaceAddr 286 | withTimeout:(NSTimeInterval)timeout 287 | error:(NSError **)errPtr; 288 | 289 | /** 290 | * Disconnects immediately. Any pending reads or writes are dropped. 291 | * If the socket is not already disconnected, the onSocketDidDisconnect delegate method 292 | * will be called immediately, before this method returns. 293 | * 294 | * Please note the recommended way of releasing an AsyncSocket instance (e.g. in a dealloc method) 295 | * [asyncSocket setDelegate:nil]; 296 | * [asyncSocket disconnect]; 297 | * [asyncSocket release]; 298 | **/ 299 | - (void)disconnect; 300 | 301 | /** 302 | * Disconnects after all pending reads have completed. 303 | * After calling this, the read and write methods will do nothing. 304 | * The socket will disconnect even if there are still pending writes. 305 | **/ 306 | - (void)disconnectAfterReading; 307 | 308 | /** 309 | * Disconnects after all pending writes have completed. 310 | * After calling this, the read and write methods will do nothing. 311 | * The socket will disconnect even if there are still pending reads. 312 | **/ 313 | - (void)disconnectAfterWriting; 314 | 315 | /** 316 | * Disconnects after all pending reads and writes have completed. 317 | * After calling this, the read and write methods will do nothing. 318 | **/ 319 | - (void)disconnectAfterReadingAndWriting; 320 | 321 | /* Returns YES if the socket and streams are open, connected, and ready for reading and writing. */ 322 | - (BOOL)isConnected; 323 | 324 | /** 325 | * Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected. 326 | * The host will be an IP address. 327 | **/ 328 | - (NSString *)connectedHost; 329 | - (UInt16)connectedPort; 330 | 331 | - (NSString *)localHost; 332 | - (UInt16)localPort; 333 | 334 | /** 335 | * Returns the local or remote address to which this socket is connected, 336 | * specified as a sockaddr structure wrapped in a NSData object. 337 | * 338 | * See also the connectedHost, connectedPort, localHost and localPort methods. 339 | **/ 340 | - (NSData *)connectedAddress; 341 | - (NSData *)localAddress; 342 | 343 | /** 344 | * Returns whether the socket is IPv4 or IPv6. 345 | * An accepting socket may be both. 346 | **/ 347 | - (BOOL)isIPv4; 348 | - (BOOL)isIPv6; 349 | 350 | // The readData and writeData methods won't block (they are asynchronous). 351 | // 352 | // When a read is complete the onSocket:didReadData:withTag: delegate method is called. 353 | // When a write is complete the onSocket:didWriteDataWithTag: delegate method is called. 354 | // 355 | // You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.) 356 | // If a read/write opertion times out, the corresponding "onSocket:shouldTimeout..." delegate method 357 | // is called to optionally allow you to extend the timeout. 358 | // Upon a timeout, the "onSocket:willDisconnectWithError:" method is called, followed by "onSocketDidDisconnect". 359 | // 360 | // The tag is for your convenience. 361 | // You can use it as an array index, step number, state id, pointer, etc. 362 | 363 | /** 364 | * Reads the first available bytes that become available on the socket. 365 | * 366 | * If the timeout value is negative, the read operation will not use a timeout. 367 | **/ 368 | - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag; 369 | 370 | /** 371 | * Reads the first available bytes that become available on the socket. 372 | * The bytes will be appended to the given byte buffer starting at the given offset. 373 | * The given buffer will automatically be increased in size if needed. 374 | * 375 | * If the timeout value is negative, the read operation will not use a timeout. 376 | * If the buffer if nil, the socket will create a buffer for you. 377 | * 378 | * If the bufferOffset is greater than the length of the given buffer, 379 | * the method will do nothing, and the delegate will not be called. 380 | * 381 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 382 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 383 | * That is, it will reference the bytes that were appended to the given buffer. 384 | **/ 385 | - (void)readDataWithTimeout:(NSTimeInterval)timeout 386 | buffer:(NSMutableData *)buffer 387 | bufferOffset:(NSUInteger)offset 388 | tag:(long)tag; 389 | 390 | /** 391 | * Reads the first available bytes that become available on the socket. 392 | * The bytes will be appended to the given byte buffer starting at the given offset. 393 | * The given buffer will automatically be increased in size if needed. 394 | * A maximum of length bytes will be read. 395 | * 396 | * If the timeout value is negative, the read operation will not use a timeout. 397 | * If the buffer if nil, a buffer will automatically be created for you. 398 | * If maxLength is zero, no length restriction is enforced. 399 | * 400 | * If the bufferOffset is greater than the length of the given buffer, 401 | * the method will do nothing, and the delegate will not be called. 402 | * 403 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 404 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 405 | * That is, it will reference the bytes that were appended to the given buffer. 406 | **/ 407 | - (void)readDataWithTimeout:(NSTimeInterval)timeout 408 | buffer:(NSMutableData *)buffer 409 | bufferOffset:(NSUInteger)offset 410 | maxLength:(NSUInteger)length 411 | tag:(long)tag; 412 | 413 | /** 414 | * Reads the given number of bytes. 415 | * 416 | * If the timeout value is negative, the read operation will not use a timeout. 417 | * 418 | * If the length is 0, this method does nothing and the delegate is not called. 419 | **/ 420 | - (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag; 421 | 422 | /** 423 | * Reads the given number of bytes. 424 | * The bytes will be appended to the given byte buffer starting at the given offset. 425 | * The given buffer will automatically be increased in size if needed. 426 | * 427 | * If the timeout value is negative, the read operation will not use a timeout. 428 | * If the buffer if nil, a buffer will automatically be created for you. 429 | * 430 | * If the length is 0, this method does nothing and the delegate is not called. 431 | * If the bufferOffset is greater than the length of the given buffer, 432 | * the method will do nothing, and the delegate will not be called. 433 | * 434 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 435 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 436 | * That is, it will reference the bytes that were appended to the given buffer. 437 | **/ 438 | - (void)readDataToLength:(NSUInteger)length 439 | withTimeout:(NSTimeInterval)timeout 440 | buffer:(NSMutableData *)buffer 441 | bufferOffset:(NSUInteger)offset 442 | tag:(long)tag; 443 | 444 | /** 445 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 446 | * 447 | * If the timeout value is negative, the read operation will not use a timeout. 448 | * 449 | * If you pass nil or zero-length data as the "data" parameter, 450 | * the method will do nothing, and the delegate will not be called. 451 | * 452 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 453 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 454 | * a character, the read will prematurely end. 455 | **/ 456 | - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 457 | 458 | /** 459 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 460 | * The bytes will be appended to the given byte buffer starting at the given offset. 461 | * The given buffer will automatically be increased in size if needed. 462 | * 463 | * If the timeout value is negative, the read operation will not use a timeout. 464 | * If the buffer if nil, a buffer will automatically be created for you. 465 | * 466 | * If the bufferOffset is greater than the length of the given buffer, 467 | * the method will do nothing, and the delegate will not be called. 468 | * 469 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 470 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 471 | * That is, it will reference the bytes that were appended to the given buffer. 472 | * 473 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 474 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 475 | * a character, the read will prematurely end. 476 | **/ 477 | - (void)readDataToData:(NSData *)data 478 | withTimeout:(NSTimeInterval)timeout 479 | buffer:(NSMutableData *)buffer 480 | bufferOffset:(NSUInteger)offset 481 | tag:(long)tag; 482 | 483 | /** 484 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 485 | * 486 | * If the timeout value is negative, the read operation will not use a timeout. 487 | * 488 | * If maxLength is zero, no length restriction is enforced. 489 | * Otherwise if maxLength bytes are read without completing the read, 490 | * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError. 491 | * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. 492 | * 493 | * If you pass nil or zero-length data as the "data" parameter, 494 | * the method will do nothing, and the delegate will not be called. 495 | * If you pass a maxLength parameter that is less than the length of the data parameter, 496 | * the method will do nothing, and the delegate will not be called. 497 | * 498 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 499 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 500 | * a character, the read will prematurely end. 501 | **/ 502 | - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag; 503 | 504 | /** 505 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 506 | * The bytes will be appended to the given byte buffer starting at the given offset. 507 | * The given buffer will automatically be increased in size if needed. 508 | * A maximum of length bytes will be read. 509 | * 510 | * If the timeout value is negative, the read operation will not use a timeout. 511 | * If the buffer if nil, a buffer will automatically be created for you. 512 | * 513 | * If maxLength is zero, no length restriction is enforced. 514 | * Otherwise if maxLength bytes are read without completing the read, 515 | * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError. 516 | * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. 517 | * 518 | * If you pass a maxLength parameter that is less than the length of the data parameter, 519 | * the method will do nothing, and the delegate will not be called. 520 | * If the bufferOffset is greater than the length of the given buffer, 521 | * the method will do nothing, and the delegate will not be called. 522 | * 523 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 524 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 525 | * That is, it will reference the bytes that were appended to the given buffer. 526 | * 527 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 528 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 529 | * a character, the read will prematurely end. 530 | **/ 531 | - (void)readDataToData:(NSData *)data 532 | withTimeout:(NSTimeInterval)timeout 533 | buffer:(NSMutableData *)buffer 534 | bufferOffset:(NSUInteger)offset 535 | maxLength:(NSUInteger)length 536 | tag:(long)tag; 537 | 538 | /** 539 | * Writes data to the socket, and calls the delegate when finished. 540 | * 541 | * If you pass in nil or zero-length data, this method does nothing and the delegate will not be called. 542 | * If the timeout value is negative, the write operation will not use a timeout. 543 | **/ 544 | - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 545 | 546 | /** 547 | * Returns progress of current read or write, from 0.0 to 1.0, or NaN if no read/write (use isnan() to check). 548 | * "tag", "done" and "total" will be filled in if they aren't NULL. 549 | **/ 550 | - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; 551 | - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; 552 | 553 | /** 554 | * Secures the connection using SSL/TLS. 555 | * 556 | * This method may be called at any time, and the TLS handshake will occur after all pending reads and writes 557 | * are finished. This allows one the option of sending a protocol dependent StartTLS message, and queuing 558 | * the upgrade to TLS at the same time, without having to wait for the write to finish. 559 | * Any reads or writes scheduled after this method is called will occur over the secured connection. 560 | * 561 | * The possible keys and values for the TLS settings are well documented. 562 | * Some possible keys are: 563 | * - kCFStreamSSLLevel 564 | * - kCFStreamSSLAllowsExpiredCertificates 565 | * - kCFStreamSSLAllowsExpiredRoots 566 | * - kCFStreamSSLAllowsAnyRoot 567 | * - kCFStreamSSLValidatesCertificateChain 568 | * - kCFStreamSSLPeerName 569 | * - kCFStreamSSLCertificates 570 | * - kCFStreamSSLIsServer 571 | * 572 | * Please refer to Apple's documentation for associated values, as well as other possible keys. 573 | * 574 | * If you pass in nil or an empty dictionary, the default settings will be used. 575 | * 576 | * The default settings will check to make sure the remote party's certificate is signed by a 577 | * trusted 3rd party certificate agency (e.g. verisign) and that the certificate is not expired. 578 | * However it will not verify the name on the certificate unless you 579 | * give it a name to verify against via the kCFStreamSSLPeerName key. 580 | * The security implications of this are important to understand. 581 | * Imagine you are attempting to create a secure connection to MySecureServer.com, 582 | * but your socket gets directed to MaliciousServer.com because of a hacked DNS server. 583 | * If you simply use the default settings, and MaliciousServer.com has a valid certificate, 584 | * the default settings will not detect any problems since the certificate is valid. 585 | * To properly secure your connection in this particular scenario you 586 | * should set the kCFStreamSSLPeerName property to "MySecureServer.com". 587 | * If you do not know the peer name of the remote host in advance (for example, you're not sure 588 | * if it will be "domain.com" or "www.domain.com"), then you can use the default settings to validate the 589 | * certificate, and then use the X509Certificate class to verify the issuer after the socket has been secured. 590 | * The X509Certificate class is part of the CocoaAsyncSocket open source project. 591 | **/ 592 | - (void)startTLS:(NSDictionary *)tlsSettings; 593 | 594 | /** 595 | * For handling readDataToData requests, data is necessarily read from the socket in small increments. 596 | * The performance can be much improved by allowing AsyncSocket to read larger chunks at a time and 597 | * store any overflow in a small internal buffer. 598 | * This is termed pre-buffering, as some data may be read for you before you ask for it. 599 | * If you use readDataToData a lot, enabling pre-buffering will result in better performance, especially on the iPhone. 600 | * 601 | * The default pre-buffering state is controlled by the DEFAULT_PREBUFFERING definition. 602 | * It is highly recommended one leave this set to YES. 603 | * 604 | * This method exists in case pre-buffering needs to be disabled by default for some unforeseen reason. 605 | * In that case, this method exists to allow one to easily enable pre-buffering when ready. 606 | **/ 607 | - (void)enablePreBuffering; 608 | 609 | /** 610 | * When you create an AsyncSocket, it is added to the runloop of the current thread. 611 | * So for manually created sockets, it is easiest to simply create the socket on the thread you intend to use it. 612 | * 613 | * If a new socket is accepted, the delegate method onSocket:wantsRunLoopForNewSocket: is called to 614 | * allow you to place the socket on a separate thread. This works best in conjunction with a thread pool design. 615 | * 616 | * If, however, you need to move the socket to a separate thread at a later time, this 617 | * method may be used to accomplish the task. 618 | * 619 | * This method must be called from the thread/runloop the socket is currently running on. 620 | * 621 | * Note: After calling this method, all further method calls to this object should be done from the given runloop. 622 | * Also, all delegate calls will be sent on the given runloop. 623 | **/ 624 | - (BOOL)moveToRunLoop:(NSRunLoop *)runLoop; 625 | 626 | /** 627 | * Allows you to configure which run loop modes the socket uses. 628 | * The default set of run loop modes is NSDefaultRunLoopMode. 629 | * 630 | * If you'd like your socket to continue operation during other modes, you may want to add modes such as 631 | * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes. 632 | * 633 | * Accepted sockets will automatically inherit the same run loop modes as the listening socket. 634 | * 635 | * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes. 636 | **/ 637 | - (BOOL)setRunLoopModes:(NSArray *)runLoopModes; 638 | - (BOOL)addRunLoopMode:(NSString *)runLoopMode; 639 | - (BOOL)removeRunLoopMode:(NSString *)runLoopMode; 640 | 641 | /** 642 | * Returns the current run loop modes the AsyncSocket instance is operating in. 643 | * The default set of run loop modes is NSDefaultRunLoopMode. 644 | **/ 645 | - (NSArray *)runLoopModes; 646 | 647 | /** 648 | * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read 649 | * any data that's left on the socket. 650 | **/ 651 | - (NSData *)unreadData; 652 | 653 | /* A few common line separators, for use with the readDataToData:... methods. */ 654 | + (NSData *)CRLFData; // 0x0D0A 655 | + (NSData *)CRData; // 0x0D 656 | + (NSData *)LFData; // 0x0A 657 | + (NSData *)ZeroData; // 0x00 658 | 659 | @end 660 | --------------------------------------------------------------------------------