jens@3: // jens@3: // BLIPEchoClient.m jens@3: // MYNetwork jens@3: // jens@3: // Created by Jens Alfke on 5/24/08. jens@3: // Copyright 2008 Jens Alfke. All rights reserved. jens@4: // Adapted from Apple sample code "CocoaEcho": jens@4: // http://developer.apple.com/samplecode/CocoaEcho/index.html jens@3: // jens@3: jens@3: #import "BLIPEchoClient.h" jens@3: #import "BLIP.h" jens@3: #import "IPAddress.h" jens@3: #import "Target.h" jens@3: jens@3: jens@3: @implementation BLIPEchoClient jens@3: jens@3: @synthesize serviceList=_serviceList; jens@3: jens@3: - (void)awakeFromNib jens@3: { jens@3: _serviceBrowser = [[NSNetServiceBrowser alloc] init]; jens@3: _serviceList = [[NSMutableArray alloc] init]; jens@3: [_serviceBrowser setDelegate:self]; jens@3: jens@3: [_serviceBrowser searchForServicesOfType:@"_blipecho._tcp." inDomain:@""]; jens@3: } jens@3: jens@3: #pragma mark - jens@3: #pragma mark BLIPConnection support jens@3: jens@4: /* Opens a BLIP connection to the given address. */ jens@3: - (void)openConnection: (IPAddress*)address jens@3: { jens@3: _connection = [[BLIPConnection alloc] initToAddress: address]; jens@3: [_connection open]; jens@3: } jens@3: jens@4: /* Closes the currently open BLIP connection. */ jens@3: - (void)closeConnection jens@3: { jens@3: [_connection close]; jens@3: [_connection release]; jens@3: _connection = nil; jens@3: } jens@3: jens@3: #pragma mark - jens@3: #pragma mark NSNetServiceBrowser delegate methods jens@3: jens@3: // We broadcast the willChangeValueForKey: and didChangeValueForKey: for the NSTableView binding to work. jens@3: jens@3: - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing { jens@3: if (![_serviceList containsObject:aNetService]) { jens@3: [self willChangeValueForKey:@"serviceList"]; jens@3: [_serviceList addObject:aNetService]; jens@3: [self didChangeValueForKey:@"serviceList"]; jens@3: } jens@3: } jens@3: jens@3: - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didRemoveService:(NSNetService *)aNetService moreComing:(BOOL)moreComing { jens@3: if ([_serviceList containsObject:aNetService]) { jens@3: [self willChangeValueForKey:@"serviceList"]; jens@3: [_serviceList removeObject:aNetService]; jens@3: [self didChangeValueForKey:@"serviceList"]; jens@3: } jens@3: } jens@3: jens@3: #pragma mark - jens@3: #pragma mark NSNetService delegate methods jens@3: jens@4: /* Stop any current Bonjour address resolution */ jens@3: - (void)stopResolving jens@3: { jens@3: if( _resolvingService ) { jens@3: _resolvingService.delegate = nil; jens@3: [_resolvingService stop]; jens@3: [_resolvingService release]; jens@3: _resolvingService = nil; jens@3: } jens@3: } jens@3: jens@4: /* Ask Bonjour to resolve (look up) the IP address of the given service. */ jens@3: - (void)startResolving: (NSNetService*)service jens@3: { jens@3: [self stopResolving]; jens@3: _resolvingService = [service retain]; jens@3: _resolvingService.delegate = self; jens@3: [_resolvingService resolveWithTimeout: 5.0]; jens@3: jens@3: } jens@3: jens@4: /* NSNetService delegate method that will be called when address resolution finishes. */ jens@3: - (void)netServiceDidResolveAddress:(NSNetService *)sender jens@3: { jens@3: if( sender == _resolvingService ) { jens@4: // Get the first address, which is an NSData containing a struct sockaddr: jens@3: NSArray *addresses = _resolvingService.addresses; jens@3: if( addresses.count > 0 ) { jens@3: NSData *addressData = [addresses objectAtIndex: 0]; jens@3: IPAddress *address = [[IPAddress alloc] initWithSockAddr: addressData.bytes]; jens@3: [self openConnection: address]; jens@3: [address release]; jens@3: } jens@3: [self stopResolving]; jens@3: } jens@3: } jens@3: jens@3: #pragma mark - jens@3: #pragma mark GUI action methods jens@3: jens@3: - (IBAction)serverClicked:(id)sender { jens@3: NSTableView * table = (NSTableView *)sender; jens@3: int selectedRow = [table selectedRow]; jens@3: jens@3: [self closeConnection]; jens@3: [self stopResolving]; jens@3: jens@3: if (-1 != selectedRow) { jens@3: [self startResolving: [_serviceList objectAtIndex:selectedRow]]; jens@3: } jens@3: } jens@3: jens@4: /* Send a BLIP request containing the string in the textfield */ jens@3: - (IBAction)sendText:(id)sender jens@3: { jens@3: BLIPRequest *r = [_connection requestWithBody: nil]; jens@3: r.bodyString = [sender stringValue]; jens@3: BLIPResponse *response = [r send]; jens@3: response.onComplete = $target(self,gotResponse:); jens@3: } jens@3: jens@4: /* Receive the response to the BLIP request, and put its contents into the response field */ jens@3: - (void) gotResponse: (BLIPResponse*)response jens@3: { jens@3: [responseField setObjectValue: response.bodyString]; jens@3: } jens@3: jens@3: jens@3: @end jens@3: jens@3: int main(int argc, char *argv[]) jens@3: { jens@3: return NSApplicationMain(argc, (const char **) argv); jens@3: }