1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
|
#import "SimpleOBEXClient.h"
#import <LightAquaBlue/LightAquaBlue.h>
#import <IOBluetooth/IOBluetoothUtilities.h>
#import <IOBluetoothUI/objc/IOBluetoothServiceBrowserController.h>
@implementation SimpleOBEXClient
- (void)awakeFromNib
{
[[connectButton window] center];
[[connectButton window] performSelector:@selector(makeFirstResponder:)
withObject:connectButton
afterDelay:0.0];
}
- (void)log:(NSString *)text
{
[logTextView insertText:text];
[logTextView insertText:@"\n"];
}
- (NSNumber *)getSizeOfFile:(NSString *)filePath
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:filePath traverseLink:YES];
if (fileAttributes != nil)
return [fileAttributes objectForKey:NSFileSize];
return nil;
}
- (IBAction)findService:(id)sender
{
IOBluetoothServiceBrowserController *browser =
[IOBluetoothServiceBrowserController serviceBrowserController:0];
if ([browser runModal] == kIOBluetoothUISuccess) {
IOBluetoothSDPServiceRecord *service = [[browser getResults] objectAtIndex:0];
[addressField setStringValue:[[service getDevice] getAddressString]];
BluetoothRFCOMMChannelID channelID;
if ([service getRFCOMMChannelID:&channelID] == kIOReturnSuccess)
[channelField setIntValue:channelID];
}
}
- (IBAction)connectOrDisconnect:(id)sender
{
if (!mClient) {
if (![BBLocalDevice isPoweredOn]) {
[self log:@"Bluetooth device is not available!"];
return;
}
NSString *deviceAddressString = [addressField stringValue];
BluetoothDeviceAddress deviceAddress;
if (IOBluetoothNSStringToDeviceAddress(deviceAddressString, &deviceAddress) != kIOReturnSuccess) {
[self log:[NSString stringWithFormat:@"%@ is not a valid Bluetooth device address!",
deviceAddressString]];
return;
}
// Create a BBBluetoothOBEXClient that will connect to the OBEX
// server on the specified address and channel.
mClient = [[BBBluetoothOBEXClient alloc] initWithRemoteDeviceAddress:&deviceAddress
channelID:[channelField intValue]
delegate:self];
}
if (![mClient isConnected]) {
[self log:[NSString stringWithFormat:@"Connecting to %@ on channel %d...",
[addressField stringValue], [channelField intValue]]];
// Send a Connect request to start the OBEX session.
// You must send a Connect request before you send any other types of
// requests.
OBEXError status = [mClient sendConnectRequestWithHeaders:nil];
if (status == kOBEXSuccess) {
[self log:@"Sent 'Connect' request, waiting for response..."];
[connectionProgress startAnimation:nil];
[connectButton setEnabled:NO];
} else {
[self log:[NSString stringWithFormat:@"Connection error! (%d)", status]];
}
} else {
[self log:@"Disconnecting..."];
// Send a Disconnect requst to close the OBEX session.
OBEXError status = [mClient sendDisconnectRequestWithHeaders:nil];
if (status == kOBEXSuccess) {
[self log:@"Sent 'Disconnect' request, waiting for response..."];
[connectionProgress startAnimation:nil];
[connectButton setEnabled:NO];
} else {
[self log:[NSString stringWithFormat:@"Disconnection error! (%d)", status]];
}
}
}
- (IBAction)chooseFile:(id)sender
{
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
if ([openPanel runModalForTypes:nil] == NSOKButton)
[filePathField setStringValue:[[openPanel filenames] objectAtIndex:0]];
}
- (IBAction)sendFile:(id)sender
{
NSString *filePath = [filePathField stringValue];
// Open a stream that will read from the local file. It doesn't have to be
// retained because the client will retain it for the duration of the
// request.
NSInputStream *fileInputStream = [NSInputStream inputStreamWithFileAtPath:filePath];
[fileInputStream open]; // must be opened
// Attach some request headers that tell the server the name and size of
// the file that we are sending.
BBMutableOBEXHeaderSet *headerSet = [BBMutableOBEXHeaderSet headerSet];
[headerSet setValueForNameHeader:[filePath lastPathComponent]];
NSNumber *fileSize = [self getSizeOfFile:filePath];
if (fileSize) {
[headerSet setValueForLengthHeader:[fileSize unsignedIntValue]];
[transferProgress setIndeterminate:NO];
[transferProgress setMaxValue:[fileSize unsignedIntValue]];
[self log:[NSString stringWithFormat:@"Sending file of size: %d",
[fileSize unsignedIntValue]]];
} else {
[transferProgress setIndeterminate:YES];
}
[self log:[NSString stringWithFormat:@"Sending Put request with file <%@>",
filePath]];
// send the request
OBEXError status = [mClient sendPutRequestWithHeaders:headerSet
readFromStream:fileInputStream];
if (status == kOBEXSuccess) {
[self log:@"Sending file..."];
[sendButton setEnabled:NO];
[cancelButton setEnabled:YES];
[transferProgress startAnimation:nil];
} else {
[self log:[NSString stringWithFormat:@"Put request error! (%d)", status]];
}
}
- (IBAction)cancelFileTransfer:(id)sender
{
[self log:@"Attempting to cancel transfer..."];
[mClient abortCurrentRequest];
}
#pragma mark -
#pragma mark BBBluetoothOBEXClient delegate methods
// The following delegate methods allow the BBBluetoothOBEXClient to notify
// you when an OBEX event has occurred. You must wait for a notification
// that a request has finished before start the next request! For example,
// if you send a Connect request, you must wait for
// client:didFinishConnectRequestWithError:response: to
// be called until you send another request. Otherwise, the OBEX server on the
// other end cannot process your requests correctly.
- (void)client:(BBBluetoothOBEXClient *)client
didFinishConnectRequestWithError:(OBEXError)error
response:(BBOBEXResponse *)response
{
if (error == kOBEXSuccess) {
if ([response responseCode] == kOBEXResponseCodeSuccessWithFinalBit) {
[self log:@"Connected."];
[connectButton setTitle:@"Disconnect"];
} else {
[self log:[NSString stringWithFormat:@"Connect request refused (%@)",
[response responseCodeDescription]]];
}
} else {
[self log:[NSString stringWithFormat:@"Connect error! (%d)", error]];
}
[connectButton setEnabled:YES];
[connectionProgress stopAnimation:nil];
}
- (void)client:(BBBluetoothOBEXClient *)client
didFinishDisconnectRequestWithError:(OBEXError)error
response:(BBOBEXResponse *)response
{
if (error == kOBEXSuccess) {
if ([response responseCode] == kOBEXResponseCodeSuccessWithFinalBit) {
[self log:@"Disconnected."];
} else {
[self log:[NSString stringWithFormat:@"Disconnect request refused (%@)",
[response responseCodeDescription]]];
}
} else {
[self log:[NSString stringWithFormat:@"Disconnect error! (%d)", error]];
}
// close the baseband connection to the remote device
[[[client RFCOMMChannel] getDevice] closeConnection];
[connectButton setTitle:@"Connect"];
[connectButton setEnabled:YES];
[connectionProgress stopAnimation:nil];
}
- (void)client:(BBBluetoothOBEXClient *)client
didFinishPutRequestForStream:(NSInputStream *)inputStream
error:(OBEXError)error
response:(BBOBEXResponse *)response
{
if (error == kOBEXSuccess) {
if ([response responseCode] == kOBEXResponseCodeSuccessWithFinalBit) {
[self log:@"File sent successfully."];
} else {
[self log:[NSString stringWithFormat:@"Put request refused (%@)",
[response responseCodeDescription]]];
}
} else {
[self log:[NSString stringWithFormat:@"Put error! (%d)", error]];
}
[inputStream close];
[transferProgress stopAnimation:nil];
[sendButton setEnabled:YES];
[cancelButton setEnabled:NO];
}
- (void)client:(BBBluetoothOBEXClient *)client
didSendDataOfLength:(unsigned)length
{
[self log:[NSString stringWithFormat:@"Sent another %d bytes...", length]];
[transferProgress incrementBy:length];
}
- (void)client:(BBBluetoothOBEXClient *)session
didAbortRequestWithStream:(NSStream *)stream
error:(OBEXError)error
response:(BBOBEXResponse *)response
{
if (error == kOBEXSuccess) {
if ([response responseCode] == kOBEXResponseCodeSuccessWithFinalBit) {
[self log:@"File transfer cancelled."];
} else {
[self log:[NSString stringWithFormat:@"Abort request refused (%@)",
[response responseCodeDescription]]];
}
} else {
[self log:[NSString stringWithFormat:@"Abort error! (%d)", error]];
}
[stream close];
[transferProgress stopAnimation:nil];
[transferProgress setDoubleValue:0];
[sendButton setEnabled:YES];
[cancelButton setEnabled:NO];
}
- (void)dealloc
{
[mClient release];
[super dealloc];
}
@end
|